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