]> SALOME platform Git repositories - modules/paravis.git/blob - src/Plugins/JSONReader/JSONParser/vtkJSONParser.cxx
Salome HOME
Small modif in the JSon reader: accept string values, but
[modules/paravis.git] / src / Plugins / JSONReader / JSONParser / vtkJSONParser.cxx
1 //  Copyright (C) 2015 CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author: Roman NIKOLAEV
20
21 #include "vtkJSONParser.h"
22
23 #include <vtkObjectFactory.h>
24 #include <vtkTable.h>
25 #include <vtkInformation.h>
26 #include <vtkDoubleArray.h>
27
28 #include <algorithm>
29 #include <sstream>
30 #include <list>
31 #include <map>
32
33 //DEBUG macro
34 //#define __DEBUG
35
36
37 // Key words
38 #define MD  "_metadata"
39 #define CMT "_comment"
40 #define TBN "table_name"
41 #define TBD "table_description"
42 #define SHT "short_names"
43 #define LNG "long_names"
44 #define UNT "units"
45 #define DT "date"
46
47 // Separators
48 #define COMMA ','
49
50 #define COLON ':'
51
52 #define OSB '['
53 #define CSB ']'
54
55 #define OCB '{'
56 #define CCB '}'
57 #define ENDL '\n'
58 #define QTS  '"'
59 #define SPS ' '
60 #define TAB  '\t'
61
62 #define NA   "n/a"
63
64
65 #define addInfo(info) \
66   Info I; \
67   I.type = info; \
68   I.ln = this->LineNumber; \
69   I.cn = this->ColumnNumber; \
70   I.pos = ftell(this->File); \
71   this->CInfoVector.push_back(I);
72
73 //---------------------------------------------------
74 bool isBlankOrEnd(const char c) {
75   return c ==  SPS || c == ENDL || c == TAB || c == EOF;
76 }
77
78 bool isDigitOrDot(const char c) {
79   return (c >= '.' && c <='9') || c == '+' || c == '-' || c == 'e';
80 }
81
82 // Exception
83 //---------------------------------------------------
84 vtkJSONException::vtkJSONException(const char *reason) : Reason(reason) {
85 }
86
87 //---------------------------------------------------
88 vtkJSONException::~vtkJSONException() throw () {
89 }
90
91 //---------------------------------------------------
92 const char* vtkJSONException::what() const throw() {
93   return Reason.c_str();
94 }
95
96 // Containers to store information about nodes:
97
98 // Base node
99 //---------------------------------------------------
100 class vtkJSONNode {
101 public:
102   vtkJSONNode() { Name = 0; }
103   virtual ~vtkJSONNode() { }
104   const char* GetName() { return this->Name ; }
105   void SetName(const char* name) { this->Name  = name; }
106 private:
107   const char* Name;
108 };
109
110 class vtkJSONMetaNode : public vtkJSONNode {
111 public:  
112   vtkJSONMetaNode() : vtkJSONNode() {
113     this->SetName(MD);
114   this->Comment  = 0;
115   this->TableName = 0;
116   this->TableDescription = 0;
117   this->Date = 0;
118   }
119
120   virtual ~vtkJSONMetaNode() {
121     delete this->Comment; this->Comment = 0;
122     delete this->TableName; this->TableName = 0;
123     delete this->Date; this->Date= 0;
124     delete this->TableDescription; this->TableDescription = 0;
125     for(int i = 0; i < this->ShortNames.size(); i++) {
126       delete this->ShortNames[i]; this->ShortNames[i] = 0;
127     }
128     for(int i = 0; i < this->LongNames.size(); i++) {
129       delete this->LongNames[i]; this->LongNames[i] = 0;
130     }
131     for(int i = 0; i < this->Units.size(); i++) {
132       delete this->Units[i]; this->Units[i] = 0;
133     }
134   }
135
136   void SetComment(const char* comment) { this->Comment = comment; }
137   const char* GetComment() { return this->Comment; }
138
139   void SetTableName(const char* name) { this->TableName = name; }
140   const char* GetTableName() { return this->TableName; }
141
142   void SetDate(const char* name) { this->Date = name; }
143   const char* GetDate() { return this->Date; }
144
145   void SetTableDescription(const char* description) { this->TableDescription = description; }
146   const char* GetDescription() { return this->TableDescription; }
147
148   void SetShortNames(std::vector<const char*> names) { this->ShortNames = names; }
149   std::vector<const char*> GetShortNames() { return this->ShortNames; }
150
151   void SetLongNames(std::vector<const char*> names) { this->LongNames = names; }
152   std::vector<const char*> GetLongNames() { return this->LongNames; }
153
154   void SetUnits(std::vector<const char*> units) { this->Units = units; }
155   std::vector<const char*> GetUnits() { return this->Units; }
156
157 private:
158   const char* Comment;
159   const char* TableName;
160   const char* TableDescription;
161   const char* Date;
162   std::vector<const char*> ShortNames;
163   std::vector<const char*> LongNames;
164   std::vector<const char*> Units;
165 };
166
167 struct char_cmp { 
168   bool operator () (const char *a, const char *b) const 
169   {
170     return strcmp(a,b)<0;
171   } 
172 };
173
174 typedef std::map<const char*, double, char_cmp> vtkJSONMap;
175
176 class vtkJSONInfoNode : public vtkJSONNode {
177 public:  
178   vtkJSONInfoNode(const char* name) : vtkJSONNode() {
179     this->SetName(name);
180   }
181   virtual ~vtkJSONInfoNode() {
182     vtkJSONMap::iterator it = this->Values.begin();
183     for( ;it != this->Values.end(); it++) {
184       delete it->first;
185       const char* c = it->first;
186       c = 0;
187     }
188   }
189   void AddValue(const char* key, const double value) {
190     this->Values.insert(std::pair<const char*,double>(key,value)); 
191   }
192   vtkJSONMap& GetValues() { return this->Values; }
193 private:  
194   vtkJSONMap Values;
195 };
196
197
198 //---------------------------------------------------
199 vtkStandardNewMacro(vtkJSONParser);
200
201 //---------------------------------------------------
202 vtkJSONParser::vtkJSONParser()
203 {
204   this->FileName = NULL;
205   this->LineNumber = 1;
206   this->ColumnNumber = 0;
207   this->File = 0;
208   this->InsideQuotes = false;
209   this->LastString = 0;
210   this->CurrentNode = 0;
211   this->ParseList = false;
212   this->ParseObjectList = false;
213   this->LastValue = NAN;
214   this->ShortNamesFilled = false;
215 }
216
217 //---------------------------------------------------
218 vtkJSONParser::~vtkJSONParser()
219 {
220   delete this->FileName;
221   this->FileName = 0;
222 }
223
224
225 //---------------------------------------------------
226 int vtkJSONParser::Parse(vtkTable* theTable) 
227 {
228   if(!this->FileName) {
229     vtkErrorMacro("The name of the file is not defined");
230     return 1;
231   }
232   this->File = fopen( this->FileName, "r" );
233   
234   if( !this->File ) {
235     std::string message  = std::string("Can't open file: ") + std::string(this->FileName);
236     throwSimpleException(message.c_str());
237     return 1;
238   }
239   char ch = 0;
240
241   this->ExpectedCharacters.push_back(OCB);
242   
243   while( ch != EOF ) {
244     ch = fgetc(this->File);
245     processCharacter(ch);
246     if(isDigitsAllowed() && isDigitOrDot(ch)) {
247       readDoubleValue();
248     }
249     int nb = 1;
250     switch(ch) {
251     case OCB: processOCB(); break;
252     case CCB: processCCB(); break;
253
254     case OSB: processOSB(); break;
255     case CSB: processCSB(); break;
256
257     case ENDL: processENDL(); nb = 0; break;
258
259     case QTS: processQTS(); break;
260
261     case COLON: processCOLON(); break;
262
263     case COMMA: processCOMMA(); break;
264     }
265     this->ColumnNumber+=nb;
266   }  
267   fclose(this->File);
268
269   if(this->CInfoVector.size() > 0 ) {
270     throwException("braket is not closed ", 
271            this->CInfoVector.back().ln,
272            this->CInfoVector.back().cn);
273   }
274
275   finalize(theTable);
276   clean();
277   return 1;
278 }
279
280 //---------------------------------------------------
281 void vtkJSONParser::finalize( vtkTable *t ) {
282   std::vector<vtkJSONNode*>::iterator it = this->Nodes.begin();
283   vtkJSONMetaNode* mn = 0;
284   for( ; it != this->Nodes.end(); it++ ) {
285     mn = dynamic_cast<vtkJSONMetaNode*>(*it);
286     if (mn)
287       break;
288   }
289   std::vector<const char*> units;
290   if(mn) {
291     if(!mn->GetShortNames().empty()) {
292       this->ShortNames.clear();
293       this->ShortNames = mn->GetShortNames();
294     }
295     t->GetInformation()->Set(vtkDataObject::FIELD_NAME(), mn->GetTableName() ? mn->GetTableName() : "");
296     units = mn->GetUnits();
297   }
298   
299   long nbRow = mn ? (this->Nodes.size() - 1 ) : this->Nodes.size();
300   for (long col=0; col < this->ShortNames.size(); col++) {
301     vtkDoubleArray* newCol = vtkDoubleArray::New();
302     newCol->SetNumberOfValues(nbRow);
303     vtkJSONInfoNode* in = 0;
304     std::string name = this->ShortNames[col];
305     name += "[";
306     if(col < units.size()){
307       name += units[col];
308     } else {
309       name += NA;
310     }
311     name += "]";
312     newCol->SetName(name.c_str());
313     it = this->Nodes.begin();
314     long row = 0;
315     for( ; it != this->Nodes.end(); it++ ) {
316       in = dynamic_cast<vtkJSONInfoNode*>(*it);
317       if (in) {
318           vtkJSONMap& vl = in->GetValues();
319           vtkJSONMap::iterator mit = vl.find(this->ShortNames[col]);
320           if(mit != vl.end()) {
321               newCol->SetValue(row, mit->second);
322               vl.erase(mit);
323               delete mit->first;
324               const char* c = mit->first;
325               c = 0;
326               row++;
327           } else {
328               std::string s("Item with name '");
329               s+=in->GetName();
330               s+="' has no key (or not a numerical value for key) '";
331               s+=this->ShortNames[col];
332               s+="'! Value set to 0.0.";
333               //throwSimpleException(s.c_str());
334               std::ostringstream oss;
335               oss << "vtkJSONParser::finalize(): " << s << std::endl;
336               if(this->HasObserver("ErrorEvent") )
337                 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
338               else
339                 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
340               vtkObject::BreakOnError();
341
342               newCol->SetValue(row, 0.0);
343           }
344       }
345     }
346     t->AddColumn(newCol);
347   } 
348   it = this->Nodes.begin();
349   vtkJSONInfoNode* in = 0;
350   for( ; it != this->Nodes.end(); it++ ) {
351     in = dynamic_cast<vtkJSONInfoNode*>(*it);
352     if (in) {     
353       vtkJSONMap& vl = in->GetValues();
354       if(vl.size() > 0 ) {
355           std::string s("Item with name '");
356           s+=in->GetName();
357           s+="' has unexpected key '";
358           s+=vl.begin()->first;
359           s+="' !";
360           throwSimpleException(s.c_str());
361       }
362     }
363   }
364 }
365
366 //---------------------------------------------------
367 void vtkJSONParser::processQTS() {
368   this->InsideQuotes = !this->InsideQuotes;
369   if(this->InsideQuotes) {
370     addInfo(QTS);
371   } else {
372     // Quotes is closed, get content
373     Info i =  this->CInfoVector.back();
374     this->CInfoVector.pop_back();
375     if(i.type == QTS) {
376       long begin = i.pos;
377       long end = ftell(this->File) - 1;
378       this->LastString = getString(begin, end);
379       bool parse_list = (this->CInfoVector.size() >= 1 && this->CInfoVector.back().type == OSB);
380       if(parse_list) {
381     this->CurrentList.push_back(this->LastString);
382       } else {
383     this->Strings.push_back(this->LastString);
384     processMetaNode();
385       }
386 #ifdef __DEBUG
387       std::cout<<"String  : "<<this->LastString<<std::endl;
388 #endif
389       
390       this->ExpectedCharacters.clear();
391       this->ExpectedCharacters.push_back(COLON);
392       this->ExpectedCharacters.push_back(COMMA);
393       this->ExpectedCharacters.push_back(CCB);
394       this->ExpectedCharacters.push_back(CSB); 
395     }
396   }
397 }
398
399 //---------------------------------------------------
400 void vtkJSONParser::processCOLON() {
401   if (this->InsideQuotes)
402     return;
403   this->ExpectedCharacters.clear();
404   this->ExpectedCharacters.push_back(OCB);
405   this->ExpectedCharacters.push_back(QTS);
406   this->ExpectedCharacters.push_back(OSB);
407   if(GetInfoNode() && Strings.size() ==  1 ) {
408     allowsDigits();
409   }
410 }
411
412 //---------------------------------------------------
413 void vtkJSONParser::processOCB() { 
414   if (this->InsideQuotes)
415     return;
416   this->ExpectedCharacters.clear();
417   this->ExpectedCharacters.push_back(QTS);
418   this->ExpectedCharacters.push_back(CCB);
419   
420   // Create node
421   if(this->CInfoVector.size() >= 1) {    
422     if ( !GetMetaNode() && this->Strings.size() > 0 && 
423      this->Strings.back() &&
424      strcmp(this->Strings.back(), MD) == 0 ) {
425 #ifdef __DEBUG
426       std::cout<<"Create new Meta Node !!!"<<std::endl;
427 #endif      
428       this->CurrentNode = new vtkJSONMetaNode();
429       delete this->Strings.back();
430       this->Strings.back() = 0;
431       this->Strings.pop_back();
432     } else {
433       if(this->CInfoVector.back().type == OSB ) {
434     this->ParseObjectList = true;
435       }
436 #ifdef __DEBUG
437       std::cout<<"Create new Node with name '"<<(this->Strings.size() == 0 ? "" : this->Strings.back())<<"' !!!"<<std::endl;
438 #endif          
439       this->CurrentNode = new vtkJSONInfoNode(this->Strings.size() == 0 ? "" : this->Strings.back());
440       if(!this->ParseObjectList && this->Strings.size() == 1) {
441     this->Strings.pop_back();
442       }
443     }
444   }
445   addInfo(OCB);
446 }
447
448 //---------------------------------------------------
449 vtkJSONMetaNode* vtkJSONParser::GetMetaNode() {
450   vtkJSONMetaNode *mnode = 0;
451   if( this->CurrentNode ) {
452     mnode = dynamic_cast<vtkJSONMetaNode*>(this->CurrentNode);
453   }
454   return mnode;
455 }
456
457 //---------------------------------------------------
458 vtkJSONInfoNode* vtkJSONParser::GetInfoNode() {
459   vtkJSONInfoNode *mnode = 0;
460   if( this->CurrentNode ) {
461     mnode = dynamic_cast<vtkJSONInfoNode*>(this->CurrentNode);
462   }
463   return mnode;
464 }
465
466 //---------------------------------------------------
467 void vtkJSONParser::processENDL() { 
468   if(this->InsideQuotes) {
469
470     throwException("quote is not closed !");
471   }
472   this->LineNumber++;
473   this->ColumnNumber=0;
474 }
475
476
477 //---------------------------------------------------
478 void vtkJSONParser::processCSB() {
479   if (this->InsideQuotes)
480     return;  
481  
482   if(this->CInfoVector.back().type == OSB) {
483     if(this->ParseList) {
484       this->ParseList = false;
485     }    
486     if(this->ParseObjectList) {
487       this->ParseObjectList = false;
488     }
489     this->CInfoVector.pop_back();
490   }
491
492   this->ExpectedCharacters.clear();
493   this->ExpectedCharacters.push_back(COMMA);
494   this->ExpectedCharacters.push_back(OCB);
495   this->ExpectedCharacters.push_back(CCB);
496 }
497
498 //---------------------------------------------------
499 void vtkJSONParser::processOSB() {
500   if (this->InsideQuotes)
501     return;
502
503   if(this->ParseList) {
504     Info i = CInfoVector.back();
505     if(i.type == OSB) {
506       throwException("list, which has been opened in this place, has not been closed !", i.ln, i.cn);
507     }
508   }  
509   if(GetMetaNode()) {
510     this->ParseList = true;
511   } else {
512     if( this->Strings.size() > 0 ) {
513       delete this->Strings[Strings.size()-1];
514       this->Strings[Strings.size()-1] = 0;
515       this->Strings.pop_back();
516     }
517   }
518   addInfo(OSB);
519   this->ExpectedCharacters.clear();
520   this->ExpectedCharacters.push_back(QTS);
521   this->ExpectedCharacters.push_back(OCB);
522 }
523
524 //---------------------------------------------------
525 void vtkJSONParser::processCCB() {
526   if (this->InsideQuotes)
527     return;
528
529   this->ExpectedCharacters.clear();
530   this->ExpectedCharacters.push_back(COMMA);
531   this->ExpectedCharacters.push_back(CCB);
532   if(this->ParseObjectList) {
533     this->ExpectedCharacters.push_back(CSB);
534   }
535
536   processMetaNode();
537   processInfoNode();
538
539   if(this->CurrentNode)
540     this->Nodes.push_back(this->CurrentNode);
541   if( !this->ShortNamesFilled ){
542     vtkJSONInfoNode* n = dynamic_cast<vtkJSONInfoNode*>(this->CurrentNode);
543     if(n){
544       this->ShortNamesFilled = true;
545     }
546   }
547
548 #ifdef __DEBUG
549   if(this->CurrentNode)
550     std::cout<<"End parsing node with name '"<<this->CurrentNode->GetName()<<"' !!!!"<<std::endl;
551 #endif
552
553   if (this->CInfoVector.size() > 0 && this->CInfoVector.back().type == OCB ) {
554     this->CInfoVector.pop_back();
555   } else{
556     throwException ("unexpected closed braket '}' !");
557   }
558
559   this->CurrentNode = 0;
560 }
561
562 //---------------------------------------------------
563 void vtkJSONParser::processCOMMA() {
564   if (this->InsideQuotes)
565     return;
566   this->ExpectedCharacters.clear();
567   this->ExpectedCharacters.push_back(QTS);
568   this->ExpectedCharacters.push_back(OCB);
569   processMetaNode();
570   processInfoNode();
571 }
572
573 void vtkJSONParser::processMetaNode() {
574  vtkJSONMetaNode* mn = GetMetaNode();
575   if(mn) {
576     bool strings  = this->Strings.size() == 2 && !this->ParseList;
577     bool str_and_list = (this->Strings.size() == 1 && this->CurrentList.size() > 0 && !this->ParseList);
578     
579     if( strings ) {
580       if ( strcmp(this->Strings[0], CMT) == 0 ) {
581     mn->SetComment(this->Strings[1]);
582 #ifdef __DEBUG
583       std::cout<<"Table Comment  : "<<this->Strings[1]<<std::endl;
584 #endif
585       } else if ( strcmp(this->Strings[0], TBN) == 0 ) { 
586     mn->SetTableName(this->Strings[1]);
587 #ifdef __DEBUG
588       std::cout<<"Table Name  : "<<this->Strings[1]<<std::endl;
589 #endif
590       } else if ( strcmp(this->Strings[0], TBD) == 0 ) {
591     mn->SetTableDescription(this->Strings[1]);
592 #ifdef __DEBUG
593     std::cout<<"Table Description  : "<<this->Strings[1]<<std::endl;
594 #endif
595       } else if ( strcmp(this->Strings[0], DT) == 0 ) {
596     mn->SetDate(this->Strings[1]);
597 #ifdef __DEBUG
598       std::cout<<"Date  : "<<this->Strings[1]<<std::endl;
599 #endif
600       } else {
601     std::stringstream s;
602     s << "File : "<< this->FileName;
603     s << ", line "<<this->LineNumber;
604     s << " unexpected key word: '"<<this->Strings[0]<<"'";
605       }
606       delete this->Strings[0];
607       this->Strings[0] = 0;
608       Strings.pop_back();
609       Strings.pop_back();
610       
611     } else if(str_and_list) {
612       if ( strcmp(this->Strings[0], SHT) == 0 ) { 
613     std::vector<const char*>::const_iterator it = this->CurrentList.begin();
614     for( ;it != this->CurrentList.end(); it++) {
615       checkShortName(*it);
616     }
617     mn->SetShortNames(this->CurrentList);
618 #ifdef __DEBUG
619     std::cout<<"Short Names : "<<std::endl;
620 #endif
621       } else if ( strcmp(this->Strings[0], LNG) == 0 ) { 
622     mn->SetLongNames(this->CurrentList);
623 #ifdef __DEBUG
624     std::cout<<"Long Names : "<<std::endl;
625 #endif
626       } else if ( strcmp(this->Strings[0], UNT) == 0 ) { 
627     mn->SetUnits(this->CurrentList);
628 #ifdef __DEBUG
629     std::cout<<"Units : ";
630 #endif
631       } else {
632     std::stringstream s;
633     s << "File : "<< this->FileName;
634     s << ", line "<<this->LineNumber;
635     s << " unexpected key word: '"<<this->Strings[0]<<"'";
636       }
637       delete this->Strings[0];
638       this->Strings[0] = 0;
639       Strings.pop_back();
640 #ifdef __DEBUG
641       std::vector<const char*>::const_iterator it = this->CurrentList.begin();
642       std::cout<<"[ ";
643       for( ;it != this->CurrentList.end(); it++) {
644         std::cout<<"'"<<*it<<"'";
645     if ( it+1 != this->CurrentList.end() )
646       std::cout<<", ";
647       }
648       std::cout<<" ]"<<std::endl;
649 #endif
650       this->CurrentList.clear();
651     }
652   }
653 }
654 //---------------------------------------------------
655 void vtkJSONParser::processInfoNode() { 
656   vtkJSONInfoNode* in = GetInfoNode();
657   if(in) {
658       if(this->Strings.size() == 1 && !isnan(this->LastValue)) {
659           in->AddValue(this->Strings[0],this->LastValue);
660           if(!ShortNamesFilled) {
661               char* name = new char[strlen(Strings[0])];
662               strcpy(name, Strings[0]);
663               this->ShortNames.push_back(name);
664           }
665           this->Strings.pop_back();
666           this->LastValue = NAN;
667       }
668       if(this->Strings.size() == 2)     {
669           std::string s("Item with name '");
670           s+=in->GetName();
671           s+="' has not a numerical value for key '";
672           s+=Strings[0];
673           s+="'! Value set to 0.0.";
674           //throwSimpleException(s.c_str());
675           std::ostringstream oss;
676           oss << "vtkJSONParser::processInfoNode(): " << s << std::endl;
677           if(this->HasObserver("ErrorEvent") )
678             this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
679           else
680             vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
681           vtkObject::BreakOnError();
682
683           in->AddValue(this->Strings[0],0.0);
684           if(!ShortNamesFilled) {
685               char* name = new char[strlen(Strings[0])];
686               strcpy(name, Strings[0]);
687               this->ShortNames.push_back(name);
688           }
689           this->Strings.clear();
690           this->LastValue = NAN;
691         }
692   }
693 }
694
695 //---------------------------------------------------
696 void vtkJSONParser::processCharacter(const char ch) {
697   if (this->InsideQuotes)
698     return;
699   if(isBlankOrEnd(ch))
700     return;
701
702   if(this->ExpectedCharacters.empty())
703     return;
704   
705   std::vector<char>::const_iterator it = std::find(this->ExpectedCharacters.begin(),
706                            this->ExpectedCharacters.end(),
707                            ch);
708   
709   // Unexpected character is found
710   if(it == this->ExpectedCharacters.end()) {
711     std::string s("unexpected character '");
712     s+=ch;
713     s+="' !";
714     throwException(s.c_str());
715
716   }
717 }
718
719 //---------------------------------------------------
720 char* vtkJSONParser::getString(long b, long e) {
721   char* result = 0;
722
723   long old_pos = ftell(this->File);
724   fseek(this->File, b, SEEK_SET);
725   long data_s = e - b;
726   result = new char[data_s];
727   result[0] = 0;
728   size_t nb_read = fread(result, sizeof(char), data_s, this->File);  
729   result[nb_read] = '\0';
730   fseek(this->File, old_pos, SEEK_SET);
731   return result;
732 }
733
734 //---------------------------------------------------
735 void vtkJSONParser::allowsDigits() {
736   for(char c = '.'; c <= '9'; c++) {
737     ExpectedCharacters.push_back(c);
738   }
739   ExpectedCharacters.push_back('-');
740   ExpectedCharacters.push_back('+');
741   ExpectedCharacters.push_back('e');
742 }
743
744 //---------------------------------------------------
745 bool vtkJSONParser::isDigitsAllowed() {
746   std::vector<char>::const_iterator it = std::find(this->ExpectedCharacters.begin(),
747                            this->ExpectedCharacters.end(),
748                            '0');
749   return (it != this->ExpectedCharacters.end());
750 }
751
752 //---------------------------------------------------
753 void vtkJSONParser::readDoubleValue() {
754   long b = ftell(this->File);
755
756   while(1) {
757     char ch = fgetc(this->File); 
758     if(!isDigitOrDot(ch)) {
759       break;
760     }
761   }
762
763   long e = ftell(this->File);
764   fseek(this->File, b-1, SEEK_SET);
765   long data_s = e - b;
766   char* result = new char[data_s];
767   result[0] = 0;
768   size_t nb_read = fread(result, sizeof(char), data_s, this->File);  
769   result[nb_read] = '\0';
770   this->ExpectedCharacters.clear();
771   this->ExpectedCharacters.push_back(COMMA);
772   this->ExpectedCharacters.push_back(CCB);
773   this->LastValue = atof(result);
774 #ifdef __DEBUG
775   std::cout<<"Read number : "<<this->LastValue<<std::endl;
776 #endif
777 }
778
779 //---------------------------------------------------
780 void vtkJSONParser::checkShortName(const char* name) {
781   size_t ln = strlen(name);
782   if( ln > 0 ){
783     for( size_t i = 0; i < ln; i++ ) { 
784       // a - z
785       if(!(name[i] >= 'a' &&  name[i] <= 'z') && 
786       // A - Z
787      !(name[i] >= 'A' &&  name[i] <= 'Z') ) {
788     std::string s("wrong short name '");
789     s += name;
790     s += "' !";
791     throwException(s.c_str(), this->LineNumber);
792       }
793     }
794   }
795 }
796
797 void vtkJSONParser::clean() {
798   std::vector<vtkJSONNode*>::iterator it = this->Nodes.begin();
799   for( ; it != this->Nodes.end(); it++ ) {
800     delete *(it);
801     *it = 0;
802   }
803 }
804
805 //---------------------------------------------------
806 void vtkJSONParser::throwException(const char* message) {
807     std::stringstream s;
808     s << "File : "<< this->FileName;
809     s << ", line "<<this->LineNumber;
810     s << ", column " << this->ColumnNumber<<" : ";
811     s << message;
812     clean();
813     throw vtkJSONException(s.str().c_str());  
814 }
815
816 //---------------------------------------------------
817 void vtkJSONParser::throwException(const char* message, int ln, int cn) {
818     std::stringstream s;
819     s << "File : "<< this->FileName;
820     s << ", line "<<ln;
821     s << ", column :" << cn << "  ";
822     s << message;
823     clean();
824     throw vtkJSONException(s.str().c_str());  
825 }
826 //---------------------------------------------------
827 void vtkJSONParser::throwException(const char* message, int ln) {
828   std::stringstream s;
829    s << "File "<< this->FileName;
830    s << ", line "<<ln <<" : ";
831    s << message;
832    clean();
833    throw vtkJSONException(s.str().c_str());  
834 }
835
836 //---------------------------------------------------
837 void vtkJSONParser::throwSimpleException(const char* message) {
838   clean();
839   throw vtkJSONException(message);
840 }