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