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