#include <dali-toolkit/internal/builder/json-parser-state.h>
// EXTERNAL INCLUDES
-#include <string>
#include <algorithm>
+#include <string>
namespace Dali
{
-
namespace Toolkit
{
-
namespace Internal
{
-
namespace
{
-
// true if character represent a digit
inline bool IsDigit(char c)
{
}
// convert string to integer
-bool StringToInteger(const char *first, const char *last, int& out)
+bool StringToInteger(const char* first, const char* last, int& out)
{
int sign = 1;
- if (first != last)
+ if(first != last)
{
- if (*first == '-')
+ if(*first == '-')
{
sign = -1;
++first;
}
- else if (*first == '+')
+ else if(*first == '+')
{
++first;
}
}
// json error for int starting with zero
- if( 0 == (*first - '0') && (first+1 != last))
+ if(0 == (*first - '0') && (first + 1 != last))
{
return false;
}
int result = 0;
- for (; first != last && IsDigit(*first); ++first)
+ for(; first != last && IsDigit(*first); ++first)
{
result = 10 * result + (*first - '0');
}
}
// convert hexadecimal string to unsigned integer
-bool HexStringToUnsignedInteger(const char *first, const char *last, unsigned int& out)
+bool HexStringToUnsignedInteger(const char* first, const char* last, unsigned int& out)
{
unsigned int result = 0;
- for (; first != last; ++first)
+ for(; first != last; ++first)
{
int digit;
- if (IsDigit(*first))
+ if(IsDigit(*first))
{
digit = *first - '0';
}
- else if (*first >= 'a' && *first <= 'f')
+ else if(*first >= 'a' && *first <= 'f')
{
digit = *first - 'a' + 10;
}
- else if (*first >= 'A' && *first <= 'F')
+ else if(*first >= 'A' && *first <= 'F')
{
digit = *first - 'A' + 10;
}
{
// sign
float sign = 1;
- if (first != last)
+ if(first != last)
{
- if (*first == '-')
+ if(*first == '-')
{
sign = -1;
++first;
}
- else if (*first == '+')
+ else if(*first == '+')
{
++first;
}
// integer part
float result = 0;
- for (; first != last && IsDigit(*first); ++first)
+ for(; first != last && IsDigit(*first); ++first)
{
result = 10 * result + (*first - '0');
}
// fraction part
- if (first != last && *first == '.')
+ if(first != last && *first == '.')
{
++first;
float inv_base = 0.1f;
- for (; first != last && IsDigit(*first); ++first)
+ for(; first != last && IsDigit(*first); ++first)
{
result += (*first - '0') * inv_base;
inv_base *= 0.1f;
// exponent
bool exponent_negative = false;
- int exponent = 0;
- if (first != last && (*first == 'e' || *first == 'E'))
+ int exponent = 0;
+ if(first != last && (*first == 'e' || *first == 'E'))
{
++first;
- if (*first == '-')
+ if(*first == '-')
{
exponent_negative = true;
++first;
}
- else if (*first == '+')
+ else if(*first == '+')
{
++first;
}
return false;
}
- for (; first != last && IsDigit(*first); ++first)
+ for(; first != last && IsDigit(*first); ++first)
{
exponent = 10 * exponent + (*first - '0');
}
}
- if (exponent)
+ if(exponent)
{
float power_of_ten = 10;
- for (; exponent > 1; exponent--)
+ for(; exponent > 1; exponent--)
{
power_of_ten *= 10;
}
- if (exponent_negative)
+ if(exponent_negative)
{
result /= power_of_ten;
}
}
}
-
bool IsNumber(char c)
{
bool ret = false;
- switch( c )
+ switch(c)
{
case '0':
case '1':
return ret;
}
-} // anon namespace
-
+} // namespace
JsonParserState::JsonParserState(TreeNode* _root)
- : mRoot(_root), mCurrent(_root),
- mErrorDescription(NULL), mErrorNewLine(0), mErrorColumn(0), mErrorPosition(0),
- mNumberOfParsedChars(0), mNumberOfCreatedNodes(0), mFirstParse(false),
- mState(STATE_START)
+: mRoot(_root),
+ mCurrent(_root),
+ mErrorDescription(nullptr),
+ mErrorNewLine(0),
+ mErrorColumn(0),
+ mErrorPosition(0),
+ mNumberOfParsedChars(0),
+ mNumberOfCreatedNodes(0),
+ mFirstParse(false),
+ mState(STATE_START)
{
- if(_root == NULL)
+ if(_root == nullptr)
{
mFirstParse = true;
}
TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType type)
{
- TreeNode* node = NULL;
+ TreeNode* node = nullptr;
node = TreeNodeManipulator::NewTreeNode();
TreeNodeManipulator modifyNew(node);
modifyNew.SetType(type);
modifyNew.SetName(name);
- if(mRoot == NULL)
+ if(mRoot == nullptr)
{
mRoot = node;
mCurrent = TreeNodeManipulator(mRoot);
++mNumberOfCreatedNodes;
return node;
-
}
TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
{
- TreeNode* node = NULL;
+ TreeNode* node = nullptr;
if(mFirstParse)
{
if(name)
{
const TreeNode* found = mCurrent.GetChild(name);
- if( NULL != found )
+ if(nullptr != found)
{
node = const_cast<TreeNode*>(found);
}
else
{
// if root node
- if( mCurrent.GetParent() == NULL )
+ if(mCurrent.GetParent() == nullptr)
{
node = mRoot;
}
bool c_comment = false;
bool cpp_comment = false;
- if( mIter == mEnd )
+ if(mIter == mEnd)
{
return true;
}
NewLine();
}
- if( AtLeast(2) )
+ if(AtLeast(2))
{
nextChar = mIter[1];
}
nextChar = 0;
}
- if( cpp_comment )
+ if(cpp_comment)
{
- if( '\n' == c )
+ if('\n' == c)
{
cpp_comment = false;
Advance(1);
continue; // rather than carry on as comments may be back to back
}
}
- else if( !c_comment && (c == '/' && nextChar == '/') )
+ else if(!c_comment && (c == '/' && nextChar == '/'))
{
cpp_comment = true;
}
- if( c_comment )
+ if(c_comment)
{
- if( c == '*' && nextChar == '/' )
+ if(c == '*' && nextChar == '/')
{
c_comment = false;
Advance(2);
continue;
}
}
- else if( !cpp_comment && (c == '/' && nextChar == '*') )
+ else if(!cpp_comment && (c == '/' && nextChar == '*'))
{
c_comment = true;
}
- if( ! (c_comment || cpp_comment) )
+ if(!(c_comment || cpp_comment))
{
- if( ! (c == '\x20' || c == '\x9' || c == '\xD' || c == '\xA' ) )
+ if(!(c == '\x20' || c == '\x9' || c == '\xD' || c == '\xA'))
{
break;
}
}
- if( AdvanceEnded(1) )
+ if(AdvanceEnded(1))
{
break;
}
bool JsonParserState::ParseSymbol(const std::string& symbol)
{
- if( AtLeast( symbol.size() ) )
+ if(AtLeast(symbol.size()))
{
- for(int i = 0; i < static_cast<int>( symbol.size() ); ++i)
+ for(int i = 0; i < static_cast<int>(symbol.size()); ++i)
{
if(*mIter != symbol[i])
{
bool JsonParserState::ParseTrue()
{
- if( ParseSymbol("true") )
+ if(ParseSymbol("true"))
{
mCurrent.SetInteger(1);
mCurrent.SetType(TreeNode::BOOLEAN);
bool JsonParserState::ParseFalse()
{
- if( ParseSymbol("false") )
+ if(ParseSymbol("false"))
{
mCurrent.SetInteger(0);
mCurrent.SetType(TreeNode::BOOLEAN);
bool JsonParserState::ParseNULL()
{
- if( ParseSymbol("null") )
+ if(ParseSymbol("null"))
{
mCurrent.SetType(TreeNode::IS_NULL);
return true;
bool JsonParserState::ParseNumber()
{
- mCurrent.SetType( TreeNode::INTEGER );
+ mCurrent.SetType(TreeNode::INTEGER);
VectorCharIter first = mIter;
- char c = Char();
+ char c = Char();
- if( !(c == '-' || IsNumber(c) ) )
+ if(!(c == '-' || IsNumber(c)))
{
return Error("Number must start with '-' or 0-9");
}
- while ( IsNumber(c) || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-' )
+ while(IsNumber(c) || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-')
{
- if (c == '.' || c == 'e' || c == 'E')
+ if(c == '.' || c == 'e' || c == 'E')
{
- mCurrent.SetType( TreeNode::FLOAT );
+ mCurrent.SetType(TreeNode::FLOAT);
}
Advance(1);
c = Char();
}
- if( mCurrent.GetType() == TreeNode::INTEGER )
+ if(mCurrent.GetType() == TreeNode::INTEGER)
{
int i = 0;
- if( StringToInteger(&(*first), &(*mIter), i ) )
+ if(StringToInteger(&(*first), &(*mIter), i))
{
mCurrent.SetInteger(i);
}
if(mCurrent.GetType() == TreeNode::FLOAT)
{
float f = 0.f;
- if( StringToFloat(&(*first), &(*mIter), f) )
+ if(StringToFloat(&(*first), &(*mIter), f))
{
mCurrent.SetFloat(f);
}
}
}
- return (mCurrent.GetType() == TreeNode::INTEGER) || (mCurrent.GetType() == TreeNode::FLOAT);
+ return (mCurrent.GetType() == TreeNode::INTEGER) || (mCurrent.GetType() == TreeNode::FLOAT);
}
char* JsonParserState::EncodeString()
{
- int substitution = 0;
- VectorCharIter first = mIter;
- VectorCharIter last = mIter;
+ int substitution = 0;
+ VectorCharIter first = mIter;
+ VectorCharIter last = mIter;
- while (*mIter)
+ while(*mIter)
{
- if (static_cast<unsigned char>(*mIter) < '\x20')
+ if(static_cast<unsigned char>(*mIter) < '\x20')
{
- static_cast<void>( Error("Control characters not allowed in strings") );
- return NULL;
+ static_cast<void>(Error("Control characters not allowed in strings"));
+ return nullptr;
}
- else if (*mIter == '\\' && AtLeast(2))
+ else if(*mIter == '\\' && AtLeast(2))
{
- switch (*(mIter+1))
+ switch(*(mIter + 1))
{
case '"':
{
case 'u':
{
unsigned int codepoint;
- if( !AtLeast(6) )
+ if(!AtLeast(6))
{
- static_cast<void>( Error("Bad unicode codepoint; not enough characters") );
- return NULL;
+ static_cast<void>(Error("Bad unicode codepoint; not enough characters"));
+ return nullptr;
}
- if ( !HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint) )
+ if(!HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint))
{
- static_cast<void>( Error("Bad unicode codepoint") );
- return NULL;
+ static_cast<void>(Error("Bad unicode codepoint"));
+ return nullptr;
}
- if (codepoint <= 0x7F)
+ if(codepoint <= 0x7F)
{
*last = (char)codepoint;
}
- else if (codepoint <= 0x7FF)
+ else if(codepoint <= 0x7FF)
{
*last++ = (char)(0xC0 | (codepoint >> 6));
- *last = (char)(0x80 | (codepoint & 0x3F));
+ *last = (char)(0x80 | (codepoint & 0x3F));
}
- else if (codepoint <= 0xFFFF)
+ else if(codepoint <= 0xFFFF)
{
*last++ = (char)(0xE0 | (codepoint >> 12));
*last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
- *last = (char)(0x80 | (codepoint & 0x3F));
+ *last = (char)(0x80 | (codepoint & 0x3F));
}
Advance(4);
default:
{
- static_cast<void>( Error("Unrecognized escape sequence") );
- return NULL;
+ static_cast<void>(Error("Unrecognized escape sequence"));
+ return nullptr;
}
}
++last;
Advance(2);
}
- else if (*mIter == '{')
+ else if(*mIter == '{')
{
if((0 == substitution) && (*last != '\\'))
{
*last++ = *mIter;
Advance(1);
}
- else if (*mIter == '}')
+ else if(*mIter == '}')
{
if(substitution)
{
*last++ = *mIter;
Advance(1);
}
- else if (*mIter == '"')
+ else if(*mIter == '"')
{
*last = 0;
Advance(1);
} // while(*mIter)
mNumberOfParsedChars += last - first;
- mNumberOfParsedChars += 1 ; // null terminator
+ mNumberOfParsedChars += 1; // null terminator
- mCurrent.SetSubstitution( substitution > 1 );
+ mCurrent.SetSubstitution(substitution > 1);
// return true;
return &(*first);
} // ParseString()
+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;
+}
+
bool JsonParserState::ParseJson(VectorChar& source)
{
Reset();
- if( 0 == source.size() )
+ if(0 == source.size())
{
return Error("Empty source buffer to parse");
}
mIter = source.begin();
mEnd = source.end();
- char* name = NULL;
- char currentChar = 0;
- char lastCharacter = 0;
+ char* name = nullptr;
+ char currentChar = 0;
+ char lastCharacter = 0;
- if( !ParseWhiteSpace() )
+ if(!ParseWhiteSpace())
{
return false;
}
while(mIter != mEnd)
{
lastCharacter = currentChar;
- currentChar = Char();
+ currentChar = Char();
- switch( mState )
+ switch(mState)
{
case STATE_START:
{
- if( '{' == currentChar )
+ if(!HandleStartState(name, 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 []");
+ return false;
}
-
- AdvanceSkipWhiteSpace(1);
break;
}
case STATE_OBJECT:
{
- if( '}' == currentChar )
- {
- if(',' == lastCharacter)
- {
- return Error("Unexpected comma");
- }
-
- if( !UpToParent() )
- {
- return false;
- }
- mState = STATE_VALUE;
- }
- else if ( '"' == currentChar )
- {
- mState = STATE_KEY;
- }
- else
+ if(!HandleObjectState(currentChar, lastCharacter))
{
- return Error("Unexpected character");
+ return false;
}
-
- AdvanceSkipWhiteSpace(1);
break;
}
case STATE_KEY:
{
- name = EncodeString();
- if( NULL == name )
- {
- return false;
- }
- if( !ParseWhiteSpace() )
- {
- return false;
- }
- if( ':' != Char())
- {
- return Error("Expected ':'");
- }
- if( !ParseWhiteSpace() )
+ if(!HandleKeyState(name))
{
return false;
}
- mState = STATE_VALUE;
-
- AdvanceSkipWhiteSpace(1);
break;
}
case STATE_VALUE:
{
- if( '"' == currentChar )
- {
- Advance(1);
- NewNode(name, TreeNode::STRING);
- if( char* value = EncodeString() )
- {
- mCurrent.SetString(value);
- }
- else
- {
- return false;
- }
- if( !UpToParent() )
- {
- return false;
- }
- AdvanceSkipWhiteSpace(0);
- }
- else if( IsNumber(currentChar) || currentChar == '-' )
+ if(!HandleValueState(name, currentChar, lastCharacter))
{
- NewNode(name, TreeNode::IS_NULL);
- if( !ParseNumber() )
- {
- return false;
- }
- if( !UpToParent() )
- {
- return false;
- }
- AdvanceSkipWhiteSpace(0);
- }
- else if( '{' == currentChar )
- {
- if( '}' == lastCharacter )
- {
- return Error("Expected a comma");
- }
- else
- {
- NewNode(name, TreeNode::OBJECT);
- mState = STATE_OBJECT;
- AdvanceSkipWhiteSpace(1);
- }
- }
- else if( '}' == currentChar )
- {
- if(',' == lastCharacter)
- {
- return Error("Expected another value");
- }
-
- if(mCurrent.GetType() != TreeNode::OBJECT)
- {
- return Error("Mismatched array definition");
- }
-
- if(mCurrent.GetParent() == NULL)
- {
- mState = STATE_END;
- }
- else
- {
- if( !UpToParent() )
- {
- return false;
- }
- }
- AdvanceSkipWhiteSpace(1);
- }
- else if( '[' == currentChar )
- {
- NewNode(name, TreeNode::ARRAY);
- mState = STATE_VALUE;
- AdvanceSkipWhiteSpace(1);
- }
- else if( ']' == currentChar )
- {
- if(',' == lastCharacter)
- {
- return Error("Expected a value");
- }
-
- if(mCurrent.GetType() != TreeNode::ARRAY)
- {
- return Error("Mismatched braces in object definition");
- }
-
- if(mCurrent.GetParent() == NULL)
- {
- mState = STATE_END;
- }
- else
- {
- if( !UpToParent() )
- {
- return false;
- }
- }
- AdvanceSkipWhiteSpace(1);
- }
- else if( 't' == currentChar )
- {
- NewNode(name, TreeNode::BOOLEAN);
- if( !ParseTrue() )
- {
- return false;
- }
- if( !UpToParent() )
- {
- return false;
- }
- AdvanceSkipWhiteSpace(0);
- }
- else if( 'n' == currentChar )
- {
- NewNode(name, TreeNode::IS_NULL);
- if( !ParseNULL() )
- {
- return false;
- }
- if( !UpToParent() )
- {
- return false;
- }
- AdvanceSkipWhiteSpace(0);
- }
- else if( 'f' == currentChar)
- {
- NewNode(name, TreeNode::BOOLEAN);
- if( !ParseFalse() )
- {
- return false;
- }
- if( !UpToParent() )
- {
- return false;
- }
- AdvanceSkipWhiteSpace(0);
- }
- else if( ',' == currentChar )
- {
- if( 0 == mCurrent.Size() )
- {
- return Error("Missing Value");
- }
-
- if(mCurrent.GetType() == TreeNode::OBJECT)
- {
- mState = STATE_OBJECT; // to get '"' in '"key":val'
- }
- else if(mCurrent.GetType() == TreeNode::ARRAY)
- {
- mState = STATE_VALUE; // array so just get next value
- }
- else
- {
- return Error("Unexpected character");
- }
- AdvanceSkipWhiteSpace(1);
- }
- else
- {
- return Error("Unexpected character");
+ return false;
}
-
- name = NULL;
-
break;
} // case STATE_VALUE
case STATE_END:
} // while(1)
//
- if( mState != STATE_END )
+ if(mState != STATE_END)
{
return Error("Unexpected termination character");
}
} // ParseJson
-
void JsonParserState::Reset()
{
mCurrent = TreeNodeManipulator(mRoot);
- mErrorDescription = NULL;
- mErrorNewLine = 0;
- mErrorColumn = 0;
- mErrorPosition = 0;
+ mErrorDescription = nullptr;
+ mErrorNewLine = 0;
+ mErrorColumn = 0;
+ mErrorPosition = 0;
+}
+
+bool JsonParserState::HandleCharacterBracesStart(const char* name, const char lastCharacter)
+{
+ if('}' == lastCharacter)
+ {
+ return Error("Expected a comma");
+ }
+ else
+ {
+ NewNode(name, TreeNode::OBJECT);
+ mState = STATE_OBJECT;
+ AdvanceSkipWhiteSpace(1);
+ }
+ return true;
+}
+
+bool JsonParserState::HandleCharacterBracesEnd(const char lastCharacter)
+{
+ if(',' == lastCharacter)
+ {
+ return Error("Expected another value");
+ }
+
+ if(mCurrent.GetType() != TreeNode::OBJECT)
+ {
+ return Error("Mismatched array definition");
+ }
+
+ if(mCurrent.GetParent() == nullptr)
+ {
+ mState = STATE_END;
+ }
+ else
+ {
+ if(!UpToParent())
+ {
+ return false;
+ }
+ }
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterSquareBracketStart(const char* name)
+{
+ NewNode(name, TreeNode::ARRAY);
+ mState = STATE_VALUE;
+ AdvanceSkipWhiteSpace(1);
+ return true;
}
+bool JsonParserState::HandleCharacterSquareBracketEnd(const char lastCharacter)
+{
+ if(',' == lastCharacter)
+ {
+ return Error("Expected a value");
+ }
+
+ if(mCurrent.GetType() != TreeNode::ARRAY)
+ {
+ return Error("Mismatched braces in object definition");
+ }
+
+ if(mCurrent.GetParent() == nullptr)
+ {
+ mState = STATE_END;
+ }
+ else
+ {
+ if(!UpToParent())
+ {
+ return false;
+ }
+ }
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterLowercaseT(const char* name)
+{
+ NewNode(name, TreeNode::BOOLEAN);
+ if(!ParseTrue())
+ {
+ return false;
+ }
+ if(!UpToParent())
+ {
+ return false;
+ }
+ AdvanceSkipWhiteSpace(0);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterLowercaseN(const char* name)
+{
+ NewNode(name, TreeNode::IS_NULL);
+ if(!ParseNULL())
+ {
+ return false;
+ }
+ if(!UpToParent())
+ {
+ return false;
+ }
+ AdvanceSkipWhiteSpace(0);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterLowercaseF(const char* name)
+{
+ NewNode(name, TreeNode::BOOLEAN);
+ if(!ParseFalse())
+ {
+ return false;
+ }
+ if(!UpToParent())
+ {
+ return false;
+ }
+ AdvanceSkipWhiteSpace(0);
+ return true;
+}
+
+bool JsonParserState::HandleCharacterComma(const char* name)
+{
+ if(0 == mCurrent.Size())
+ {
+ return Error("Missing Value");
+ }
+
+ if(mCurrent.GetType() == TreeNode::OBJECT)
+ {
+ mState = STATE_OBJECT; // to get '"' in '"key":val'
+ }
+ else if(mCurrent.GetType() == TreeNode::ARRAY)
+ {
+ mState = STATE_VALUE; // array so just get next value
+ }
+ else
+ {
+ return Error("Unexpected character");
+ }
+ AdvanceSkipWhiteSpace(1);
+ return true;
+}
} // namespace Internal