EasyScanner.cpp
Go to the documentation of this file.
1 
6 #include <iostream>
7 #include <cstdio>
8 #include <cctype>
9 #include <cstdlib>
10 #include <cmath>
11 #include <cstring>
12 #include <boost/format.hpp>
13 #include <errno.h>
14 
15 #include "EasyScanner.h"
16 
17 using namespace std;
18 using namespace boost;
19 using namespace hrp;
20 
21 
22 // Replacement for 'strtod()' function in Visual C++
23 // This is neccessary because the implementation of VC++6.0 uses 'strlen()' in the function,
24 // so that it becomes too slow for a string buffer which has long length.
25 #ifdef _MSC_VER
26 static double mystrtod(const char* nptr, char** endptr)
27 {
28  const char* org = nptr;
29  bool valid = false;
30  double value = 0.0;
31  double sign = +1.0;
32 
33  if(*nptr == '+'){
34  nptr++;
35  } else if(*nptr == '-'){
36  sign = -1.0;
37  nptr++;
38  }
39  if(isdigit((unsigned char)*nptr)){
40  valid = true;
41  do {
42  value = value * 10.0 + (*nptr - '0');
43  nptr++;
44  } while(isdigit((unsigned char)*nptr));
45  }
46  if(*nptr == '.'){
47  valid = false;
48  nptr++;
49  if(isdigit((unsigned char)*nptr)){
50  double small = 0.1;
51  valid = true;
52  do {
53  value += small * (*nptr - '0');
54  small *= 0.1;
55  nptr++;
56  } while(isdigit((unsigned char)*nptr));
57  }
58  }
59  if(valid && (*nptr == 'e' || *nptr == 'E')){
60  nptr++;
61  valid = false;
62  double psign = +1.0;
63  if(*nptr == '+'){
64  nptr++;
65  } else if(*nptr == '-'){
66  psign = -1.0;
67  nptr++;
68  }
69  if(isdigit((unsigned char)*nptr)){
70  valid = true;
71  double p = 0.0;
72  do {
73  p = p * 10.0 + (*nptr - '0');
74  nptr++;
75  } while(isdigit((unsigned char)*nptr));
76  value *= pow(10.0, psign * p);
77  }
78  }
79  if(valid){
80  *endptr = (char*)nptr;
81  } else {
82  *endptr = (char*)org;
83  }
84  return sign * value;
85 }
86 #else
87 static inline double mystrtod(const char* nptr, char** endptr) {
88  return strtod(nptr, endptr);
89 }
90 #endif
91 
92 
93 std::string EasyScanner::Exception::getFullMessage()
94 {
95  string m(message);
96 
97  if(lineNumber > 0){
98  m += str(format(" at line %1%") % lineNumber);
99  }
100 
101  if(!filename.empty()){
102  m += str(format(" of %1%") % filename);
103  }
104 
105  return m;
106 }
107 
108 
109 EasyScanner::EasyScanner()
110 {
111  init();
112 }
113 
114 
118 EasyScanner::EasyScanner(string filename)
119 {
120  init();
121  loadFile(filename);
122 }
123 
124 
125 void EasyScanner::init()
126 {
127  textBuf = 0;
128  size = 0;
129  textBufEnd = 0;
130  lineNumberOffset = 1;
131 
132  commentChar = '#';
133  quoteChar = 0xffff;
134  isLineOriented = true;
135  defaultErrorMessage = "unknown error of the lexical scanner";
136 
137  whiteSpaceChars.push_back(' ');
138  whiteSpaceChars.push_back('\t');
139 
140  symbols.reset(new SymbolMap());
141 }
142 
143 
149 EasyScanner::EasyScanner(const EasyScanner& org, bool copyText) :
150  whiteSpaceChars(org.whiteSpaceChars)
151 {
152  commentChar = org.commentChar;
153  quoteChar = org.quoteChar;
155  filename = org.filename;
157  lineNumber = org.lineNumber;
159 
160  symbols = org.symbols;
161 
162  if(copyText && org.textBuf){
163  size = org.size;
164  textBuf = new char[size+1];
165  memcpy(textBuf, org.textBuf, size+1);
166  text = textBuf;
167  textBufEnd = textBuf + size;
168  } else {
169  textBuf = 0;
170  size = 0;
171  textBufEnd = 0;
172  }
173 }
174 
175 
177 void EasyScanner::setText(const char* text, int len)
178 {
179  if(textBuf) delete[] textBuf;
180 
181  size = len;
182  textBuf = new char[size+1];
183  memcpy(textBuf, text, len);
184  textBuf[size] = 0;
185  this->text = textBuf;
186  textBufEnd = textBuf + size;
188  filename = "";
189 }
190 
191 
193 {
194  if(textBuf) delete[] textBuf;
195 }
196 
197 
199 {
200  lineNumberOffset = offset;
201 }
202 
203 
205 {
206  text = textBuf;
208 }
209 
210 
212 {
213  SymbolMap::iterator p = symbols->begin();
214  while(p != symbols->end()){
215  cout << p->first << " = " << p->second << std::endl;
216  p++;
217  }
218 }
219 
220 
221 void EasyScanner::throwException(const char* message)
222 {
223  Exception ex;
224  ex.message = message ? message : defaultErrorMessage;
225  ex.filename = filename;
226  ex.lineNumber = lineNumber;
227  throw ex;
228 }
229 
230 
231 void EasyScanner::throwException(const std::string& message)
232 {
233  throwException(message.c_str());
234 }
235 
236 
242 {
243  commentChar = cc ? cc : 0xffff;
244 }
245 
246 
248 {
249  isLineOriented = on;
250 }
251 
252 
255 {
256  whiteSpaceChars.push_back(ws);
257 }
258 
259 
265 {
266  quoteChar = qs;
267 }
268 
269 
274 void EasyScanner::loadFile(const string& filename)
275 {
276  this->filename.clear();
277 
278  FILE* file = fopen(filename.c_str(), "rb");
279 
280  if(!file){
281  this->lineNumber = -1;
282  string message;
283  switch(errno){
284  case ENOENT:
285  message = filename + " cannot be found.";
286  break;
287  default:
288  message = string("I/O error in accessing ") + filename;
289  break;
290  }
291  throwException(message.c_str());
292  }
293 
294  this->filename = filename;
295 
296  fseek(file, 0, SEEK_END);
297  size = ftell(file);
298  rewind(file);
299  if(textBuf) delete[] textBuf;
300  textBuf = new char[size+1];
301  fread(textBuf, sizeof(char), size, file);
302  textBuf[size] = 0;
303  fclose(file);
304  text = textBuf;
305  textBufEnd = textBuf + size;
307 }
308 
309 
314 {
315  while(*text != '\r' && *text != '\n' && *text != '\0') text++;
316 }
317 
318 
320 {
321  int n = whiteSpaceChars.size();
322  while(true){
323  int i=0;
324  while(i < n){
325  if(*text == whiteSpaceChars[i]){
326  text++;
327  i = 0;
328  } else {
329  i++;
330  }
331  }
332  if(*text == commentChar){
333  text++;
334  skipToLineEnd();
335  }
336 
337  if(isLineOriented){
338  break;
339  }
340  if(*text == '\n'){
341  text++;
342  } else if(*text == '\r'){
343  text++;
344  if(*text == '\n'){
345  text++;
346  }
347  } else {
348  break;
349  }
350  lineNumber++;
351  }
352 }
353 
354 
360 {
361  if(*text == '\n'){
362  text++;
363  lineNumber++;
364  return true;
365  } else if(*text == '\r'){
366  text++;
367  if(*text == '\n'){
368  text++;
369  }
370  lineNumber++;
371  return true;
372  }
373  return false;
374 }
375 
376 
378 {
379  char* current = text;
380  if(readLF()){
381  text = current;
382  return true;
383  }
384  return false;
385 }
386 
387 
389 {
390  skipSpace();
391 
392  if(isdigit((unsigned char)*text) || *text == '+' || *text == '-'){
393  char* tail;
394  intValue = strtol(text, &tail, 0);
395  if(tail != text){
396  text = tail;
397  return T_INTEGER;
398  }
399  doubleValue = mystrtod(text, &tail);
400  if(tail != text){
401  text = tail;
402  return T_DOUBLE;
403  }
404  charValue = *text;
405  text++;
406  return T_SIGLUM;
407 
408  } else if(isalpha((unsigned char)*text)){
409  char* org = text;
410  text++;
411  while(isalnum((unsigned char)*text) || *text == '_') text++;
412  stringValue.assign(org, text - org);
413  if(stringValue.size() == 1){
414  charValue = *org;
415  return T_ALPHABET;
416  } else {
417  return T_WORD;
418  }
419 
420  } else if(*text == quoteChar) {
422 
423  } else if(ispunct((unsigned char)*text)){
424  charValue = *text;
425  text++;
426  return T_SIGLUM;
427 
428  } else if(readLF0()){
429  return T_LF;
430 
431  } else if(*text == '\0'){
432  return T_EOF;
433  }
434 
435  return T_NONE;
436 }
437 
438 
439 
440 
441 
446 {
447  for(size_t i=0; i < stringValue.size(); ++i){
448  stringValue[i] = tolower(stringValue[i]);
449  }
450 }
451 
452 
454 {
455  text++;
456  char* org = text;
457 
458  if(isLineOriented){
459  while(true){
460  if(*text == '\r' || *text == '\n' || *text == '\0'){
461  text = org;
462  return false;
463  }
464  if(*text == quoteChar) break;
465  text++;
466  }
467  } else {
468  while(true){
469  if(*text == '\0'){
470  text = org;
471  return false;
472  }
473  readLF0();
474  if(*text == quoteChar) break;
475  text++;
476  }
477  }
478 
479  stringValue.assign(org, text - org);
480  text++;
481  return true;
482 }
483 
484 
486 {
487  char* tail;
488 
489  if(checkLF()) return false;
490 
491  doubleValue = mystrtod(text, &tail);
492 
493  if(tail != text){
494  text = tail;
495  return true;
496  }
497 
498  return false;
499 }
500 
502 {
503  char* tail;
504 
505  if(checkLF()) return false;
506 
507  intValue = strtol(text, &tail, 0);
508  if(tail != text){
509  text = tail;
510  return true;
511  }
512 
513  return false;
514 }
515 
516 
518 {
519  skipSpace();
520 
521  if(isgraph((unsigned char)*text)){
522  charValue = *text;
523  text++;
524  return true;
525  }
526 
527  return false;
528 }
529 
530 
531 bool EasyScanner::readChar(int chara)
532 {
533  skipSpace();
534 
535  if(*text == chara){
536  text++;
537  return true;
538  }
539 
540  return false;
541 }
542 
544 {
545  skipSpace();
546 
547  return *text;
548 }
549 
550 
552 {
553  char* org = text;
554 
555  while(true){
556  int c = (unsigned char)*text;
557  if(!isalnum(c) && isascii(c) && c != '_'){
558  break;
559  }
560  text++;
561  }
562 
563  if(text - org > 0){
564  stringValue.assign(org, text - org);
565  return true;
566  }
567 
568  return false;
569 }
570 
571 
572 bool EasyScanner::readString0(const int delimiterChar)
573 {
574  char* org = text;
575 
576  while(true){
577  int c = (unsigned char)*text;
578  if(isspace(c) || iscntrl(c) || c == delimiterChar){
579  break;
580  }
581  text++;
582  }
583 
584  if(text - org > 0){
585  stringValue.assign(org, text - org);
586  return true;
587  }
588 
589  return false;
590 }
591 
592 
593 bool EasyScanner::readString(const char* str)
594 {
595  skipSpace();
596 
597  char* org = text;
598  while(*str != '\0'){
599  if(*str++ != *text++){
600  text = org;
601  return false;
602  }
603  }
604 
605  return true;
606 }
607 
608 
613 bool EasyScanner::readQuotedString(bool allowNoQuotedWord)
614 {
615  skipSpace();
616 
617  if(*text == quoteChar){
618  return extractQuotedString();
619 
620  } else if(allowNoQuotedWord){
621  return readString0(' ');
622  }
623 
624  return false;
625 }
626 
627 
629 {
630  skipSpace();
631 
632  char* org = text;
633  while(true){
634  if(*text == '\r' || *text == '\n' || *text == commentChar || *text == '\0'){
635  break;
636  }
637  text++;
638  }
639 
640  if(text != org){
641  stringValue.assign(org, text - org);
642  return true;
643  }
644  return false;
645 }
646 
647 
648 
650 {
651  if(readWord()){
653  if(symbolValue){
654  return true;
655  }
656  }
657 
658  return false;
659 }
660 
661 
663 {
664  char* org = text;
665  int orglineNumber = lineNumber;
666 
667  if(readWord()){
669  if(symbolValue == id){
670  return true;
671  } else {
672  text = org;
673  lineNumber = orglineNumber;
674  }
675  }
676 
677  return false;
678 }
679 
680 
681 
683 {
684  while(true){
685  if(readLF0()){
686  return true;
687  }
688  if(*text == '\0'){
689  return false;
690  }
691  text++;
692  }
693 }
694 
695 
697 {
698  char* org = text;
699 
700  if(skipLine()){
701  // eliminate newline code
702  char* end = text - 1;
703  if(*end == '\n'){
704  end--;
705  if(*end == '\r'){
706  end--;
707  }
708  }
709  end++;
710 
711  stringValue.assign(org, end - org);
712  return true;
713  }
714 
715  return false;
716 }
717 
718 
720 {
721  do {
722  if(*text == '\0'){
723  return false;
724  }
725  } while(readLF());
726 
727  return true;
728 }
729 
730 
731 // operators
732 
733 EasyScanner& operator>>(EasyScanner& scanner, double& value)
734 {
735  if(!scanner.readDouble()){
736  scanner.throwException("scan error: can't read double value");
737  }
738  value = scanner.doubleValue;
739  return scanner;
740 }
741 
742 
743 EasyScanner& operator>>(EasyScanner& scanner, int& value)
744 {
745  if(!scanner.readInt()){
746  scanner.throwException("scan error: can't read int value");
747  throw scanner;
748  }
749  value = scanner.intValue;
750  return scanner;
751 }
752 
753 
754 EasyScanner& operator>>(EasyScanner& scanner, const char* matchString)
755 {
756  scanner.skipSpace();
757  while(*matchString != '\0'){
758  if(*scanner.text++ != *matchString++){
759  scanner.throwException("scan error: unmatched string");
760  }
761  }
762  return scanner;
763 }
764 
765 
766 EasyScanner& operator>>(EasyScanner& scanner, char matchChar)
767 {
768  scanner.skipSpace();
769  if(*scanner.text++ != matchChar){
770  scanner.throwException("scan error: unmatched cahracter");
771  }
772  return scanner;
773 }
774 
775 
776 EasyScanner& operator>>(EasyScanner& scanner, string& str)
777 {
778  scanner.skipSpace();
779  if(!scanner.readQuotedString(true)){
780  scanner.throwException("scan error: can't read string");
781  }
782  str = scanner.stringValue;
783  return scanner;
784 }
785 
786 
788 {
789  if(!scanner.readLF()){
790  scanner.throwException("scan error: end of line unmatched");
791  }
792  return scanner;
793 }
void setLineOriented(bool on)
int c
Definition: autoplay.py:16
void setCommentChar(char cc)
if 0, comment is disabled
bool readString(const int delimiterChar= ',')
Definition: EasyScanner.h:112
SymbolMapPtr symbols
Definition: EasyScanner.h:261
Modifications controlling boost library behavior.
Definition: ColladaUtil.h:306
std::string filename
Definition: EasyScanner.h:240
char * filename
Definition: cdjpeg.h:133
void loadFile(const std::string &filename)
png_uint_32 size
Definition: png.h:1521
#define SEEK_END
Definition: zconf.h:298
bool readLF()
reading a line feed
Definition: EasyScanner.h:136
png_voidp int value
Definition: png.h:2113
string message
bool readQuotedString(bool allowNoQuotedWord=false)
void setQuoteChar(char qc)
png_uint_32 i
Definition: png.h:2735
void setWhiteSpaceChar(char ws)
static double mystrtod(const char *nptr, char **endptr)
Definition: EasyScanner.cpp:87
void throwException(const char *message)
std::vector< int > whiteSpaceChars
Definition: EasyScanner.h:259
virtual ~EasyScanner()
std::map< std::string, int > SymbolMap
Definition: EasyScanner.h:48
int getSymbolID(const std::string &symbol)
Definition: EasyScanner.h:65
std::string stringValue
Definition: EasyScanner.h:231
org
void setText(const char *text, int len)
std::string defaultErrorMessage
Definition: EasyScanner.h:235
bool readString0(const int delimiterChar)
friend HRP_UTIL_EXPORT EasyScanner & operator>>(EasyScanner &scanner, double &value)
The header file of a text scanner class.
bool readUnquotedTextBlock()
void setLineNumberOffset(int offset)


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Sat Apr 13 2019 02:14:21