From bcf450dbc7318ede5f8b1b693fce33c40ec7ffc3 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Thu, 29 Nov 2018 20:25:51 +0100 Subject: [PATCH] automatic code formatting --- example/jsondump.c | 194 +++++++-------- example/simple.c | 115 ++++----- jsmn.c | 516 ++++++++++++++++++++------------------- jsmn.h | 43 ++-- test/test.h | 22 +- test/tests.c | 594 ++++++++++++++++++++------------------------- test/testutil.h | 150 ++++++------ 7 files changed, 802 insertions(+), 832 deletions(-) diff --git a/example/jsondump.c b/example/jsondump.c index a9f2c92..d7217bd 100644 --- a/example/jsondump.c +++ b/example/jsondump.c @@ -1,9 +1,9 @@ +#include "../jsmn.h" +#include #include #include -#include #include -#include -#include "../jsmn.h" +#include /* Function realloc_it() is a wrapper function for standard realloc() * with one difference - it frees old memory pointer in case of realloc @@ -12,12 +12,12 @@ * memory can't be re-allocated - use standard realloc() instead. */ static inline void *realloc_it(void *ptrmem, size_t size) { - void *p = realloc(ptrmem, size); - if (!p) { - free (ptrmem); - fprintf(stderr, "realloc(): errno=%d\n", errno); - } - return p; + void *p = realloc(ptrmem, size); + if (!p) { + free(ptrmem); + fprintf(stderr, "realloc(): errno=%d\n", errno); + } + return p; } /* @@ -26,101 +26,103 @@ static inline void *realloc_it(void *ptrmem, size_t size) { */ static int dump(const char *js, jsmntok_t *t, size_t count, int indent) { - int i, j, k; - if (count == 0) { - return 0; - } - if (t->type == JSMN_PRIMITIVE) { - printf("%.*s", t->end - t->start, js+t->start); - return 1; - } else if (t->type == JSMN_STRING) { - printf("'%.*s'", t->end - t->start, js+t->start); - return 1; - } else if (t->type == JSMN_OBJECT) { - printf("\n"); - j = 0; - for (i = 0; i < t->size; i++) { - for (k = 0; k < indent; k++) printf(" "); - j += dump(js, t+1+j, count-j, indent+1); - printf(": "); - j += dump(js, t+1+j, count-j, indent+1); - printf("\n"); - } - return j+1; - } else if (t->type == JSMN_ARRAY) { - j = 0; - printf("\n"); - for (i = 0; i < t->size; i++) { - for (k = 0; k < indent-1; k++) printf(" "); - printf(" - "); - j += dump(js, t+1+j, count-j, indent+1); - printf("\n"); - } - return j+1; - } - return 0; + int i, j, k; + if (count == 0) { + return 0; + } + if (t->type == JSMN_PRIMITIVE) { + printf("%.*s", t->end - t->start, js + t->start); + return 1; + } else if (t->type == JSMN_STRING) { + printf("'%.*s'", t->end - t->start, js + t->start); + return 1; + } else if (t->type == JSMN_OBJECT) { + printf("\n"); + j = 0; + for (i = 0; i < t->size; i++) { + for (k = 0; k < indent; k++) + printf(" "); + j += dump(js, t + 1 + j, count - j, indent + 1); + printf(": "); + j += dump(js, t + 1 + j, count - j, indent + 1); + printf("\n"); + } + return j + 1; + } else if (t->type == JSMN_ARRAY) { + j = 0; + printf("\n"); + for (i = 0; i < t->size; i++) { + for (k = 0; k < indent - 1; k++) + printf(" "); + printf(" - "); + j += dump(js, t + 1 + j, count - j, indent + 1); + printf("\n"); + } + return j + 1; + } + return 0; } int main() { - int r; - int eof_expected = 0; - char *js = NULL; - size_t jslen = 0; - char buf[BUFSIZ]; + int r; + int eof_expected = 0; + char *js = NULL; + size_t jslen = 0; + char buf[BUFSIZ]; - jsmn_parser p; - jsmntok_t *tok; - size_t tokcount = 2; + jsmn_parser p; + jsmntok_t *tok; + size_t tokcount = 2; - /* Prepare parser */ - jsmn_init(&p); + /* Prepare parser */ + jsmn_init(&p); - /* Allocate some tokens as a start */ - tok = malloc(sizeof(*tok) * tokcount); - if (tok == NULL) { - fprintf(stderr, "malloc(): errno=%d\n", errno); - return 3; - } + /* Allocate some tokens as a start */ + tok = malloc(sizeof(*tok) * tokcount); + if (tok == NULL) { + fprintf(stderr, "malloc(): errno=%d\n", errno); + return 3; + } - for (;;) { - /* Read another chunk */ - r = fread(buf, 1, sizeof(buf), stdin); - if (r < 0) { - fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); - return 1; - } - if (r == 0) { - if (eof_expected != 0) { - return 0; - } else { - fprintf(stderr, "fread(): unexpected EOF\n"); - return 2; - } - } + for (;;) { + /* Read another chunk */ + r = fread(buf, 1, sizeof(buf), stdin); + if (r < 0) { + fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); + return 1; + } + if (r == 0) { + if (eof_expected != 0) { + return 0; + } else { + fprintf(stderr, "fread(): unexpected EOF\n"); + return 2; + } + } - js = realloc_it(js, jslen + r + 1); - if (js == NULL) { - return 3; - } - strncpy(js + jslen, buf, r); - jslen = jslen + r; + js = realloc_it(js, jslen + r + 1); + if (js == NULL) { + return 3; + } + strncpy(js + jslen, buf, r); + jslen = jslen + r; -again: - r = jsmn_parse(&p, js, jslen, tok, tokcount); - if (r < 0) { - if (r == JSMN_ERROR_NOMEM) { - tokcount = tokcount * 2; - tok = realloc_it(tok, sizeof(*tok) * tokcount); - if (tok == NULL) { - return 3; - } - goto again; - } - } else { - dump(js, tok, p.toknext, 0); - eof_expected = 1; - } - } + again: + r = jsmn_parse(&p, js, jslen, tok, tokcount); + if (r < 0) { + if (r == JSMN_ERROR_NOMEM) { + tokcount = tokcount * 2; + tok = realloc_it(tok, sizeof(*tok) * tokcount); + if (tok == NULL) { + return 3; + } + goto again; + } + } else { + dump(js, tok, p.toknext, 0); + eof_expected = 1; + } + } - return EXIT_SUCCESS; + return EXIT_SUCCESS; } diff --git a/example/simple.c b/example/simple.c index aeb9cf4..1254575 100644 --- a/example/simple.c +++ b/example/simple.c @@ -1,7 +1,7 @@ +#include "../jsmn.h" #include #include #include -#include "../jsmn.h" /* * A small example of jsmn parsing when JSON structure is known and number of @@ -9,68 +9,69 @@ */ static const char *JSON_STRING = - "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " - "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}"; + "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " + "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}"; static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { - if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && - strncmp(json + tok->start, s, tok->end - tok->start) == 0) { - return 0; - } - return -1; + if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; } int main() { - int i; - int r; - jsmn_parser p; - jsmntok_t t[128]; /* We expect no more than 128 tokens */ + int i; + int r; + jsmn_parser p; + jsmntok_t t[128]; /* We expect no more than 128 tokens */ - jsmn_init(&p); - r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0])); - if (r < 0) { - printf("Failed to parse JSON: %d\n", r); - return 1; - } + jsmn_init(&p); + r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, + sizeof(t) / sizeof(t[0])); + if (r < 0) { + printf("Failed to parse JSON: %d\n", r); + return 1; + } - /* Assume the top-level element is an object */ - if (r < 1 || t[0].type != JSMN_OBJECT) { - printf("Object expected\n"); - return 1; - } + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_OBJECT) { + printf("Object expected\n"); + return 1; + } - /* Loop over all keys of the root object */ - for (i = 1; i < r; i++) { - if (jsoneq(JSON_STRING, &t[i], "user") == 0) { - /* We may use strndup() to fetch string value */ - printf("- User: %.*s\n", t[i+1].end-t[i+1].start, - JSON_STRING + t[i+1].start); - i++; - } else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) { - /* We may additionally check if the value is either "true" or "false" */ - printf("- Admin: %.*s\n", t[i+1].end-t[i+1].start, - JSON_STRING + t[i+1].start); - i++; - } else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) { - /* We may want to do strtol() here to get numeric value */ - printf("- UID: %.*s\n", t[i+1].end-t[i+1].start, - JSON_STRING + t[i+1].start); - i++; - } else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) { - int j; - printf("- Groups:\n"); - if (t[i+1].type != JSMN_ARRAY) { - continue; /* We expect groups to be an array of strings */ - } - for (j = 0; j < t[i+1].size; j++) { - jsmntok_t *g = &t[i+j+2]; - printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start); - } - i += t[i+1].size + 1; - } else { - printf("Unexpected key: %.*s\n", t[i].end-t[i].start, - JSON_STRING + t[i].start); - } - } - return EXIT_SUCCESS; + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + if (jsoneq(JSON_STRING, &t[i], "user") == 0) { + /* We may use strndup() to fetch string value */ + printf("- User: %.*s\n", t[i + 1].end - t[i + 1].start, + JSON_STRING + t[i + 1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) { + /* We may additionally check if the value is either "true" or "false" */ + printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start, + JSON_STRING + t[i + 1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf("- UID: %.*s\n", t[i + 1].end - t[i + 1].start, + JSON_STRING + t[i + 1].start); + i++; + } else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) { + int j; + printf("- Groups:\n"); + if (t[i + 1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i + 1].size; j++) { + jsmntok_t *g = &t[i + j + 2]; + printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start); + } + i += t[i + 1].size + 1; + } else { + printf("Unexpected key: %.*s\n", t[i].end - t[i].start, + JSON_STRING + t[i].start); + } + } + return EXIT_SUCCESS; } diff --git a/jsmn.c b/jsmn.c index 853c3f1..ed41be6 100644 --- a/jsmn.c +++ b/jsmn.c @@ -3,303 +3,334 @@ /** * Allocates a fresh unused token from the token pool. */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; #ifdef JSMN_PARENT_LINKS - tok->parent = -1; + tok->parent = -1; #endif - return tok; + return tok; } /** * Fills token type and boundaries. */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; +static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, int start, + int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; } /** * Fills next available token with JSON primitive. */ -static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, size_t len, + jsmntok_t *tokens, size_t num_tokens) { + jsmntok_t *token; + int start; - start = parser->pos; + start = parser->pos; - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { #ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': #endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } #ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; #endif found: - if (tokens == NULL) { - parser->pos--; - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); #ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; + token->parent = parser->toksuper; #endif - parser->pos--; - return 0; + parser->pos--; + return 0; } /** * Fills next token with JSON string. */ -static int jsmn_parse_string(jsmn_parser *parser, const char *js, - size_t len, jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; +static int jsmn_parse_string(jsmn_parser *parser, const char *js, size_t len, + jsmntok_t *tokens, size_t num_tokens) { + jsmntok_t *token; - int start = parser->pos; + int start = parser->pos; - parser->pos++; + parser->pos++; - /* Skip starting quote */ - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; - /* Quote: end of string */ - if (c == '\"') { - if (tokens == NULL) { - return 0; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); #ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; + token->parent = parser->toksuper; #endif - return 0; - } + return 0; + } - /* Backslash: Quoted symbol expected */ - if (c == '\\' && parser->pos + 1 < len) { - int i; - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - parser->pos++; - for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { - /* If it isn't a hex character we have an error */ - if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ - (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ - (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ - parser->pos = start; - return JSMN_ERROR_INVAL; - } - parser->pos++; - } - parser->pos--; - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; } /** * Parse JSON string and fill tokens. */ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens) { - int r; - int i; - jsmntok_t *token; - int count = parser->toknext; + jsmntok_t *tokens, unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; - for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; - c = js[parser->pos]; - switch (c) { - case '{': case '[': - count++; - if (tokens == NULL) { - break; - } - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) + return JSMN_ERROR_NOMEM; + if (parser->toksuper != -1) { + tokens[parser->toksuper].size++; #ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; + token->parent = parser->toksuper; #endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - if (tokens == NULL) - break; - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) + break; + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); #ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - if(token->type != type || parser->toksuper == -1) { - return JSMN_ERROR_INVAL; - } - break; - } - token = &tokens[token->parent]; - } + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } #else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) + return JSMN_ERROR_INVAL; + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } #endif - break; - case '\"': - r = jsmn_parse_string(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ' ': - break; - case ':': - parser->toksuper = parser->toknext - 1; - break; - case ',': - if (tokens != NULL && parser->toksuper != -1 && - tokens[parser->toksuper].type != JSMN_ARRAY && - tokens[parser->toksuper].type != JSMN_OBJECT) { + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) + return r; + count++; + if (parser->toksuper != -1 && tokens != NULL) + tokens[parser->toksuper].size++; + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { #ifdef JSMN_PARENT_LINKS - parser->toksuper = tokens[parser->toksuper].parent; + parser->toksuper = tokens[parser->toksuper].parent; #else - for (i = parser->toknext - 1; i >= 0; i--) { - if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { - if (tokens[i].start != -1 && tokens[i].end == -1) { - parser->toksuper = i; - break; - } - } - } + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } #endif - } - break; + } + break; #ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : - /* And they must not be keys of the object */ - if (tokens != NULL && parser->toksuper != -1) { - jsmntok_t *t = &tokens[parser->toksuper]; - if (t->type == JSMN_OBJECT || - (t->type == JSMN_STRING && t->size != 0)) { - return JSMN_ERROR_INVAL; - } - } + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } #else - /* In non-strict mode every unquoted value is a primitive */ - default: + /* In non-strict mode every unquoted value is a primitive */ + default: #endif - r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); - if (r < 0) return r; - count++; - if (parser->toksuper != -1 && tokens != NULL) - tokens[parser->toksuper].size++; - break; + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) + return r; + count++; + if (parser->toksuper != -1 && tokens != NULL) + tokens[parser->toksuper].size++; + break; #ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; #endif - } - } + } + } - if (tokens != NULL) { - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - } + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } - return count; + return count; } /** @@ -307,8 +338,7 @@ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, * available. */ void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; } - diff --git a/jsmn.h b/jsmn.h index 5a5200e..967ae03 100644 --- a/jsmn.h +++ b/jsmn.h @@ -15,20 +15,20 @@ extern "C" { * o Other primitive: number, boolean (true/false) or null */ typedef enum { - JSMN_UNDEFINED = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3, - JSMN_PRIMITIVE = 4 + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 } jsmntype_t; enum jsmnerr { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3 + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 }; /** @@ -38,12 +38,12 @@ enum jsmnerr { * end end position in JSON data string */ typedef struct { - jsmntype_t type; - int start; - int end; - int size; + jsmntype_t type; + int start; + int end; + int size; #ifdef JSMN_PARENT_LINKS - int parent; + int parent; #endif } jsmntok_t; @@ -52,9 +52,9 @@ typedef struct { * the string being parsed now and current position in that string */ typedef struct { - unsigned int pos; /* offset in the JSON string */ - unsigned int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g parent object or array */ } jsmn_parser; /** @@ -63,11 +63,12 @@ typedef struct { void jsmn_init(jsmn_parser *parser); /** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing * a single JSON object. */ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, - jsmntok_t *tokens, unsigned int num_tokens); + jsmntok_t *tokens, unsigned int num_tokens); #ifdef __cplusplus } diff --git a/test/test.h b/test/test.h index 35f704f..a1c0957 100644 --- a/test/test.h +++ b/test/test.h @@ -5,23 +5,27 @@ static int test_passed = 0; static int test_failed = 0; /* Terminate current test with error */ -#define fail() return __LINE__ +#define fail() return __LINE__ /* Successful end of the test case */ #define done() return 0 /* Check single condition */ -#define check(cond) do { if (!(cond)) fail(); } while (0) +#define check(cond) \ + do { \ + if (!(cond)) \ + fail(); \ + } while (0) /* Test runner */ static void test(int (*func)(void), const char *name) { - int r = func(); - if (r == 0) { - test_passed++; - } else { - test_failed++; - printf("FAILED: %s (at line %d)\n", name, r); - } + int r = func(); + if (r == 0) { + test_passed++; + } else { + test_failed++; + printf("FAILED: %s (at line %d)\n", name, r); + } } #endif /* __TEST_H__ */ diff --git a/test/tests.c b/test/tests.c index 31761cd..c473a23 100644 --- a/test/tests.c +++ b/test/tests.c @@ -1,407 +1,339 @@ +#include #include #include #include -#include #include "test.h" #include "testutil.h" int test_empty(void) { - check(parse("{}", 1, 1, - JSMN_OBJECT, 0, 2, 0)); - check(parse("[]", 1, 1, - JSMN_ARRAY, 0, 2, 0)); - check(parse("[{},{}]", 3, 3, - JSMN_ARRAY, 0, 7, 2, - JSMN_OBJECT, 1, 3, 0, - JSMN_OBJECT, 4, 6, 0)); - return 0; + check(parse("{}", 1, 1, JSMN_OBJECT, 0, 2, 0)); + check(parse("[]", 1, 1, JSMN_ARRAY, 0, 2, 0)); + check(parse("[{},{}]", 3, 3, JSMN_ARRAY, 0, 7, 2, JSMN_OBJECT, 1, 3, 0, + JSMN_OBJECT, 4, 6, 0)); + return 0; } int test_object(void) { - check(parse("{\"a\":0}", 3, 3, - JSMN_OBJECT, 0, 7, 1, - JSMN_STRING, "a", 1, - JSMN_PRIMITIVE, "0")); - check(parse("{\"a\":[]}", 3, 3, - JSMN_OBJECT, 0, 8, 1, - JSMN_STRING, "a", 1, - JSMN_ARRAY, 5, 7, 0)); - check(parse("{\"a\":{},\"b\":{}}", 5, 5, - JSMN_OBJECT, -1, -1, 2, - JSMN_STRING, "a", 1, - JSMN_OBJECT, -1, -1, 0, - JSMN_STRING, "b", 1, - JSMN_OBJECT, -1, -1, 0)); - check(parse("{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }", 7, 7, - JSMN_OBJECT, -1, -1, 3, - JSMN_STRING, "Day", 1, - JSMN_PRIMITIVE, "26", - JSMN_STRING, "Month", 1, - JSMN_PRIMITIVE, "9", - JSMN_STRING, "Year", 1, - JSMN_PRIMITIVE, "12")); - check(parse("{\"a\": 0, \"b\": \"c\"}", 5, 5, - JSMN_OBJECT, -1, -1, 2, - JSMN_STRING, "a", 1, - JSMN_PRIMITIVE, "0", - JSMN_STRING, "b", 1, - JSMN_STRING, "c", 0)); + check(parse("{\"a\":0}", 3, 3, JSMN_OBJECT, 0, 7, 1, JSMN_STRING, "a", 1, + JSMN_PRIMITIVE, "0")); + check(parse("{\"a\":[]}", 3, 3, JSMN_OBJECT, 0, 8, 1, JSMN_STRING, "a", 1, + JSMN_ARRAY, 5, 7, 0)); + check(parse("{\"a\":{},\"b\":{}}", 5, 5, JSMN_OBJECT, -1, -1, 2, JSMN_STRING, + "a", 1, JSMN_OBJECT, -1, -1, 0, JSMN_STRING, "b", 1, JSMN_OBJECT, + -1, -1, 0)); + check(parse("{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }", 7, 7, + JSMN_OBJECT, -1, -1, 3, JSMN_STRING, "Day", 1, JSMN_PRIMITIVE, + "26", JSMN_STRING, "Month", 1, JSMN_PRIMITIVE, "9", JSMN_STRING, + "Year", 1, JSMN_PRIMITIVE, "12")); + check(parse("{\"a\": 0, \"b\": \"c\"}", 5, 5, JSMN_OBJECT, -1, -1, 2, + JSMN_STRING, "a", 1, JSMN_PRIMITIVE, "0", JSMN_STRING, "b", 1, + JSMN_STRING, "c", 0)); #ifdef JSMN_STRICT - check(parse("{\"a\"\n0}", JSMN_ERROR_INVAL, 3)); - check(parse("{\"a\", 0}", JSMN_ERROR_INVAL, 3)); - check(parse("{\"a\": {2}}", JSMN_ERROR_INVAL, 3)); - check(parse("{\"a\": {2: 3}}", JSMN_ERROR_INVAL, 3)); - check(parse("{\"a\": {\"a\": 2 3}}", JSMN_ERROR_INVAL, 5)); - /* FIXME */ - /*check(parse("{\"a\"}", JSMN_ERROR_INVAL, 2));*/ - /*check(parse("{\"a\": 1, \"b\"}", JSMN_ERROR_INVAL, 4));*/ - /*check(parse("{\"a\",\"b\":1}", JSMN_ERROR_INVAL, 4));*/ - /*check(parse("{\"a\":1,}", JSMN_ERROR_INVAL, 4));*/ - /*check(parse("{\"a\":\"b\":\"c\"}", JSMN_ERROR_INVAL, 4));*/ - /*check(parse("{,}", JSMN_ERROR_INVAL, 4));*/ + check(parse("{\"a\"\n0}", JSMN_ERROR_INVAL, 3)); + check(parse("{\"a\", 0}", JSMN_ERROR_INVAL, 3)); + check(parse("{\"a\": {2}}", JSMN_ERROR_INVAL, 3)); + check(parse("{\"a\": {2: 3}}", JSMN_ERROR_INVAL, 3)); + check(parse("{\"a\": {\"a\": 2 3}}", JSMN_ERROR_INVAL, 5)); +/* FIXME */ +/*check(parse("{\"a\"}", JSMN_ERROR_INVAL, 2));*/ +/*check(parse("{\"a\": 1, \"b\"}", JSMN_ERROR_INVAL, 4));*/ +/*check(parse("{\"a\",\"b\":1}", JSMN_ERROR_INVAL, 4));*/ +/*check(parse("{\"a\":1,}", JSMN_ERROR_INVAL, 4));*/ +/*check(parse("{\"a\":\"b\":\"c\"}", JSMN_ERROR_INVAL, 4));*/ +/*check(parse("{,}", JSMN_ERROR_INVAL, 4));*/ #endif - return 0; + return 0; } int test_array(void) { - /* FIXME */ - /*check(parse("[10}", JSMN_ERROR_INVAL, 3));*/ - /*check(parse("[1,,3]", JSMN_ERROR_INVAL, 3)*/ - check(parse("[10]", 2, 2, - JSMN_ARRAY, -1, -1, 1, - JSMN_PRIMITIVE, "10")); - check(parse("{\"a\": 1]", JSMN_ERROR_INVAL, 3)); - /* FIXME */ - /*check(parse("[\"a\": 1]", JSMN_ERROR_INVAL, 3));*/ - return 0; + /* FIXME */ + /*check(parse("[10}", JSMN_ERROR_INVAL, 3));*/ + /*check(parse("[1,,3]", JSMN_ERROR_INVAL, 3)*/ + check(parse("[10]", 2, 2, JSMN_ARRAY, -1, -1, 1, JSMN_PRIMITIVE, "10")); + check(parse("{\"a\": 1]", JSMN_ERROR_INVAL, 3)); + /* FIXME */ + /*check(parse("[\"a\": 1]", JSMN_ERROR_INVAL, 3));*/ + return 0; } int test_primitive(void) { - check(parse("{\"boolVar\" : true }", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "boolVar", 1, - JSMN_PRIMITIVE, "true")); - check(parse("{\"boolVar\" : false }", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "boolVar", 1, - JSMN_PRIMITIVE, "false")); - check(parse("{\"nullVar\" : null }", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "nullVar", 1, - JSMN_PRIMITIVE, "null")); - check(parse("{\"intVar\" : 12}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "intVar", 1, - JSMN_PRIMITIVE, "12")); - check(parse("{\"floatVar\" : 12.345}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "floatVar", 1, - JSMN_PRIMITIVE, "12.345")); - return 0; + check(parse("{\"boolVar\" : true }", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "true")); + check(parse("{\"boolVar\" : false }", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "false")); + check(parse("{\"nullVar\" : null }", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "nullVar", 1, JSMN_PRIMITIVE, "null")); + check(parse("{\"intVar\" : 12}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING, + "intVar", 1, JSMN_PRIMITIVE, "12")); + check(parse("{\"floatVar\" : 12.345}", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "floatVar", 1, JSMN_PRIMITIVE, "12.345")); + return 0; } int test_string(void) { - check(parse("{\"strVar\" : \"hello world\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "strVar", 1, - JSMN_STRING, "hello world", 0)); - check(parse("{\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "strVar", 1, - JSMN_STRING, "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\", 0)); - check(parse("{\"strVar\": \"\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "strVar", 1, - JSMN_STRING, "", 0)); - check(parse("{\"a\":\"\\uAbcD\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "a", 1, - JSMN_STRING, "\\uAbcD", 0)); - check(parse("{\"a\":\"str\\u0000\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "a", 1, - JSMN_STRING, "str\\u0000", 0)); - check(parse("{\"a\":\"\\uFFFFstr\"}", 3, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "a", 1, - JSMN_STRING, "\\uFFFFstr", 0)); - check(parse("{\"a\":[\"\\u0280\"]}", 4, 4, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "a", 1, - JSMN_ARRAY, -1, -1, 1, - JSMN_STRING, "\\u0280", 0)); - - check(parse("{\"a\":\"str\\uFFGFstr\"}", JSMN_ERROR_INVAL, 3)); - check(parse("{\"a\":\"str\\u@FfF\"}", JSMN_ERROR_INVAL, 3)); - check(parse("{{\"a\":[\"\\u028\"]}", JSMN_ERROR_INVAL, 4)); - return 0; + check(parse("{\"strVar\" : \"hello world\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "strVar", 1, JSMN_STRING, "hello world", 0)); + check(parse("{\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"}", 3, 3, + JSMN_OBJECT, -1, -1, 1, JSMN_STRING, "strVar", 1, JSMN_STRING, + "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\", 0)); + check(parse("{\"strVar\": \"\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING, + "strVar", 1, JSMN_STRING, "", 0)); + check(parse("{\"a\":\"\\uAbcD\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING, + "a", 1, JSMN_STRING, "\\uAbcD", 0)); + check(parse("{\"a\":\"str\\u0000\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "a", 1, JSMN_STRING, "str\\u0000", 0)); + check(parse("{\"a\":\"\\uFFFFstr\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "a", 1, JSMN_STRING, "\\uFFFFstr", 0)); + check(parse("{\"a\":[\"\\u0280\"]}", 4, 4, JSMN_OBJECT, -1, -1, 1, + JSMN_STRING, "a", 1, JSMN_ARRAY, -1, -1, 1, JSMN_STRING, + "\\u0280", 0)); + + check(parse("{\"a\":\"str\\uFFGFstr\"}", JSMN_ERROR_INVAL, 3)); + check(parse("{\"a\":\"str\\u@FfF\"}", JSMN_ERROR_INVAL, 3)); + check(parse("{{\"a\":[\"\\u028\"]}", JSMN_ERROR_INVAL, 4)); + return 0; } int test_partial_string(void) { - int i; - int r; - jsmn_parser p; - jsmntok_t tok[5]; - const char *js = "{\"x\": \"va\\\\ue\", \"y\": \"value y\"}"; - - jsmn_init(&p); - for (i = 1; i <= strlen(js); i++) { - r = jsmn_parse(&p, js, i, tok, sizeof(tok)/sizeof(tok[0])); - if (i == strlen(js)) { - check(r == 5); - check(tokeq(js, tok, 5, - JSMN_OBJECT, -1, -1, 2, - JSMN_STRING, "x", 1, - JSMN_STRING, "va\\\\ue", 0, - JSMN_STRING, "y", 1, - JSMN_STRING, "value y", 0)); - } else { - check(r == JSMN_ERROR_PART); - } - } - return 0; + int i; + int r; + jsmn_parser p; + jsmntok_t tok[5]; + const char *js = "{\"x\": \"va\\\\ue\", \"y\": \"value y\"}"; + + jsmn_init(&p); + for (i = 1; i <= strlen(js); i++) { + r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0])); + if (i == strlen(js)) { + check(r == 5); + check(tokeq(js, tok, 5, JSMN_OBJECT, -1, -1, 2, JSMN_STRING, "x", 1, + JSMN_STRING, "va\\\\ue", 0, JSMN_STRING, "y", 1, JSMN_STRING, + "value y", 0)); + } else { + check(r == JSMN_ERROR_PART); + } + } + return 0; } int test_partial_array(void) { #ifdef JSMN_STRICT - int r; - int i; - jsmn_parser p; - jsmntok_t tok[10]; - const char *js = "[ 1, true, [123, \"hello\"]]"; - - jsmn_init(&p); - for (i = 1; i <= strlen(js); i++) { - r = jsmn_parse(&p, js, i, tok, sizeof(tok)/sizeof(tok[0])); - if (i == strlen(js)) { - check(r == 6); - check(tokeq(js, tok, 6, - JSMN_ARRAY, -1, -1, 3, - JSMN_PRIMITIVE, "1", - JSMN_PRIMITIVE, "true", - JSMN_ARRAY, -1, -1, 2, - JSMN_PRIMITIVE, "123", - JSMN_STRING, "hello", 0)); - } else { - check(r == JSMN_ERROR_PART); - } - } + int r; + int i; + jsmn_parser p; + jsmntok_t tok[10]; + const char *js = "[ 1, true, [123, \"hello\"]]"; + + jsmn_init(&p); + for (i = 1; i <= strlen(js); i++) { + r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0])); + if (i == strlen(js)) { + check(r == 6); + check(tokeq(js, tok, 6, JSMN_ARRAY, -1, -1, 3, JSMN_PRIMITIVE, "1", + JSMN_PRIMITIVE, "true", JSMN_ARRAY, -1, -1, 2, JSMN_PRIMITIVE, + "123", JSMN_STRING, "hello", 0)); + } else { + check(r == JSMN_ERROR_PART); + } + } #endif - return 0; + return 0; } int test_array_nomem(void) { - int i; - int r; - jsmn_parser p; - jsmntok_t toksmall[10], toklarge[10]; - const char *js; - - js = " [ 1, true, [123, \"hello\"]]"; - - for (i = 0; i < 6; i++) { - jsmn_init(&p); - memset(toksmall, 0, sizeof(toksmall)); - memset(toklarge, 0, sizeof(toklarge)); - r = jsmn_parse(&p, js, strlen(js), toksmall, i); - check(r == JSMN_ERROR_NOMEM); - - memcpy(toklarge, toksmall, sizeof(toksmall)); - - r = jsmn_parse(&p, js, strlen(js), toklarge, 10); - check(r >= 0); - check(tokeq(js, toklarge, 4, - JSMN_ARRAY, -1, -1, 3, - JSMN_PRIMITIVE, "1", - JSMN_PRIMITIVE, "true", - JSMN_ARRAY, -1, -1, 2, - JSMN_PRIMITIVE, "123", - JSMN_STRING, "hello", 0)); - } - return 0; + int i; + int r; + jsmn_parser p; + jsmntok_t toksmall[10], toklarge[10]; + const char *js; + + js = " [ 1, true, [123, \"hello\"]]"; + + for (i = 0; i < 6; i++) { + jsmn_init(&p); + memset(toksmall, 0, sizeof(toksmall)); + memset(toklarge, 0, sizeof(toklarge)); + r = jsmn_parse(&p, js, strlen(js), toksmall, i); + check(r == JSMN_ERROR_NOMEM); + + memcpy(toklarge, toksmall, sizeof(toksmall)); + + r = jsmn_parse(&p, js, strlen(js), toklarge, 10); + check(r >= 0); + check(tokeq(js, toklarge, 4, JSMN_ARRAY, -1, -1, 3, JSMN_PRIMITIVE, "1", + JSMN_PRIMITIVE, "true", JSMN_ARRAY, -1, -1, 2, JSMN_PRIMITIVE, + "123", JSMN_STRING, "hello", 0)); + } + return 0; } int test_unquoted_keys(void) { #ifndef JSMN_STRICT - int r; - jsmn_parser p; - jsmntok_t tok[10]; - const char *js; - - jsmn_init(&p); - js = "key1: \"value\"\nkey2 : 123"; - - r = jsmn_parse(&p, js, strlen(js), tok, 10); - check(r >= 0); - check(tokeq(js, tok, 4, - JSMN_PRIMITIVE, "key1", - JSMN_STRING, "value", 0, - JSMN_PRIMITIVE, "key2", - JSMN_PRIMITIVE, "123")); + int r; + jsmn_parser p; + jsmntok_t tok[10]; + const char *js; + + jsmn_init(&p); + js = "key1: \"value\"\nkey2 : 123"; + + r = jsmn_parse(&p, js, strlen(js), tok, 10); + check(r >= 0); + check(tokeq(js, tok, 4, JSMN_PRIMITIVE, "key1", JSMN_STRING, "value", 0, + JSMN_PRIMITIVE, "key2", JSMN_PRIMITIVE, "123")); #endif - return 0; + return 0; } int test_issue_22(void) { - int r; - jsmn_parser p; - jsmntok_t tokens[128]; - const char *js; - - js = "{ \"height\":10, \"layers\":[ { \"data\":[6,6], \"height\":10, " - "\"name\":\"Calque de Tile 1\", \"opacity\":1, \"type\":\"tilelayer\", " - "\"visible\":true, \"width\":10, \"x\":0, \"y\":0 }], " - "\"orientation\":\"orthogonal\", \"properties\": { }, \"tileheight\":32, " - "\"tilesets\":[ { \"firstgid\":1, \"image\":\"..\\/images\\/tiles.png\", " - "\"imageheight\":64, \"imagewidth\":160, \"margin\":0, \"name\":\"Tiles\", " - "\"properties\":{}, \"spacing\":0, \"tileheight\":32, \"tilewidth\":32 }], " - "\"tilewidth\":32, \"version\":1, \"width\":10 }"; - jsmn_init(&p); - r = jsmn_parse(&p, js, strlen(js), tokens, 128); - check(r >= 0); - return 0; + int r; + jsmn_parser p; + jsmntok_t tokens[128]; + const char *js; + + js = + "{ \"height\":10, \"layers\":[ { \"data\":[6,6], \"height\":10, " + "\"name\":\"Calque de Tile 1\", \"opacity\":1, \"type\":\"tilelayer\", " + "\"visible\":true, \"width\":10, \"x\":0, \"y\":0 }], " + "\"orientation\":\"orthogonal\", \"properties\": { }, \"tileheight\":32, " + "\"tilesets\":[ { \"firstgid\":1, \"image\":\"..\\/images\\/tiles.png\", " + "\"imageheight\":64, \"imagewidth\":160, \"margin\":0, " + "\"name\":\"Tiles\", " + "\"properties\":{}, \"spacing\":0, \"tileheight\":32, \"tilewidth\":32 " + "}], " + "\"tilewidth\":32, \"version\":1, \"width\":10 }"; + jsmn_init(&p); + r = jsmn_parse(&p, js, strlen(js), tokens, 128); + check(r >= 0); + return 0; } int test_issue_27(void) { - const char *js = - "{ \"name\" : \"Jack\", \"age\" : 27 } { \"name\" : \"Anna\", "; - check(parse(js, JSMN_ERROR_PART, 8)); - return 0; + const char *js = + "{ \"name\" : \"Jack\", \"age\" : 27 } { \"name\" : \"Anna\", "; + check(parse(js, JSMN_ERROR_PART, 8)); + return 0; } int test_input_length(void) { - const char *js; - int r; - jsmn_parser p; - jsmntok_t tokens[10]; - - js = "{\"a\": 0}garbage"; - - jsmn_init(&p); - r = jsmn_parse(&p, js, 8, tokens, 10); - check(r == 3); - check(tokeq(js, tokens, 3, - JSMN_OBJECT, -1, -1, 1, - JSMN_STRING, "a", 1, - JSMN_PRIMITIVE, "0")); - return 0; + const char *js; + int r; + jsmn_parser p; + jsmntok_t tokens[10]; + + js = "{\"a\": 0}garbage"; + + jsmn_init(&p); + r = jsmn_parse(&p, js, 8, tokens, 10); + check(r == 3); + check(tokeq(js, tokens, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING, "a", 1, + JSMN_PRIMITIVE, "0")); + return 0; } int test_count(void) { - jsmn_parser p; - const char *js; + jsmn_parser p; + const char *js; - js = "{}"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1); + js = "{}"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1); - js = "[]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1); + js = "[]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1); - js = "[[]]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 2); + js = "[[]]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 2); - js = "[[], []]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3); + js = "[[], []]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3); - js = "[[], []]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3); + js = "[[], []]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3); - js = "[[], [[]], [[], []]]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7); + js = "[[], [[]], [[], []]]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7); - js = "[\"a\", [[], []]]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5); + js = "[\"a\", [[], []]]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5); - js = "[[], \"[], [[]]\", [[]]]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5); + js = "[[], \"[], [[]]\", [[]]]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5); - js = "[1, 2, 3]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 4); + js = "[1, 2, 3]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 4); - js = "[1, 2, [3, \"a\"], null]"; - jsmn_init(&p); - check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7); + js = "[1, 2, [3, \"a\"], null]"; + jsmn_init(&p); + check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7); - return 0; + return 0; } - int test_nonstrict(void) { #ifndef JSMN_STRICT - const char *js; - js = "a: 0garbage"; - check(parse(js, 2, 2, - JSMN_PRIMITIVE, "a", - JSMN_PRIMITIVE, "0garbage")); - - js = "Day : 26\nMonth : Sep\n\nYear: 12"; - check(parse(js, 6, 6, - JSMN_PRIMITIVE, "Day", - JSMN_PRIMITIVE, "26", - JSMN_PRIMITIVE, "Month", - JSMN_PRIMITIVE, "Sep", - JSMN_PRIMITIVE, "Year", - JSMN_PRIMITIVE, "12")); - - //nested {s don't cause a parse error. - js = "\"key {1\": 1234"; - check(parse(js, 2, 2, - JSMN_STRING, "key {1", 1, - JSMN_PRIMITIVE, "1234")); + const char *js; + js = "a: 0garbage"; + check(parse(js, 2, 2, JSMN_PRIMITIVE, "a", JSMN_PRIMITIVE, "0garbage")); + + js = "Day : 26\nMonth : Sep\n\nYear: 12"; + check(parse(js, 6, 6, JSMN_PRIMITIVE, "Day", JSMN_PRIMITIVE, "26", + JSMN_PRIMITIVE, "Month", JSMN_PRIMITIVE, "Sep", JSMN_PRIMITIVE, + "Year", JSMN_PRIMITIVE, "12")); + // nested {s don't cause a parse error. + js = "\"key {1\": 1234"; + check(parse(js, 2, 2, JSMN_STRING, "key {1", 1, JSMN_PRIMITIVE, "1234")); #endif - return 0; + return 0; } int test_unmatched_brackets(void) { - const char *js; - js = "\"key 1\": 1234}"; - check(parse(js, JSMN_ERROR_INVAL, 2)); - js = "{\"key 1\": 1234"; - check(parse(js, JSMN_ERROR_PART, 3)); - js = "{\"key 1\": 1234}}"; - check(parse(js, JSMN_ERROR_INVAL, 3)); - js = "\"key 1\"}: 1234"; - check(parse(js, JSMN_ERROR_INVAL, 3)); - js = "{\"key {1\": 1234}"; - check(parse(js, 3, 3, - JSMN_OBJECT, 0, 16, 1, - JSMN_STRING, "key {1", 1, - JSMN_PRIMITIVE, "1234")); - js = "{{\"key 1\": 1234}"; - check(parse(js, JSMN_ERROR_PART, 4)); - return 0; + const char *js; + js = "\"key 1\": 1234}"; + check(parse(js, JSMN_ERROR_INVAL, 2)); + js = "{\"key 1\": 1234"; + check(parse(js, JSMN_ERROR_PART, 3)); + js = "{\"key 1\": 1234}}"; + check(parse(js, JSMN_ERROR_INVAL, 3)); + js = "\"key 1\"}: 1234"; + check(parse(js, JSMN_ERROR_INVAL, 3)); + js = "{\"key {1\": 1234}"; + check(parse(js, 3, 3, JSMN_OBJECT, 0, 16, 1, JSMN_STRING, "key {1", 1, + JSMN_PRIMITIVE, "1234")); + js = "{{\"key 1\": 1234}"; + check(parse(js, JSMN_ERROR_PART, 4)); + return 0; } int main(void) { - test(test_empty, "test for a empty JSON objects/arrays"); - test(test_object, "test for a JSON objects"); - test(test_array, "test for a JSON arrays"); - test(test_primitive, "test primitive JSON data types"); - test(test_string, "test string JSON data types"); - - test(test_partial_string, "test partial JSON string parsing"); - test(test_partial_array, "test partial array reading"); - test(test_array_nomem, "test array reading with a smaller number of tokens"); - test(test_unquoted_keys, "test unquoted keys (like in JavaScript)"); - test(test_input_length, "test strings that are not null-terminated"); - test(test_issue_22, "test issue #22"); - test(test_issue_27, "test issue #27"); - test(test_count, "test tokens count estimation"); - test(test_nonstrict, "test for non-strict mode"); - test(test_unmatched_brackets, "test for unmatched brackets"); - printf("\nPASSED: %d\nFAILED: %d\n", test_passed, test_failed); - return (test_failed > 0); + test(test_empty, "test for a empty JSON objects/arrays"); + test(test_object, "test for a JSON objects"); + test(test_array, "test for a JSON arrays"); + test(test_primitive, "test primitive JSON data types"); + test(test_string, "test string JSON data types"); + + test(test_partial_string, "test partial JSON string parsing"); + test(test_partial_array, "test partial array reading"); + test(test_array_nomem, "test array reading with a smaller number of tokens"); + test(test_unquoted_keys, "test unquoted keys (like in JavaScript)"); + test(test_input_length, "test strings that are not null-terminated"); + test(test_issue_22, "test issue #22"); + test(test_issue_27, "test issue #27"); + test(test_count, "test tokens count estimation"); + test(test_nonstrict, "test for non-strict mode"); + test(test_unmatched_brackets, "test for unmatched brackets"); + printf("\nPASSED: %d\nFAILED: %d\n", test_passed, test_failed); + return (test_failed > 0); } diff --git a/test/testutil.h b/test/testutil.h index 9a1eb2d..6b20e3c 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -4,91 +4,91 @@ #include "../jsmn.c" static int vtokeq(const char *s, jsmntok_t *t, int numtok, va_list ap) { - if (numtok > 0) { - int i, start, end, size; - int type; - char *value; + if (numtok > 0) { + int i, start, end, size; + int type; + char *value; - size = -1; - value = NULL; - for (i = 0; i < numtok; i++) { - type = va_arg(ap, int); - if (type == JSMN_STRING) { - value = va_arg(ap, char *); - size = va_arg(ap, int); - start = end = -1; - } else if (type == JSMN_PRIMITIVE) { - value = va_arg(ap, char *); - start = end = size = -1; - } else { - start = va_arg(ap, int); - end = va_arg(ap, int); - size = va_arg(ap, int); - value = NULL; - } - if (t[i].type != type) { - printf("token %d type is %d, not %d\n", i, t[i].type, type); - return 0; - } - if (start != -1 && end != -1) { - if (t[i].start != start) { - printf("token %d start is %d, not %d\n", i, t[i].start, start); - return 0; - } - if (t[i].end != end ) { - printf("token %d end is %d, not %d\n", i, t[i].end, end); - return 0; - } - } - if (size != -1 && t[i].size != size) { - printf("token %d size is %d, not %d\n", i, t[i].size, size); - return 0; - } + size = -1; + value = NULL; + for (i = 0; i < numtok; i++) { + type = va_arg(ap, int); + if (type == JSMN_STRING) { + value = va_arg(ap, char *); + size = va_arg(ap, int); + start = end = -1; + } else if (type == JSMN_PRIMITIVE) { + value = va_arg(ap, char *); + start = end = size = -1; + } else { + start = va_arg(ap, int); + end = va_arg(ap, int); + size = va_arg(ap, int); + value = NULL; + } + if (t[i].type != type) { + printf("token %d type is %d, not %d\n", i, t[i].type, type); + return 0; + } + if (start != -1 && end != -1) { + if (t[i].start != start) { + printf("token %d start is %d, not %d\n", i, t[i].start, start); + return 0; + } + if (t[i].end != end) { + printf("token %d end is %d, not %d\n", i, t[i].end, end); + return 0; + } + } + if (size != -1 && t[i].size != size) { + printf("token %d size is %d, not %d\n", i, t[i].size, size); + return 0; + } - if (s != NULL && value != NULL) { - const char *p = s + t[i].start; - if (strlen(value) != t[i].end - t[i].start || - strncmp(p, value, t[i].end - t[i].start) != 0) { - printf("token %d value is %.*s, not %s\n", i, t[i].end-t[i].start, - s+t[i].start, value); - return 0; - } - } - } - } - return 1; + if (s != NULL && value != NULL) { + const char *p = s + t[i].start; + if (strlen(value) != t[i].end - t[i].start || + strncmp(p, value, t[i].end - t[i].start) != 0) { + printf("token %d value is %.*s, not %s\n", i, t[i].end - t[i].start, + s + t[i].start, value); + return 0; + } + } + } + } + return 1; } static int tokeq(const char *s, jsmntok_t *tokens, int numtok, ...) { - int ok; - va_list args; - va_start(args, numtok); - ok = vtokeq(s, tokens, numtok, args); - va_end(args); - return ok; + int ok; + va_list args; + va_start(args, numtok); + ok = vtokeq(s, tokens, numtok, args); + va_end(args); + return ok; } static int parse(const char *s, int status, int numtok, ...) { - int r; - int ok = 1; - va_list args; - jsmn_parser p; - jsmntok_t *t = malloc(numtok * sizeof(jsmntok_t)); + int r; + int ok = 1; + va_list args; + jsmn_parser p; + jsmntok_t *t = malloc(numtok * sizeof(jsmntok_t)); - jsmn_init(&p); - r = jsmn_parse(&p, s, strlen(s), t, numtok); - if (r != status) { - printf("status is %d, not %d\n", r, status); - return 0; - } + jsmn_init(&p); + r = jsmn_parse(&p, s, strlen(s), t, numtok); + if (r != status) { + printf("status is %d, not %d\n", r, status); + return 0; + } - if (status >= 0) { - va_start(args, numtok); - ok = vtokeq(s, t, numtok, args); - va_end(args); - } - free(t); - return ok; + if (status >= 0) { + va_start(args, numtok); + ok = vtokeq(s, t, numtok, args); + va_end(args); + } + free(t); + return ok; } #endif /* __TEST_UTIL_H__ */