From 64a7aceeb6fe6a28de93f9fb05a5ce2d79f546a0 Mon Sep 17 00:00:00 2001 From: Alex Fabijanic Date: Thu, 18 Jan 2018 22:36:14 -0600 Subject: [PATCH] update json sources --- JSON/JSON_x64_vs140.vcxproj | 4 +- JSON/JSON_x64_vs140.vcxproj.filters | 4 +- JSON/src/pd_json.c | 1201 ++++++++++++++------------- JSON/src/pd_json.h | 65 +- JSON/src/pd_json_private.h | 65 +- 5 files changed, 701 insertions(+), 638 deletions(-) diff --git a/JSON/JSON_x64_vs140.vcxproj b/JSON/JSON_x64_vs140.vcxproj index ba29fb66d..aa9e8384b 100644 --- a/JSON/JSON_x64_vs140.vcxproj +++ b/JSON/JSON_x64_vs140.vcxproj @@ -290,8 +290,6 @@ - - @@ -305,6 +303,8 @@ + + diff --git a/JSON/JSON_x64_vs140.vcxproj.filters b/JSON/JSON_x64_vs140.vcxproj.filters index d6a1aa27c..0fea7e8bd 100644 --- a/JSON/JSON_x64_vs140.vcxproj.filters +++ b/JSON/JSON_x64_vs140.vcxproj.filters @@ -89,10 +89,10 @@ Header Files - + Header Files - + Header Files diff --git a/JSON/src/pd_json.c b/JSON/src/pd_json.c index cd4fd3fe6..17b7aafef 100644 --- a/JSON/src/pd_json.c +++ b/JSON/src/pd_json.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 201112L #include #include #include @@ -23,792 +24,838 @@ static void json_error_s(json_stream *json, int err) { - char errbuf[1024] = {0}; - strerror_r(err, errbuf, sizeof(errbuf)); - json_error(json, "%s", errbuf); + char errbuf[1024] = { 0 }; + strerror_r(err, errbuf, sizeof(errbuf)); + json_error(json, "%s", errbuf); } static enum json_type push(json_stream *json, enum json_type type) { - json->stack_top++; + json->stack_top++; - if (json->stack_top >= json->stack_size) { - struct json_stack *stack; - stack = json->alloc.realloc(json->stack, - (json->stack_size + STACK_INC) * sizeof(*json->stack)); - if (stack == NULL) { - json_error_s(json, errno); - return JSON_ERROR; - } + if (json->stack_top >= json->stack_size) { + struct json_stack *stack; + stack = json->alloc.realloc(json->stack, + (json->stack_size + STACK_INC) * sizeof(*json->stack)); + if (stack == NULL) { + json_error_s(json, errno); + return JSON_ERROR; + } - json->stack_size += STACK_INC; - json->stack = stack; - } + json->stack_size += STACK_INC; + json->stack = stack; + } - json->stack[json->stack_top].type = type; - json->stack[json->stack_top].count = 0; + json->stack[json->stack_top].type = type; + json->stack[json->stack_top].count = 0; - return type; + return type; } static enum json_type pop(json_stream *json, int c, enum json_type expected) { - if (json->stack == NULL || json->stack[json->stack_top].type != expected) { - json_error(json, "unexpected byte, '%c'", c); - json->alloc.free(json->stack); - return JSON_ERROR; - } - json->stack_top--; - return expected == JSON_ARRAY ? JSON_ARRAY_END : JSON_OBJECT_END; -} - -static void pop_all(json_stream *json) -{ - json->alloc.free(json->stack); + if (json->stack == NULL || json->stack[json->stack_top].type != expected) { + json_error(json, "unexpected byte, '%c'", c); + return JSON_ERROR; + } + json->stack_top--; + return expected == JSON_ARRAY ? JSON_ARRAY_END : JSON_OBJECT_END; } static int buffer_peek(struct json_source *source) { - if (source->position < source->source.buffer.length) - return source->source.buffer.buffer[source->position]; - else - return EOF; + if (source->position < source->source.buffer.length) + return source->source.buffer.buffer[source->position]; + else + return EOF; } static int buffer_get(struct json_source *source) { - int c = source->peek(source); - source->position++; - return c; + int c = source->peek(source); + source->position++; + return c; } static int stream_get(struct json_source *source) { - source->position++; - return fgetc(source->source.stream.stream); + source->position++; + return fgetc(source->source.stream.stream); } static int stream_peek(struct json_source *source) { - int c = fgetc(source->source.stream.stream); - ungetc(c, source->source.stream.stream); - return c; + int c = fgetc(source->source.stream.stream); + ungetc(c, source->source.stream.stream); + return c; } static void init(json_stream *json) { - json->lineno = 1; - json->error = 0; - json->errmsg[0] = '\0'; - json->ntokens = 0; - json->next = 0; - json->streaming = true; + json->lineno = 1; + json->error = 0; + json->errmsg[0] = '\0'; + json->ntokens = 0; + json->next = 0; + json->streaming = true; - json->stack = NULL; - json->stack_top = -1; - json->stack_size = 0; + json->stack = NULL; + json->stack_top = -1; + json->stack_size = 0; - json->data.string = NULL; - json->data.string_size = 0; - json->data.string_fill = 0; - json->source.position = 0; + json->data.string = NULL; + json->data.string_size = 0; + json->data.string_fill = 0; + json->source.position = 0; - json->alloc.malloc = malloc; - json->alloc.realloc = realloc; - json->alloc.free = free; + json->alloc.malloc = malloc; + json->alloc.realloc = realloc; + json->alloc.free = free; } static enum json_type is_match(json_stream *json, const char *pattern, enum json_type type) { - for (const char *p = pattern; *p; p++) - if (*p != json->source.get(&json->source)) - return JSON_ERROR; - return type; + for (const char *p = pattern; *p; p++) + if (*p != json->source.get(&json->source)) + return JSON_ERROR; + return type; } static int pushchar(json_stream *json, int c) { - if (json->data.string_fill == json->data.string_size) { - size_t size = json->data.string_size * 2; - char *buffer = json->alloc.realloc(json->data.string, size); - if (buffer == NULL) { - json_error_s(json, errno); - return -1; - } else { - json->data.string_size = size; - json->data.string = buffer; - } - } - json->data.string[json->data.string_fill++] = c; - return 0; + if (json->data.string_fill == json->data.string_size) { + size_t size = json->data.string_size * 2; + char *buffer = json->alloc.realloc(json->data.string, size); + if (buffer == NULL) { + json_error_s(json, errno); + return -1; + } + else { + json->data.string_size = size; + json->data.string = buffer; + } + } + json->data.string[json->data.string_fill++] = c; + return 0; } static int init_string(json_stream *json) { - json->data.string_fill = 0; - if (json->data.string == NULL) { - json->data.string_size = 1024; - json->data.string = json->alloc.malloc(json->data.string_size); - if (json->data.string == NULL) { - json_error_s(json, errno); - return -1; - } - } - json->data.string[0] = '\0'; - return 0; + json->data.string_fill = 0; + if (json->data.string == NULL) { + json->data.string_size = 1024; + json->data.string = json->alloc.malloc(json->data.string_size); + if (json->data.string == NULL) { + json_error_s(json, errno); + return -1; + } + } + json->data.string[0] = '\0'; + return 0; } static int encode_utf8(json_stream *json, unsigned long c) { - if (c < 0x80UL) { - return pushchar(json, c); - } else if (c < 0x0800UL) { - return !((pushchar(json, (c >> 6 & 0x1F) | 0xC0) == 0) && - (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); - } else if (c < 0x010000UL) { - if (c >= 0xd800 && c <= 0xdfff) { - json_error(json, "invalid codepoint %06lx", c); - return -1; - } - return !((pushchar(json, (c >> 12 & 0x0F) | 0xE0) == 0) && - (pushchar(json, (c >> 6 & 0x3F) | 0x80) == 0) && - (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); - } else if (c < 0x110000UL) { - return !((pushchar(json, (c >> 18 & 0x07) | 0xF0) == 0) && - (pushchar(json, (c >> 12 & 0x3F) | 0x80) == 0) && - (pushchar(json, (c >> 6 & 0x3F) | 0x80) == 0) && - (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); - } else { - json_error(json, "can't encode UTF-8 for %06lx", c); - return -1; - } + if (c < 0x80UL) { + return pushchar(json, c); + } + else if (c < 0x0800UL) { + return !((pushchar(json, (c >> 6 & 0x1F) | 0xC0) == 0) && + (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); + } + else if (c < 0x010000UL) { + if (c >= 0xd800 && c <= 0xdfff) { + json_error(json, "invalid codepoint %06lx", c); + return -1; + } + return !((pushchar(json, (c >> 12 & 0x0F) | 0xE0) == 0) && + (pushchar(json, (c >> 6 & 0x3F) | 0x80) == 0) && + (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); + } + else if (c < 0x110000UL) { + return !((pushchar(json, (c >> 18 & 0x07) | 0xF0) == 0) && + (pushchar(json, (c >> 12 & 0x3F) | 0x80) == 0) && + (pushchar(json, (c >> 6 & 0x3F) | 0x80) == 0) && + (pushchar(json, (c >> 0 & 0x3F) | 0x80) == 0)); + } + else { + json_error(json, "can't encode UTF-8 for %06lx", c); + return -1; + } } static int hexchar(int c) { - switch (c) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': - case 'A': return 10; - case 'b': - case 'B': return 11; - case 'c': - case 'C': return 12; - case 'd': - case 'D': return 13; - case 'e': - case 'E': return 14; - case 'f': - case 'F': return 15; - default: - return -1; - } + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': + case 'A': return 10; + case 'b': + case 'B': return 11; + case 'c': + case 'C': return 12; + case 'd': + case 'D': return 13; + case 'e': + case 'E': return 14; + case 'f': + case 'F': return 15; + default: + return -1; + } } static long read_unicode_cp(json_stream *json) { - long cp = 0; - int shift = 12; + long cp = 0; + int shift = 12; - for (size_t i = 0; i < 4; i++) { - int c = json->source.get(&json->source); - int hc; + for (size_t i = 0; i < 4; i++) { + int c = json->source.get(&json->source); + int hc; - if (c == EOF) { - json_error(json, "%s", "unterminated string literal in unicode"); - return -1; - } else if ((hc = hexchar(c)) == -1) { - json_error(json, "bad escape unicode byte, '%c'", c); - return -1; - } + if (c == EOF) { + json_error(json, "%s", "unterminated string literal in unicode"); + return -1; + } + else if ((hc = hexchar(c)) == -1) { + json_error(json, "bad escape unicode byte, '%c'", c); + return -1; + } - cp += hc * (1 << shift); - shift -= 4; - } + cp += hc * (1 << shift); + shift -= 4; + } - return cp; + return cp; } static int read_unicode(json_stream *json) { - long cp, h, l; + long cp, h, l; - if ((cp = read_unicode_cp(json)) == -1) { - return -1; - } + if ((cp = read_unicode_cp(json)) == -1) { + return -1; + } - if (cp >= 0xd800 && cp <= 0xdbff) { - /* This is the high portion of a surrogate pair; we need to read the - * lower portion to get the codepoint - */ - h = cp; + if (cp >= 0xd800 && cp <= 0xdbff) { + /* This is the high portion of a surrogate pair; we need to read the + * lower portion to get the codepoint + */ + h = cp; - int c = json->source.get(&json->source); - if (c == EOF) { - json_error(json, "%s", "unterminated string literal in unicode"); - return -1; - } else if (c != '\\') { - json_error(json, "invalid continuation for surrogate pair: '%c', " - "expected '\\'", c); - return -1; - } + int c = json->source.get(&json->source); + if (c == EOF) { + json_error(json, "%s", "unterminated string literal in unicode"); + return -1; + } + else if (c != '\\') { + json_error(json, "invalid continuation for surrogate pair: '%c', " + "expected '\\'", c); + return -1; + } - c = json->source.get(&json->source); - if (c == EOF) { - json_error(json, "%s", "unterminated string literal in unicode"); - return -1; - } else if (c != 'u') { - json_error(json, "invalid continuation for surrogate pair: '%c', " - "expected 'u'", c); - return -1; - } + c = json->source.get(&json->source); + if (c == EOF) { + json_error(json, "%s", "unterminated string literal in unicode"); + return -1; + } + else if (c != 'u') { + json_error(json, "invalid continuation for surrogate pair: '%c', " + "expected 'u'", c); + return -1; + } - if ((l = read_unicode_cp(json)) == -1) { - return -1; - } + if ((l = read_unicode_cp(json)) == -1) { + return -1; + } - if (l < 0xdc00 || l > 0xdfff) { - json_error(json, "invalid surrogate pair continuation \\u%04lx out " - "of range (dc00-dfff)", l); - return -1; - } + if (l < 0xdc00 || l > 0xdfff) { + json_error(json, "invalid surrogate pair continuation \\u%04lx out " + "of range (dc00-dfff)", l); + return -1; + } - cp = ((h - 0xd800) * 0x400) + ((l - 0xdc00) + 0x10000); - } else if (cp >= 0xdc00 && cp <= 0xdfff) { - json_error(json, "dangling surrogate \\u%04lx", cp); - return -1; - } + cp = ((h - 0xd800) * 0x400) + ((l - 0xdc00) + 0x10000); + } + else if (cp >= 0xdc00 && cp <= 0xdfff) { + json_error(json, "dangling surrogate \\u%04lx", cp); + return -1; + } - return encode_utf8(json, cp); + return encode_utf8(json, cp); } int read_escaped(json_stream *json) { - int c = json->source.get(&json->source); - if (c == EOF) { - json_error(json, "%s", "unterminated string literal in escape"); - return -1; - } else if (c == 'u') { - if (read_unicode(json) != 0) - return -1; - } else { - switch (c) { - case '\\': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - case '/': - case '"': - { - const char *codes = "\\bfnrt/\""; - char *p = strchr(codes, c); - if (pushchar(json, "\\\b\f\n\r\t/\""[p - codes]) != 0) - return -1; - } - break; - default: - json_error(json, "bad escaped byte, '%c'", c); - return -1; - } - } - return 0; + int c = json->source.get(&json->source); + if (c == EOF) { + json_error(json, "%s", "unterminated string literal in escape"); + return -1; + } + else if (c == 'u') { + if (read_unicode(json) != 0) + return -1; + } + else { + switch (c) { + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case '/': + case '"': + { + const char *codes = "\\bfnrt/\""; + char *p = strchr(codes, c); + if (pushchar(json, "\\\b\f\n\r\t/\""[p - codes]) != 0) + return -1; + } + break; + default: + json_error(json, "bad escaped byte, '%c'", c); + return -1; + } + } + return 0; } static int char_needs_escaping(int c) { - if ((c >= 0) && (c < 0x20 || c == 0x22 || c == 0x5c)) { - return 1; - } + if ((c >= 0) && (c < 0x20 || c == 0x22 || c == 0x5c)) { + return 1; + } - return 0; + return 0; } static int utf8_seq_length(char byte) { - unsigned char u = (unsigned char) byte; - if (u < 0x80) return 1; + unsigned char u = (unsigned char)byte; + if (u < 0x80) return 1; - if (0x80 <= u && u <= 0xBF) - { - // second, third or fourth byte of a multi-byte - // sequence, i.e. a "continuation byte" - return 0; - } - else if (u == 0xC0 || u == 0xC1) - { - // overlong encoding of an ASCII byte - return 0; - } - else if (0xC2 <= u && u <= 0xDF) - { - // 2-byte sequence - return 2; - } - else if (0xE0 <= u && u <= 0xEF) - { - // 3-byte sequence - return 3; - } - else if (0xF0 <= u && u <= 0xF4) - { - // 4-byte sequence - return 4; - } - else - { - // u >= 0xF5 - // Restricted (start of 4-, 5- or 6-byte sequence) or invalid UTF-8 - return 0; - } + if (0x80 <= u && u <= 0xBF) + { + // second, third or fourth byte of a multi-byte + // sequence, i.e. a "continuation byte" + return 0; + } + else if (u == 0xC0 || u == 0xC1) + { + // overlong encoding of an ASCII byte + return 0; + } + else if (0xC2 <= u && u <= 0xDF) + { + // 2-byte sequence + return 2; + } + else if (0xE0 <= u && u <= 0xEF) + { + // 3-byte sequence + return 3; + } + else if (0xF0 <= u && u <= 0xF4) + { + // 4-byte sequence + return 4; + } + else + { + // u >= 0xF5 + // Restricted (start of 4-, 5- or 6-byte sequence) or invalid UTF-8 + return 0; + } } static int is_legal_utf8(const unsigned char *bytes, int length) { - if (0 == bytes || 0 == length) return 0; + if (0 == bytes || 0 == length) return 0; - unsigned char a; - const unsigned char* srcptr = bytes + length; - switch (length) - { - default: - return 0; - // Everything else falls through when true. - case 4: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 3: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 2: - a = (*--srcptr); - switch (*bytes) - { - case 0xE0: - if (a < 0xA0 || a > 0xBF) return 0; - break; - case 0xED: - if (a < 0x80 || a > 0x9F) return 0; - break; - case 0xF0: - if (a < 0x90 || a > 0xBF) return 0; - break; - case 0xF4: - if (a < 0x80 || a > 0x8F) return 0; - break; - default: - if (a < 0x80 || a > 0xBF) return 0; - } - case 1: - if (*bytes >= 0x80 && *bytes < 0xC2) return 0; - } - return *bytes <= 0xF4; + unsigned char a; + const unsigned char* srcptr = bytes + length; + switch (length) + { + default: + return 0; + // Everything else falls through when true. + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; + case 2: + a = (*--srcptr); + switch (*bytes) + { + case 0xE0: + if (a < 0xA0 || a > 0xBF) return 0; + break; + case 0xED: + if (a < 0x80 || a > 0x9F) return 0; + break; + case 0xF0: + if (a < 0x90 || a > 0xBF) return 0; + break; + case 0xF4: + if (a < 0x80 || a > 0x8F) return 0; + break; + default: + if (a < 0x80 || a > 0xBF) return 0; + } + case 1: + if (*bytes >= 0x80 && *bytes < 0xC2) return 0; + } + return *bytes <= 0xF4; } static int read_utf8(json_stream* json, int next_char) { - int count = utf8_seq_length(next_char); - if (!count) - { - json_error(json, "%s", "Bad character."); - return -1; - } + int count = utf8_seq_length(next_char); + if (!count) + { + json_error(json, "%s", "Bad character."); + return -1; + } - char buffer[4]; - buffer[0] = next_char; - for (int i = 1; i < count; ++i) - { - buffer[i] = json->source.get(&json->source);; - } + char buffer[4]; + buffer[0] = next_char; + for (int i = 1; i < count; ++i) + { + buffer[i] = json->source.get(&json->source);; + } - if (!is_legal_utf8((unsigned char*) buffer, count)) - { - json_error(json, "%s", "No legal UTF8 found"); - return -1; - } + if (!is_legal_utf8((unsigned char*)buffer, count)) + { + json_error(json, "%s", "No legal UTF8 found"); + return -1; + } - for (int i = 0; i < count; ++i) - { - if (pushchar(json, buffer[i]) != 0) - return -1; - } - return 0; + for (int i = 0; i < count; ++i) + { + if (pushchar(json, buffer[i]) != 0) + return -1; + } + return 0; } static enum json_type read_string(json_stream *json) { - if (init_string(json) != 0) - return JSON_ERROR; - while (1) { - int c = json->source.get(&json->source); - if (c == EOF) { - json_error(json, "%s", "unterminated string literal"); - return JSON_ERROR; - } else if (c == '"') { - if (pushchar(json, '\0') == 0) - return JSON_STRING; - else - return JSON_ERROR; - } else if (c == '\\') { - if (read_escaped(json) != 0) - return JSON_ERROR; - } else if ((unsigned) c >= 0x80) { - if (read_utf8(json, c) != 0) - return JSON_ERROR; - } else { - if (char_needs_escaping(c)) { - json_error(json, "%s:%u", "unescaped control character in string", (unsigned)c); - return JSON_ERROR; - } + if (init_string(json) != 0) + return JSON_ERROR; + while (1) { + int c = json->source.get(&json->source); + if (c == EOF) { + json_error(json, "%s", "unterminated string literal"); + return JSON_ERROR; + } + else if (c == '"') { + if (pushchar(json, '\0') == 0) + return JSON_STRING; + else + return JSON_ERROR; + } + else if (c == '\\') { + if (read_escaped(json) != 0) + return JSON_ERROR; + } + else if ((unsigned)c >= 0x80) { + if (read_utf8(json, c) != 0) + return JSON_ERROR; + } + else { + if (char_needs_escaping(c)) { + json_error(json, "%s", "unescaped control character in string"); + return JSON_ERROR; + } - if (pushchar(json, c) != 0) - return JSON_ERROR; - } - } - return JSON_ERROR; + if (pushchar(json, c) != 0) + return JSON_ERROR; + } + } + return JSON_ERROR; } static int is_digit(int c) { - return c >= 48 /*0*/ && c <= 57 /*9*/; + return c >= 48 /*0*/ && c <= 57 /*9*/; } static int read_digits(json_stream *json) { - unsigned nread = 0; - while (is_digit(json->source.peek(&json->source))) { - if (pushchar(json, json->source.get(&json->source)) != 0) - return -1; + unsigned nread = 0; + while (is_digit(json->source.peek(&json->source))) { + if (pushchar(json, json->source.get(&json->source)) != 0) + return -1; - nread++; - } + nread++; + } - if (nread == 0) { - return -1; - } + if (nread == 0) { + return -1; + } - return 0; + return 0; } static enum json_type read_number(json_stream *json, int c) { - if (pushchar(json, c) != 0) - return JSON_ERROR; - if (c == '-') { - c = json->source.get(&json->source); - if (is_digit(c)) { - return read_number(json, c); - } else { - json_error(json, "unexpected byte, '%c'", c); - } - } else if (strchr("123456789", c) != NULL) { - c = json->source.peek(&json->source); - if (is_digit(c)) { - if (read_digits(json) != 0) - return JSON_ERROR; - } - } - /* Up to decimal or exponent has been read. */ - c = json->source.peek(&json->source); - if (strchr(".eE", c) == NULL) { - if (pushchar(json, '\0') != 0) - return JSON_ERROR; - else - return JSON_NUMBER; - } - if (c == '.') { - json->source.get(&json->source); // consume . - if (pushchar(json, c) != 0) - return JSON_ERROR; - if (read_digits(json) != 0) - return JSON_ERROR; - } - /* Check for exponent. */ - c = json->source.peek(&json->source); - if (c == 'e' || c == 'E') { - json->source.get(&json->source); // consume e/E - if (pushchar(json, c) != 0) - return JSON_ERROR; - c = json->source.peek(&json->source); - if (c == '+' || c == '-') { - json->source.get(&json->source); // consume - if (pushchar(json, c) != 0) - return JSON_ERROR; - if (read_digits(json) != 0) - return JSON_ERROR; - } else if (is_digit(c)) { - if (read_digits(json) != 0) - return JSON_ERROR; - } else { - json_error(json, "unexpected byte in number, '%c'", c); - return JSON_ERROR; - } - } - if (pushchar(json, '\0') != 0) - return JSON_ERROR; - else - return JSON_NUMBER; + if (pushchar(json, c) != 0) + return JSON_ERROR; + if (c == '-') { + c = json->source.get(&json->source); + if (is_digit(c)) { + return read_number(json, c); + } + else { + json_error(json, "unexpected byte, '%c'", c); + } + } + else if (strchr("123456789", c) != NULL) { + c = json->source.peek(&json->source); + if (is_digit(c)) { + if (read_digits(json) != 0) + return JSON_ERROR; + } + } + /* Up to decimal or exponent has been read. */ + c = json->source.peek(&json->source); + if (strchr(".eE", c) == NULL) { + if (pushchar(json, '\0') != 0) + return JSON_ERROR; + else + return JSON_NUMBER; + } + if (c == '.') { + json->source.get(&json->source); // consume . + if (pushchar(json, c) != 0) + return JSON_ERROR; + if (read_digits(json) != 0) + return JSON_ERROR; + } + /* Check for exponent. */ + c = json->source.peek(&json->source); + if (c == 'e' || c == 'E') { + json->source.get(&json->source); // consume e/E + if (pushchar(json, c) != 0) + return JSON_ERROR; + c = json->source.peek(&json->source); + if (c == '+' || c == '-') { + json->source.get(&json->source); // consume + if (pushchar(json, c) != 0) + return JSON_ERROR; + if (read_digits(json) != 0) + return JSON_ERROR; + } + else if (is_digit(c)) { + if (read_digits(json) != 0) + return JSON_ERROR; + } + else { + json_error(json, "unexpected byte in number, '%c'", c); + return JSON_ERROR; + } + } + if (pushchar(json, '\0') != 0) + return JSON_ERROR; + else + return JSON_NUMBER; } static int json_isspace(int c) { - switch (c) { - case 0x09: - case 0x0a: - case 0x0d: - case 0x20: - return 1; - } + switch (c) { + case 0x09: + case 0x0a: + case 0x0d: + case 0x20: + return 1; + } - return 0; + return 0; } /* Returns the next non-whitespace character in the stream. */ static int next(json_stream *json) { - int c; - while (json_isspace(c = json->source.get(&json->source))) - if (c == '\n') - json->lineno++; - return c; + int c; + while (json_isspace(c = json->source.get(&json->source))) + if (c == '\n') + json->lineno++; + return c; } static enum json_type read_value(json_stream *json, int c) { - json->ntokens++; - switch (c) { - case EOF: - json_error(json, "%s", "unexpected end of data"); - return JSON_ERROR; - case '{': - return push(json, JSON_OBJECT); - case '[': - return push(json, JSON_ARRAY); - case '"': - return read_string(json); - case 'n': - return is_match(json, "ull", JSON_NULL); - case 'f': - return is_match(json, "alse", JSON_FALSE); - case 't': - return is_match(json, "rue", JSON_TRUE); - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - if (init_string(json) != 0) - return JSON_ERROR; - return read_number(json, c); - default: - json_error(json, "unexpected byte, '%c'", c); - return JSON_ERROR; - } + json->ntokens++; + switch (c) { + case EOF: + json_error(json, "%s", "unexpected end of data"); + return JSON_ERROR; + case '{': + return push(json, JSON_OBJECT); + case '[': + return push(json, JSON_ARRAY); + case '"': + return read_string(json); + case 'n': + return is_match(json, "ull", JSON_NULL); + case 'f': + return is_match(json, "alse", JSON_FALSE); + case 't': + return is_match(json, "rue", JSON_TRUE); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + if (init_string(json) != 0) + return JSON_ERROR; + return read_number(json, c); + default: + json_error(json, "unexpected byte, '%c'", c); + return JSON_ERROR; + } } enum json_type json_peek(json_stream *json) { - enum json_type next = json_next(json); - json->next = next; - return next; + enum json_type next = json_next(json); + json->next = next; + return next; } enum json_type json_next(json_stream *json) { - if (json->error) - return JSON_ERROR; - if (json->next != 0) { - enum json_type next = json->next; - json->next = 0; - return next; - } - if (json->ntokens > 0 && json->stack_top == (size_t)-1) { - int c; + if (json->error) + return JSON_ERROR; + if (json->next != 0) { + enum json_type next = json->next; + json->next = 0; + return next; + } + if (json->ntokens > 0 && json->stack_top == (size_t)-1) { + int c; - do { - c = json->source.peek(&json->source); - if (json_isspace(c)) { - c = json->source.get(&json->source); - } - } while (json_isspace(c)); - if (!json->streaming && c != EOF) { - return JSON_ERROR; - } - return JSON_DONE; - } - int c = next(json); - if (json->stack == NULL) - return read_value(json, c); - if (json->stack[json->stack_top].type == JSON_ARRAY) { - if (json->stack[json->stack_top].count == 0) { - if (c == ']') { - return pop(json, c, JSON_ARRAY); - } - json->stack[json->stack_top].count++; - return read_value(json, c); - } else if (c == ',') { - json->stack[json->stack_top].count++; - return read_value(json, next(json)); - } else if (c == ']') { - return pop(json, c, JSON_ARRAY); - } else { - json_error(json, "unexpected byte, '%c'", c); - return JSON_ERROR; - } - } else if (json->stack[json->stack_top].type == JSON_OBJECT) { - if (json->stack[json->stack_top].count == 0) { - if (c == '}') { - return pop(json, c, JSON_OBJECT); - } + do { + c = json->source.peek(&json->source); + if (json_isspace(c)) { + c = json->source.get(&json->source); + } + } while (json_isspace(c)); - /* No property value pairs yet. */ - enum json_type value = read_value(json, c); - if (value != JSON_STRING) { - json_error(json, "%s", "expected property name or '}'"); - return JSON_ERROR; - } else { - json->stack[json->stack_top].count++; - return value; - } - } else if ((json->stack[json->stack_top].count % 2) == 0) { - /* Expecting comma followed by property name. */ - if (c != ',' && c != '}') { - json_error(json, "%s", "expected ',' or '}'"); - return JSON_ERROR; - } else if (c == '}') { - return pop(json, c, JSON_OBJECT); - } else { - enum json_type value = read_value(json, next(json)); - if (value != JSON_STRING) { - json_error(json, "%s", "expected property name"); - return JSON_ERROR; - } else { - json->stack[json->stack_top].count++; - return value; - } - } - } else if ((json->stack[json->stack_top].count % 2) == 1) { - /* Expecting colon followed by value. */ - if (c != ':') { - json_error(json, "%s", "expected ':' after property name"); - return JSON_ERROR; - } else { - json->stack[json->stack_top].count++; - return read_value(json, next(json)); - } - } - } - json_error(json, "%s", "invalid parser state"); - return JSON_ERROR; + if (!json->streaming && c != EOF) { + return JSON_ERROR; + } + + return JSON_DONE; + } + int c = next(json); + if (json->stack_top == (size_t)-1) + return read_value(json, c); + if (json->stack[json->stack_top].type == JSON_ARRAY) { + if (json->stack[json->stack_top].count == 0) { + if (c == ']') { + return pop(json, c, JSON_ARRAY); + } + json->stack[json->stack_top].count++; + return read_value(json, c); + } + else if (c == ',') { + json->stack[json->stack_top].count++; + return read_value(json, next(json)); + } + else if (c == ']') { + return pop(json, c, JSON_ARRAY); + } + else { + json_error(json, "unexpected byte, '%c'", c); + return JSON_ERROR; + } + } + else if (json->stack[json->stack_top].type == JSON_OBJECT) { + if (json->stack[json->stack_top].count == 0) { + if (c == '}') { + return pop(json, c, JSON_OBJECT); + } + + /* No property value pairs yet. */ + enum json_type value = read_value(json, c); + if (value != JSON_STRING) { + json_error(json, "%s", "expected property name or '}'"); + return JSON_ERROR; + } + else { + json->stack[json->stack_top].count++; + return value; + } + } + else if ((json->stack[json->stack_top].count % 2) == 0) { + /* Expecting comma followed by property name. */ + if (c != ',' && c != '}') { + json_error(json, "%s", "expected ',' or '}'"); + return JSON_ERROR; + } + else if (c == '}') { + return pop(json, c, JSON_OBJECT); + } + else { + enum json_type value = read_value(json, next(json)); + if (value != JSON_STRING) { + json_error(json, "%s", "expected property name"); + return JSON_ERROR; + } + else { + json->stack[json->stack_top].count++; + return value; + } + } + } + else if ((json->stack[json->stack_top].count % 2) == 1) { + /* Expecting colon followed by value. */ + if (c != ':') { + json_error(json, "%s", "expected ':' after property name"); + return JSON_ERROR; + } + else { + json->stack[json->stack_top].count++; + return read_value(json, next(json)); + } + } + } + json_error(json, "%s", "invalid parser state"); + return JSON_ERROR; } void json_reset(json_stream *json) { - pop_all(json); - json->ntokens = 0; - json->error = 0; - json->errmsg[0] = '\0'; + json->stack_top = -1; + json->ntokens = 0; + json->error = 0; + json->errmsg[0] = '\0'; } const char *json_get_string(json_stream *json, size_t *length) { - if (length != NULL) - *length = json->data.string_fill; - if (json->data.string == NULL) - return ""; - else - return json->data.string; + if (length != NULL) + *length = json->data.string_fill; + if (json->data.string == NULL) + return ""; + else + return json->data.string; } double json_get_number(json_stream *json) { - char *p = json->data.string; - return p == NULL ? 0 : strtod(p, NULL); + char *p = json->data.string; + return p == NULL ? 0 : strtod(p, NULL); } const char *json_get_error(json_stream *json) { - return json->error ? json->errmsg : NULL; + return json->error ? json->errmsg : NULL; } size_t json_get_lineno(json_stream *json) { - return json->lineno; + return json->lineno; } size_t json_get_position(json_stream *json) { - return json->source.position; + return json->source.position; } size_t json_get_depth(json_stream *json) { - return json->stack_top + 1; + return json->stack_top + 1; } void json_open_buffer(json_stream *json, const void *buffer, size_t size) { - init(json); - json->source.get = buffer_get; - json->source.peek = buffer_peek; - json->source.source.buffer.buffer = buffer; - json->source.source.buffer.length = size; + init(json); + json->source.get = buffer_get; + json->source.peek = buffer_peek; + json->source.source.buffer.buffer = buffer; + json->source.source.buffer.length = size; } void json_open_string(json_stream *json, const char *string) { - json_open_buffer(json, string, strlen(string)); + json_open_buffer(json, string, strlen(string)); } void json_open_stream(json_stream *json, FILE * stream) { - init(json); - json->source.get = stream_get; - json->source.peek = stream_peek; - json->source.source.stream.stream = stream; + init(json); + json->source.get = stream_get; + json->source.peek = stream_peek; + json->source.source.stream.stream = stream; +} + +static int user_get(struct json_source *json) +{ + return json->source.user.get(json->source.user.ptr); +} + +static int user_peek(struct json_source *json) +{ + return json->source.user.peek(json->source.user.ptr); +} + +void json_open_user(json_stream *json, json_user_io get, json_user_io peek, void *user) +{ + init(json); + json->source.get = user_get; + json->source.peek = user_peek; + json->source.source.user.ptr = user; + json->source.source.user.get = get; + json->source.source.user.peek = peek; } void json_set_allocator(json_stream *json, json_allocator *a) { - json->alloc = *a; + json->alloc = *a; } void json_set_streaming(json_stream *json, bool streaming) { - json->streaming = streaming; + json->streaming = streaming; } void json_close(json_stream *json) { - pop_all(json); - json->alloc.free(json->data.string); -} + json->alloc.free(json->stack); + json->alloc.free(json->data.string); +} \ No newline at end of file diff --git a/JSON/src/pd_json.h b/JSON/src/pd_json.h index 6446fcc0e..13b15487d 100644 --- a/JSON/src/pd_json.h +++ b/JSON/src/pd_json.h @@ -1,42 +1,53 @@ #ifndef PDJSON_H #define PDJSON_H +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + #include -enum json_type { - JSON_ERROR = 1, JSON_DONE, - JSON_OBJECT, JSON_OBJECT_END, JSON_ARRAY, JSON_ARRAY_END, - JSON_STRING, JSON_NUMBER, JSON_TRUE, JSON_FALSE, JSON_NULL -}; + enum json_type { + JSON_ERROR = 1, JSON_DONE, + JSON_OBJECT, JSON_OBJECT_END, JSON_ARRAY, JSON_ARRAY_END, + JSON_STRING, JSON_NUMBER, JSON_TRUE, JSON_FALSE, JSON_NULL + }; -struct json_allocator { - void *(*malloc)(size_t); - void *(*realloc)(void *, size_t); - void (*free)(void *); -}; + struct json_allocator { + void *(*malloc)(size_t); + void *(*realloc)(void *, size_t); + void(*free)(void *); + }; + + typedef int(*json_user_io) (void *user); #include "pd_json_private.h" -typedef struct json_stream json_stream; -typedef struct json_allocator json_allocator; + typedef struct json_stream json_stream; + typedef struct json_allocator json_allocator; -void json_open_buffer(json_stream *json, const void *buffer, size_t size); -void json_open_string(json_stream *json, const char *string); -void json_open_stream(json_stream *json, FILE *stream); -void json_close(json_stream *json); + void json_open_buffer(json_stream *json, const void *buffer, size_t size); + void json_open_string(json_stream *json, const char *string); + void json_open_stream(json_stream *json, FILE *stream); + void json_open_user(json_stream *json, json_user_io get, json_user_io peek, void *user); + void json_close(json_stream *json); -void json_set_allocator(json_stream *json, json_allocator *a); -void json_set_streaming(json_stream *json, bool strict); + void json_set_allocator(json_stream *json, json_allocator *a); + void json_set_streaming(json_stream *json, bool strict); -enum json_type json_next(json_stream *json); -enum json_type json_peek(json_stream *json); -void json_reset(json_stream *json); -const char *json_get_string(json_stream *json, size_t *length); -double json_get_number(json_stream *json); + enum json_type json_next(json_stream *json); + enum json_type json_peek(json_stream *json); + void json_reset(json_stream *json); + const char *json_get_string(json_stream *json, size_t *length); + double json_get_number(json_stream *json); -size_t json_get_lineno(json_stream *json); -size_t json_get_position(json_stream *json); -size_t json_get_depth(json_stream *json); -const char *json_get_error(json_stream *json); + size_t json_get_lineno(json_stream *json); + size_t json_get_position(json_stream *json); + size_t json_get_depth(json_stream *json); + const char *json_get_error(json_stream *json); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus #endif diff --git a/JSON/src/pd_json_private.h b/JSON/src/pd_json_private.h index 1d3a7c905..6612dc557 100644 --- a/JSON/src/pd_json_private.h +++ b/JSON/src/pd_json_private.h @@ -5,46 +5,51 @@ #include struct json_source { - int (*get) (struct json_source *); - int (*peek) (struct json_source *); - size_t position; - union { - struct { - FILE *stream; - } stream; - struct { - const char *buffer; - size_t length; - } buffer; - } source; + int(*get) (struct json_source *); + int(*peek) (struct json_source *); + size_t position; + union { + struct { + FILE *stream; + } stream; + struct { + const char *buffer; + size_t length; + } buffer; + struct { + void *ptr; + json_user_io get; + json_user_io peek; + } user; + } source; }; struct json_stack { - enum json_type type; - long count; + enum json_type type; + long count; }; struct json_stream { - size_t lineno; + size_t lineno; - struct json_stack *stack; - size_t stack_top; - size_t stack_size; - enum json_type next; - int error : 31; - bool streaming : 1; + struct json_stack *stack; + size_t stack_top; + size_t stack_size; + enum json_type next; + int error : 31; + bool streaming : 1; - struct { - char *string; - size_t string_fill; - size_t string_size; - } data; + struct { + char *string; + size_t string_fill; + size_t string_size; + } data; - size_t ntokens; + size_t ntokens; - struct json_source source; - struct json_allocator alloc; - char errmsg[128]; + struct json_source source; + struct json_allocator alloc; + char errmsg[128]; }; #endif