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