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