1 /*
2   Copyright (c) 2009 Dave Gamble
3   Copyright (c) 2015-2016 The Khronos Group Inc.
4   Copyright (c) 2015-2016 Valve Corporation
5   Copyright (c) 2015-2016 LunarG, Inc.
6 
7   Permission is hereby granted, free of charge, to any person obtaining a copy
8   of this software and associated documentation files (the "Software"), to deal
9   in the Software without restriction, including without limitation the rights
10   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11   copies of the Software, and to permit persons to whom the Software is
12   furnished to do so, subject to the following conditions:
13 
14   The above copyright notice and this permission notice shall be included in
15   all copies or substantial portions of the Software.
16 
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23   THE SOFTWARE.
24 */
25 
26 /* cJSON */
27 /* JSON parser in C. */
28 
29 #include <string.h>
30 #include <stdio.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <float.h>
34 #include <limits.h>
35 #include <ctype.h>
36 #include "cJSON.h"
37 
38 static const char *ep;
39 
cJSON_GetErrorPtr(void)40 const char *cJSON_GetErrorPtr(void) { return ep; }
41 
42 static void *(*cJSON_malloc)(size_t sz) = malloc;
43 static void (*cJSON_free)(void *ptr) = free;
44 
cJSON_strdup(const char * str)45 static char *cJSON_strdup(const char *str) {
46     size_t len;
47     char *copy;
48 
49     len = strlen(str) + 1;
50     if (!(copy = (char *)cJSON_malloc(len)))
51         return 0;
52     memcpy(copy, str, len);
53     return copy;
54 }
55 
cJSON_InitHooks(cJSON_Hooks * hooks)56 void cJSON_InitHooks(cJSON_Hooks *hooks) {
57     if (!hooks) { /* Reset hooks */
58         cJSON_malloc = malloc;
59         cJSON_free = free;
60         return;
61     }
62 
63     cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
64     cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
65 }
66 
67 /* Internal constructor. */
cJSON_New_Item(void)68 static cJSON *cJSON_New_Item(void) {
69     cJSON *node = (cJSON *)cJSON_malloc(sizeof(cJSON));
70     if (node)
71         memset(node, 0, sizeof(cJSON));
72     return node;
73 }
74 
75 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * c)76 void cJSON_Delete(cJSON *c) {
77     cJSON *next;
78     while (c) {
79         next = c->next;
80         if (!(c->type & cJSON_IsReference) && c->child)
81             cJSON_Delete(c->child);
82         if (!(c->type & cJSON_IsReference) && c->valuestring)
83             cJSON_free(c->valuestring);
84         if (!(c->type & cJSON_StringIsConst) && c->string)
85             cJSON_free(c->string);
86         cJSON_free(c);
87         c = next;
88     }
89 }
90 
91 /* Parse the input text to generate a number, and populate the result into item.
92  */
parse_number(cJSON * item,const char * num)93 static const char *parse_number(cJSON *item, const char *num) {
94     double n = 0, sign = 1, scale = 0;
95     int subscale = 0, signsubscale = 1;
96 
97     if (*num == '-')
98         sign = -1, num++; /* Has sign? */
99     if (*num == '0')
100         num++; /* is zero */
101     if (*num >= '1' && *num <= '9')
102         do
103             n = (n * 10.0) + (*num++ - '0');
104         while (*num >= '0' && *num <= '9'); /* Number? */
105     if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
106         num++;
107         do
108             n = (n * 10.0) + (*num++ - '0'), scale--;
109         while (*num >= '0' && *num <= '9');
110     }                               /* Fractional part? */
111     if (*num == 'e' || *num == 'E') /* Exponent? */
112     {
113         num++;
114         if (*num == '+')
115             num++;
116         else if (*num == '-')
117             signsubscale = -1, num++; /* With sign? */
118         while (*num >= '0' && *num <= '9')
119             subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
120     }
121 
122     n = sign * n *
123         pow(10.0, (scale + subscale * signsubscale)); /* number = +/-
124                                                          number.fraction *
125                                                          10^+/- exponent */
126 
127     item->valuedouble = n;
128     item->valueint = (int)n;
129     item->type = cJSON_Number;
130     return num;
131 }
132 
pow2gt(size_t x)133 static size_t pow2gt(size_t x) {
134     --x;
135     x |= x >> 1;
136     x |= x >> 2;
137     x |= x >> 4;
138     x |= x >> 8;
139     x |= x >> 16;
140     return x + 1;
141 }
142 
143 typedef struct {
144     char *buffer;
145     size_t length;
146     size_t offset;
147 } printbuffer;
148 
ensure(printbuffer * p,size_t needed)149 static char *ensure(printbuffer *p, size_t needed) {
150     char *newbuffer;
151     size_t newsize;
152     if (!p || !p->buffer)
153         return 0;
154     needed += p->offset;
155     if (needed <= p->length)
156         return p->buffer + p->offset;
157 
158     newsize = pow2gt(needed);
159     newbuffer = (char *)cJSON_malloc(newsize);
160     if (!newbuffer) {
161         cJSON_free(p->buffer);
162         p->length = 0, p->buffer = 0;
163         return 0;
164     }
165     if (newbuffer)
166         memcpy(newbuffer, p->buffer, p->length);
167     cJSON_free(p->buffer);
168     p->length = newsize;
169     p->buffer = newbuffer;
170     return newbuffer + p->offset;
171 }
172 
update(printbuffer * p)173 static size_t update(printbuffer *p) {
174     char *str;
175     if (!p || !p->buffer)
176         return 0;
177     str = p->buffer + p->offset;
178     return p->offset + strlen(str);
179 }
180 
181 /* Render the number nicely from the given item into a string. */
print_number(cJSON * item,printbuffer * p)182 static char *print_number(cJSON *item, printbuffer *p) {
183     char *str = 0;
184     double d = item->valuedouble;
185     if (d == 0) {
186         if (p)
187             str = ensure(p, 2);
188         else
189             str = (char *)cJSON_malloc(2); /* special case for 0. */
190         if (str)
191             strcpy(str, "0");
192     } else if (fabs(((double)item->valueint) - d) <= DBL_EPSILON &&
193                d <= INT_MAX && d >= INT_MIN) {
194         if (p)
195             str = ensure(p, 21);
196         else
197             str = (char *)cJSON_malloc(
198                 21); /* 2^64+1 can be represented in 21 chars. */
199         if (str)
200             sprintf(str, "%d", item->valueint);
201     } else {
202         if (p)
203             str = ensure(p, 64);
204         else
205             str = (char *)cJSON_malloc(64); /* This is a nice tradeoff. */
206         if (str) {
207             if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)
208                 sprintf(str, "%.0f", d);
209             else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
210                 sprintf(str, "%e", d);
211             else
212                 sprintf(str, "%f", d);
213         }
214     }
215     return str;
216 }
217 
parse_hex4(const char * str)218 static unsigned parse_hex4(const char *str) {
219     unsigned h = 0;
220     if (*str >= '0' && *str <= '9')
221         h += (*str) - '0';
222     else if (*str >= 'A' && *str <= 'F')
223         h += 10 + (*str) - 'A';
224     else if (*str >= 'a' && *str <= 'f')
225         h += 10 + (*str) - 'a';
226     else
227         return 0;
228     h = h << 4;
229     str++;
230     if (*str >= '0' && *str <= '9')
231         h += (*str) - '0';
232     else if (*str >= 'A' && *str <= 'F')
233         h += 10 + (*str) - 'A';
234     else if (*str >= 'a' && *str <= 'f')
235         h += 10 + (*str) - 'a';
236     else
237         return 0;
238     h = h << 4;
239     str++;
240     if (*str >= '0' && *str <= '9')
241         h += (*str) - '0';
242     else if (*str >= 'A' && *str <= 'F')
243         h += 10 + (*str) - 'A';
244     else if (*str >= 'a' && *str <= 'f')
245         h += 10 + (*str) - 'a';
246     else
247         return 0;
248     h = h << 4;
249     str++;
250     if (*str >= '0' && *str <= '9')
251         h += (*str) - '0';
252     else if (*str >= 'A' && *str <= 'F')
253         h += 10 + (*str) - 'A';
254     else if (*str >= 'a' && *str <= 'f')
255         h += 10 + (*str) - 'a';
256     else
257         return 0;
258     return h;
259 }
260 
261 /* Parse the input text into an unescaped cstring, and populate item. */
262 static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0,
263                                                0xF0, 0xF8, 0xFC};
parse_string(cJSON * item,const char * str)264 static const char *parse_string(cJSON *item, const char *str) {
265     const char *ptr = str + 1;
266     char *ptr2;
267     char *out;
268     int len = 0;
269     unsigned uc, uc2;
270     if (*str != '\"') {
271         ep = str;
272         return 0;
273     } /* not a string! */
274 
275     while (*ptr != '\"' && *ptr && ++len)
276         if (*ptr++ == '\\')
277             ptr++; /* Skip escaped quotes. */
278 
279     out = (char *)cJSON_malloc(
280         len + 1); /* This is how long we need for the string, roughly. */
281     if (!out)
282         return 0;
283 
284     ptr = str + 1;
285     ptr2 = out;
286     while (*ptr != '\"' && *ptr) {
287         if (*ptr != '\\')
288             *ptr2++ = *ptr++;
289         else {
290             ptr++;
291             switch (*ptr) {
292             case 'b':
293                 *ptr2++ = '\b';
294                 break;
295             case 'f':
296                 *ptr2++ = '\f';
297                 break;
298             case 'n':
299                 *ptr2++ = '\n';
300                 break;
301             case 'r':
302                 *ptr2++ = '\r';
303                 break;
304             case 't':
305                 *ptr2++ = '\t';
306                 break;
307             case 'u': /* transcode utf16 to utf8. */
308                 uc = parse_hex4(ptr + 1);
309                 ptr += 4; /* get the unicode char. */
310 
311                 if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)
312                     break; /* check for invalid.	*/
313 
314                 if (uc >= 0xD800 &&
315                     uc <= 0xDBFF) /* UTF16 surrogate pairs.	*/
316                 {
317                     if (ptr[1] != '\\' || ptr[2] != 'u')
318                         break; /* missing second-half of surrogate.	*/
319                     uc2 = parse_hex4(ptr + 3);
320                     ptr += 6;
321                     if (uc2 < 0xDC00 || uc2 > 0xDFFF)
322                         break; /* invalid second-half of surrogate.	*/
323                     uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
324                 }
325 
326                 len = 4;
327                 if (uc < 0x80)
328                     len = 1;
329                 else if (uc < 0x800)
330                     len = 2;
331                 else if (uc < 0x10000)
332                     len = 3;
333                 ptr2 += len;
334 
335                 switch (len) {
336                 case 4:
337                     *--ptr2 = ((uc | 0x80) & 0xBF);
338                     uc >>= 6;
339                 case 3:
340                     *--ptr2 = ((uc | 0x80) & 0xBF);
341                     uc >>= 6;
342                 case 2:
343                     *--ptr2 = ((uc | 0x80) & 0xBF);
344                     uc >>= 6;
345                 case 1:
346                     *--ptr2 = ((unsigned char)uc | firstByteMark[len]);
347                 }
348                 ptr2 += len;
349                 break;
350             default:
351                 *ptr2++ = *ptr;
352                 break;
353             }
354             ptr++;
355         }
356     }
357     *ptr2 = 0;
358     if (*ptr == '\"')
359         ptr++;
360     item->valuestring = out;
361     item->type = cJSON_String;
362     return ptr;
363 }
364 
365 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const char * str,printbuffer * p)366 static char *print_string_ptr(const char *str, printbuffer *p) {
367     const char *ptr;
368     char *ptr2;
369     char *out;
370     size_t len = 0, flag = 0;
371     unsigned char token;
372 
373     for (ptr = str; *ptr; ptr++)
374         flag |= ((*ptr > 0 && *ptr < 32) || (*ptr == '\"') || (*ptr == '\\'))
375                     ? 1
376                     : 0;
377     if (!flag) {
378         len = ptr - str;
379         if (p)
380             out = ensure(p, len + 3);
381         else
382             out = (char *)cJSON_malloc(len + 3);
383         if (!out)
384             return 0;
385         ptr2 = out;
386         *ptr2++ = '\"';
387         strcpy(ptr2, str);
388         ptr2[len] = '\"';
389         ptr2[len + 1] = 0;
390         return out;
391     }
392 
393     if (!str) {
394         if (p)
395             out = ensure(p, 3);
396         else
397             out = (char *)cJSON_malloc(3);
398         if (!out)
399             return 0;
400         strcpy(out, "\"\"");
401         return out;
402     }
403     ptr = str;
404     while ((token = *ptr) && ++len) {
405         if (strchr("\"\\\b\f\n\r\t", token))
406             len++;
407         else if (token < 32)
408             len += 5;
409         ptr++;
410     }
411 
412     if (p)
413         out = ensure(p, len + 3);
414     else
415         out = (char *)cJSON_malloc(len + 3);
416     if (!out)
417         return 0;
418 
419     ptr2 = out;
420     ptr = str;
421     *ptr2++ = '\"';
422     while (*ptr) {
423         if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
424             *ptr2++ = *ptr++;
425         else {
426             *ptr2++ = '\\';
427             switch (token = *ptr++) {
428             case '\\':
429                 *ptr2++ = '\\';
430                 break;
431             case '\"':
432                 *ptr2++ = '\"';
433                 break;
434             case '\b':
435                 *ptr2++ = 'b';
436                 break;
437             case '\f':
438                 *ptr2++ = 'f';
439                 break;
440             case '\n':
441                 *ptr2++ = 'n';
442                 break;
443             case '\r':
444                 *ptr2++ = 'r';
445                 break;
446             case '\t':
447                 *ptr2++ = 't';
448                 break;
449             default:
450                 sprintf(ptr2, "u%04x", token);
451                 ptr2 += 5;
452                 break; /* escape and print */
453             }
454         }
455     }
456     *ptr2++ = '\"';
457     *ptr2++ = 0;
458     return out;
459 }
460 /* Invote print_string_ptr (which is useful) on an item. */
print_string(cJSON * item,printbuffer * p)461 static char *print_string(cJSON *item, printbuffer *p) {
462     return print_string_ptr(item->valuestring, p);
463 }
464 
465 /* Predeclare these prototypes. */
466 static const char *parse_value(cJSON *item, const char *value);
467 static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p);
468 static const char *parse_array(cJSON *item, const char *value);
469 static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p);
470 static const char *parse_object(cJSON *item, const char *value);
471 static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p);
472 
473 /* Utility to jump whitespace and cr/lf */
skip(const char * in)474 static const char *skip(const char *in) {
475     while (in && *in && (unsigned char)*in <= 32)
476         in++;
477     return in;
478 }
479 
480 /* Parse an object - create a new root, and populate. */
cJSON_ParseWithOpts(const char * value,const char ** return_parse_end,int require_null_terminated)481 cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
482                            int require_null_terminated) {
483     const char *end = 0;
484     cJSON *c = cJSON_New_Item();
485     ep = 0;
486     if (!c)
487         return 0; /* memory fail */
488 
489     end = parse_value(c, skip(value));
490     if (!end) {
491         cJSON_Delete(c);
492         return 0;
493     } /* parse failure. ep is set. */
494 
495     /* if we require null-terminated JSON without appended garbage, skip and
496      * then check for a null terminator */
497     if (require_null_terminated) {
498         end = skip(end);
499         if (*end) {
500             cJSON_Delete(c);
501             ep = end;
502             return 0;
503         }
504     }
505     if (return_parse_end)
506         *return_parse_end = end;
507     return c;
508 }
509 /* Default options for cJSON_Parse */
cJSON_Parse(const char * value)510 cJSON *cJSON_Parse(const char *value) {
511     return cJSON_ParseWithOpts(value, 0, 0);
512 }
513 
514 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(cJSON * item)515 char *cJSON_Print(cJSON *item) { return print_value(item, 0, 1, 0); }
cJSON_PrintUnformatted(cJSON * item)516 char *cJSON_PrintUnformatted(cJSON *item) { return print_value(item, 0, 0, 0); }
517 
cJSON_PrintBuffered(cJSON * item,int prebuffer,int fmt)518 char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt) {
519     printbuffer p;
520     p.buffer = (char *)cJSON_malloc(prebuffer);
521     p.length = prebuffer;
522     p.offset = 0;
523     return print_value(item, 0, fmt, &p);
524 }
525 
526 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * item,const char * value)527 static const char *parse_value(cJSON *item, const char *value) {
528     if (!value)
529         return 0; /* Fail on null. */
530     if (!strncmp(value, "null", 4)) {
531         item->type = cJSON_NULL;
532         return value + 4;
533     }
534     if (!strncmp(value, "false", 5)) {
535         item->type = cJSON_False;
536         return value + 5;
537     }
538     if (!strncmp(value, "true", 4)) {
539         item->type = cJSON_True;
540         item->valueint = 1;
541         return value + 4;
542     }
543     if (*value == '\"') {
544         return parse_string(item, value);
545     }
546     if (*value == '-' || (*value >= '0' && *value <= '9')) {
547         return parse_number(item, value);
548     }
549     if (*value == '[') {
550         return parse_array(item, value);
551     }
552     if (*value == '{') {
553         return parse_object(item, value);
554     }
555 
556     ep = value;
557     return 0; /* failure. */
558 }
559 
560 /* Render a value to text. */
print_value(cJSON * item,int depth,int fmt,printbuffer * p)561 static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p) {
562     char *out = 0;
563     if (!item)
564         return 0;
565     if (p) {
566         switch ((item->type) & 255) {
567         case cJSON_NULL: {
568             out = ensure(p, 5);
569             if (out)
570                 strcpy(out, "null");
571             break;
572         }
573         case cJSON_False: {
574             out = ensure(p, 6);
575             if (out)
576                 strcpy(out, "false");
577             break;
578         }
579         case cJSON_True: {
580             out = ensure(p, 5);
581             if (out)
582                 strcpy(out, "true");
583             break;
584         }
585         case cJSON_Number:
586             out = print_number(item, p);
587             break;
588         case cJSON_String:
589             out = print_string(item, p);
590             break;
591         case cJSON_Array:
592             out = print_array(item, depth, fmt, p);
593             break;
594         case cJSON_Object:
595             out = print_object(item, depth, fmt, p);
596             break;
597         }
598     } else {
599         switch ((item->type) & 255) {
600         case cJSON_NULL:
601             out = cJSON_strdup("null");
602             break;
603         case cJSON_False:
604             out = cJSON_strdup("false");
605             break;
606         case cJSON_True:
607             out = cJSON_strdup("true");
608             break;
609         case cJSON_Number:
610             out = print_number(item, 0);
611             break;
612         case cJSON_String:
613             out = print_string(item, 0);
614             break;
615         case cJSON_Array:
616             out = print_array(item, depth, fmt, 0);
617             break;
618         case cJSON_Object:
619             out = print_object(item, depth, fmt, 0);
620             break;
621         }
622     }
623     return out;
624 }
625 
626 /* Build an array from input text. */
parse_array(cJSON * item,const char * value)627 static const char *parse_array(cJSON *item, const char *value) {
628     cJSON *child;
629     if (*value != '[') {
630         ep = value;
631         return 0;
632     } /* not an array! */
633 
634     item->type = cJSON_Array;
635     value = skip(value + 1);
636     if (*value == ']')
637         return value + 1; /* empty array. */
638 
639     item->child = child = cJSON_New_Item();
640     if (!item->child)
641         return 0; /* memory fail */
642     value = skip(
643         parse_value(child, skip(value))); /* skip any spacing, get the value. */
644     if (!value)
645         return 0;
646 
647     while (*value == ',') {
648         cJSON *new_item;
649         if (!(new_item = cJSON_New_Item()))
650             return 0; /* memory fail */
651         child->next = new_item;
652         new_item->prev = child;
653         child = new_item;
654         value = skip(parse_value(child, skip(value + 1)));
655         if (!value)
656             return 0; /* memory fail */
657     }
658 
659     if (*value == ']')
660         return value + 1; /* end of array */
661     ep = value;
662     return 0; /* malformed. */
663 }
664 
665 /* Render an array to text */
print_array(cJSON * item,int depth,int fmt,printbuffer * p)666 static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p) {
667     char **entries;
668     char *out = 0, *ptr, *ret;
669     size_t len = 5;
670     cJSON *child = item->child;
671     int numentries = 0, fail = 0, j = 0;
672     size_t tmplen = 0, i = 0;
673 
674     /* How many entries in the array? */
675     while (child)
676         numentries++, child = child->next;
677     /* Explicitly handle numentries==0 */
678     if (!numentries) {
679         if (p)
680             out = ensure(p, 3);
681         else
682             out = (char *)cJSON_malloc(3);
683         if (out)
684             strcpy(out, "[]");
685         return out;
686     }
687 
688     if (p) {
689         /* Compose the output array. */
690         i = p->offset;
691         ptr = ensure(p, 1);
692         if (!ptr)
693             return 0;
694         *ptr = '[';
695         p->offset++;
696         child = item->child;
697         while (child && !fail) {
698             print_value(child, depth + 1, fmt, p);
699             p->offset = update(p);
700             if (child->next) {
701                 len = fmt ? 2 : 1;
702                 ptr = ensure(p, len + 1);
703                 if (!ptr)
704                     return 0;
705                 *ptr++ = ',';
706                 if (fmt)
707                     *ptr++ = ' ';
708                 *ptr = 0;
709                 p->offset += len;
710             }
711             child = child->next;
712         }
713         ptr = ensure(p, 2);
714         if (!ptr)
715             return 0;
716         *ptr++ = ']';
717         *ptr = 0;
718         out = (p->buffer) + i;
719     } else {
720         /* Allocate an array to hold the values for each */
721         entries = (char **)cJSON_malloc(numentries * sizeof(char *));
722         if (!entries)
723             return 0;
724         memset(entries, 0, numentries * sizeof(char *));
725         /* Retrieve all the results: */
726         child = item->child;
727         while (child && !fail) {
728             ret = print_value(child, depth + 1, fmt, 0);
729             entries[i++] = ret;
730             if (ret)
731                 len += strlen(ret) + 2 + (fmt ? 1 : 0);
732             else
733                 fail = 1;
734             child = child->next;
735         }
736 
737         /* If we didn't fail, try to malloc the output string */
738         if (!fail)
739             out = (char *)cJSON_malloc(len);
740         /* If that fails, we fail. */
741         if (!out)
742             fail = 1;
743 
744         /* Handle failure. */
745         if (fail) {
746             for (j = 0; j < numentries; j++)
747                 if (entries[j])
748                     cJSON_free(entries[j]);
749             cJSON_free(entries);
750             return 0;
751         }
752 
753         /* Compose the output array. */
754         *out = '[';
755         ptr = out + 1;
756         *ptr = 0;
757         for (j = 0; j < numentries; j++) {
758             tmplen = strlen(entries[j]);
759             memcpy(ptr, entries[j], tmplen);
760             ptr += tmplen;
761             if (j != numentries - 1) {
762                 *ptr++ = ',';
763                 if (fmt)
764                     *ptr++ = ' ';
765                 *ptr = 0;
766             }
767             cJSON_free(entries[j]);
768         }
769         cJSON_free(entries);
770         *ptr++ = ']';
771         *ptr++ = 0;
772     }
773     return out;
774 }
775 
776 /* Build an object from the text. */
parse_object(cJSON * item,const char * value)777 static const char *parse_object(cJSON *item, const char *value) {
778     cJSON *child;
779     if (*value != '{') {
780         ep = value;
781         return 0;
782     } /* not an object! */
783 
784     item->type = cJSON_Object;
785     value = skip(value + 1);
786     if (*value == '}')
787         return value + 1; /* empty array. */
788 
789     item->child = child = cJSON_New_Item();
790     if (!item->child)
791         return 0;
792     value = skip(parse_string(child, skip(value)));
793     if (!value)
794         return 0;
795     child->string = child->valuestring;
796     child->valuestring = 0;
797     if (*value != ':') {
798         ep = value;
799         return 0;
800     } /* fail! */
801     value = skip(parse_value(
802         child, skip(value + 1))); /* skip any spacing, get the value. */
803     if (!value)
804         return 0;
805 
806     while (*value == ',') {
807         cJSON *new_item;
808         if (!(new_item = cJSON_New_Item()))
809             return 0; /* memory fail */
810         child->next = new_item;
811         new_item->prev = child;
812         child = new_item;
813         value = skip(parse_string(child, skip(value + 1)));
814         if (!value)
815             return 0;
816         child->string = child->valuestring;
817         child->valuestring = 0;
818         if (*value != ':') {
819             ep = value;
820             return 0;
821         } /* fail! */
822         value = skip(parse_value(
823             child, skip(value + 1))); /* skip any spacing, get the value. */
824         if (!value)
825             return 0;
826     }
827 
828     if (*value == '}')
829         return value + 1; /* end of array */
830     ep = value;
831     return 0; /* malformed. */
832 }
833 
834 /* Render an object to text. */
print_object(cJSON * item,int depth,int fmt,printbuffer * p)835 static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p) {
836     char **entries = 0, **names = 0;
837     char *out = 0, *ptr, *ret, *str;
838     int j;
839     cJSON *child = item->child;
840     int numentries = 0, fail = 0, k;
841     size_t tmplen = 0, i = 0, len = 7;
842     /* Count the number of entries. */
843     while (child)
844         numentries++, child = child->next;
845     /* Explicitly handle empty object case */
846     if (!numentries) {
847         if (p)
848             out = ensure(p, fmt ? depth + 4 : 3);
849         else
850             out = (char *)cJSON_malloc(fmt ? depth + 4 : 3);
851         if (!out)
852             return 0;
853         ptr = out;
854         *ptr++ = '{';
855         if (fmt) {
856             *ptr++ = '\n';
857             for (j = 0; j < depth - 1; j++)
858                 *ptr++ = '\t';
859         }
860         *ptr++ = '}';
861         *ptr++ = 0;
862         return out;
863     }
864     if (p) {
865         /* Compose the output: */
866         i = p->offset;
867         len = fmt ? 2 : 1;
868         ptr = ensure(p, len + 1);
869         if (!ptr)
870             return 0;
871         *ptr++ = '{';
872         if (fmt)
873             *ptr++ = '\n';
874         *ptr = 0;
875         p->offset += len;
876         child = item->child;
877         depth++;
878         while (child) {
879             if (fmt) {
880                 ptr = ensure(p, depth);
881                 if (!ptr)
882                     return 0;
883                 for (j = 0; j < depth; j++)
884                     *ptr++ = '\t';
885                 p->offset += depth;
886             }
887             print_string_ptr(child->string, p);
888             p->offset = update(p);
889 
890             len = fmt ? 2 : 1;
891             ptr = ensure(p, len);
892             if (!ptr)
893                 return 0;
894             *ptr++ = ':';
895             if (fmt)
896                 *ptr++ = '\t';
897             p->offset += len;
898 
899             print_value(child, depth, fmt, p);
900             p->offset = update(p);
901 
902             len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
903             ptr = ensure(p, len + 1);
904             if (!ptr)
905                 return 0;
906             if (child->next)
907                 *ptr++ = ',';
908             if (fmt)
909                 *ptr++ = '\n';
910             *ptr = 0;
911             p->offset += len;
912             child = child->next;
913         }
914         ptr = ensure(p, fmt ? (depth + 1) : 2);
915         if (!ptr)
916             return 0;
917         if (fmt)
918             for (j = 0; j < depth - 1; j++)
919                 *ptr++ = '\t';
920         *ptr++ = '}';
921         *ptr = 0;
922         out = (p->buffer) + i;
923     } else {
924         /* Allocate space for the names and the objects */
925         entries = (char **)cJSON_malloc(numentries * sizeof(char *));
926         if (!entries)
927             return 0;
928         names = (char **)cJSON_malloc(numentries * sizeof(char *));
929         if (!names) {
930             cJSON_free(entries);
931             return 0;
932         }
933         memset(entries, 0, sizeof(char *) * numentries);
934         memset(names, 0, sizeof(char *) * numentries);
935 
936         /* Collect all the results into our arrays: */
937         child = item->child;
938         depth++;
939         if (fmt)
940             len += depth;
941         while (child) {
942             names[i] = str = print_string_ptr(child->string, 0);
943             entries[i++] = ret = print_value(child, depth, fmt, 0);
944             if (str && ret)
945                 len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
946             else
947                 fail = 1;
948             child = child->next;
949         }
950 
951         /* Try to allocate the output string */
952         if (!fail)
953             out = (char *)cJSON_malloc(len);
954         if (!out)
955             fail = 1;
956 
957         /* Handle failure */
958         if (fail) {
959             for (j = 0; j < numentries; j++) {
960                 if (names[i])
961                     cJSON_free(names[j]);
962                 if (entries[j])
963                     cJSON_free(entries[j]);
964             }
965             cJSON_free(names);
966             cJSON_free(entries);
967             return 0;
968         }
969 
970         /* Compose the output: */
971         *out = '{';
972         ptr = out + 1;
973         if (fmt)
974             *ptr++ = '\n';
975         *ptr = 0;
976         for (j = 0; j < numentries; j++) {
977             if (fmt)
978                 for (k = 0; k < depth; k++)
979                     *ptr++ = '\t';
980             tmplen = strlen(names[j]);
981             memcpy(ptr, names[j], tmplen);
982             ptr += tmplen;
983             *ptr++ = ':';
984             if (fmt)
985                 *ptr++ = '\t';
986             strcpy(ptr, entries[j]);
987             ptr += strlen(entries[j]);
988             if (j != numentries - 1)
989                 *ptr++ = ',';
990             if (fmt)
991                 *ptr++ = '\n';
992             *ptr = 0;
993             cJSON_free(names[j]);
994             cJSON_free(entries[j]);
995         }
996 
997         cJSON_free(names);
998         cJSON_free(entries);
999         if (fmt)
1000             for (j = 0; j < depth - 1; j++)
1001                 *ptr++ = '\t';
1002         *ptr++ = '}';
1003         *ptr++ = 0;
1004     }
1005     return out;
1006 }
1007 
1008 /* Get Array size/item / object item. */
cJSON_GetArraySize(cJSON * array)1009 int cJSON_GetArraySize(cJSON *array) {
1010     cJSON *c = array->child;
1011     int i = 0;
1012     while (c)
1013         i++, c = c->next;
1014     return i;
1015 }
cJSON_GetArrayItem(cJSON * array,int item)1016 cJSON *cJSON_GetArrayItem(cJSON *array, int item) {
1017     cJSON *c = array->child;
1018     while (c && item > 0)
1019         item--, c = c->next;
1020     return c;
1021 }
cJSON_GetObjectItem(cJSON * object,const char * string)1022 cJSON *cJSON_GetObjectItem(cJSON *object, const char *string) {
1023     cJSON *c = object->child;
1024     while (c && strcmp(c->string, string))
1025         c = c->next;
1026     return c;
1027 }
1028 
1029 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)1030 static void suffix_object(cJSON *prev, cJSON *item) {
1031     prev->next = item;
1032     item->prev = prev;
1033 }
1034 /* Utility for handling references. */
create_reference(cJSON * item)1035 static cJSON *create_reference(cJSON *item) {
1036     cJSON *ref = cJSON_New_Item();
1037     if (!ref)
1038         return 0;
1039     memcpy(ref, item, sizeof(cJSON));
1040     ref->string = 0;
1041     ref->type |= cJSON_IsReference;
1042     ref->next = ref->prev = 0;
1043     return ref;
1044 }
1045 
1046 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)1047 void cJSON_AddItemToArray(cJSON *array, cJSON *item) {
1048     cJSON *c = array->child;
1049     if (!item)
1050         return;
1051     if (!c) {
1052         array->child = item;
1053     } else {
1054         while (c && c->next)
1055             c = c->next;
1056         suffix_object(c, item);
1057     }
1058 }
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)1059 void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) {
1060     if (!item)
1061         return;
1062     if (item->string)
1063         cJSON_free(item->string);
1064     item->string = cJSON_strdup(string);
1065     cJSON_AddItemToArray(object, item);
1066 }
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)1067 void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) {
1068     if (!item)
1069         return;
1070     if (!(item->type & cJSON_StringIsConst) && item->string)
1071         cJSON_free(item->string);
1072     item->string = (char *)string;
1073     item->type |= cJSON_StringIsConst;
1074     cJSON_AddItemToArray(object, item);
1075 }
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)1076 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {
1077     cJSON_AddItemToArray(array, create_reference(item));
1078 }
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)1079 void cJSON_AddItemReferenceToObject(cJSON *object, const char *string,
1080                                     cJSON *item) {
1081     cJSON_AddItemToObject(object, string, create_reference(item));
1082 }
1083 
cJSON_DetachItemFromArray(cJSON * array,int which)1084 cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) {
1085     cJSON *c = array->child;
1086     while (c && which > 0)
1087         c = c->next, which--;
1088     if (!c)
1089         return 0;
1090     if (c->prev)
1091         c->prev->next = c->next;
1092     if (c->next)
1093         c->next->prev = c->prev;
1094     if (c == array->child)
1095         array->child = c->next;
1096     c->prev = c->next = 0;
1097     return c;
1098 }
cJSON_DeleteItemFromArray(cJSON * array,int which)1099 void cJSON_DeleteItemFromArray(cJSON *array, int which) {
1100     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
1101 }
cJSON_DetachItemFromObject(cJSON * object,const char * string)1102 cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) {
1103     int i = 0;
1104     cJSON *c = object->child;
1105     while (c && strcmp(c->string, string))
1106         i++, c = c->next;
1107     if (c)
1108         return cJSON_DetachItemFromArray(object, i);
1109     return 0;
1110 }
cJSON_DeleteItemFromObject(cJSON * object,const char * string)1111 void cJSON_DeleteItemFromObject(cJSON *object, const char *string) {
1112     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
1113 }
1114 
1115 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)1116 void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) {
1117     cJSON *c = array->child;
1118     while (c && which > 0)
1119         c = c->next, which--;
1120     if (!c) {
1121         cJSON_AddItemToArray(array, newitem);
1122         return;
1123     }
1124     newitem->next = c;
1125     newitem->prev = c->prev;
1126     c->prev = newitem;
1127     if (c == array->child)
1128         array->child = newitem;
1129     else
1130         newitem->prev->next = newitem;
1131 }
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)1132 void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) {
1133     cJSON *c = array->child;
1134     while (c && which > 0)
1135         c = c->next, which--;
1136     if (!c)
1137         return;
1138     newitem->next = c->next;
1139     newitem->prev = c->prev;
1140     if (newitem->next)
1141         newitem->next->prev = newitem;
1142     if (c == array->child)
1143         array->child = newitem;
1144     else
1145         newitem->prev->next = newitem;
1146     c->next = c->prev = 0;
1147     cJSON_Delete(c);
1148 }
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)1149 void cJSON_ReplaceItemInObject(cJSON *object, const char *string,
1150                                cJSON *newitem) {
1151     int i = 0;
1152     cJSON *c = object->child;
1153     while (c && strcmp(c->string, string))
1154         i++, c = c->next;
1155     if (c) {
1156         newitem->string = cJSON_strdup(string);
1157         cJSON_ReplaceItemInArray(object, i, newitem);
1158     }
1159 }
1160 
1161 /* Create basic types: */
cJSON_CreateNull(void)1162 cJSON *cJSON_CreateNull(void) {
1163     cJSON *item = cJSON_New_Item();
1164     if (item)
1165         item->type = cJSON_NULL;
1166     return item;
1167 }
cJSON_CreateTrue(void)1168 cJSON *cJSON_CreateTrue(void) {
1169     cJSON *item = cJSON_New_Item();
1170     if (item)
1171         item->type = cJSON_True;
1172     return item;
1173 }
cJSON_CreateFalse(void)1174 cJSON *cJSON_CreateFalse(void) {
1175     cJSON *item = cJSON_New_Item();
1176     if (item)
1177         item->type = cJSON_False;
1178     return item;
1179 }
cJSON_CreateBool(int b)1180 cJSON *cJSON_CreateBool(int b) {
1181     cJSON *item = cJSON_New_Item();
1182     if (item)
1183         item->type = b ? cJSON_True : cJSON_False;
1184     return item;
1185 }
cJSON_CreateNumber(double num)1186 cJSON *cJSON_CreateNumber(double num) {
1187     cJSON *item = cJSON_New_Item();
1188     if (item) {
1189         item->type = cJSON_Number;
1190         item->valuedouble = num;
1191         item->valueint = (int)num;
1192     }
1193     return item;
1194 }
cJSON_CreateString(const char * string)1195 cJSON *cJSON_CreateString(const char *string) {
1196     cJSON *item = cJSON_New_Item();
1197     if (item) {
1198         item->type = cJSON_String;
1199         item->valuestring = cJSON_strdup(string);
1200     }
1201     return item;
1202 }
cJSON_CreateArray(void)1203 cJSON *cJSON_CreateArray(void) {
1204     cJSON *item = cJSON_New_Item();
1205     if (item)
1206         item->type = cJSON_Array;
1207     return item;
1208 }
cJSON_CreateObject(void)1209 cJSON *cJSON_CreateObject(void) {
1210     cJSON *item = cJSON_New_Item();
1211     if (item)
1212         item->type = cJSON_Object;
1213     return item;
1214 }
1215 
1216 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)1217 cJSON *cJSON_CreateIntArray(const int *numbers, int count) {
1218     int i;
1219     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1220     for (i = 0; a && i < count; i++) {
1221         n = cJSON_CreateNumber(numbers[i]);
1222         if (!i)
1223             a->child = n;
1224         else
1225             suffix_object(p, n);
1226         p = n;
1227     }
1228     return a;
1229 }
cJSON_CreateFloatArray(const float * numbers,int count)1230 cJSON *cJSON_CreateFloatArray(const float *numbers, int count) {
1231     int i;
1232     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1233     for (i = 0; a && i < count; i++) {
1234         n = cJSON_CreateNumber(numbers[i]);
1235         if (!i)
1236             a->child = n;
1237         else
1238             suffix_object(p, n);
1239         p = n;
1240     }
1241     return a;
1242 }
cJSON_CreateDoubleArray(const double * numbers,int count)1243 cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) {
1244     int i;
1245     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1246     for (i = 0; a && i < count; i++) {
1247         n = cJSON_CreateNumber(numbers[i]);
1248         if (!i)
1249             a->child = n;
1250         else
1251             suffix_object(p, n);
1252         p = n;
1253     }
1254     return a;
1255 }
cJSON_CreateStringArray(const char ** strings,int count)1256 cJSON *cJSON_CreateStringArray(const char **strings, int count) {
1257     int i;
1258     cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1259     for (i = 0; a && i < count; i++) {
1260         n = cJSON_CreateString(strings[i]);
1261         if (!i)
1262             a->child = n;
1263         else
1264             suffix_object(p, n);
1265         p = n;
1266     }
1267     return a;
1268 }
1269 
1270 /* Duplication */
cJSON_Duplicate(cJSON * item,int recurse)1271 cJSON *cJSON_Duplicate(cJSON *item, int recurse) {
1272     cJSON *newitem, *cptr, *nptr = 0, *newchild;
1273     /* Bail on bad ptr */
1274     if (!item)
1275         return 0;
1276     /* Create new item */
1277     newitem = cJSON_New_Item();
1278     if (!newitem)
1279         return 0;
1280     /* Copy over all vars */
1281     newitem->type = item->type & (~cJSON_IsReference),
1282     newitem->valueint = item->valueint,
1283     newitem->valuedouble = item->valuedouble;
1284     if (item->valuestring) {
1285         newitem->valuestring = cJSON_strdup(item->valuestring);
1286         if (!newitem->valuestring) {
1287             cJSON_Delete(newitem);
1288             return 0;
1289         }
1290     }
1291     if (item->string) {
1292         newitem->string = cJSON_strdup(item->string);
1293         if (!newitem->string) {
1294             cJSON_Delete(newitem);
1295             return 0;
1296         }
1297     }
1298     /* If non-recursive, then we're done! */
1299     if (!recurse)
1300         return newitem;
1301     /* Walk the ->next chain for the child. */
1302     cptr = item->child;
1303     while (cptr) {
1304         newchild = cJSON_Duplicate(
1305             cptr,
1306             1); /* Duplicate (with recurse) each item in the ->next chain */
1307         if (!newchild) {
1308             cJSON_Delete(newitem);
1309             return 0;
1310         }
1311         if (nptr) {
1312             nptr->next = newchild, newchild->prev = nptr;
1313             nptr = newchild;
1314         } /* If newitem->child already set, then crosswire ->prev and ->next and
1315              move on */
1316         else {
1317             newitem->child = newchild;
1318             nptr = newchild;
1319         } /* Set newitem->child and move to it */
1320         cptr = cptr->next;
1321     }
1322     return newitem;
1323 }
1324 
cJSON_Minify(char * json)1325 void cJSON_Minify(char *json) {
1326     char *into = json;
1327     while (*json) {
1328         if (*json == ' ')
1329             json++;
1330         else if (*json == '\t')
1331             json++; /* Whitespace characters. */
1332         else if (*json == '\r')
1333             json++;
1334         else if (*json == '\n')
1335             json++;
1336         else if (*json == '/' && json[1] == '/')
1337             while (*json && *json != '\n')
1338                 json++; /* double-slash comments, to end of line. */
1339         else if (*json == '/' && json[1] == '*') {
1340             while (*json && !(*json == '*' && json[1] == '/'))
1341                 json++;
1342             json += 2;
1343         } /* multiline comments. */
1344         else if (*json == '\"') {
1345             *into++ = *json++;
1346             while (*json && *json != '\"') {
1347                 if (*json == '\\')
1348                     *into++ = *json++;
1349                 *into++ = *json++;
1350             }
1351             *into++ = *json++;
1352         } /* string literals, which are \" sensitive. */
1353         else
1354             *into++ = *json++; /* All other characters. */
1355     }
1356     *into = 0; /* and null-terminate. */
1357 }
1358