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