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