X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Flib%2Fgscpaux%2Fjson.cpp;h=0339e83853840a5b92d26c6e09d8931cdf777a24;hb=07495effe193ca3f73c3bf0ce417068f9ac9dcdd;hp=149c4c59f6978a871dafa046111d9b38ff291db2;hpb=93d248304a68de7a8f9daf4aa74f9ee4cd27410c;p=com%2Fgs-lite.git diff --git a/src/lib/gscpaux/json.cpp b/src/lib/gscpaux/json.cpp index 149c4c5..0339e83 100644 --- a/src/lib/gscpaux/json.cpp +++ b/src/lib/gscpaux/json.cpp @@ -1,475 +1,475 @@ -// Distributed under the MIT license. Copyright (c) 2010, Ivan Vashchaev - -#include -#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 + +#include +#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; +}