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