[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / json-parser-state.cpp
index 1547156..3262a81 100644 (file)
 // CLASS HEADER
 #include <dali-toolkit/internal/builder/json-parser-state.h>
 
-// EXTERNAL
+// EXTERNAL INCLUDES
 #include <algorithm>
+#include <string>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-
 // true if character represent a digit
 inline bool IsDigit(char c)
 {
@@ -40,30 +37,30 @@ 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');
   }
@@ -80,21 +77,21 @@ bool StringToInteger(const char *first, const char *last, int& out)
 }
 
 // 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;
     }
@@ -121,14 +118,14 @@ bool StringToFloat(const char* first, const char* last, float& out)
 {
   // sign
   float sign = 1;
-  if (first != last)
+  if(first != last)
   {
-    if (*first == '-')
+    if(*first == '-')
     {
       sign = -1;
       ++first;
     }
-    else if (*first == '+')
+    else if(*first == '+')
     {
       ++first;
     }
@@ -136,18 +133,18 @@ bool StringToFloat(const char* first, const char* last, float& out)
 
   // 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;
@@ -159,17 +156,17 @@ bool StringToFloat(const char* first, const char* last, float& out)
 
   // 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;
     }
@@ -179,21 +176,21 @@ bool StringToFloat(const char* first, const char* last, float& out)
       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;
     }
@@ -215,11 +212,10 @@ bool StringToFloat(const char* first, const char* last, float& out)
   }
 }
 
-
 bool IsNumber(char c)
 {
   bool ret = false;
-  switch( c )
+  switch(c)
   {
     case '0':
     case '1':
@@ -243,16 +239,21 @@ bool IsNumber(char c)
   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;
   }
@@ -260,13 +261,13 @@ JsonParserState::JsonParserState(TreeNode* _root)
 
 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);
@@ -280,12 +281,11 @@ TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType ty
   ++mNumberOfCreatedNodes;
 
   return node;
-
 }
 
 TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
 {
-  TreeNode* node = NULL;
+  TreeNode* node = nullptr;
 
   if(mFirstParse)
   {
@@ -298,7 +298,7 @@ TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
     if(name)
     {
       const TreeNode* found = mCurrent.GetChild(name);
-      if( NULL != found )
+      if(nullptr != found)
       {
         node = const_cast<TreeNode*>(found);
       }
@@ -306,7 +306,7 @@ TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
     else
     {
       // if root node
-      if( mCurrent.GetParent() == NULL )
+      if(mCurrent.GetParent() == nullptr)
       {
         node = mRoot;
       }
@@ -318,8 +318,13 @@ TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
       TreeNodeManipulator modify(node);
 
       modify.SetName(name);
-      // Set the type of the existing node, this may remove children where necessary
-      // (changing from container type to value type)
+
+      // Set the type of the existing node.
+      // Where the new type is different, then any children of this node will
+      // be deleted.
+      // When the type is an array of numbers, then this will also remove any children
+      // When the type is an object or other array, then the children will not be removed,
+      // but will instead follow these replace rules.
       modify.SetType(type);
 
       mCurrent = modify;
@@ -350,7 +355,7 @@ bool JsonParserState::ParseWhiteSpace()
   bool c_comment   = false;
   bool cpp_comment = false;
 
-  if( mIter == mEnd )
+  if(mIter == mEnd)
   {
     return true;
   }
@@ -366,7 +371,7 @@ bool JsonParserState::ParseWhiteSpace()
       NewLine();
     }
 
-    if( AtLeast(2) )
+    if(AtLeast(2))
     {
       nextChar = mIter[1];
     }
@@ -375,43 +380,43 @@ bool JsonParserState::ParseWhiteSpace()
       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;
     }
@@ -423,9 +428,9 @@ bool JsonParserState::ParseWhiteSpace()
 
 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])
       {
@@ -443,7 +448,7 @@ bool JsonParserState::ParseSymbol(const std::string& symbol)
 
 bool JsonParserState::ParseTrue()
 {
-  if( ParseSymbol("true") )
+  if(ParseSymbol("true"))
   {
     mCurrent.SetInteger(1);
     mCurrent.SetType(TreeNode::BOOLEAN);
@@ -457,7 +462,7 @@ bool JsonParserState::ParseTrue()
 
 bool JsonParserState::ParseFalse()
 {
-  if( ParseSymbol("false") )
+  if(ParseSymbol("false"))
   {
     mCurrent.SetInteger(0);
     mCurrent.SetType(TreeNode::BOOLEAN);
@@ -471,7 +476,7 @@ bool JsonParserState::ParseFalse()
 
 bool JsonParserState::ParseNULL()
 {
-  if( ParseSymbol("null") )
+  if(ParseSymbol("null"))
   {
     mCurrent.SetType(TreeNode::IS_NULL);
     return true;
@@ -484,30 +489,30 @@ bool JsonParserState::ParseNULL()
 
 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);
     }
@@ -520,7 +525,7 @@ bool JsonParserState::ParseNumber()
   if(mCurrent.GetType() == TreeNode::FLOAT)
   {
     float f = 0.f;
-    if( StringToFloat(&(*first), &(*mIter), f) )
+    if(StringToFloat(&(*first), &(*mIter), f))
     {
       mCurrent.SetFloat(f);
     }
@@ -530,25 +535,25 @@ bool JsonParserState::ParseNumber()
     }
   }
 
-  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 '"':
         {
@@ -593,31 +598,31 @@ char* JsonParserState::EncodeString()
         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);
@@ -626,15 +631,15 @@ char* JsonParserState::EncodeString()
 
         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 != '\\'))
       {
@@ -643,7 +648,7 @@ char* JsonParserState::EncodeString()
       *last++ = *mIter;
       Advance(1);
     }
-    else if (*mIter == '}')
+    else if(*mIter == '}')
     {
       if(substitution)
       {
@@ -652,7 +657,7 @@ char* JsonParserState::EncodeString()
       *last++ = *mIter;
       Advance(1);
     }
-    else if (*mIter == '"')
+    else if(*mIter == '"')
     {
       *last = 0;
       Advance(1);
@@ -667,20 +672,186 @@ char* JsonParserState::EncodeString()
   } // 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");
   }
@@ -688,11 +859,11 @@ bool JsonParserState::ParseJson(VectorChar& source)
   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;
   }
@@ -700,250 +871,40 @@ bool JsonParserState::ParseJson(VectorChar& source)
   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 == '-' )
-        {
-          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 )
+        if(!HandleValueState(name, currentChar, lastCharacter))
         {
-          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:
@@ -956,7 +917,7 @@ bool JsonParserState::ParseJson(VectorChar& source)
   } // while(1)
 
   //
-  if( mState != STATE_END )
+  if(mState != STATE_END)
   {
     return Error("Unexpected termination character");
   }
@@ -967,17 +928,160 @@ bool JsonParserState::ParseJson(VectorChar& source)
 
 } // 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