diff --git a/Makefile b/Makefile index dcbdd89d..81004afe 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ simple_example: example/simple.c jsmn.h jsondump: example/jsondump.c jsmn.h $(CC) $(LDFLAGS) $< -o $@ +tokendump: example/tokendump.c jsmn.h + $(CC) $(LDFLAGS) $< -o $@ + fmt: clang-format -i jsmn.h test/*.[ch] example/*.[ch] @@ -31,6 +34,7 @@ clean: rm -f *.o example/*.o rm -f simple_example rm -f jsondump + rm -f tokendump .PHONY: clean test diff --git a/example/tokendump.c b/example/tokendump.c new file mode 100644 index 00000000..1ad3e9f5 --- /dev/null +++ b/example/tokendump.c @@ -0,0 +1,77 @@ +//#define JSMN_TOKNEXT + +#include "../jsmn.h" + +#include +#include +#include + +void dump(char *js, jsmntok_t* tokens, int tokenCount) { + puts("index type[size] start-end toknext value"); + puts("-------------------------------------------"); + for (int ti = 0; ti < tokenCount; ti++) { + jsmntok_t t = tokens[ti]; + char *type; + switch (t.type) { + case JSMN_ARRAY: + type = "ARRAY"; + break; + case JSMN_OBJECT: + type = "OBJECT"; + break; + case JSMN_PRIMITIVE: + type = "PRIMITIVE"; + break; + case JSMN_STRING: + type = "STRING"; + break; + } + printf("%3d: %9s[%03d]: %4d-%4d: %4d", ti, type, t.size, t.start, t.end, + jsmn_next_token(tokens, tokenCount, ti)); + switch (t.type) { + case JSMN_PRIMITIVE: + case JSMN_STRING: + printf(": "); + for (int i = t.start; i < t.end;) + putchar(js[i++]); + } + putchar('\n'); + } +} + +void help() { + puts("tokendump "); + exit(1); +} + +int main(int argc, char *args[]) { + if (argc != 2) + help(); + FILE *f = fopen(args[1], "r"); + if (f == NULL) + help(); + + // load file to memory + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + char *js = malloc(size + 1); + for (int i = 0; i < size;) + js[i++] = fgetc(f); + js[size] = 0; + fclose(f); + + // count tokens first + jsmn_parser parser; + jsmn_init(&parser); + int len = strlen(js); + int tokenCount = jsmn_parse(&parser, js, len, NULL, -1); + if (tokenCount > 0) { + // parse them + jsmntok_t *tokens = malloc(tokenCount * sizeof(jsmntok_t)); + jsmn_init(&parser); + jsmn_parse(&parser, (const char *)js, len, tokens, tokenCount); + // and dump finally + dump(js, tokens, tokenCount); + } +} diff --git a/jsmn.h b/jsmn.h index 8ac14c1b..5bdec6b0 100644 --- a/jsmn.h +++ b/jsmn.h @@ -74,6 +74,9 @@ typedef struct jsmntok { #ifdef JSMN_PARENT_LINKS int parent; #endif +#ifdef JSMN_TOKNEXT + int toknext; +#endif } jsmntok_t; /** @@ -114,6 +117,9 @@ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, tok->size = 0; #ifdef JSMN_PARENT_LINKS tok->parent = -1; +#endif +#ifdef JSMN_TOKNEXT + tok->toknext = -1; #endif return tok; } @@ -342,7 +348,10 @@ JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, } parser->toksuper = -1; token->end = parser->pos + 1; - break; +#ifdef JSMN_TOKNEXT + token->toknext = parser->toknext; +#endif + break; } } /* Error if unmatched closing bracket */ @@ -462,6 +471,23 @@ JSMN_API void jsmn_init(jsmn_parser *parser) { parser->toksuper = -1; } +/** + * Find next token on the same level of JSON structure. + */ +JSMN_API int jsmn_next_token(jsmntok_t *tokens, const size_t num_tokens, int i) { +#ifdef JSMN_TOKNEXT + int toknext = tokens[i].toknext; + if (toknext > 0) + return toknext; +#endif + int end = tokens[i++].end; + for (; i < num_tokens; i++) { + if (tokens[i].start > end) + break; + } + return i; +} + #endif /* JSMN_HEADER */ #ifdef __cplusplus