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