• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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