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
23 // This is necessary for a locale-free version
24 static inline double mystrtod(const char* nptr, char** endptr)
25 {
26  const char* org = nptr;
27  bool valid = false;
28  double value = 0.0;
29  double sign = +1.0;
30 
31  if(*nptr == '+'){
32  nptr++;
33  } else if(*nptr == '-'){
34  sign = -1.0;
35  nptr++;
36  }
37  if(*nptr == 'n' || *nptr == 'N')
38  {
39  nptr++;
40  if(*nptr == 'a' || *nptr == 'A')
41  {
42  nptr++;
43  if(*nptr == 'n' || *nptr == 'N')
44  {
45  nptr++;
46  *endptr = (char *)nptr;
47  return NAN;
48  }
49  }
50  else
51  {
52  valid = false;
53  *endptr = (char *)org;
54  return 0;
55  }
56  }
57  if(isdigit((unsigned char)*nptr)){
58  valid = true;
59  do {
60  value = value * 10.0 + (*nptr - '0');
61  nptr++;
62  } while(isdigit((unsigned char)*nptr));
63  }
64  if(*nptr == '.'){
65  valid = false;
66  nptr++;
67  if(isdigit((unsigned char)*nptr)){
68  double small = 0.1;
69  valid = true;
70  do {
71  value += small * (*nptr - '0');
72  small *= 0.1;
73  nptr++;
74  } while(isdigit((unsigned char)*nptr));
75  }
76  }
77  if(valid && (*nptr == 'e' || *nptr == 'E')){
78  nptr++;
79  valid = false;
80  double psign = +1.0;
81  if(*nptr == '+'){
82  nptr++;
83  } else if(*nptr == '-'){
84  psign = -1.0;
85  nptr++;
86  }
87  if(isdigit((unsigned char)*nptr)){
88  valid = true;
89  double p = 0.0;
90  do {
91  p = p * 10.0 + (*nptr - '0');
92  nptr++;
93  } while(isdigit((unsigned char)*nptr));
94  value *= pow(10.0, psign * p);
95  }
96  }
97  if(valid){
98  *endptr = (char*)nptr;
99  } else {
100  *endptr = (char*)org;
101  }
102  return sign * value;
103 }
104 
105 
106 std::string EasyScanner::Exception::getFullMessage()
107 {
108  string m(message);
109 
110  if(lineNumber > 0){
111  m += str(format(" at line %1%") % lineNumber);
112  }
113 
114  if(!filename.empty()){
115  m += str(format(" of %1%") % filename);
116  }
117 
118  return m;
119 }
120 
121 
122 EasyScanner::EasyScanner()
123 {
124  init();
125 }
126 
127 
131 EasyScanner::EasyScanner(string filename)
132 {
133  init();
134  loadFile(filename);
135 }
136 
137 
138 void EasyScanner::init()
139 {
140  textBuf = 0;
141  size = 0;
142  textBufEnd = 0;
143  lineNumberOffset = 1;
144 
145  commentChar = '#';
146  quoteChar = 0xffff;
147  isLineOriented = true;
148  defaultErrorMessage = "unknown error of the lexical scanner";
149 
150  whiteSpaceChars.push_back(' ');
151  whiteSpaceChars.push_back('\t');
152 
153  symbols.reset(new SymbolMap());
154 }
155 
156 
162 EasyScanner::EasyScanner(const EasyScanner& org, bool copyText) :
163  whiteSpaceChars(org.whiteSpaceChars)
164 {
165  commentChar = org.commentChar;
166  quoteChar = org.quoteChar;
168  filename = org.filename;
170  lineNumber = org.lineNumber;
172 
173  symbols = org.symbols;
174 
175  if(copyText && org.textBuf){
176  size = org.size;
177  textBuf = new char[size+1];
178  memcpy(textBuf, org.textBuf, size+1);
179  text = textBuf;
180  textBufEnd = textBuf + size;
181  } else {
182  textBuf = 0;
183  size = 0;
184  textBufEnd = 0;
185  }
186 }
187 
188 
190 void EasyScanner::setText(const char* text, int len)
191 {
192  if(textBuf) delete[] textBuf;
193 
194  size = len;
195  textBuf = new char[size+1];
196  memcpy(textBuf, text, len);
197  textBuf[size] = 0;
198  this->text = textBuf;
199  textBufEnd = textBuf + size;
201  filename = "";
202 }
203 
204 
206 {
207  if(textBuf) delete[] textBuf;
208 }
209 
210 
212 {
213  lineNumberOffset = offset;
214 }
215 
216 
218 {
219  text = textBuf;
221 }
222 
223 
225 {
226  SymbolMap::iterator p = symbols->begin();
227  while(p != symbols->end()){
228  cout << p->first << " = " << p->second << std::endl;
229  p++;
230  }
231 }
232 
233 
234 void EasyScanner::throwException(const char* message)
235 {
236  Exception ex;
237  ex.message = message ? message : defaultErrorMessage;
238  ex.filename = filename;
239  ex.lineNumber = lineNumber;
240  throw ex;
241 }
242 
243 
244 void EasyScanner::throwException(const std::string& message)
245 {
246  throwException(message.c_str());
247 }
248 
249 
255 {
256  commentChar = cc ? cc : 0xffff;
257 }
258 
259 
261 {
262  isLineOriented = on;
263 }
264 
265 
268 {
269  whiteSpaceChars.push_back(ws);
270 }
271 
272 
278 {
279  quoteChar = qs;
280 }
281 
282 
287 void EasyScanner::loadFile(const string& filename)
288 {
289  this->filename.clear();
290 
291  FILE* file = fopen(filename.c_str(), "rb");
292 
293  if(!file){
294  this->lineNumber = -1;
295  string message;
296  switch(errno){
297  case ENOENT:
298  message = filename + " cannot be found.";
299  break;
300  default:
301  message = string("I/O error in accessing ") + filename;
302  break;
303  }
304  throwException(message.c_str());
305  }
306 
307  this->filename = filename;
308 
309  fseek(file, 0, SEEK_END);
310  size = ftell(file);
311  rewind(file);
312  if(textBuf) delete[] textBuf;
313  textBuf = new char[size+1];
314  fread(textBuf, sizeof(char), size, file);
315  textBuf[size] = 0;
316  fclose(file);
317  text = textBuf;
318  textBufEnd = textBuf + size;
320 }
321 
322 
327 {
328  while(*text != '\r' && *text != '\n' && *text != '\0') text++;
329 }
330 
331 
333 {
334  int n = whiteSpaceChars.size();
335  while(true){
336  int i=0;
337  while(i < n){
338  if(*text == whiteSpaceChars[i]){
339  text++;
340  i = 0;
341  } else {
342  i++;
343  }
344  }
345  if(*text == commentChar){
346  text++;
347  skipToLineEnd();
348  }
349 
350  if(isLineOriented){
351  break;
352  }
353  if(*text == '\n'){
354  text++;
355  } else if(*text == '\r'){
356  text++;
357  if(*text == '\n'){
358  text++;
359  }
360  } else {
361  break;
362  }
363  lineNumber++;
364  }
365 }
366 
367 
373 {
374  if(*text == '\n'){
375  text++;
376  lineNumber++;
377  return true;
378  } else if(*text == '\r'){
379  text++;
380  if(*text == '\n'){
381  text++;
382  }
383  lineNumber++;
384  return true;
385  }
386  return false;
387 }
388 
389 
391 {
392  char* current = text;
393  if(readLF()){
394  text = current;
395  return true;
396  }
397  return false;
398 }
399 
400 
402 {
403  skipSpace();
404 
405  if(isdigit((unsigned char)*text) || *text == '+' || *text == '-'){
406  char* tail;
407  intValue = strtol(text, &tail, 0);
408  if(tail != text){
409  text = tail;
410  return T_INTEGER;
411  }
412  doubleValue = mystrtod(text, &tail);
413  if(tail != text){
414  text = tail;
415  return T_DOUBLE;
416  }
417  charValue = *text;
418  text++;
419  return T_SIGLUM;
420 
421  } else if(isalpha((unsigned char)*text)){
422  char* org = text;
423  text++;
424  while(isalnum((unsigned char)*text) || *text == '_') text++;
425  stringValue.assign(org, text - org);
426  if(stringValue.size() == 1){
427  charValue = *org;
428  return T_ALPHABET;
429  } else {
430  return T_WORD;
431  }
432 
433  } else if(*text == quoteChar) {
435 
436  } else if(ispunct((unsigned char)*text)){
437  charValue = *text;
438  text++;
439  return T_SIGLUM;
440 
441  } else if(readLF0()){
442  return T_LF;
443 
444  } else if(*text == '\0'){
445  return T_EOF;
446  }
447 
448  return T_NONE;
449 }
450 
451 
452 
453 
454 
459 {
460  for(size_t i=0; i < stringValue.size(); ++i){
461  stringValue[i] = tolower(stringValue[i]);
462  }
463 }
464 
465 
467 {
468  text++;
469  char* org = text;
470 
471  if(isLineOriented){
472  while(true){
473  if(*text == '\r' || *text == '\n' || *text == '\0'){
474  text = org;
475  return false;
476  }
477  if(*text == quoteChar) break;
478  text++;
479  }
480  } else {
481  while(true){
482  if(*text == '\0'){
483  text = org;
484  return false;
485  }
486  readLF0();
487  if(*text == quoteChar) break;
488  text++;
489  }
490  }
491 
492  stringValue.assign(org, text - org);
493  text++;
494  return true;
495 }
496 
497 
499 {
500  char* tail;
501 
502  if(checkLF()) return false;
503 
504  doubleValue = mystrtod(text, &tail);
505 
506  if(tail != text){
507  text = tail;
508  return true;
509  }
510 
511  return false;
512 }
513 
515 {
516  char* tail;
517 
518  if(checkLF()) return false;
519 
520  intValue = strtol(text, &tail, 0);
521  if(tail != text){
522  text = tail;
523  return true;
524  }
525 
526  return false;
527 }
528 
529 
531 {
532  skipSpace();
533 
534  if(isgraph((unsigned char)*text)){
535  charValue = *text;
536  text++;
537  return true;
538  }
539 
540  return false;
541 }
542 
543 
544 bool EasyScanner::readChar(int chara)
545 {
546  skipSpace();
547 
548  if(*text == chara){
549  text++;
550  return true;
551  }
552 
553  return false;
554 }
555 
557 {
558  skipSpace();
559 
560  return *text;
561 }
562 
563 
565 {
566  char* org = text;
567 
568  while(true){
569  int c = (unsigned char)*text;
570  if(!isalnum(c) && isascii(c) && c != '_'){
571  break;
572  }
573  text++;
574  }
575 
576  if(text - org > 0){
577  stringValue.assign(org, text - org);
578  return true;
579  }
580 
581  return false;
582 }
583 
584 
585 bool EasyScanner::readString0(const int delimiterChar)
586 {
587  char* org = text;
588 
589  while(true){
590  int c = (unsigned char)*text;
591  if(isspace(c) || iscntrl(c) || c == delimiterChar){
592  break;
593  }
594  text++;
595  }
596 
597  if(text - org > 0){
598  stringValue.assign(org, text - org);
599  return true;
600  }
601 
602  return false;
603 }
604 
605 
606 bool EasyScanner::readString(const char* str)
607 {
608  skipSpace();
609 
610  char* org = text;
611  while(*str != '\0'){
612  if(*str++ != *text++){
613  text = org;
614  return false;
615  }
616  }
617 
618  return true;
619 }
620 
621 
626 bool EasyScanner::readQuotedString(bool allowNoQuotedWord)
627 {
628  skipSpace();
629 
630  if(*text == quoteChar){
631  return extractQuotedString();
632 
633  } else if(allowNoQuotedWord){
634  return readString0(' ');
635  }
636 
637  return false;
638 }
639 
640 
642 {
643  skipSpace();
644 
645  char* org = text;
646  while(true){
647  if(*text == '\r' || *text == '\n' || *text == commentChar || *text == '\0'){
648  break;
649  }
650  text++;
651  }
652 
653  if(text != org){
654  stringValue.assign(org, text - org);
655  return true;
656  }
657  return false;
658 }
659 
660 
661 
663 {
664  if(readWord()){
666  if(symbolValue){
667  return true;
668  }
669  }
670 
671  return false;
672 }
673 
674 
676 {
677  char* org = text;
678  int orglineNumber = lineNumber;
679 
680  if(readWord()){
682  if(symbolValue == id){
683  return true;
684  } else {
685  text = org;
686  lineNumber = orglineNumber;
687  }
688  }
689 
690  return false;
691 }
692 
693 
694 
696 {
697  while(true){
698  if(readLF0()){
699  return true;
700  }
701  if(*text == '\0'){
702  return false;
703  }
704  text++;
705  }
706 }
707 
708 
710 {
711  char* org = text;
712 
713  if(skipLine()){
714  // eliminate newline code
715  char* end = text - 1;
716  if(*end == '\n'){
717  end--;
718  if(*end == '\r'){
719  end--;
720  }
721  }
722  end++;
723 
724  stringValue.assign(org, end - org);
725  return true;
726  }
727 
728  return false;
729 }
730 
731 
733 {
734  do {
735  if(*text == '\0'){
736  return false;
737  }
738  } while(readLF());
739 
740  return true;
741 }
742 
743 
744 // operators
745 
747 {
748  if(!scanner.readDouble()){
749  scanner.throwException("scan error: can't read double value");
750  }
751  value = scanner.doubleValue;
752  return scanner;
753 }
754 
755 
757 {
758  if(!scanner.readInt()){
759  scanner.throwException("scan error: can't read int value");
760  throw scanner;
761  }
762  value = scanner.intValue;
763  return scanner;
764 }
765 
766 
767 EasyScanner& operator>>(EasyScanner& scanner, const char* matchString)
768 {
769  scanner.skipSpace();
770  while(*matchString != '\0'){
771  if(*scanner.text++ != *matchString++){
772  scanner.throwException("scan error: unmatched string");
773  }
774  }
775  return scanner;
776 }
777 
778 
779 EasyScanner& operator>>(EasyScanner& scanner, char matchChar)
780 {
781  scanner.skipSpace();
782  if(*scanner.text++ != matchChar){
783  scanner.throwException("scan error: unmatched cahracter");
784  }
785  return scanner;
786 }
787 
788 
789 EasyScanner& operator>>(EasyScanner& scanner, string& str)
790 {
791  scanner.skipSpace();
792  if(!scanner.readQuotedString(true)){
793  scanner.throwException("scan error: can't read string");
794  }
795  str = scanner.stringValue;
796  return scanner;
797 }
798 
799 
801 {
802  if(!scanner.readLF()){
803  scanner.throwException("scan error: end of line unmatched");
804  }
805  return scanner;
806 }
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:24
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 May 8 2021 02:42:37