#include "../jsmn.h" #include #include #include #include #include /* Function realloc_it() is a wrapper function for standard realloc() * with one difference - it frees old memory pointer in case of realloc * failure. Thus, DO NOT use old data pointer in anyway after call to * realloc_it(). If your code has some kind of fallback algorithm if * 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; } /* * An example of reading JSON from stdin and printing its content to stdout. * The output looks like YAML, but I'm not sure if it's really compatible. */ static int dump(const char *js, jsmntok_t *t, size_t count, int indent) { int i, j, k; jsmntok_t *key; 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(" "); } key = t + 1 + j; j += dump(js, key, count - j, indent + 1); if (key->size > 0) { 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]; jsmn_parser p; jsmntok_t *tok; size_t tokcount = 2; /* 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; } 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; 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; }