1 #include "../jsmn.h"
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 
8 /* Function realloc_it() is a wrapper function for standard realloc()
9  * with one difference - it frees old memory pointer in case of realloc
10  * failure. Thus, DO NOT use old data pointer in anyway after call to
11  * realloc_it(). If your code has some kind of fallback algorithm if
12  * memory can't be re-allocated - use standard realloc() instead.
13  */
realloc_it(void * ptrmem,size_t size)14 static inline void *realloc_it(void *ptrmem, size_t size) {
15   void *p = realloc(ptrmem, size);
16   if (!p) {
17     free(ptrmem);
18     fprintf(stderr, "realloc(): errno=%d\n", errno);
19   }
20   return p;
21 }
22 
23 /*
24  * An example of reading JSON from stdin and printing its content to stdout.
25  * The output looks like YAML, but I'm not sure if it's really compatible.
26  */
27 
dump(const char * js,jsmntok_t * t,size_t count,int indent)28 static int dump(const char *js, jsmntok_t *t, size_t count, int indent) {
29   int i, j, k;
30   jsmntok_t *key;
31   if (count == 0) {
32     return 0;
33   }
34   if (t->type == JSMN_PRIMITIVE) {
35     printf("%.*s", t->end - t->start, js + t->start);
36     return 1;
37   } else if (t->type == JSMN_STRING) {
38     printf("'%.*s'", t->end - t->start, js + t->start);
39     return 1;
40   } else if (t->type == JSMN_OBJECT) {
41     printf("\n");
42     j = 0;
43     for (i = 0; i < t->size; i++) {
44       for (k = 0; k < indent; k++) {
45         printf("  ");
46       }
47       key = t + 1 + j;
48       j += dump(js, key, count - j, indent + 1);
49       if (key->size > 0) {
50         printf(": ");
51         j += dump(js, t + 1 + j, count - j, indent + 1);
52       }
53       printf("\n");
54     }
55     return j + 1;
56   } else if (t->type == JSMN_ARRAY) {
57     j = 0;
58     printf("\n");
59     for (i = 0; i < t->size; i++) {
60       for (k = 0; k < indent - 1; k++) {
61         printf("  ");
62       }
63       printf("   - ");
64       j += dump(js, t + 1 + j, count - j, indent + 1);
65       printf("\n");
66     }
67     return j + 1;
68   }
69   return 0;
70 }
71 
main()72 int main() {
73   int r;
74   int eof_expected = 0;
75   char *js = NULL;
76   size_t jslen = 0;
77   char buf[BUFSIZ];
78 
79   jsmn_parser p;
80   jsmntok_t *tok;
81   size_t tokcount = 2;
82 
83   /* Prepare parser */
84   jsmn_init(&p);
85 
86   /* Allocate some tokens as a start */
87   tok = malloc(sizeof(*tok) * tokcount);
88   if (tok == NULL) {
89     fprintf(stderr, "malloc(): errno=%d\n", errno);
90     return 3;
91   }
92 
93   for (;;) {
94     /* Read another chunk */
95     r = fread(buf, 1, sizeof(buf), stdin);
96     if (r < 0) {
97       fprintf(stderr, "fread(): %d, errno=%d\n", r, errno);
98       return 1;
99     }
100     if (r == 0) {
101       if (eof_expected != 0) {
102         return 0;
103       } else {
104         fprintf(stderr, "fread(): unexpected EOF\n");
105         return 2;
106       }
107     }
108 
109     js = realloc_it(js, jslen + r + 1);
110     if (js == NULL) {
111       return 3;
112     }
113     strncpy(js + jslen, buf, r);
114     jslen = jslen + r;
115 
116   again:
117     r = jsmn_parse(&p, js, jslen, tok, tokcount);
118     if (r < 0) {
119       if (r == JSMN_ERROR_NOMEM) {
120         tokcount = tokcount * 2;
121         tok = realloc_it(tok, sizeof(*tok) * tokcount);
122         if (tok == NULL) {
123           return 3;
124         }
125         goto again;
126       }
127     } else {
128       dump(js, tok, p.toknext, 0);
129       eof_expected = 1;
130     }
131   }
132 
133   return EXIT_SUCCESS;
134 }
135