2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include <dali-toolkit/internal/builder/json-parser-state.h>
35 // true if character represent a digit
36 inline bool IsDigit(char c)
38 return (c >= '0' && c <= '9');
41 // convert string to integer
42 bool StringToInteger(const char *first, const char *last, int& out)
52 else if (*first == '+')
58 // json error for int starting with zero
59 if( 0 == (*first - '0') && (first+1 != last))
65 for (; first != last && IsDigit(*first); ++first)
67 result = 10 * result + (*first - '0');
81 // convert hexadecimal string to unsigned integer
82 bool HexStringToUnsignedInteger(const char *first, const char *last, unsigned int& out)
84 unsigned int result = 0;
85 for (; first != last; ++first)
92 else if (*first >= 'a' && *first <= 'f')
94 digit = *first - 'a' + 10;
96 else if (*first >= 'A' && *first <= 'F')
98 digit = *first - 'A' + 10;
104 result = 16 * result + digit;
118 // convert string to floating point
119 bool StringToFloat(const char* first, const char* last, float& out)
130 else if (*first == '+')
138 for (; first != last && IsDigit(*first); ++first)
140 result = 10 * result + (*first - '0');
144 if (first != last && *first == '.')
148 float inv_base = 0.1f;
149 for (; first != last && IsDigit(*first); ++first)
151 result += (*first - '0') * inv_base;
156 // result w\o exponent
160 bool exponent_negative = false;
162 if (first != last && (*first == 'e' || *first == 'E'))
168 exponent_negative = true;
171 else if (*first == '+')
176 if(first == last || !IsDigit(*first))
181 for (; first != last && IsDigit(*first); ++first)
183 exponent = 10 * exponent + (*first - '0');
189 float power_of_ten = 10;
190 for (; exponent > 1; exponent--)
195 if (exponent_negative)
197 result /= power_of_ten;
201 result *= power_of_ten;
218 bool IsNumber(char c)
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),
260 TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType type)
262 TreeNode* node = NULL;
264 node = TreeNodeManipulator::NewTreeNode();
265 TreeNodeManipulator modifyNew(node);
266 modifyNew.SetType(type);
267 modifyNew.SetName(name);
271 mCurrent = TreeNodeManipulator(mRoot);
275 mCurrent.AddChild(node);
276 mCurrent = modifyNew;
279 ++mNumberOfCreatedNodes;
285 TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
287 TreeNode* node = NULL;
291 node = CreateNewNode(name, type);
299 const TreeNode* found = mCurrent.GetChild(name);
302 node = const_cast<TreeNode*>(found);
308 if( mCurrent.GetParent() == NULL )
316 // walk tree and deallocate children as were replacing this node
317 TreeNodeManipulator modify(node);
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);
328 // if not found then create new
329 node = CreateNewNode(name, type);
336 TreeNode* JsonParserState::GetRoot()
341 bool JsonParserState::Error(const char* description)
343 mErrorDescription = description;
347 bool JsonParserState::ParseWhiteSpace()
349 bool c_comment = false;
350 bool cpp_comment = false;
378 continue; // rather than carry on as comments may be back to back
381 else if( !c_comment && (c == '/' && nextChar == '/') )
388 if( c == '*' && nextChar == '/' )
395 else if( !cpp_comment && (c == '/' && nextChar == '*') )
400 if( ! (c_comment || cpp_comment) )
402 if( ! (c == '\x20' || c == '\x9' || c == '\xD' || c == '\xA' ) )
408 if( AdvanceEnded(1) )
418 bool JsonParserState::ParseSymbol(const std::string& symbol)
420 if( AtLeast( symbol.size() ) )
422 for(int i = 0; i < static_cast<int>( symbol.size() ); ++i)
424 if(*mIter != symbol[i])
438 bool JsonParserState::ParseTrue()
440 if( ParseSymbol("true") )
442 mCurrent.SetInteger(1);
443 mCurrent.SetType(TreeNode::BOOLEAN);
448 return Error("Unexpected character; expected symbol ie 'true'");
452 bool JsonParserState::ParseFalse()
454 if( ParseSymbol("false") )
456 mCurrent.SetInteger(0);
457 mCurrent.SetType(TreeNode::BOOLEAN);
462 return Error("Unexpected character; expected symbol ie 'false'");
466 bool JsonParserState::ParseNULL()
468 if( ParseSymbol("null") )
470 mCurrent.SetType(TreeNode::IS_NULL);
475 return Error("Unexpected character; expected symbol ie 'null'");
479 bool JsonParserState::ParseNumber()
481 mCurrent.SetType( TreeNode::INTEGER );
483 VectorCharIter first = mIter;
486 if( !(c == '-' || IsNumber(c) ) )
488 return Error("Number must start with '-' or 0-9");
491 while ( IsNumber(c) || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-' )
493 if (c == '.' || c == 'e' || c == 'E')
495 mCurrent.SetType( TreeNode::FLOAT );
501 if( mCurrent.GetType() == TreeNode::INTEGER )
504 if( StringToInteger(&(*first), &(*mIter), i ) )
506 mCurrent.SetInteger(i);
510 return Error("Bad integer number");
514 if(mCurrent.GetType() == TreeNode::FLOAT)
517 if( StringToFloat(&(*first), &(*mIter), f) )
519 mCurrent.SetFloat(f);
523 return Error("Bad float number");
527 return (mCurrent.GetType() == TreeNode::INTEGER) || (mCurrent.GetType() == TreeNode::FLOAT);
530 char* JsonParserState::EncodeString()
532 int substitution = 0;
533 VectorCharIter first = mIter;
534 VectorCharIter last = mIter;
538 if (static_cast<unsigned char>(*mIter) < '\x20')
540 static_cast<void>( Error("Control characters not allowed in strings") );
543 else if (*mIter == '\\' && AtLeast(2))
589 unsigned int codepoint;
592 static_cast<void>( Error("Bad unicode codepoint; not enough characters") );
595 if ( !HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint) )
597 static_cast<void>( Error("Bad unicode codepoint") );
601 if (codepoint <= 0x7F)
603 *last = (char)codepoint;
605 else if (codepoint <= 0x7FF)
607 *last++ = (char)(0xC0 | (codepoint >> 6));
608 *last = (char)(0x80 | (codepoint & 0x3F));
610 else if (codepoint <= 0xFFFF)
612 *last++ = (char)(0xE0 | (codepoint >> 12));
613 *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
614 *last = (char)(0x80 | (codepoint & 0x3F));
619 } // case 'u' unicode
623 static_cast<void>( Error("Unrecognized escape sequence") );
631 else if (*mIter == '{')
633 if((0 == substitution) && (*last != '\\'))
640 else if (*mIter == '}')
649 else if (*mIter == '"')
663 mNumberOfParsedChars += last - first;
664 mNumberOfParsedChars += 1 ; // null terminator
666 mCurrent.SetSubstitution( substitution > 1 );
673 bool JsonParserState::ParseJson(VectorChar& source)
677 if( 0 == source.size() )
679 return Error("Empty source buffer to parse");
682 mIter = source.begin();
686 char currentChar = 0;
687 char lastCharacter = 0;
689 if( !ParseWhiteSpace() )
696 lastCharacter = currentChar;
697 currentChar = Char();
703 if( '{' == currentChar )
705 NewNode(name, TreeNode::OBJECT);
706 mState = STATE_OBJECT;
708 else if( '[' == currentChar )
710 NewNode(name, TreeNode::ARRAY);
711 mState = STATE_VALUE;
715 return Error("Json must start with object {} or array []");
718 AdvanceSkipWhiteSpace(1);
723 if( '}' == currentChar )
725 if(',' == lastCharacter)
727 return Error("Unexpected comma");
734 mState = STATE_VALUE;
736 else if ( '"' == currentChar )
742 return Error("Unexpected character");
745 AdvanceSkipWhiteSpace(1);
750 name = EncodeString();
755 if( !ParseWhiteSpace() )
761 return Error("Expected ':'");
763 if( !ParseWhiteSpace() )
767 mState = STATE_VALUE;
769 AdvanceSkipWhiteSpace(1);
774 if( '"' == currentChar )
777 NewNode(name, TreeNode::STRING);
778 if( char* value = EncodeString() )
780 mCurrent.SetString(value);
790 AdvanceSkipWhiteSpace(0);
792 else if( IsNumber(currentChar) || currentChar == '-' )
794 NewNode(name, TreeNode::IS_NULL);
803 AdvanceSkipWhiteSpace(0);
805 else if( '{' == currentChar )
807 if( '}' == lastCharacter )
809 return Error("Expected a comma");
813 NewNode(name, TreeNode::OBJECT);
814 mState = STATE_OBJECT;
815 AdvanceSkipWhiteSpace(1);
818 else if( '}' == currentChar )
820 if(',' == lastCharacter)
822 return Error("Expected another value");
825 if(mCurrent.GetType() != TreeNode::OBJECT)
827 return Error("Mismatched array definition");
830 if(mCurrent.GetParent() == NULL)
841 AdvanceSkipWhiteSpace(1);
843 else if( '[' == currentChar )
845 NewNode(name, TreeNode::ARRAY);
846 mState = STATE_VALUE;
847 AdvanceSkipWhiteSpace(1);
849 else if( ']' == currentChar )
851 if(',' == lastCharacter)
853 return Error("Expected a value");
856 if(mCurrent.GetType() != TreeNode::ARRAY)
858 return Error("Mismatched braces in object definition");
861 if(mCurrent.GetParent() == NULL)
872 AdvanceSkipWhiteSpace(1);
874 else if( 't' == currentChar )
876 NewNode(name, TreeNode::BOOLEAN);
885 AdvanceSkipWhiteSpace(0);
887 else if( 'n' == currentChar )
889 NewNode(name, TreeNode::IS_NULL);
898 AdvanceSkipWhiteSpace(0);
900 else if( 'f' == currentChar)
902 NewNode(name, TreeNode::BOOLEAN);
911 AdvanceSkipWhiteSpace(0);
913 else if( ',' == currentChar )
915 if( 0 == mCurrent.Size() )
917 return Error("Missing Value");
920 if(mCurrent.GetType() == TreeNode::OBJECT)
922 mState = STATE_OBJECT; // to get '"' in '"key":val'
924 else if(mCurrent.GetType() == TreeNode::ARRAY)
926 mState = STATE_VALUE; // array so just get next value
930 return Error("Unexpected character");
932 AdvanceSkipWhiteSpace(1);
936 return Error("Unexpected character");
942 } // case STATE_VALUE
945 return Error("Unexpected character. Json must have one object or array at its root");
953 if( mState != STATE_END )
955 return Error("Unexpected termination character");
958 mIter = source.end();
965 void JsonParserState::Reset()
967 mCurrent = TreeNodeManipulator(mRoot);
969 mErrorDescription = NULL;
976 } // namespace Internal
978 } // namespace Toolkit