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