(JSON Parser State) Reduce Cyclomatic Complexity of ParseJson 70/245070/4
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 30 Sep 2020 10:47:46 +0000 (11:47 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 30 Sep 2020 13:13:43 +0000 (14:13 +0100)
Change-Id: Iba20de994253d3dfaac8f92b9381c18aaeb76861

dali-toolkit/internal/builder/json-parser-state.cpp
dali-toolkit/internal/builder/json-parser-state.h

index 636bac1..40ec632 100644 (file)
@@ -249,11 +249,11 @@ bool IsNumber(char c)
 
 JsonParserState::JsonParserState(TreeNode* _root)
   : mRoot(_root), mCurrent(_root),
-    mErrorDescription(NULL), mErrorNewLine(0), mErrorColumn(0), mErrorPosition(0),
+    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;
   }
@@ -261,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);
@@ -286,7 +286,7 @@ TreeNode* JsonParserState::CreateNewNode(const char* name, TreeNode::NodeType ty
 
 TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
 {
-  TreeNode* node = NULL;
+  TreeNode* node = nullptr;
 
   if(mFirstParse)
   {
@@ -299,7 +299,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);
       }
@@ -307,7 +307,7 @@ TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type)
     else
     {
       // if root node
-      if( mCurrent.GetParent() == NULL )
+      if( mCurrent.GetParent() == nullptr )
       {
         node = mRoot;
       }
@@ -550,7 +550,7 @@ char* JsonParserState::EncodeString()
     if (static_cast<unsigned char>(*mIter) < '\x20')
     {
       static_cast<void>( Error("Control characters not allowed in strings") );
-      return NULL;
+      return nullptr;
     }
     else if (*mIter == '\\' && AtLeast(2))
     {
@@ -602,12 +602,12 @@ char* JsonParserState::EncodeString()
           if( !AtLeast(6) )
           {
             static_cast<void>( Error("Bad unicode codepoint; not enough characters") );
-            return NULL;
+            return nullptr;
           }
           if ( !HexStringToUnsignedInteger(&(*(mIter + 2)), &(*(mIter + 6)), codepoint) )
           {
             static_cast<void>( Error("Bad unicode codepoint") );
-            return NULL;
+            return nullptr;
           }
 
           if (codepoint <= 0x7F)
@@ -633,7 +633,7 @@ char* JsonParserState::EncodeString()
         default:
         {
           static_cast<void>( Error("Unrecognized escape sequence") );
-          return NULL;
+          return nullptr;
         }
       }
 
@@ -682,6 +682,172 @@ char* JsonParserState::EncodeString()
 
 } // 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();
@@ -694,7 +860,7 @@ bool JsonParserState::ParseJson(VectorChar& source)
   mIter = source.begin();
   mEnd  = source.end();
 
-  char* name = NULL;
+  char* name = nullptr;
   char currentChar   = 0;
   char lastCharacter = 0;
 
@@ -712,244 +878,34 @@ bool JsonParserState::ParseJson(VectorChar& source)
     {
       case STATE_START:
       {
-        if( '{' == currentChar )
-        {
-          NewNode(name, TreeNode::OBJECT);
-          mState = STATE_OBJECT;
-        }
-        else if( '[' == currentChar )
+        if(!HandleStartState(name, 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(!HandleObjectState(currentChar, lastCharacter))
         {
-          if(',' == lastCharacter)
-          {
-            return Error("Unexpected comma");
-          }
-
-          if( !UpToParent() )
-          {
-            return false;
-          }
-          mState = STATE_VALUE;
-        }
-        else if ( '"' == currentChar )
-        {
-          mState = STATE_KEY;
-        }
-        else
-        {
-          return Error("Unexpected character");
+          return false;
         }
-
-        AdvanceSkipWhiteSpace(1);
         break;
       }
       case STATE_KEY:
       {
-        name = EncodeString();
-        if( NULL == name )
+        if(!HandleKeyState(name))
         {
           return false;
         }
-        if( !ParseWhiteSpace() )
-        {
-          return false;
-        }
-        if( ':' != Char())
-        {
-          return Error("Expected ':'");
-        }
-        if( !ParseWhiteSpace() )
-        {
-          return false;
-        }
-        mState = STATE_VALUE;
-
-        AdvanceSkipWhiteSpace(1);
         break;
       }
       case STATE_VALUE:
       {
-        if( '"' == currentChar )
+        if(!HandleValueState(name, currentChar, lastCharacter))
         {
-          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 )
-        {
-          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:
@@ -973,17 +929,160 @@ bool JsonParserState::ParseJson(VectorChar& source)
 
 } // ParseJson
 
-
 void JsonParserState::Reset()
 {
   mCurrent = TreeNodeManipulator(mRoot);
 
-  mErrorDescription   = NULL;
+  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
 
index 210c11f..4d7e7a4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_JSON_PARSE_STATE_H
 
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ namespace Toolkit
 namespace Internal
 {
 
-/*
+/**
  * A safer std::advance()
  */
 template <typename IteratorType,typename EndIteratorType>
@@ -52,7 +52,7 @@ inline int AdvanceIter(IteratorType& iter, EndIteratorType& end, int n)
   return n;
 }
 
-/*
+/**
  * Maintains parser state machine
  *
  * If a NULL root node is passed in the constructor then a faster non merging parse is performed (the first pass).
@@ -61,13 +61,13 @@ inline int AdvanceIter(IteratorType& iter, EndIteratorType& end, int n)
 class JsonParserState
 {
 public:
-  /*
+  /**
    * Constructor
    * @param tree Tree to start with, pass NULL if no existing tree
    */
   explicit JsonParserState(TreeNode* tree);
 
-  /*
+  /**
    * Parse json source
    * The source is modified in place
    * @param source The vector buffer to parse
@@ -75,43 +75,43 @@ public:
    */
   bool ParseJson(VectorChar& source);
 
-  /*
+  /**
    * Get the root node
    * @return The root TreeNode
    */
   TreeNode* GetRoot();
 
-  /*
+  /**
    * Get the error description of the last parse
    * @return The error description or NULL if no error
    */
   const char* GetErrorDescription() { return mErrorDescription; }
 
-  /*
+  /**
    * Get the error line number
    * @return The line number of the error
    */
   int GetErrorLineNumber() { return mErrorNewLine; }
 
-  /*
+  /**
    * Get the error column
    * @return The error column
    */
   int GetErrorColumn() { return mErrorColumn; }
 
-  /*
+  /**
    * Get the error position
    * @return The error position
    */
   int GetErrorPosition() { return mErrorPosition; }
 
-  /*
+  /**
    * Get the size of the string data that has been parsed
    * @return The size of string data
    */
   int GetParsedStringSize() { return mNumberOfParsedChars; };
 
-  /*
+  /**
    * Get the number of nodes created
    * @return The number of nodes
    */
@@ -131,7 +131,7 @@ private:
   int mNumberOfCreatedNodes;           ///< The number of nodes created
   bool mFirstParse;                    ///< Flag if first parse
 
-  /*
+  /**
    * The current parse state
    */
   enum State
@@ -149,49 +149,49 @@ private:
   JsonParserState(const JsonParserState&);
   const JsonParserState& operator=(const JsonParserState&);
 
-  /*
+  /**
    * Parse over white space
    * Increments the current position
    * @return true if no parse errors
    */
   bool ParseWhiteSpace();
 
-  /*
+  /**
    * Parse over a number, setting the current node if found
    * Increments the current position. Sets error data if parse error.
    * @return true if found, false if parse error
    */
   bool ParseNumber();
 
-  /*
+  /**
    * Parse over a symbol
    * Increments the current position. Sets error data if parse error.
    * @return true if found, false if parse error
    */
   bool ParseSymbol(const std::string& symbol);
 
-  /*
+  /**
    * Parse over 'true' symbol, setting the current node if found
    * Increments the current position. Sets error data if parse error.
    * @return true if found, false if parse error
    */
   bool ParseTrue();
 
-  /*
+  /**
    * Parse over 'false' symbol, setting the current node if found
    * Increments the current position. Sets error data if parse error.
    * @return true if found, false if parse error
    */
   bool ParseFalse();
 
-  /*
+  /**
    * Parse over 'null' symbol, setting the current node if found
    * Increments the current position. Sets error data if parse error.
    * @return true if found, false if parse error
    */
   bool ParseNULL();
 
-  /*
+  /**
    * Parse over a string from the current position and insert escaped
    * control characters in place in the string and a null terminator.
    * This function works from and modifes the current buffer position.
@@ -199,29 +199,29 @@ private:
    */
   char* EncodeString();
 
-  /*
+  /**
    * Create a new node with name and type
    */
   TreeNode* CreateNewNode(const char* name, TreeNode::NodeType type);
 
-  /*
+  /**
    * Create a new node if first parse, else check if the node already
    * exists and set it to a new type
    */
   TreeNode* NewNode(const char* name, TreeNode::NodeType type);
 
-  /*
+  /**
    * Set error meta data
    * @returns always false.
    */
   bool Error(const char* description);
 
-  /*
+  /**
    * Reset state for another parse
    */
   void Reset();
 
-  /*
+  /**
    * Set current to its parent
    * @return true if we had a parent, false and error otherwise
    */
@@ -235,7 +235,7 @@ private:
     return true;
   }
 
-  /*
+  /**
    * Get the current character
    */
   inline char Char()
@@ -243,7 +243,7 @@ private:
     return *mIter;
   }
 
-  /*
+  /**
    * @return True if there are at least n character left
    */
   inline bool AtLeast(int n)
@@ -254,7 +254,7 @@ private:
     return (mEnd - mIter) > n;
   }
 
-  /*
+  /**
    * @return True if at the end of the data to parse
    */
   inline bool AtEnd()
@@ -262,7 +262,7 @@ private:
     return mEnd == mIter;
   }
 
-  /*
+  /**
    * Advance current position by n characters or stop at mEnd
    */
   inline void Advance(int n)
@@ -272,7 +272,7 @@ private:
     mErrorColumn   += c;
   }
 
-  /*
+  /**
    * Advance by n charaters and return true if we reached the end
    */
   inline bool AdvanceEnded(int n)
@@ -283,7 +283,7 @@ private:
     return mEnd == mIter;
   }
 
-  /*
+  /**
    * Advance by at least n characters (stopping at mEnd) and skip any whitespace after n.
    */
   inline void AdvanceSkipWhiteSpace(int n)
@@ -294,7 +294,7 @@ private:
     static_cast<void>( ParseWhiteSpace() );
   }
 
-  /*
+  /**
    * Increment new line counters
    */
   inline void NewLine()
@@ -303,6 +303,122 @@ private:
     mErrorColumn = 0;
   }
 
+  /**
+   * @brief Called by ParseJson if we are in STATE_START.
+   *
+   * @param[in] name The current name
+   * @param[in] currentChar The current character being parsed
+   * @return true if successfully parsed
+   */
+  bool HandleStartState(const char* name, const char currentChar);
+
+  /**
+   * @brief Called by ParseJson if we are in STATE_OBJECT.
+   *
+   * @param[in] currentChar The current character being parsed
+   * @param[in] lastCharacter The last character we parsed
+   * @return true if successfully parsed
+   */
+  bool HandleObjectState(const char currentChar, const char lastCharacter);
+
+  /**
+   * @brief Called by ParseJson if we are in STATE_KEY.
+   *
+   * @param[in/out] name A reference to the name variable
+   * @return true if successfully parsed
+   */
+  bool HandleKeyState(char*& name);
+
+  /**
+   * @brief Called by ParseJson if we are in STATE_VALUE.
+   *
+   * @param[in/out] name A reference to the name variable
+   * @param[in] currentChar The current character being parsed
+   * @param[in] lastCharacter The last character we parsed
+   * @return true if successfully parsed
+   */
+  bool HandleValueState(char*& name, const char currentChar, const char lastCharacter);
+
+  /**
+   * @brief Called by HandleValueState to parse a '"' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterQuote(char*& name);
+
+  /**
+   * @brief Called by HandleValueState to parse a number or hyphen character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterNumberOrHyphen(const char* name);
+
+  /**
+   * @brief Called by HandleValueState to parse a '{' character.
+   *
+   * @param[in] name The current name
+   * @param[in] lastCharacter The last character we parsed
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterBracesStart(const char* name, const char lastCharacter);
+
+  /**
+   * @brief Called by HandleValueState to parse a '}' character.
+   *
+   * @param[in] lastCharacter The last character we parsed
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterBracesEnd(const char lastCharacter);
+
+  /**
+   * @brief Called by HandleValueState to parse a '[' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterSquareBracketStart(const char* name);
+
+  /**
+   * @brief Called by HandleValueState to parse a ']' character.
+   *
+   * @param[in] lastCharacter The last character we parsed
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterSquareBracketEnd(const char lastCharacter);
+
+  /**
+   * @brief Called by HandleValueState to parse a 't' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterLowercaseT(const char* name);
+
+  /**
+   * @brief Called by HandleValueState to parse a 'n' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterLowercaseN(const char* name);
+
+  /**
+   * @brief Called by HandleValueState to parse a 'f' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterLowercaseF(const char* name);
+
+  /**
+   * @brief Called by HandleValueState to parse a ',' character.
+   *
+   * @param[in] name The current name
+   * @return true if successfully parsed
+   */
+  bool HandleCharacterComma(const char* name);
 };