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