Revert "Revert "[SRUK] (StyleManager) Create a style manager""
[platform/core/uifw/dali-toolkit.git] / base / 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(',' == lastCharacter)
726           {
727             return Error("Unexpected comma");
728           }
729
730           if( !UpToParent() )
731           {
732             return false;
733           }
734           mState = STATE_VALUE;
735         }
736         else if ( '"' == currentChar )
737         {
738           mState = STATE_KEY;
739         }
740         else
741         {
742           return Error("Unexpected character");
743         }
744
745         AdvanceSkipWhiteSpace(1);
746         break;
747       }
748       case STATE_KEY:
749       {
750         name = EncodeString();
751         if( NULL == name )
752         {
753           return false;
754         }
755         if( !ParseWhiteSpace() )
756         {
757           return false;
758         }
759         if( ':' != Char())
760         {
761           return Error("Expected ':'");
762         }
763         if( !ParseWhiteSpace() )
764         {
765           return false;
766         }
767         mState = STATE_VALUE;
768
769         AdvanceSkipWhiteSpace(1);
770         break;
771       }
772       case STATE_VALUE:
773       {
774         if( '"' == currentChar )
775         {
776           Advance(1);
777           NewNode(name, TreeNode::STRING);
778           if( char* value = EncodeString() )
779           {
780             mCurrent.SetString(value);
781           }
782           else
783           {
784             return false;
785           }
786           if( !UpToParent() )
787           {
788             return false;
789           }
790           AdvanceSkipWhiteSpace(0);
791         }
792         else if( IsNumber(currentChar) || currentChar == '-' )
793         {
794           NewNode(name, TreeNode::IS_NULL);
795           if( !ParseNumber() )
796           {
797             return false;
798           }
799           if( !UpToParent() )
800           {
801             return false;
802           }
803           AdvanceSkipWhiteSpace(0);
804         }
805         else if( '{' == currentChar )
806         {
807           if( '}' == lastCharacter )
808           {
809             return Error("Expected a comma");
810           }
811           else
812           {
813             NewNode(name, TreeNode::OBJECT);
814             mState = STATE_OBJECT;
815             AdvanceSkipWhiteSpace(1);
816           }
817         }
818         else if( '}' == currentChar )
819         {
820           if(',' == lastCharacter)
821           {
822             return Error("Expected another value");
823           }
824
825           if(mCurrent.GetType() != TreeNode::OBJECT)
826           {
827             return Error("Mismatched array definition");
828           }
829
830           if(mCurrent.GetParent() == NULL)
831           {
832             mState = STATE_END;
833           }
834           else
835           {
836             if( !UpToParent() )
837             {
838               return false;
839             }
840           }
841           AdvanceSkipWhiteSpace(1);
842         }
843         else if( '[' == currentChar )
844         {
845           NewNode(name, TreeNode::ARRAY);
846           mState = STATE_VALUE;
847           AdvanceSkipWhiteSpace(1);
848         }
849         else if( ']' == currentChar )
850         {
851           if(',' == lastCharacter)
852           {
853             return Error("Expected a value");
854           }
855
856           if(mCurrent.GetType() != TreeNode::ARRAY)
857           {
858             return Error("Mismatched braces in object definition");
859           }
860
861           if(mCurrent.GetParent() == NULL)
862           {
863             mState = STATE_END;
864           }
865           else
866           {
867             if( !UpToParent() )
868             {
869               return false;
870             }
871           }
872           AdvanceSkipWhiteSpace(1);
873         }
874         else if( 't' == currentChar )
875         {
876           NewNode(name, TreeNode::BOOLEAN);
877           if( !ParseTrue() )
878           {
879             return false;
880           }
881           if( !UpToParent() )
882           {
883             return false;
884           }
885           AdvanceSkipWhiteSpace(0);
886         }
887         else if( 'n' == currentChar )
888         {
889           NewNode(name, TreeNode::IS_NULL);
890           if( !ParseNULL() )
891           {
892             return false;
893           }
894           if( !UpToParent() )
895           {
896             return false;
897           }
898           AdvanceSkipWhiteSpace(0);
899         }
900         else if( 'f' == currentChar)
901         {
902           NewNode(name, TreeNode::BOOLEAN);
903           if( !ParseFalse() )
904           {
905             return false;
906           }
907           if( !UpToParent() )
908           {
909             return false;
910           }
911           AdvanceSkipWhiteSpace(0);
912         }
913         else if( ',' == currentChar )
914         {
915           if( 0 == mCurrent.Size() )
916           {
917             return Error("Missing Value");
918           }
919
920           if(mCurrent.GetType() == TreeNode::OBJECT)
921           {
922             mState = STATE_OBJECT; // to get '"' in '"key":val'
923           }
924           else if(mCurrent.GetType() == TreeNode::ARRAY)
925           {
926             mState = STATE_VALUE; // array so just get next value
927           }
928           else
929           {
930             return Error("Unexpected character");
931           }
932           AdvanceSkipWhiteSpace(1);
933         }
934         else
935         {
936           return Error("Unexpected character");
937         }
938
939         name = NULL;
940
941         break;
942       } // case STATE_VALUE
943       case STATE_END:
944       {
945         return Error("Unexpected character. Json must have one object or array at its root");
946         break;
947       }
948     } // switch(mState)
949
950   } // while(1)
951
952   //
953   if( mState != STATE_END )
954   {
955     return Error("Unexpected termination character");
956   }
957
958   mIter = source.end();
959
960   return true;
961
962 } // ParseJson
963
964
965 void JsonParserState::Reset()
966 {
967   mCurrent = TreeNodeManipulator(mRoot);
968
969   mErrorDescription   = NULL;
970   mErrorNewLine       = 0;
971   mErrorColumn        = 0;
972   mErrorPosition      = 0;
973 }
974
975
976 } // namespace Internal
977
978 } // namespace Toolkit
979
980 } // namespace Dali