// https://github.com/vivkin/gason - pulled January 10, 2016#include "gason.h"#include <stdlib.h>#define JSON_ZONE_SIZE 4096#define JSON_STACK_SIZE 32const char *jsonStrError(int err) {switch (err) {#define XX(no, str) \case JSON_##no: \return str;JSON_ERRNO_MAP(XX)#undef XXdefault:return "unknown";}}void *JsonAllocator::allocate(size_t size) {size = (size + 7) & ~7;if (head && head->used + size <= JSON_ZONE_SIZE) {char *p = (char *)head + head->used;head->used += size;return p;}size_t allocSize = sizeof(Zone) + size;Zone *zone = (Zone *)malloc(allocSize <= JSON_ZONE_SIZE ? JSON_ZONE_SIZE : allocSize);if (zone == nullptr)return nullptr;zone->used = allocSize;if (allocSize <= JSON_ZONE_SIZE || head == nullptr) {zone->next = head;head = zone;} else {zone->next = head->next;head->next = zone;}return (char *)zone + sizeof(Zone);}void JsonAllocator::deallocate() {while (head) {Zone *next = head->next;free(head);head = next;}}static inline bool isspace(char c) {return c == ' ' || (c >= '\t' && c <= '\r');}static inline bool isdelim(char c) {return c == ',' || c == ':' || c == ']' || c == '}' || isspace(c) || !c;}static inline bool isdigit(char c) {return c >= '0' && c <= '9';}static inline bool isxdigit(char c) {return (c >= '0' && c <= '9') || ((c & ~' ') >= 'A' && (c & ~' ') <= 'F');}static inline int char2int(char c) {if (c <= '9')return c - '0';return (c & ~' ') - 'A' + 10;}static double string2double(char *s, char **endptr) {char ch = *s;if (ch == '-')++s;double result = 0;while (isdigit(*s))result = (result * 10) + (*s++ - '0');if (*s == '.') {++s;double fraction = 1;while (isdigit(*s)) {fraction *= 0.1;result += (*s++ - '0') * fraction;}}if (*s == 'e' || *s == 'E') {++s;double base = 10;if (*s == '+')++s;else if (*s == '-') {++s;base = 0.1;}unsigned int exponent = 0;while (isdigit(*s))exponent = (exponent * 10) + (*s++ - '0');double power = 1;for (; exponent; exponent >>= 1, base *= base)if (exponent & 1)power *= base;result *= power;}*endptr = s;return ch == '-' ? -result : result;}static inline JsonNode *insertAfter(JsonNode *tail, JsonNode *node) {if (!tail)return node->next = node;node->next = tail->next;tail->next = node;return node;}static inline JsonValue listToValue(JsonTag tag, JsonNode *tail) {if (tail) {auto head = tail->next;tail->next = nullptr;return JsonValue(tag, head);}return JsonValue(tag, nullptr);}int jsonParse(char *s, char **endptr, JsonValue *value, JsonAllocator &allocator) {JsonNode *tails[JSON_STACK_SIZE];JsonTag tags[JSON_STACK_SIZE];char *keys[JSON_STACK_SIZE];JsonValue o;int pos = -1;bool separator = true;JsonNode *node;*endptr = s;while (*s) {while (isspace(*s)) {++s;if (!*s) break;}*endptr = s++;switch (**endptr) {case '-':if (!isdigit(*s) && *s != '.') {*endptr = s;return JSON_BAD_NUMBER;}case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':o = JsonValue(string2double(*endptr, &s));if (!isdelim(*s)) {*endptr = s;return JSON_BAD_NUMBER;}break;case '"':o = JsonValue(JSON_STRING, s);for (char *it = s; *s; ++it, ++s) {int c = *it = *s;if (c == '\\') {c = *++s;switch (c) {case '\\':case '"':case '/':*it = c;break;case 'b':*it = '\b';break;case 'f':*it = '\f';break;case 'n':*it = '\n';break;case 'r':*it = '\r';break;case 't':*it = '\t';break;case 'u':c = 0;for (int i = 0; i < 4; ++i) {if (isxdigit(*++s)) {c = c * 16 + char2int(*s);} else {*endptr = s;return JSON_BAD_STRING;}}if (c < 0x80) {*it = c;} else if (c < 0x800) {*it++ = 0xC0 | (c >> 6);*it = 0x80 | (c & 0x3F);} else {*it++ = 0xE0 | (c >> 12);*it++ = 0x80 | ((c >> 6) & 0x3F);*it = 0x80 | (c & 0x3F);}break;default:*endptr = s;return JSON_BAD_STRING;}} else if ((unsigned int)c < ' ' || c == '\x7F') {*endptr = s;return JSON_BAD_STRING;} else if (c == '"') {*it = 0;++s;break;}}if (!isdelim(*s)) {*endptr = s;return JSON_BAD_STRING;}break;case 't':if (!(s[0] == 'r' && s[1] == 'u' && s[2] == 'e' && isdelim(s[3])))return JSON_BAD_IDENTIFIER;o = JsonValue(JSON_TRUE);s += 3;break;case 'f':if (!(s[0] == 'a' && s[1] == 'l' && s[2] == 's' && s[3] == 'e' && isdelim(s[4])))return JSON_BAD_IDENTIFIER;o = JsonValue(JSON_FALSE);s += 4;break;case 'n':if (!(s[0] == 'u' && s[1] == 'l' && s[2] == 'l' && isdelim(s[3])))return JSON_BAD_IDENTIFIER;o = JsonValue(JSON_NULL);s += 3;break;case ']':if (pos == -1)return JSON_STACK_UNDERFLOW;if (tags[pos] != JSON_ARRAY)return JSON_MISMATCH_BRACKET;o = listToValue(JSON_ARRAY, tails[pos--]);break;case '}':if (pos == -1)return JSON_STACK_UNDERFLOW;if (tags[pos] != JSON_OBJECT)return JSON_MISMATCH_BRACKET;if (keys[pos] != nullptr)return JSON_UNEXPECTED_CHARACTER;o = listToValue(JSON_OBJECT, tails[pos--]);break;case '[':if (++pos == JSON_STACK_SIZE)return JSON_STACK_OVERFLOW;tails[pos] = nullptr;tags[pos] = JSON_ARRAY;keys[pos] = nullptr;separator = true;continue;case '{':if (++pos == JSON_STACK_SIZE)return JSON_STACK_OVERFLOW;tails[pos] = nullptr;tags[pos] = JSON_OBJECT;keys[pos] = nullptr;separator = true;continue;case ':':if (separator || keys[pos] == nullptr)return JSON_UNEXPECTED_CHARACTER;separator = true;continue;case ',':if (separator || keys[pos] != nullptr)return JSON_UNEXPECTED_CHARACTER;separator = true;continue;case '0円':continue;default:return JSON_UNEXPECTED_CHARACTER;}separator = false;if (pos == -1) {*endptr = s;*value = o;return JSON_OK;}if (tags[pos] == JSON_OBJECT) {if (!keys[pos]) {if (o.getTag() != JSON_STRING)return JSON_UNQUOTED_KEY;keys[pos] = o.toString();continue;}if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode))) == nullptr)return JSON_ALLOCATION_FAILURE;tails[pos] = insertAfter(tails[pos], node);tails[pos]->key = keys[pos];keys[pos] = nullptr;} else {if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode) - sizeof(char *))) == nullptr)return JSON_ALLOCATION_FAILURE;tails[pos] = insertAfter(tails[pos], node);}tails[pos]->value = o;}return JSON_BREAKING_BAD;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。