Fixed newline characters throughout the code
[com/gs-lite.git] / src / lib / gscpaux / json.cpp
index 0339e83..149c4c5 100644 (file)
-// Distributed under the MIT license. Copyright (c) 2010, Ivan Vashchaev\r
-\r
-#include <string.h>\r
-#include "json.h"\r
-\r
-// true if character represent a digit\r
-#define IS_DIGIT(c) (c >= '0' && c <= '9')\r
-\r
-// convert string to integer\r
-static char *atoi(char *first, char *last, int *out)\r
-{\r
-       int sign = 1;\r
-       if (first != last)\r
-       {\r
-               if (*first == '-')\r
-               {\r
-                       sign = -1;\r
-                       ++first;\r
-               }\r
-               else if (*first == '+')\r
-               {\r
-                       ++first;\r
-               }\r
-       }\r
-\r
-       int result = 0;\r
-       for (; first != last && IS_DIGIT(*first); ++first)\r
-       {\r
-               result = 10 * result + (*first - '0');\r
-       }\r
-       *out = result * sign;\r
-\r
-       return first;\r
-}\r
-\r
-// convert hexadecimal string to unsigned integer\r
-static char *hatoui(char *first, char *last, unsigned int *out)\r
-{\r
-       unsigned int result = 0;\r
-       for (; first != last; ++first)\r
-       {\r
-               int digit;\r
-               if (IS_DIGIT(*first))\r
-               {\r
-                       digit = *first - '0';\r
-               }\r
-               else if (*first >= 'a' && *first <= 'f')\r
-               {\r
-                       digit = *first - 'a' + 10;\r
-               }\r
-               else if (*first >= 'A' && *first <= 'F')\r
-               {\r
-                       digit = *first - 'A' + 10;\r
-               }\r
-               else\r
-               {\r
-                       break;\r
-               }\r
-               result = 16 * result + (unsigned int)digit;\r
-       }\r
-       *out = result;\r
-\r
-       return first;\r
-}\r
-\r
-// convert string to floating point\r
-static char *atof(char *first, char *last, float *out)\r
-{\r
-       // sign\r
-       float sign = 1;\r
-       if (first != last)\r
-       {\r
-               if (*first == '-')\r
-               {\r
-                       sign = -1;\r
-                       ++first;\r
-               }\r
-               else if (*first == '+')\r
-               {\r
-                       ++first;\r
-               }\r
-       }\r
-\r
-       // integer part\r
-       float result = 0;\r
-       for (; first != last && IS_DIGIT(*first); ++first)\r
-       {\r
-               result = 10 * result + (float)(*first - '0');\r
-       }\r
-\r
-       // fraction part\r
-       if (first != last && *first == '.')\r
-       {\r
-               ++first;\r
-\r
-               float inv_base = 0.1f;\r
-               for (; first != last && IS_DIGIT(*first); ++first)\r
-               {\r
-                       result += (float)(*first - '0') * inv_base;\r
-                       inv_base *= 0.1f;\r
-               }\r
-       }\r
-\r
-       // result w\o exponent\r
-       result *= sign;\r
-\r
-       // exponent\r
-       bool exponent_negative = false;\r
-       int exponent = 0;\r
-       if (first != last && (*first == 'e' || *first == 'E'))\r
-       {\r
-               ++first;\r
-\r
-               if (*first == '-')\r
-               {\r
-                       exponent_negative = true;\r
-                       ++first;\r
-               }\r
-               else if (*first == '+')\r
-               {\r
-                       ++first;\r
-               }\r
-\r
-               for (; first != last && IS_DIGIT(*first); ++first)\r
-               {\r
-                       exponent = 10 * exponent + (*first - '0');\r
-               }\r
-       }\r
-\r
-       if (exponent)\r
-       {\r
-               float power_of_ten = 10;\r
-               for (; exponent > 1; exponent--)\r
-               {\r
-                       power_of_ten *= 10;\r
-               }\r
-\r
-               if (exponent_negative)\r
-               {\r
-                       result /= power_of_ten;\r
-               }\r
-               else\r
-               {\r
-                       result *= power_of_ten;\r
-               }\r
-       }\r
-\r
-       *out = result;\r
-\r
-       return first;\r
-}\r
-\r
-static inline json_value *json_alloc(block_allocator *allocator)\r
-{\r
-       json_value *value = (json_value *)allocator->malloc(sizeof(json_value));\r
-       memset(value, 0, sizeof(json_value));\r
-       return value;\r
-}\r
-\r
-static inline void json_append(json_value *lhs, json_value *rhs)\r
-{\r
-       rhs->parent = lhs;\r
-       if (lhs->last_child)\r
-       {\r
-               lhs->last_child = lhs->last_child->next_sibling = rhs;\r
-       }\r
-       else\r
-       {\r
-               lhs->first_child = lhs->last_child = rhs;\r
-       }\r
-}\r
-\r
-#define ERROR(it, desc)\\r
-       *error_pos = it;\\r
-       *error_desc = desc;\\r
-       *error_line = 1 - escaped_newlines;\\r
-       for (char *c = it; c != source; --c)\\r
-               if (*c == '\n') ++*error_line;\\r
-       return 0\r
-\r
-#define CHECK_TOP() if (!top) {ERROR(it, "Unexpected character");}\r
-\r
-json_value *json_parse(char *source, char **error_pos, const char **error_desc, int *error_line, block_allocator *allocator)\r
-{\r
-       json_value *root = 0;\r
-       json_value *top = 0;\r
-\r
-       char *name = 0;\r
-       char *it = source;\r
-\r
-       int escaped_newlines = 0;\r
-\r
-       while (*it)\r
-       {\r
-               // skip white space\r
-               while (*it == '\x20' || *it == '\x9' || *it == '\xD' || *it == '\xA')\r
-               {\r
-                       ++it;\r
-               }\r
-\r
-               switch (*it)\r
-               {\r
-               case '\0':\r
-                       break;\r
-               case '{':\r
-               case '[':\r
-                       {\r
-                               // create new value\r
-                               json_value *object = json_alloc(allocator);\r
-\r
-                               // name\r
-                               object->name = name;\r
-                               name = 0;\r
-\r
-                               // type\r
-                               object->type = (*it == '{') ? JSON_OBJECT : JSON_ARRAY;\r
-\r
-                               // skip open character\r
-                               ++it;\r
-\r
-                               // set top and root\r
-                               if (top)\r
-                               {\r
-                                       json_append(top, object);\r
-                               }\r
-                               else if (!root)\r
-                               {\r
-                                       root = object;\r
-                               }\r
-                               else\r
-                               {\r
-                                       ERROR(it, "Second root. Only one root allowed");\r
-                               }\r
-                               top = object;\r
-                       }\r
-                       break;\r
-\r
-               case '}':\r
-               case ']':\r
-                       {\r
-                               if (!top || top->type != ((*it == '}') ? JSON_OBJECT : JSON_ARRAY))\r
-                               {\r
-                                       ERROR(it, "Mismatch closing brace/bracket");\r
-                               }\r
-\r
-                               // skip close character\r
-                               ++it;\r
-\r
-                               // set top\r
-                               top = top->parent;\r
-                       }\r
-                       break;\r
-\r
-               case ':':\r
-                       if (!top || top->type != JSON_OBJECT)\r
-                       {\r
-                               ERROR(it, "Unexpected character");\r
-                       }\r
-                       ++it;\r
-                       break;\r
-\r
-               case ',':\r
-                       CHECK_TOP();\r
-                       ++it;\r
-                       break;\r
-\r
-               case '"':\r
-                       {\r
-                               CHECK_TOP();\r
-\r
-                               // skip '"' character\r
-                               ++it;\r
-\r
-                               char *first = it;\r
-                               char *last = it;\r
-                               while (*it)\r
-                               {\r
-                                       if ((unsigned char)*it < '\x20')\r
-                                       {\r
-                                               ERROR(first, "Control characters not allowed in strings");\r
-                                       }\r
-                                       else if (*it == '\\')\r
-                                       {\r
-                                               switch (it[1])\r
-                                               {\r
-                                               case '"':\r
-                                                       *last = '"';\r
-                                                       break;\r
-                                               case '\\':\r
-                                                       *last = '\\';\r
-                                                       break;\r
-                                               case '/':\r
-                                                       *last = '/';\r
-                                                       break;\r
-                                               case 'b':\r
-                                                       *last = '\b';\r
-                                                       break;\r
-                                               case 'f':\r
-                                                       *last = '\f';\r
-                                                       break;\r
-                                               case 'n':\r
-                                                       *last = '\n';\r
-                                                       ++escaped_newlines;\r
-                                                       break;\r
-                                               case 'r':\r
-                                                       *last = '\r';\r
-                                                       break;\r
-                                               case 't':\r
-                                                       *last = '\t';\r
-                                                       break;\r
-                                               case 'u':\r
-                                                       {\r
-                                                               unsigned int codepoint;\r
-                                                               if (hatoui(it + 2, it + 6, &codepoint) != it + 6)\r
-                                                               {\r
-                                                                       ERROR(it, "Bad unicode codepoint");\r
-                                                               }\r
-\r
-                                                               if (codepoint <= 0x7F)\r
-                                                               {\r
-                                                                       *last = (char)codepoint;\r
-                                                               }\r
-                                                               else if (codepoint <= 0x7FF)\r
-                                                               {\r
-                                                                       *last++ = (char)(0xC0 | (codepoint >> 6));\r
-                                                                       *last = (char)(0x80 | (codepoint & 0x3F));\r
-                                                               }\r
-                                                               else if (codepoint <= 0xFFFF)\r
-                                                               {\r
-                                                                       *last++ = (char)(0xE0 | (codepoint >> 12));\r
-                                                                       *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));\r
-                                                                       *last = (char)(0x80 | (codepoint & 0x3F));\r
-                                                               }\r
-                                                       }\r
-                                                       it += 4;\r
-                                                       break;\r
-                                               default:\r
-                                                       ERROR(first, "Unrecognized escape sequence");\r
-                                               }\r
-\r
-                                               ++last;\r
-                                               it += 2;\r
-                                       }\r
-                                       else if (*it == '"')\r
-                                       {\r
-                                               *last = 0;\r
-                                               ++it;\r
-                                               break;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               *last++ = *it++;\r
-                                       }\r
-                               }\r
-\r
-                               if (!name && top->type == JSON_OBJECT)\r
-                               {\r
-                                       // field name in object\r
-                                       name = first;\r
-                               }\r
-                               else\r
-                               {\r
-                                       // new string value\r
-                                       json_value *object = json_alloc(allocator);\r
-\r
-                                       object->name = name;\r
-                                       name = 0;\r
-\r
-                                       object->type = JSON_STRING;\r
-                                       object->string_value = first;\r
-\r
-                                       json_append(top, object);\r
-                               }\r
-                       }\r
-                       break;\r
-\r
-               case 'n':\r
-               case 't':\r
-               case 'f':\r
-                       {\r
-                               CHECK_TOP();\r
-\r
-                               // new null/bool value\r
-                               json_value *object = json_alloc(allocator);\r
-\r
-                               object->name = name;\r
-                               name = 0;\r
-\r
-                               // null\r
-                               if (it[0] == 'n' && it[1] == 'u' && it[2] == 'l' && it[3] == 'l')\r
-                               {\r
-                                       object->type = JSON_NULL;\r
-                                       it += 4;\r
-                               }\r
-                               // true\r
-                               else if (it[0] == 't' && it[1] == 'r' && it[2] == 'u' && it[3] == 'e')\r
-                               {\r
-                                       object->type = JSON_BOOL;\r
-                                       object->int_value = 1;\r
-                                       it += 4;\r
-                               }\r
-                               // false\r
-                               else if (it[0] == 'f' && it[1] == 'a' && it[2] == 'l' && it[3] == 's' && it[4] == 'e')\r
-                               {\r
-                                       object->type = JSON_BOOL;\r
-                                       object->int_value = 0;\r
-                                       it += 5;\r
-                               }\r
-                               else\r
-                               {\r
-                                       ERROR(it, "Unknown identifier");\r
-                               }\r
-\r
-                               json_append(top, object);\r
-                       }\r
-                       break;\r
-\r
-               case '-':\r
-               case '0':\r
-               case '1':\r
-               case '2':\r
-               case '3':\r
-               case '4':\r
-               case '5':\r
-               case '6':\r
-               case '7':\r
-               case '8':\r
-               case '9':\r
-                       {\r
-                               CHECK_TOP();\r
-\r
-                               // new number value\r
-                               json_value *object = json_alloc(allocator);\r
-\r
-                               object->name = name;\r
-                               name = 0;\r
-\r
-                               object->type = JSON_INT;\r
-\r
-                               char *first = it;\r
-                               while (*it != '\x20' && *it != '\x9' && *it != '\xD' && *it != '\xA' && *it != ',' && *it != ']' && *it != '}')\r
-                               {\r
-                                       if (*it == '.' || *it == 'e' || *it == 'E')\r
-                                       {\r
-                                               object->type = JSON_FLOAT;\r
-                                       }\r
-                                       ++it;\r
-                               }\r
-\r
-                               if (object->type == JSON_INT && atoi(first, it, &object->int_value) != it)\r
-                               {\r
-                                       ERROR(first, "Bad integer number");\r
-                               }\r
-\r
-                               if (object->type == JSON_FLOAT && atof(first, it, &object->float_value) != it)\r
-                               {\r
-                                       ERROR(first, "Bad float number");\r
-                               }\r
-\r
-                               json_append(top, object);\r
-                       }\r
-                       break;\r
-\r
-               default:\r
-                       ERROR(it, "Unexpected character");\r
-               }\r
-       }\r
-\r
-       if (top)\r
-       {\r
-               ERROR(it, "Not all objects/arrays have been properly closed");\r
-       }\r
-\r
-       return root;\r
-}\r
+// Distributed under the MIT license. Copyright (c) 2010, Ivan Vashchaev
+
+#include <string.h>
+#include "json.h"
+
+// true if character represent a digit
+#define IS_DIGIT(c) (c >= '0' && c <= '9')
+
+// convert string to integer
+static char *atoi(char *first, char *last, int *out)
+{
+       int sign = 1;
+       if (first != last)
+       {
+               if (*first == '-')
+               {
+                       sign = -1;
+                       ++first;
+               }
+               else if (*first == '+')
+               {
+                       ++first;
+               }
+       }
+
+       int result = 0;
+       for (; first != last && IS_DIGIT(*first); ++first)
+       {
+               result = 10 * result + (*first - '0');
+       }
+       *out = result * sign;
+
+       return first;
+}
+
+// convert hexadecimal string to unsigned integer
+static char *hatoui(char *first, char *last, unsigned int *out)
+{
+       unsigned int result = 0;
+       for (; first != last; ++first)
+       {
+               int digit;
+               if (IS_DIGIT(*first))
+               {
+                       digit = *first - '0';
+               }
+               else if (*first >= 'a' && *first <= 'f')
+               {
+                       digit = *first - 'a' + 10;
+               }
+               else if (*first >= 'A' && *first <= 'F')
+               {
+                       digit = *first - 'A' + 10;
+               }
+               else
+               {
+                       break;
+               }
+               result = 16 * result + (unsigned int)digit;
+       }
+       *out = result;
+
+       return first;
+}
+
+// convert string to floating point
+static char *atof(char *first, char *last, float *out)
+{
+       // sign
+       float sign = 1;
+       if (first != last)
+       {
+               if (*first == '-')
+               {
+                       sign = -1;
+                       ++first;
+               }
+               else if (*first == '+')
+               {
+                       ++first;
+               }
+       }
+
+       // integer part
+       float result = 0;
+       for (; first != last && IS_DIGIT(*first); ++first)
+       {
+               result = 10 * result + (float)(*first - '0');
+       }
+
+       // fraction part
+       if (first != last && *first == '.')
+       {
+               ++first;
+
+               float inv_base = 0.1f;
+               for (; first != last && IS_DIGIT(*first); ++first)
+               {
+                       result += (float)(*first - '0') * inv_base;
+                       inv_base *= 0.1f;
+               }
+       }
+
+       // result w\o exponent
+       result *= sign;
+
+       // exponent
+       bool exponent_negative = false;
+       int exponent = 0;
+       if (first != last && (*first == 'e' || *first == 'E'))
+       {
+               ++first;
+
+               if (*first == '-')
+               {
+                       exponent_negative = true;
+                       ++first;
+               }
+               else if (*first == '+')
+               {
+                       ++first;
+               }
+
+               for (; first != last && IS_DIGIT(*first); ++first)
+               {
+                       exponent = 10 * exponent + (*first - '0');
+               }
+       }
+
+       if (exponent)
+       {
+               float power_of_ten = 10;
+               for (; exponent > 1; exponent--)
+               {
+                       power_of_ten *= 10;
+               }
+
+               if (exponent_negative)
+               {
+                       result /= power_of_ten;
+               }
+               else
+               {
+                       result *= power_of_ten;
+               }
+       }
+
+       *out = result;
+
+       return first;
+}
+
+static inline json_value *json_alloc(block_allocator *allocator)
+{
+       json_value *value = (json_value *)allocator->malloc(sizeof(json_value));
+       memset(value, 0, sizeof(json_value));
+       return value;
+}
+
+static inline void json_append(json_value *lhs, json_value *rhs)
+{
+       rhs->parent = lhs;
+       if (lhs->last_child)
+       {
+               lhs->last_child = lhs->last_child->next_sibling = rhs;
+       }
+       else
+       {
+               lhs->first_child = lhs->last_child = rhs;
+       }
+}
+
+#define ERROR(it, desc)\
+       *error_pos = it;\
+       *error_desc = desc;\
+       *error_line = 1 - escaped_newlines;\
+       for (char *c = it; c != source; --c)\
+               if (*c == '\n') ++*error_line;\
+       return 0
+
+#define CHECK_TOP() if (!top) {ERROR(it, "Unexpected character");}
+
+json_value *json_parse(char *source, char **error_pos, const char **error_desc, int *error_line, block_allocator *allocator)
+{
+       json_value *root = 0;
+       json_value *top = 0;
+
+       char *name = 0;
+       char *it = source;
+
+       int escaped_newlines = 0;
+
+       while (*it)
+       {
+               // skip white space
+               while (*it == '\x20' || *it == '\x9' || *it == '\xD' || *it == '\xA')
+               {
+                       ++it;
+               }
+
+               switch (*it)
+               {
+               case '\0':
+                       break;
+               case '{':
+               case '[':
+                       {
+                               // create new value
+                               json_value *object = json_alloc(allocator);
+
+                               // name
+                               object->name = name;
+                               name = 0;
+
+                               // type
+                               object->type = (*it == '{') ? JSON_OBJECT : JSON_ARRAY;
+
+                               // skip open character
+                               ++it;
+
+                               // set top and root
+                               if (top)
+                               {
+                                       json_append(top, object);
+                               }
+                               else if (!root)
+                               {
+                                       root = object;
+                               }
+                               else
+                               {
+                                       ERROR(it, "Second root. Only one root allowed");
+                               }
+                               top = object;
+                       }
+                       break;
+
+               case '}':
+               case ']':
+                       {
+                               if (!top || top->type != ((*it == '}') ? JSON_OBJECT : JSON_ARRAY))
+                               {
+                                       ERROR(it, "Mismatch closing brace/bracket");
+                               }
+
+                               // skip close character
+                               ++it;
+
+                               // set top
+                               top = top->parent;
+                       }
+                       break;
+
+               case ':':
+                       if (!top || top->type != JSON_OBJECT)
+                       {
+                               ERROR(it, "Unexpected character");
+                       }
+                       ++it;
+                       break;
+
+               case ',':
+                       CHECK_TOP();
+                       ++it;
+                       break;
+
+               case '"':
+                       {
+                               CHECK_TOP();
+
+                               // skip '"' character
+                               ++it;
+
+                               char *first = it;
+                               char *last = it;
+                               while (*it)
+                               {
+                                       if ((unsigned char)*it < '\x20')
+                                       {
+                                               ERROR(first, "Control characters not allowed in strings");
+                                       }
+                                       else if (*it == '\\')
+                                       {
+                                               switch (it[1])
+                                               {
+                                               case '"':
+                                                       *last = '"';
+                                                       break;
+                                               case '\\':
+                                                       *last = '\\';
+                                                       break;
+                                               case '/':
+                                                       *last = '/';
+                                                       break;
+                                               case 'b':
+                                                       *last = '\b';
+                                                       break;
+                                               case 'f':
+                                                       *last = '\f';
+                                                       break;
+                                               case 'n':
+                                                       *last = '\n';
+                                                       ++escaped_newlines;
+                                                       break;
+                                               case 'r':
+                                                       *last = '\r';
+                                                       break;
+                                               case 't':
+                                                       *last = '\t';
+                                                       break;
+                                               case 'u':
+                                                       {
+                                                               unsigned int codepoint;
+                                                               if (hatoui(it + 2, it + 6, &codepoint) != it + 6)
+                                                               {
+                                                                       ERROR(it, "Bad unicode codepoint");
+                                                               }
+
+                                                               if (codepoint <= 0x7F)
+                                                               {
+                                                                       *last = (char)codepoint;
+                                                               }
+                                                               else if (codepoint <= 0x7FF)
+                                                               {
+                                                                       *last++ = (char)(0xC0 | (codepoint >> 6));
+                                                                       *last = (char)(0x80 | (codepoint & 0x3F));
+                                                               }
+                                                               else if (codepoint <= 0xFFFF)
+                                                               {
+                                                                       *last++ = (char)(0xE0 | (codepoint >> 12));
+                                                                       *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
+                                                                       *last = (char)(0x80 | (codepoint & 0x3F));
+                                                               }
+                                                       }
+                                                       it += 4;
+                                                       break;
+                                               default:
+                                                       ERROR(first, "Unrecognized escape sequence");
+                                               }
+
+                                               ++last;
+                                               it += 2;
+                                       }
+                                       else if (*it == '"')
+                                       {
+                                               *last = 0;
+                                               ++it;
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               *last++ = *it++;
+                                       }
+                               }
+
+                               if (!name && top->type == JSON_OBJECT)
+                               {
+                                       // field name in object
+                                       name = first;
+                               }
+                               else
+                               {
+                                       // new string value
+                                       json_value *object = json_alloc(allocator);
+
+                                       object->name = name;
+                                       name = 0;
+
+                                       object->type = JSON_STRING;
+                                       object->string_value = first;
+
+                                       json_append(top, object);
+                               }
+                       }
+                       break;
+
+               case 'n':
+               case 't':
+               case 'f':
+                       {
+                               CHECK_TOP();
+
+                               // new null/bool value
+                               json_value *object = json_alloc(allocator);
+
+                               object->name = name;
+                               name = 0;
+
+                               // null
+                               if (it[0] == 'n' && it[1] == 'u' && it[2] == 'l' && it[3] == 'l')
+                               {
+                                       object->type = JSON_NULL;
+                                       it += 4;
+                               }
+                               // true
+                               else if (it[0] == 't' && it[1] == 'r' && it[2] == 'u' && it[3] == 'e')
+                               {
+                                       object->type = JSON_BOOL;
+                                       object->int_value = 1;
+                                       it += 4;
+                               }
+                               // false
+                               else if (it[0] == 'f' && it[1] == 'a' && it[2] == 'l' && it[3] == 's' && it[4] == 'e')
+                               {
+                                       object->type = JSON_BOOL;
+                                       object->int_value = 0;
+                                       it += 5;
+                               }
+                               else
+                               {
+                                       ERROR(it, "Unknown identifier");
+                               }
+
+                               json_append(top, object);
+                       }
+                       break;
+
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       {
+                               CHECK_TOP();
+
+                               // new number value
+                               json_value *object = json_alloc(allocator);
+
+                               object->name = name;
+                               name = 0;
+
+                               object->type = JSON_INT;
+
+                               char *first = it;
+                               while (*it != '\x20' && *it != '\x9' && *it != '\xD' && *it != '\xA' && *it != ',' && *it != ']' && *it != '}')
+                               {
+                                       if (*it == '.' || *it == 'e' || *it == 'E')
+                                       {
+                                               object->type = JSON_FLOAT;
+                                       }
+                                       ++it;
+                               }
+
+                               if (object->type == JSON_INT && atoi(first, it, &object->int_value) != it)
+                               {
+                                       ERROR(first, "Bad integer number");
+                               }
+
+                               if (object->type == JSON_FLOAT && atof(first, it, &object->float_value) != it)
+                               {
+                                       ERROR(first, "Bad float number");
+                               }
+
+                               json_append(top, object);
+                       }
+                       break;
+
+               default:
+                       ERROR(it, "Unexpected character");
+               }
+       }
+
+       if (top)
+       {
+               ERROR(it, "Not all objects/arrays have been properly closed");
+       }
+
+       return root;
+}