TextInput uses style properties for PopUp and Highlight
[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 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
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       // Set the type of the existing node, this may remove children where necessary
322       // (changing from container type to value type)
323       modify.SetType(type);
324
325       mCurrent = modify;
326     }
327     else
328     {
329       // if not found then create new
330       node = CreateNewNode(name, type);
331     }
332   }
333
334   return node;
335 }
336
337 TreeNode* JsonParserState::GetRoot()
338 {
339   return mRoot;
340 }
341
342 bool JsonParserState::Error(const char* description)
343 {
344   mErrorDescription = description;
345   return false;
346 }
347
348 bool JsonParserState::ParseWhiteSpace()
349 {
350   bool c_comment   = false;
351   bool cpp_comment = false;
352
353   // skip white space
354   char nextChar = 0;
355   while(1)
356   {
357     char c = Char();
358
359     if(c == '\xA')
360     {
361       NewLine();
362     }
363
364     if( AtLeast(2) )
365     {
366       nextChar = mIter[1];
367     }
368     else
369     {
370       nextChar = 0;
371     }
372
373     if( cpp_comment )
374     {
375       if( '\n' == c )
376       {
377         cpp_comment = false;
378         Advance(1);
379         continue; // rather than carry on as comments may be back to back
380       }
381     }
382     else if( !c_comment && (c == '/' && nextChar == '/') )
383     {
384       cpp_comment = true;
385     }
386
387     if( c_comment )
388     {
389       if( c == '*' && nextChar == '/' )
390       {
391         c_comment = false;
392         Advance(2);
393         continue;
394       }
395     }
396     else if( !cpp_comment && (c == '/' && nextChar == '*') )
397     {
398       c_comment = true;
399     }
400
401     if( ! (c_comment || cpp_comment) )
402     {
403       if( ! (c == '\x20' || c == '\x9' || c == '\xD' || c == '\xA' ) )
404       {
405         break;
406       }
407     }
408
409     if( AdvanceEnded(1) )
410     {
411       break;
412     }
413
414   } // while(1)
415
416   return true;
417 } // ParseWhiteSpace
418
419 bool JsonParserState::ParseSymbol(const std::string& symbol)
420 {
421   if( AtLeast( symbol.size() ) )
422   {
423     for(int i = 0; i < static_cast<int>( symbol.size() ); ++i)
424     {
425       if(*mIter != symbol[i])
426       {
427         return false;
428       }
429       Advance(1);
430     }
431     return true;
432   }
433   else
434   {
435     return false;
436   }
437 }
438
439 bool JsonParserState::ParseTrue()
440 {
441   if( ParseSymbol("true") )
442   {
443     mCurrent.SetInteger(1);
444     mCurrent.SetType(TreeNode::BOOLEAN);
445     return true;
446   }
447   else
448   {
449     return Error("Unexpected character; expected symbol ie 'true'");
450   }
451 }
452
453 bool JsonParserState::ParseFalse()
454 {
455   if( ParseSymbol("false") )
456   {
457     mCurrent.SetInteger(0);
458     mCurrent.SetType(TreeNode::BOOLEAN);
459     return true;
460   }
461   else
462   {
463     return Error("Unexpected character; expected symbol ie 'false'");
464   }
465 }
466
467 bool JsonParserState::ParseNULL()
468 {
469   if( ParseSymbol("null") )
470   {
471     mCurrent.SetType(TreeNode::IS_NULL);
472     return true;
473   }
474   else
475   {
476     return Error("Unexpected character; expected symbol ie 'null'");
477   }
478 }
479
480 bool JsonParserState::ParseNumber()
481 {
482   mCurrent.SetType( TreeNode::INTEGER );
483
484   VectorCharIter first = mIter;
485   char c = Char();
486
487   if( !(c == '-' || IsNumber(c) ) )
488   {
489     return Error("Number must start with '-' or 0-9");
490   }
491
492   while ( IsNumber(c) || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-' )
493   {
494     if (c == '.' || c == 'e' || c == 'E')
495     {
496       mCurrent.SetType( TreeNode::FLOAT );
497     }
498     Advance(1);
499     c = Char();
500   }
501
502   if( mCurrent.GetType() == TreeNode::INTEGER )
503   {
504     int i = 0;
505     if( StringToInteger(&(*first), &(*mIter), i ) )
506     {
507       mCurrent.SetInteger(i);
508     }
509     else
510     {
511       return Error("Bad integer number");
512     }
513   }
514
515   if(mCurrent.GetType() == TreeNode::FLOAT)
516   {
517     float f = 0.f;
518     if( StringToFloat(&(*first), &(*mIter), f) )
519     {
520       mCurrent.SetFloat(f);
521     }
522     else
523     {
524       return Error("Bad float number");
525     }
526   }
527
528   return (mCurrent.GetType() == TreeNode::INTEGER)  || (mCurrent.GetType() == TreeNode::FLOAT);
529 }
530
531 char* JsonParserState::EncodeString()
532 {
533   int substitution = 0;
534   VectorCharIter first = mIter;
535   VectorCharIter last  = mIter;
536
537   while (*mIter)
538   {
539     if (static_cast<unsigned char>(*mIter) < '\x20')
540     {
541       static_cast<void>( Error("Control characters not allowed in strings") );
542       return NULL;
543     }
544     else if (*mIter == '\\' && AtLeast(2))
545     {
546       switch (*(mIter+1))
547       {
548         case '"':
549         {
550           *last = '"';
551           break;
552         }
553         case '\\':
554         {
555           *last = '\\';
556           break;
557         }
558         case '/':
559         {
560           *last = '/';
561           break;
562         }
563         case 'b':
564         {
565           *last = '\b';
566           break;
567         }
568         case 'f':
569         {
570           *last = '\f';
571           break;
572         }
573         case 'n':
574         {
575           *last = '\n';
576           break;
577         }
578         case 'r':
579         {
580           *last = '\r';
581           break;
582         }
583         case 't':
584         {
585           *last = '\t';
586           break;
587         }
588         case 'u':
589         {
590           unsigned int codepoint;
591           if( !AtLeast(6) )
592           {
593             static_cast<void>( Error("Bad unicode codepoint; not enough characters") );
594             return NULL;
595           }
596           if ( !HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint) )
597           {
598             static_cast<void>( Error("Bad unicode codepoint") );
599             return NULL;
600           }
601
602           if (codepoint <= 0x7F)
603           {
604             *last = (char)codepoint;
605           }
606           else if (codepoint <= 0x7FF)
607           {
608             *last++ = (char)(0xC0 | (codepoint >> 6));
609             *last = (char)(0x80 | (codepoint & 0x3F));
610           }
611           else if (codepoint <= 0xFFFF)
612           {
613             *last++ = (char)(0xE0 | (codepoint >> 12));
614             *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
615             *last = (char)(0x80 | (codepoint & 0x3F));
616           }
617
618           Advance(4);
619           break;
620         } // case 'u' unicode
621
622         default:
623         {
624           static_cast<void>( Error("Unrecognized escape sequence") );
625           return NULL;
626         }
627       }
628
629       ++last;
630       Advance(2);
631     }
632     else if (*mIter == '{')
633     {
634       if((0 == substitution) && (*last != '\\'))
635       {
636         substitution = 1;
637       }
638       *last++ = *mIter;
639       Advance(1);
640     }
641     else if (*mIter == '}')
642     {
643       if(substitution)
644       {
645         substitution++;
646       }
647       *last++ = *mIter;
648       Advance(1);
649     }
650     else if (*mIter == '"')
651     {
652       *last = 0;
653       Advance(1);
654       break;
655     }
656     else
657     {
658       *last++ = *mIter;
659       Advance(1);
660     }
661
662   } // while(*mIter)
663
664   mNumberOfParsedChars += last - first;
665   mNumberOfParsedChars += 1 ; // null terminator
666
667   mCurrent.SetSubstitution( substitution > 1 );
668
669   // return true;
670   return &(*first);
671
672 } // ParseString()
673
674 bool JsonParserState::ParseJson(VectorChar& source)
675 {
676   Reset();
677
678   if( 0 == source.size() )
679   {
680     return Error("Empty source buffer to parse");
681   }
682
683   mIter = source.begin();
684   mEnd  = source.end();
685
686   char* name = NULL;
687   char currentChar   = 0;
688   char lastCharacter = 0;
689
690   if( !ParseWhiteSpace() )
691   {
692     return false;
693   }
694
695   while(mIter != mEnd)
696   {
697     lastCharacter = currentChar;
698     currentChar = Char();
699
700     switch( mState )
701     {
702       case STATE_START:
703       {
704         if( '{' == currentChar )
705         {
706           NewNode(name, TreeNode::OBJECT);
707           mState = STATE_OBJECT;
708         }
709         else if( '[' == currentChar )
710         {
711           NewNode(name, TreeNode::ARRAY);
712           mState = STATE_VALUE;
713         }
714         else
715         {
716           return Error("Json must start with object {} or array []");
717         }
718
719         AdvanceSkipWhiteSpace(1);
720         break;
721       }
722       case STATE_OBJECT:
723       {
724         if( '}' == currentChar )
725         {
726           if(',' == lastCharacter)
727           {
728             return Error("Unexpected comma");
729           }
730
731           if( !UpToParent() )
732           {
733             return false;
734           }
735           mState = STATE_VALUE;
736         }
737         else if ( '"' == currentChar )
738         {
739           mState = STATE_KEY;
740         }
741         else
742         {
743           return Error("Unexpected character");
744         }
745
746         AdvanceSkipWhiteSpace(1);
747         break;
748       }
749       case STATE_KEY:
750       {
751         name = EncodeString();
752         if( NULL == name )
753         {
754           return false;
755         }
756         if( !ParseWhiteSpace() )
757         {
758           return false;
759         }
760         if( ':' != Char())
761         {
762           return Error("Expected ':'");
763         }
764         if( !ParseWhiteSpace() )
765         {
766           return false;
767         }
768         mState = STATE_VALUE;
769
770         AdvanceSkipWhiteSpace(1);
771         break;
772       }
773       case STATE_VALUE:
774       {
775         if( '"' == currentChar )
776         {
777           Advance(1);
778           NewNode(name, TreeNode::STRING);
779           if( char* value = EncodeString() )
780           {
781             mCurrent.SetString(value);
782           }
783           else
784           {
785             return false;
786           }
787           if( !UpToParent() )
788           {
789             return false;
790           }
791           AdvanceSkipWhiteSpace(0);
792         }
793         else if( IsNumber(currentChar) || currentChar == '-' )
794         {
795           NewNode(name, TreeNode::IS_NULL);
796           if( !ParseNumber() )
797           {
798             return false;
799           }
800           if( !UpToParent() )
801           {
802             return false;
803           }
804           AdvanceSkipWhiteSpace(0);
805         }
806         else if( '{' == currentChar )
807         {
808           if( '}' == lastCharacter )
809           {
810             return Error("Expected a comma");
811           }
812           else
813           {
814             NewNode(name, TreeNode::OBJECT);
815             mState = STATE_OBJECT;
816             AdvanceSkipWhiteSpace(1);
817           }
818         }
819         else if( '}' == currentChar )
820         {
821           if(',' == lastCharacter)
822           {
823             return Error("Expected another value");
824           }
825
826           if(mCurrent.GetType() != TreeNode::OBJECT)
827           {
828             return Error("Mismatched array definition");
829           }
830
831           if(mCurrent.GetParent() == NULL)
832           {
833             mState = STATE_END;
834           }
835           else
836           {
837             if( !UpToParent() )
838             {
839               return false;
840             }
841           }
842           AdvanceSkipWhiteSpace(1);
843         }
844         else if( '[' == currentChar )
845         {
846           NewNode(name, TreeNode::ARRAY);
847           mState = STATE_VALUE;
848           AdvanceSkipWhiteSpace(1);
849         }
850         else if( ']' == currentChar )
851         {
852           if(',' == lastCharacter)
853           {
854             return Error("Expected a value");
855           }
856
857           if(mCurrent.GetType() != TreeNode::ARRAY)
858           {
859             return Error("Mismatched braces in object definition");
860           }
861
862           if(mCurrent.GetParent() == NULL)
863           {
864             mState = STATE_END;
865           }
866           else
867           {
868             if( !UpToParent() )
869             {
870               return false;
871             }
872           }
873           AdvanceSkipWhiteSpace(1);
874         }
875         else if( 't' == currentChar )
876         {
877           NewNode(name, TreeNode::BOOLEAN);
878           if( !ParseTrue() )
879           {
880             return false;
881           }
882           if( !UpToParent() )
883           {
884             return false;
885           }
886           AdvanceSkipWhiteSpace(0);
887         }
888         else if( 'n' == currentChar )
889         {
890           NewNode(name, TreeNode::IS_NULL);
891           if( !ParseNULL() )
892           {
893             return false;
894           }
895           if( !UpToParent() )
896           {
897             return false;
898           }
899           AdvanceSkipWhiteSpace(0);
900         }
901         else if( 'f' == currentChar)
902         {
903           NewNode(name, TreeNode::BOOLEAN);
904           if( !ParseFalse() )
905           {
906             return false;
907           }
908           if( !UpToParent() )
909           {
910             return false;
911           }
912           AdvanceSkipWhiteSpace(0);
913         }
914         else if( ',' == currentChar )
915         {
916           if( 0 == mCurrent.Size() )
917           {
918             return Error("Missing Value");
919           }
920
921           if(mCurrent.GetType() == TreeNode::OBJECT)
922           {
923             mState = STATE_OBJECT; // to get '"' in '"key":val'
924           }
925           else if(mCurrent.GetType() == TreeNode::ARRAY)
926           {
927             mState = STATE_VALUE; // array so just get next value
928           }
929           else
930           {
931             return Error("Unexpected character");
932           }
933           AdvanceSkipWhiteSpace(1);
934         }
935         else
936         {
937           return Error("Unexpected character");
938         }
939
940         name = NULL;
941
942         break;
943       } // case STATE_VALUE
944       case STATE_END:
945       {
946         return Error("Unexpected character. Json must have one object or array at its root");
947         break;
948       }
949     } // switch(mState)
950
951   } // while(1)
952
953   //
954   if( mState != STATE_END )
955   {
956     return Error("Unexpected termination character");
957   }
958
959   mIter = source.end();
960
961   return true;
962
963 } // ParseJson
964
965
966 void JsonParserState::Reset()
967 {
968   mCurrent = TreeNodeManipulator(mRoot);
969
970   mErrorDescription   = NULL;
971   mErrorNewLine       = 0;
972   mErrorColumn        = 0;
973   mErrorPosition      = 0;
974 }
975
976
977 } // namespace Internal
978
979 } // namespace Toolkit
980
981 } // namespace Dali