+bool JsonParserState::HandleStartState(const char* name, const char currentChar)
+{
+ if('{' == currentChar)
+ {
+ NewNode(name, TreeNode::OBJECT);
+ mState = STATE_OBJECT;
+ }
+ else if('[' == currentChar)
+ {
+ NewNode(name, TreeNode::ARRAY);
+ mState = STATE_VALUE;
+ }
+ else
+ {
+ return Error("Json must start with object {} or array []");
+ }
+
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
+
+bool JsonParserState::HandleObjectState(const char currentChar, const char lastCharacter)
+{
+ if('}' == currentChar)
+ {
+ if(',' == lastCharacter)
+ {
+ return Error("Unexpected comma");
+ }
+
+ if(!UpToParent())
+ {
+ return false;
+ }
+ mState = STATE_VALUE;
+ }
+ else if('"' == currentChar)
+ {
+ mState = STATE_KEY;
+ }
+ else
+ {
+ return Error("Unexpected character");
+ }
+
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
+
+bool JsonParserState::HandleKeyState(char*& name)
+{
+ name = EncodeString();
+ if(nullptr == name)
+ {
+ return false;
+ }
+ if(!ParseWhiteSpace())
+ {
+ return false;
+ }
+ if(':' != Char())
+ {
+ return Error("Expected ':'");
+ }
+ if(!ParseWhiteSpace())
+ {
+ return false;
+ }
+ mState = STATE_VALUE;
+
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterQuote(char*& name)
+{
+ Advance(1);
+ NewNode(name, TreeNode::STRING);
+ if(char* value = EncodeString())
+ {
+ mCurrent.SetString(value);
+ }
+ else
+ {
+ return false;
+ }
+ if(!UpToParent())
+ {
+ return false;
+ }
+ AdvanceSkipWhiteSpace(0);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterNumberOrHyphen(const char* name)
+{
+ NewNode(name, TreeNode::IS_NULL);
+ if(!ParseNumber())
+ {
+ return false;
+ }
+ if(!UpToParent())
+ {
+ return false;
+ }
+ AdvanceSkipWhiteSpace(0);
+ return true;
+}
+
+bool JsonParserState::HandleValueState(char*& name, const char currentChar, const char lastCharacter)
+{
+ bool handled = true;
+
+ if('"' == currentChar)
+ {
+ handled = HandleCharacterQuote(name);
+ }
+ else if(IsNumber(currentChar) || currentChar == '-')
+ {
+ handled = HandleCharacterNumberOrHyphen(name);
+ }
+ else if('{' == currentChar)
+ {
+ handled = HandleCharacterBracesStart(name, lastCharacter);
+ }
+ else if('}' == currentChar)
+ {
+ handled = HandleCharacterBracesEnd(lastCharacter);
+ }
+ else if('[' == currentChar)
+ {
+ handled = HandleCharacterSquareBracketStart(name);
+ }
+ else if(']' == currentChar)
+ {
+ handled = HandleCharacterSquareBracketEnd(lastCharacter);
+ }
+ else if('t' == currentChar)
+ {
+ handled = HandleCharacterLowercaseT(name);
+ }
+ else if('n' == currentChar)
+ {
+ handled = HandleCharacterLowercaseN(name);
+ }
+ else if('f' == currentChar)
+ {
+ handled = HandleCharacterLowercaseF(name);
+ }
+ else if(',' == currentChar)
+ {
+ handled = HandleCharacterComma(name);
+ }
+ else
+ {
+ handled = Error("Unexpected character");
+ }
+
+ if(handled)
+ {
+ name = nullptr;
+ }
+
+ return handled;
+}
+