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