Add post processor
[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 #include <string>
24
25 namespace Dali
26 {
27 namespace Toolkit
28 {
29 namespace Internal
30 {
31 namespace
32 {
33 // true if character represent a digit
34 inline bool IsDigit(char c)
35 {
36   return (c >= '0' && c <= '9');
37 }
38
39 // convert string to integer
40 bool StringToInteger(const char* first, const char* last, int& out)
41 {
42   int sign = 1;
43   if(first != last)
44   {
45     if(*first == '-')
46     {
47       sign = -1;
48       ++first;
49     }
50     else if(*first == '+')
51     {
52       ++first;
53     }
54   }
55
56   // json error for int starting with zero
57   if(0 == (*first - '0') && (first + 1 != last))
58   {
59     return false;
60   }
61
62   int result = 0;
63   for(; first != last && IsDigit(*first); ++first)
64   {
65     result = 10 * result + (*first - '0');
66   }
67   out = result * sign;
68
69   if(first != last)
70   {
71     return false;
72   }
73   else
74   {
75     return true;
76   }
77 }
78
79 // convert hexadecimal string to unsigned integer
80 bool HexStringToUnsignedInteger(const char* first, const char* last, unsigned int& out)
81 {
82   unsigned int result = 0;
83   for(; first != last; ++first)
84   {
85     int digit;
86     if(IsDigit(*first))
87     {
88       digit = *first - '0';
89     }
90     else if(*first >= 'a' && *first <= 'f')
91     {
92       digit = *first - 'a' + 10;
93     }
94     else if(*first >= 'A' && *first <= 'F')
95     {
96       digit = *first - 'A' + 10;
97     }
98     else
99     {
100       break;
101     }
102     result = 16 * result + digit;
103   }
104   out = result;
105
106   if(first != last)
107   {
108     return false;
109   }
110   else
111   {
112     return true;
113   }
114 }
115
116 // convert string to floating point
117 bool StringToFloat(const char* first, const char* last, float& out)
118 {
119   // sign
120   float sign = 1;
121   if(first != last)
122   {
123     if(*first == '-')
124     {
125       sign = -1;
126       ++first;
127     }
128     else if(*first == '+')
129     {
130       ++first;
131     }
132   }
133
134   // integer part
135   float result = 0;
136   for(; first != last && IsDigit(*first); ++first)
137   {
138     result = 10 * result + (*first - '0');
139   }
140
141   // fraction part
142   if(first != last && *first == '.')
143   {
144     ++first;
145
146     float inv_base = 0.1f;
147     for(; first != last && IsDigit(*first); ++first)
148     {
149       result += (*first - '0') * inv_base;
150       inv_base *= 0.1f;
151     }
152   }
153
154   // result w\o exponent
155   result *= sign;
156
157   // exponent
158   bool exponent_negative = false;
159   int  exponent          = 0;
160   if(first != last && (*first == 'e' || *first == 'E'))
161   {
162     ++first;
163
164     if(*first == '-')
165     {
166       exponent_negative = true;
167       ++first;
168     }
169     else if(*first == '+')
170     {
171       ++first;
172     }
173
174     if(first == last || !IsDigit(*first))
175     {
176       return false;
177     }
178
179     for(; first != last && IsDigit(*first); ++first)
180     {
181       exponent = 10 * exponent + (*first - '0');
182     }
183   }
184
185   if(exponent)
186   {
187     float power_of_ten = 10;
188     for(; exponent > 1; exponent--)
189     {
190       power_of_ten *= 10;
191     }
192
193     if(exponent_negative)
194     {
195       result /= power_of_ten;
196     }
197     else
198     {
199       result *= power_of_ten;
200     }
201   }
202
203   out = result;
204
205   if(first != last)
206   {
207     return false;
208   }
209   else
210   {
211     return true;
212   }
213 }
214
215 bool IsNumber(char c)
216 {
217   bool ret = false;
218   switch(c)
219   {
220     case '0':
221     case '1':
222     case '2':
223     case '3':
224     case '4':
225     case '5':
226     case '6':
227     case '7':
228     case '8':
229     case '9':
230     {
231       ret = true;
232       break;
233     }
234     default:
235     {
236       ret = false;
237     }
238   }
239   return ret;
240 }
241
242 } // namespace
243
244 JsonParserState::JsonParserState(TreeNode* _root)
245 : mRoot(_root),
246   mCurrent(_root),
247   mErrorDescription(nullptr),
248   mErrorNewLine(0),
249   mErrorColumn(0),
250   mErrorPosition(0),
251   mNumberOfParsedChars(0),
252   mNumberOfCreatedNodes(0),
253   mFirstParse(false),
254   mState(STATE_START)
255 {
256   if(_root == nullptr)
257   {
258     mFirstParse = true;
259   }
260 }
261
262 TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType type)
263 {
264   TreeNode* node = nullptr;
265
266   node = TreeNodeManipulator::NewTreeNode();
267   TreeNodeManipulator modifyNew(node);
268   modifyNew.SetType(type);
269   modifyNew.SetName(name);
270   if(mRoot == nullptr)
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 TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
287 {
288   TreeNode* node = nullptr;
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(nullptr != found)
302       {
303         node = const_cast<TreeNode*>(found);
304       }
305     }
306     else
307     {
308       // if root node
309       if(mCurrent.GetParent() == nullptr)
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 nullptr;
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 nullptr;
605           }
606           if(!HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint))
607           {
608             static_cast<void>(Error("Bad unicode codepoint"));
609             return nullptr;
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 nullptr;
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::HandleStartState(const char* name, const char currentChar)
685 {
686   if('{' == currentChar)
687   {
688     NewNode(name, TreeNode::OBJECT);
689     mState = STATE_OBJECT;
690   }
691   else if('[' == currentChar)
692   {
693     NewNode(name, TreeNode::ARRAY);
694     mState = STATE_VALUE;
695   }
696   else
697   {
698     return Error("Json must start with object {} or array []");
699   }
700
701   AdvanceSkipWhiteSpace(1);
702   return true;
703 }
704
705 bool JsonParserState::HandleObjectState(const char currentChar, const char lastCharacter)
706 {
707   if('}' == currentChar)
708   {
709     if(',' == lastCharacter)
710     {
711       return Error("Unexpected comma");
712     }
713
714     if(!UpToParent())
715     {
716       return false;
717     }
718     mState = STATE_VALUE;
719   }
720   else if('"' == currentChar)
721   {
722     mState = STATE_KEY;
723   }
724   else
725   {
726     return Error("Unexpected character");
727   }
728
729   AdvanceSkipWhiteSpace(1);
730   return true;
731 }
732
733 bool JsonParserState::HandleKeyState(char*& name)
734 {
735   name = EncodeString();
736   if(nullptr == name)
737   {
738     return false;
739   }
740   if(!ParseWhiteSpace())
741   {
742     return false;
743   }
744   if(':' != Char())
745   {
746     return Error("Expected ':'");
747   }
748   if(!ParseWhiteSpace())
749   {
750     return false;
751   }
752   mState = STATE_VALUE;
753
754   AdvanceSkipWhiteSpace(1);
755   return true;
756 }
757
758 bool JsonParserState::HandleCharacterQuote(char*& name)
759 {
760   Advance(1);
761   NewNode(name, TreeNode::STRING);
762   if(char* value = EncodeString())
763   {
764     mCurrent.SetString(value);
765   }
766   else
767   {
768     return false;
769   }
770   if(!UpToParent())
771   {
772     return false;
773   }
774   AdvanceSkipWhiteSpace(0);
775   return true;
776 }
777
778 bool JsonParserState::HandleCharacterNumberOrHyphen(const char* name)
779 {
780   NewNode(name, TreeNode::IS_NULL);
781   if(!ParseNumber())
782   {
783     return false;
784   }
785   if(!UpToParent())
786   {
787     return false;
788   }
789   AdvanceSkipWhiteSpace(0);
790   return true;
791 }
792
793 bool JsonParserState::HandleValueState(char*& name, const char currentChar, const char lastCharacter)
794 {
795   bool handled = true;
796
797   if('"' == currentChar)
798   {
799     handled = HandleCharacterQuote(name);
800   }
801   else if(IsNumber(currentChar) || currentChar == '-')
802   {
803     handled = HandleCharacterNumberOrHyphen(name);
804   }
805   else if('{' == currentChar)
806   {
807     handled = HandleCharacterBracesStart(name, lastCharacter);
808   }
809   else if('}' == currentChar)
810   {
811     handled = HandleCharacterBracesEnd(lastCharacter);
812   }
813   else if('[' == currentChar)
814   {
815     handled = HandleCharacterSquareBracketStart(name);
816   }
817   else if(']' == currentChar)
818   {
819     handled = HandleCharacterSquareBracketEnd(lastCharacter);
820   }
821   else if('t' == currentChar)
822   {
823     handled = HandleCharacterLowercaseT(name);
824   }
825   else if('n' == currentChar)
826   {
827     handled = HandleCharacterLowercaseN(name);
828   }
829   else if('f' == currentChar)
830   {
831     handled = HandleCharacterLowercaseF(name);
832   }
833   else if(',' == currentChar)
834   {
835     handled = HandleCharacterComma(name);
836   }
837   else
838   {
839     handled = Error("Unexpected character");
840   }
841
842   if(handled)
843   {
844     name = nullptr;
845   }
846
847   return handled;
848 }
849
850 bool JsonParserState::ParseJson(VectorChar& source)
851 {
852   Reset();
853
854   if(0 == source.size())
855   {
856     return Error("Empty source buffer to parse");
857   }
858
859   mIter = source.begin();
860   mEnd  = source.end();
861
862   char* name          = nullptr;
863   char  currentChar   = 0;
864   char  lastCharacter = 0;
865
866   if(!ParseWhiteSpace())
867   {
868     return false;
869   }
870
871   while(mIter != mEnd)
872   {
873     lastCharacter = currentChar;
874     currentChar   = Char();
875
876     switch(mState)
877     {
878       case STATE_START:
879       {
880         if(!HandleStartState(name, currentChar))
881         {
882           return false;
883         }
884         break;
885       }
886       case STATE_OBJECT:
887       {
888         if(!HandleObjectState(currentChar, lastCharacter))
889         {
890           return false;
891         }
892         break;
893       }
894       case STATE_KEY:
895       {
896         if(!HandleKeyState(name))
897         {
898           return false;
899         }
900         break;
901       }
902       case STATE_VALUE:
903       {
904         if(!HandleValueState(name, currentChar, lastCharacter))
905         {
906           return false;
907         }
908         break;
909       } // case STATE_VALUE
910       case STATE_END:
911       {
912         return Error("Unexpected character. Json must have one object or array at its root");
913         break;
914       }
915     } // switch(mState)
916
917   } // while(1)
918
919   //
920   if(mState != STATE_END)
921   {
922     return Error("Unexpected termination character");
923   }
924
925   mIter = source.end();
926
927   return true;
928
929 } // ParseJson
930
931 void JsonParserState::Reset()
932 {
933   mCurrent = TreeNodeManipulator(mRoot);
934
935   mErrorDescription = nullptr;
936   mErrorNewLine     = 0;
937   mErrorColumn      = 0;
938   mErrorPosition    = 0;
939 }
940
941 bool JsonParserState::HandleCharacterBracesStart(const char* name, const char lastCharacter)
942 {
943   if('}' == lastCharacter)
944   {
945     return Error("Expected a comma");
946   }
947   else
948   {
949     NewNode(name, TreeNode::OBJECT);
950     mState = STATE_OBJECT;
951     AdvanceSkipWhiteSpace(1);
952   }
953   return true;
954 }
955
956 bool JsonParserState::HandleCharacterBracesEnd(const char lastCharacter)
957 {
958   if(',' == lastCharacter)
959   {
960     return Error("Expected another value");
961   }
962
963   if(mCurrent.GetType() != TreeNode::OBJECT)
964   {
965     return Error("Mismatched array definition");
966   }
967
968   if(mCurrent.GetParent() == nullptr)
969   {
970     mState = STATE_END;
971   }
972   else
973   {
974     if(!UpToParent())
975     {
976       return false;
977     }
978   }
979   AdvanceSkipWhiteSpace(1);
980   return true;
981 }
982
983 bool JsonParserState::HandleCharacterSquareBracketStart(const char* name)
984 {
985   NewNode(name, TreeNode::ARRAY);
986   mState = STATE_VALUE;
987   AdvanceSkipWhiteSpace(1);
988   return true;
989 }
990
991 bool JsonParserState::HandleCharacterSquareBracketEnd(const char lastCharacter)
992 {
993   if(',' == lastCharacter)
994   {
995     return Error("Expected a value");
996   }
997
998   if(mCurrent.GetType() != TreeNode::ARRAY)
999   {
1000     return Error("Mismatched braces in object definition");
1001   }
1002
1003   if(mCurrent.GetParent() == nullptr)
1004   {
1005     mState = STATE_END;
1006   }
1007   else
1008   {
1009     if(!UpToParent())
1010     {
1011       return false;
1012     }
1013   }
1014   AdvanceSkipWhiteSpace(1);
1015   return true;
1016 }
1017
1018 bool JsonParserState::HandleCharacterLowercaseT(const char* name)
1019 {
1020   NewNode(name, TreeNode::BOOLEAN);
1021   if(!ParseTrue())
1022   {
1023     return false;
1024   }
1025   if(!UpToParent())
1026   {
1027     return false;
1028   }
1029   AdvanceSkipWhiteSpace(0);
1030   return true;
1031 }
1032
1033 bool JsonParserState::HandleCharacterLowercaseN(const char* name)
1034 {
1035   NewNode(name, TreeNode::IS_NULL);
1036   if(!ParseNULL())
1037   {
1038     return false;
1039   }
1040   if(!UpToParent())
1041   {
1042     return false;
1043   }
1044   AdvanceSkipWhiteSpace(0);
1045   return true;
1046 }
1047
1048 bool JsonParserState::HandleCharacterLowercaseF(const char* name)
1049 {
1050   NewNode(name, TreeNode::BOOLEAN);
1051   if(!ParseFalse())
1052   {
1053     return false;
1054   }
1055   if(!UpToParent())
1056   {
1057     return false;
1058   }
1059   AdvanceSkipWhiteSpace(0);
1060   return true;
1061 }
1062
1063 bool JsonParserState::HandleCharacterComma(const char* name)
1064 {
1065   if(0 == mCurrent.Size())
1066   {
1067     return Error("Missing Value");
1068   }
1069
1070   if(mCurrent.GetType() == TreeNode::OBJECT)
1071   {
1072     mState = STATE_OBJECT; // to get '"' in '"key":val'
1073   }
1074   else if(mCurrent.GetType() == TreeNode::ARRAY)
1075   {
1076     mState = STATE_VALUE; // array so just get next value
1077   }
1078   else
1079   {
1080     return Error("Unexpected character");
1081   }
1082   AdvanceSkipWhiteSpace(1);
1083   return true;
1084 }
1085
1086 } // namespace Internal
1087
1088 } // namespace Toolkit
1089
1090 } // namespace Dali