Added quantiling UDAFs
[com/gs-lite.git] / src / lib / gscpaux / json.cpp
index 149c4c5..0339e83 100644 (file)
-// 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;
-}
+// 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