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