9b6fa4fb28cba7f93a0a785b3ebfbf95ba3efb70
[platform/core/uifw/dali-toolkit.git] / optional / dali-toolkit / internal / builder / json-parser-state.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include <dali-toolkit/internal/builder/json-parser-state.h>
19
20 // EXTERNAL
21 #include <algorithm>
22
23 namespace Dali
24 {
25
26 namespace Toolkit
27 {
28
29 namespace Internal
30 {
31
32 namespace
33 {
34
35 // true if character represent a digit
36 inline bool IsDigit(char c)
37 {
38   return (c >= '0' && c <= '9');
39 }
40
41 // convert string to integer
42 bool StringToInteger(const char *first, const char *last, int& out)
43 {
44   int sign = 1;
45   if (first != last)
46   {
47     if (*first == '-')
48     {
49       sign = -1;
50       ++first;
51     }
52     else if (*first == '+')
53     {
54       ++first;
55     }
56   }
57
58   // json error for int starting with zero
59   if( 0 == (*first - '0') && (first+1 != last))
60   {
61     return false;
62   }
63
64   int result = 0;
65   for (; first != last && IsDigit(*first); ++first)
66   {
67     result = 10 * result + (*first - '0');
68   }
69   out = result * sign;
70
71   if(first != last)
72   {
73     return false;
74   }
75   else
76   {
77     return true;
78   }
79 }
80
81 // convert hexadecimal string to unsigned integer
82 bool HexStringToUnsignedInteger(const char *first, const char *last, unsigned int& out)
83 {
84   unsigned int result = 0;
85   for (; first != last; ++first)
86   {
87     int digit;
88     if (IsDigit(*first))
89     {
90       digit = *first - '0';
91     }
92     else if (*first >= 'a' && *first <= 'f')
93     {
94       digit = *first - 'a' + 10;
95     }
96     else if (*first >= 'A' && *first <= 'F')
97     {
98       digit = *first - 'A' + 10;
99     }
100     else
101     {
102       break;
103     }
104     result = 16 * result + digit;
105   }
106   out = result;
107
108   if(first != last)
109   {
110     return false;
111   }
112   else
113   {
114     return true;
115   }
116 }
117
118 // convert string to floating point
119 bool StringToFloat(const char* first, const char* last, float& out)
120 {
121   // sign
122   float sign = 1;
123   if (first != last)
124   {
125     if (*first == '-')
126     {
127       sign = -1;
128       ++first;
129     }
130     else if (*first == '+')
131     {
132       ++first;
133     }
134   }
135
136   // integer part
137   float result = 0;
138   for (; first != last && IsDigit(*first); ++first)
139   {
140     result = 10 * result + (*first - '0');
141   }
142
143   // fraction part
144   if (first != last && *first == '.')
145   {
146     ++first;
147
148     float inv_base = 0.1f;
149     for (; first != last && IsDigit(*first); ++first)
150     {
151       result += (*first - '0') * inv_base;
152       inv_base *= 0.1f;
153     }
154   }
155
156   // result w\o exponent
157   result *= sign;
158
159   // exponent
160   bool exponent_negative = false;
161   int exponent = 0;
162   if (first != last && (*first == 'e' || *first == 'E'))
163   {
164     ++first;
165
166     if (*first == '-')
167     {
168       exponent_negative = true;
169       ++first;
170     }
171     else if (*first == '+')
172     {
173       ++first;
174     }
175
176     if(first == last || !IsDigit(*first))
177     {
178       return false;
179     }
180
181     for (; first != last && IsDigit(*first); ++first)
182     {
183       exponent = 10 * exponent + (*first - '0');
184     }
185   }
186
187   if (exponent)
188   {
189     float power_of_ten = 10;
190     for (; exponent > 1; exponent--)
191     {
192       power_of_ten *= 10;
193     }
194
195     if (exponent_negative)
196     {
197       result /= power_of_ten;
198     }
199     else
200     {
201       result *= power_of_ten;
202     }
203   }
204
205   out = result;
206
207   if(first != last)
208   {
209     return false;
210   }
211   else
212   {
213     return true;
214   }
215 }
216
217
218 bool IsNumber(char c)
219 {
220   bool ret = false;
221   switch( c )
222   {
223     case '0':
224     case '1':
225     case '2':
226     case '3':
227     case '4':
228     case '5':
229     case '6':
230     case '7':
231     case '8':
232     case '9':
233     {
234       ret = true;
235       break;
236     }
237     default:
238     {
239       ret = false;
240     }
241   }
242   return ret;
243 }
244
245 } // anon namespace
246
247
248 JsonParserState::JsonParserState(TreeNode* _root)
249   : mRoot(_root), mCurrent(_root),
250     mErrorDescription(NULL), mErrorNewLine(0), mErrorColumn(0), mErrorPosition(0),
251     mNumberOfParsedChars(0), mNumberOfCreatedNodes(0), mFirstParse(false),
252     mState(STATE_START)
253 {
254   if(_root == NULL)
255   {
256     mFirstParse = true;
257   }
258 }
259
260 TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType type)
261 {
262   TreeNode* node = NULL;
263
264   node = TreeNodeManipulator::NewTreeNode();
265   TreeNodeManipulator modifyNew(node);
266   modifyNew.SetType(type);
267   modifyNew.SetName(name);
268   if(mRoot == NULL)
269   {
270     mRoot    = node;
271     mCurrent = TreeNodeManipulator(mRoot);
272   }
273   else
274   {
275     mCurrent.AddChild(node);
276     mCurrent = modifyNew;
277   }
278
279   ++mNumberOfCreatedNodes;
280
281   return node;
282
283 }
284
285 TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
286 {
287   TreeNode* node = NULL;
288
289   if(mFirstParse)
290   {
291     node = CreateNewNode(name, type);
292   }
293   else
294   {
295     // a merging parse
296
297     if(name)
298     {
299       const TreeNode* found = mCurrent.GetChild(name);
300       if( NULL != found )
301       {
302         node = const_cast<TreeNode*>(found);
303       }
304     }
305     else
306     {
307       // if root node
308       if( mCurrent.GetParent() == NULL )
309       {
310         node = mRoot;
311       }
312     }
313
314     if(node)
315     {
316       // walk tree and deallocate children as were replacing this node
317       TreeNodeManipulator modify(node);
318
319       modify.SetName(name);
320       // Set the type of the existing node, this may remove children where necessary
321       // (changing from container type to value type)
322       modify.SetType(type);
323
324       mCurrent = modify;
325     }
326     else
327     {
328       // if not found then create new
329       node = CreateNewNode(name, type);
330     }
331   }
332
333   return node;
334 }
335
336 TreeNode* JsonParserState::GetRoot()
337 {
338   return mRoot;
339 }
340
341 bool JsonParserState::Error(const char* description)
342 {
343   mErrorDescription = description;
344   return false;
345 }
346
347 bool JsonParserState::ParseWhiteSpace()
348 {
349   bool c_comment   = false;
350   bool cpp_comment = false;
351
352   // skip white space
353   char nextChar = 0;
354   while(1)
355   {
356     char c = Char();
357
358     if(c == '\xA')
359     {
360       NewLine();
361     }
362
363     if( AtLeast(2) )
364     {
365       nextChar = mIter[1];
366     }
367     else
368     {
369       nextChar = 0;
370     }
371
372     if( cpp_comment )
373     {
374       if( '\n' == c )
375       {
376         cpp_comment = false;
377         Advance(1);
378         continue; // rather than carry on as comments may be back to back
379       }
380     }
381     else if( !c_comment && (c == '/' && nextChar == '/') )
382     {
383       cpp_comment = true;
384     }
385
386     if( c_comment )
387     {
388       if( c == '*' && nextChar == '/' )
389       {
390         c_comment = false;
391         Advance(2);
392         continue;
393       }
394     }
395     else if( !cpp_comment && (c == '/' && nextChar == '*') )
396     {
397       c_comment = true;
398     }
399
400     if( ! (c_comment || cpp_comment) )
401     {
402       if( ! (c == '\x20' || c == '\x9' || c == '\xD' || c == '\xA' ) )
403       {
404         break;
405       }
406     }
407
408     if( AdvanceEnded(1) )
409     {
410       break;
411     }
412
413   } // while(1)
414
415   return true;
416 } // ParseWhiteSpace
417
418 bool JsonParserState::ParseSymbol(const std::string& symbol)
419 {
420   if( AtLeast( symbol.size() ) )
421   {
422     for(int i = 0; i < static_cast<int>( symbol.size() ); ++i)
423     {
424       if(*mIter != symbol[i])
425       {
426         return false;
427       }
428       Advance(1);
429     }
430     return true;
431   }
432   else
433   {
434     return false;
435   }
436 }
437
438 bool JsonParserState::ParseTrue()
439 {
440   if( ParseSymbol("true") )
441   {
442     mCurrent.SetInteger(1);
443     mCurrent.SetType(TreeNode::BOOLEAN);
444     return true;
445   }
446   else
447   {
448     return Error("Unexpected character; expected symbol ie 'true'");
449   }
450 }
451
452 bool JsonParserState::ParseFalse()
453 {
454   if( ParseSymbol("false") )
455   {
456     mCurrent.SetInteger(0);
457     mCurrent.SetType(TreeNode::BOOLEAN);
458     return true;
459   }
460   else
461   {
462     return Error("Unexpected character; expected symbol ie 'false'");
463   }
464 }
465
466 bool JsonParserState::ParseNULL()
467 {
468   if( ParseSymbol("null") )
469   {
470     mCurrent.SetType(TreeNode::IS_NULL);
471     return true;
472   }
473   else
474   {
475     return Error("Unexpected character; expected symbol ie 'null'");
476   }
477 }
478
479 bool JsonParserState::ParseNumber()
480 {
481   mCurrent.SetType( TreeNode::INTEGER );
482
483   VectorCharIter first = mIter;
484   char c = Char();
485
486   if( !(c == '-' || IsNumber(c) ) )
487   {
488     return Error("Number must start with '-' or 0-9");
489   }
490
491   while ( IsNumber(c) || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-' )
492   {
493     if (c == '.' || c == 'e' || c == 'E')
494     {
495       mCurrent.SetType( TreeNode::FLOAT );
496     }
497     Advance(1);
498     c = Char();
499   }
500
501   if( mCurrent.GetType() == TreeNode::INTEGER )
502   {
503     int i = 0;
504     if( StringToInteger(&(*first), &(*mIter), i ) )
505     {
506       mCurrent.SetInteger(i);
507     }
508     else
509     {
510       return Error("Bad integer number");
511     }
512   }
513
514   if(mCurrent.GetType() == TreeNode::FLOAT)
515   {
516     float f = 0.f;
517     if( StringToFloat(&(*first), &(*mIter), f) )
518     {
519       mCurrent.SetFloat(f);
520     }
521     else
522     {
523       return Error("Bad float number");
524     }
525   }
526
527   return (mCurrent.GetType() == TreeNode::INTEGER)  || (mCurrent.GetType() == TreeNode::FLOAT);
528 }
529
530 char* JsonParserState::EncodeString()
531 {
532   int substitution = 0;
533   VectorCharIter first = mIter;
534   VectorCharIter last  = mIter;
535
536   while (*mIter)
537   {
538     if (static_cast<unsigned char>(*mIter) < '\x20')
539     {
540       static_cast<void>( Error("Control characters not allowed in strings") );
541       return NULL;
542     }
543     else if (*mIter == '\\' && AtLeast(2))
544     {
545       switch (*(mIter+1))
546       {
547         case '"':
548         {
549           *last = '"';
550           break;
551         }
552         case '\\':
553         {
554           *last = '\\';
555           break;
556         }
557         case '/':
558         {
559           *last = '/';
560           break;
561         }
562         case 'b':
563         {
564           *last = '\b';
565           break;
566         }
567         case 'f':
568         {
569           *last = '\f';
570           break;
571         }
572         case 'n':
573         {
574           *last = '\n';
575           break;
576         }
577         case 'r':
578         {
579           *last = '\r';
580           break;
581         }
582         case 't':
583         {
584           *last = '\t';
585           break;
586         }
587         case 'u':
588         {
589           unsigned int codepoint;
590           if( !AtLeast(6) )
591           {
592             static_cast<void>( Error("Bad unicode codepoint; not enough characters") );
593             return NULL;
594           }
595           if ( !HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint) )
596           {
597             static_cast<void>( Error("Bad unicode codepoint") );
598             return NULL;
599           }
600
601           if (codepoint <= 0x7F)
602           {
603             *last = (char)codepoint;
604           }
605           else if (codepoint <= 0x7FF)
606           {
607             *last++ = (char)(0xC0 | (codepoint >> 6));
608             *last = (char)(0x80 | (codepoint & 0x3F));
609           }
610           else if (codepoint <= 0xFFFF)
611           {
612             *last++ = (char)(0xE0 | (codepoint >> 12));
613             *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
614             *last = (char)(0x80 | (codepoint & 0x3F));
615           }
616
617           Advance(4);
618           break;
619         } // case 'u' unicode
620
621         default:
622         {
623           static_cast<void>( Error("Unrecognized escape sequence") );
624           return NULL;
625         }
626       }
627
628       ++last;
629       Advance(2);
630     }
631     else if (*mIter == '{')
632     {
633       if((0 == substitution) && (*last != '\\'))
634       {
635         substitution = 1;
636       }
637       *last++ = *mIter;
638       Advance(1);
639     }
640     else if (*mIter == '}')
641     {
642       if(substitution)
643       {
644         substitution++;
645       }
646       *last++ = *mIter;
647       Advance(1);
648     }
649     else if (*mIter == '"')
650     {
651       *last = 0;
652       Advance(1);
653       break;
654     }
655     else
656     {
657       *last++ = *mIter;
658       Advance(1);
659     }
660
661   } // while(*mIter)
662
663   mNumberOfParsedChars += last - first;
664   mNumberOfParsedChars += 1 ; // null terminator
665
666   mCurrent.SetSubstitution( substitution > 1 );
667
668   // return true;
669   return &(*first);
670
671 } // ParseString()
672
673 bool JsonParserState::ParseJson(VectorChar& source)
674 {
675   Reset();
676
677   if( 0 == source.size() )
678   {
679     return Error("Empty source buffer to parse");
680   }
681
682   mIter = source.begin();
683   mEnd  = source.end();
684
685   char* name = NULL;
686   char currentChar   = 0;
687   char lastCharacter = 0;
688
689   if( !ParseWhiteSpace() )
690   {
691     return false;
692   }
693
694   while(mIter != mEnd)
695   {
696     lastCharacter = currentChar;
697     currentChar = Char();
698
699     switch( mState )
700     {
701       case STATE_START:
702       {
703         if( '{' == currentChar )
704         {
705           NewNode(name, TreeNode::OBJECT);
706           mState = STATE_OBJECT;
707         }
708         else if( '[' == currentChar )
709         {
710           NewNode(name, TreeNode::ARRAY);
711           mState = STATE_VALUE;
712         }
713         else
714         {
715           return Error("Json must start with object {} or array []");
716         }
717
718         AdvanceSkipWhiteSpace(1);
719         break;
720       }
721       case STATE_OBJECT:
722       {
723         if( '}' == currentChar )
724         {
725           if( !UpToParent() )
726           {
727             return false;
728           }
729           mState = STATE_VALUE;
730         }
731         else if ( '"' == currentChar )
732         {
733           mState = STATE_KEY;
734         }
735         else
736         {
737           return Error("Unexpected character");
738         }
739
740         AdvanceSkipWhiteSpace(1);
741         break;
742       }
743       case STATE_KEY:
744       {
745         name = EncodeString();
746         if( NULL == name )
747         {
748           return false;
749         }
750         if( !ParseWhiteSpace() )
751         {
752           return false;
753         }
754         if( ':' != Char())
755         {
756           return Error("Expected ':'");
757         }
758         if( !ParseWhiteSpace() )
759         {
760           return false;
761         }
762         mState = STATE_VALUE;
763
764         AdvanceSkipWhiteSpace(1);
765         break;
766       }
767       case STATE_VALUE:
768       {
769         if( '"' == currentChar )
770         {
771           Advance(1);
772           NewNode(name, TreeNode::STRING);
773           if( char* value = EncodeString() )
774           {
775             mCurrent.SetString(value);
776           }
777           else
778           {
779             return false;
780           }
781           if( !UpToParent() )
782           {
783             return false;
784           }
785           AdvanceSkipWhiteSpace(0);
786         }
787         else if( IsNumber(currentChar) || currentChar == '-' )
788         {
789           NewNode(name, TreeNode::IS_NULL);
790           if( !ParseNumber() )
791           {
792             return false;
793           }
794           if( !UpToParent() )
795           {
796             return false;
797           }
798           AdvanceSkipWhiteSpace(0);
799         }
800         else if( '{' == currentChar )
801         {
802           NewNode(name, TreeNode::OBJECT);
803           mState = STATE_OBJECT;
804           AdvanceSkipWhiteSpace(1);
805         }
806         else if( '}' == currentChar )
807         {
808           if(',' == lastCharacter)
809           {
810             return Error("Expected a value");
811           }
812
813           if(mCurrent.GetType() != TreeNode::OBJECT)
814           {
815             return Error("Mismatched array definition");
816           }
817
818           if(mCurrent.GetParent() == NULL)
819           {
820             mState = STATE_END;
821           }
822           else
823           {
824             if( !UpToParent() )
825             {
826               return false;
827             }
828           }
829           AdvanceSkipWhiteSpace(1);
830         }
831         else if( '[' == currentChar )
832         {
833           NewNode(name, TreeNode::ARRAY);
834           mState = STATE_VALUE;
835           AdvanceSkipWhiteSpace(1);
836         }
837         else if( ']' == currentChar )
838         {
839           if(',' == lastCharacter)
840           {
841             return Error("Expected a value");
842           }
843
844           if(mCurrent.GetType() != TreeNode::ARRAY)
845           {
846             return Error("Mismatched braces in object definition");
847           }
848
849           if(mCurrent.GetParent() == NULL)
850           {
851             mState = STATE_END;
852           }
853           else
854           {
855             if( !UpToParent() )
856             {
857               return false;
858             }
859           }
860           AdvanceSkipWhiteSpace(1);
861         }
862         else if( 't' == currentChar )
863         {
864           NewNode(name, TreeNode::BOOLEAN);
865           if( !ParseTrue() )
866           {
867             return false;
868           }
869           if( !UpToParent() )
870           {
871             return false;
872           }
873           AdvanceSkipWhiteSpace(0);
874         }
875         else if( 'n' == currentChar )
876         {
877           NewNode(name, TreeNode::IS_NULL);
878           if( !ParseNULL() )
879           {
880             return false;
881           }
882           if( !UpToParent() )
883           {
884             return false;
885           }
886           AdvanceSkipWhiteSpace(0);
887         }
888         else if( 'f' == currentChar)
889         {
890           NewNode(name, TreeNode::BOOLEAN);
891           if( !ParseFalse() )
892           {
893             return false;
894           }
895           if( !UpToParent() )
896           {
897             return false;
898           }
899           AdvanceSkipWhiteSpace(0);
900         }
901         else if( ',' == currentChar )
902         {
903           if( 0 == mCurrent.Size() )
904           {
905             return Error("Missing Value");
906           }
907
908           if(mCurrent.GetType() == TreeNode::OBJECT)
909           {
910             mState = STATE_OBJECT; // to get '"' in '"key":val'
911           }
912           else if(mCurrent.GetType() == TreeNode::ARRAY)
913           {
914             mState = STATE_VALUE; // array so just get next value
915           }
916           else
917           {
918             return Error("Unexpected character");
919           }
920           AdvanceSkipWhiteSpace(1);
921         }
922         else
923         {
924           return Error("Unexpected character");
925         }
926
927         name = NULL;
928
929         break;
930       } // case STATE_VALUE
931       case STATE_END:
932       {
933         return Error("Unexpected character. Json must have one object or array at its root");
934         break;
935       }
936     } // switch(mState)
937
938   } // while(1)
939
940   //
941   if( mState != STATE_END )
942   {
943     return Error("Unexpected termination character");
944   }
945
946   mIter = source.end();
947
948   return true;
949
950 } // ParseJson
951
952
953 void JsonParserState::Reset()
954 {
955   mCurrent = TreeNodeManipulator(mRoot);
956
957   mErrorDescription   = NULL;
958   mErrorNewLine       = 0;
959   mErrorColumn        = 0;
960   mErrorPosition      = 0;
961 }
962
963
964 } // namespace Internal
965
966 } // namespace Toolkit
967
968 } // namespace Dali