1 /*
2   Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy
5   of this software and associated documentation files (the "Software"), to deal
6   in the Software without restriction, including without limitation the rights
7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8   copies of the Software, and to permit persons to whom the Software is
9   furnished to do so, subject to the following conditions:
10 
11   The above copyright notice and this permission notice shall be included in
12   all copies or substantial portions of the Software.
13 
14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   THE SOFTWARE.
21 */
22 
23 /* cJSON */
24 /* JSON parser in C. */
25 
26 /* disable warnings about old C89 functions in MSVC */
27 #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28 #define _CRT_SECURE_NO_DEPRECATE
29 #endif
30 
31 #ifdef __GNUC__
32 #pragma GCC visibility push(default)
33 #endif
34 #if defined(_MSC_VER)
35 #pragma warning (push)
36 /* disable warning about single line comments in system headers */
37 #pragma warning (disable : 4001)
38 #endif
39 
40 #include <string.h>
41 #include <stdio.h>
42 #include <math.h>
43 #include <stdlib.h>
44 #include <limits.h>
45 #include <ctype.h>
46 #include <float.h>
47 #ifdef HAVE_STDINT_H
48 #include <stdint.h>
49 #endif
50 #include <sys/types.h>
51 
52 #ifdef ENABLE_LOCALES
53 #include <locale.h>
54 #endif
55 
56 #if defined(_MSC_VER)
57 #pragma warning (pop)
58 #endif
59 #ifdef __GNUC__
60 #pragma GCC visibility pop
61 #endif
62 
63 #include "cjson.h"
64 
65 /* define our own boolean type */
66 #ifdef true
67 #undef true
68 #endif
69 #define true ((cJSON_bool)1)
70 
71 #ifdef false
72 #undef false
73 #endif
74 #define false ((cJSON_bool)0)
75 
76 /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
77 #ifndef isinf
78 #define isinf(d) (isnan((d - d)) && !isnan(d))
79 #endif
80 #ifndef isnan
81 #define isnan(d) (d != d)
82 #endif
83 
84 #ifndef NAN
85 #define NAN 0.0/0.0
86 #endif
87 
88 typedef struct {
89     const unsigned char *json;
90     size_t position;
91 } error;
92 static error global_error = { NULL, 0 };
93 
94 #ifndef LLONG_MAX
95 #define LLONG_MAX 9223372036854775807LL
96 #endif
97 #ifndef LLONG_MIN
98 #define LLONG_MIN (-LLONG_MAX - 1LL)
99 #endif
100 
cJSON_GetErrorPtr(void)101 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
102 {
103     return (const char*) (global_error.json + global_error.position);
104 }
105 
cJSON_GetStringValue(cJSON * item)106 CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
107 {
108     if (!cJSON_IsString(item))
109     {
110         return NULL;
111     }
112 
113     return item->valuestring;
114 }
115 
cJSON_GetNumberValue(cJSON * item)116 CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item)
117 {
118     if (!cJSON_IsNumber(item))
119     {
120         return NAN;
121     }
122 
123     return item->valuedouble;
124 }
125 
126 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
127 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 13)
128     #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
129 #endif
130 
cJSON_Version(void)131 CJSON_PUBLIC(const char*) cJSON_Version(void)
132 {
133     static char version[15];
134     sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
135 
136     return version;
137 }
138 
139 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
case_insensitive_strcmp(const unsigned char * string1,const unsigned char * string2)140 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
141 {
142     if ((string1 == NULL) || (string2 == NULL))
143     {
144         return 1;
145     }
146 
147     if (string1 == string2)
148     {
149         return 0;
150     }
151 
152     for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
153     {
154         if (*string1 == '\0')
155         {
156             return 0;
157         }
158     }
159 
160     return tolower(*string1) - tolower(*string2);
161 }
162 
163 typedef struct internal_hooks
164 {
165     void *(CJSON_CDECL *allocate)(size_t size);
166     void (CJSON_CDECL *deallocate)(void *pointer);
167     void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
168 } internal_hooks;
169 
170 #if defined(_MSC_VER)
171 /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
internal_malloc(size_t size)172 static void * CJSON_CDECL internal_malloc(size_t size)
173 {
174     return malloc(size);
175 }
internal_free(void * pointer)176 static void CJSON_CDECL internal_free(void *pointer)
177 {
178     free(pointer);
179 }
internal_realloc(void * pointer,size_t size)180 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
181 {
182     return realloc(pointer, size);
183 }
184 #else
185 #define internal_malloc malloc
186 #define internal_free free
187 #define internal_realloc realloc
188 #endif
189 
190 /* strlen of character literals resolved at compile time */
191 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
192 
193 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
194 
cJSON_strdup(const unsigned char * string,const internal_hooks * const hooks)195 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
196 {
197     size_t length = 0;
198     unsigned char *copy = NULL;
199 
200     if (string == NULL)
201     {
202         return NULL;
203     }
204 
205     length = strlen((const char*)string) + sizeof("");
206     copy = (unsigned char*)hooks->allocate(length);
207     if (copy == NULL)
208     {
209         return NULL;
210     }
211     memcpy(copy, string, length);
212 
213     return copy;
214 }
215 
cJSON_InitHooks(cJSON_Hooks * hooks)216 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
217 {
218     if (hooks == NULL)
219     {
220         /* Reset hooks */
221         global_hooks.allocate = malloc;
222         global_hooks.deallocate = free;
223         global_hooks.reallocate = realloc;
224         return;
225     }
226 
227     global_hooks.allocate = malloc;
228     if (hooks->malloc_fn != NULL)
229     {
230         global_hooks.allocate = hooks->malloc_fn;
231     }
232 
233     global_hooks.deallocate = free;
234     if (hooks->free_fn != NULL)
235     {
236         global_hooks.deallocate = hooks->free_fn;
237     }
238 
239     /* use realloc only if both free and malloc are used */
240     global_hooks.reallocate = NULL;
241     if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
242     {
243         global_hooks.reallocate = realloc;
244     }
245 }
246 
247 /* Internal constructor. */
cJSON_New_Item(const internal_hooks * const hooks)248 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
249 {
250     cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
251     if (node)
252     {
253         memset(node, '\0', sizeof(cJSON));
254     }
255 
256     return node;
257 }
258 
259 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * item)260 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
261 {
262     cJSON *next = NULL;
263     while (item != NULL)
264     {
265         next = item->next;
266         if (!(item->type & cJSON_IsReference) && (item->child != NULL))
267         {
268             cJSON_Delete(item->child);
269         }
270         if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
271         {
272             global_hooks.deallocate(item->valuestring);
273         }
274         if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
275         {
276             global_hooks.deallocate(item->string);
277         }
278         global_hooks.deallocate(item);
279         item = next;
280     }
281 }
282 
283 /* get the decimal point character of the current locale */
get_decimal_point(void)284 static unsigned char get_decimal_point(void)
285 {
286 #ifdef ENABLE_LOCALES
287     struct lconv *lconv = localeconv();
288     return (unsigned char) lconv->decimal_point[0];
289 #else
290     return '.';
291 #endif
292 }
293 
294 typedef struct
295 {
296     const unsigned char *content;
297     size_t length;
298     size_t offset;
299     size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
300     internal_hooks hooks;
301 } parse_buffer;
302 
303 /* check if the given size is left to read in a given parse buffer (starting with 1) */
304 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
305 /* check if the buffer can be accessed at the given index (starting with 0) */
306 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
307 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
308 /* get a pointer to the buffer at the position */
309 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
310 
311 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)312 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
313 {
314     double number = 0;
315     unsigned char *after_end = NULL;
316     unsigned char number_c_string[64];
317     unsigned char decimal_point = get_decimal_point();
318     size_t i = 0;
319 
320     if ((input_buffer == NULL) || (input_buffer->content == NULL))
321     {
322         return false;
323     }
324 
325     /* copy the number into a temporary buffer and replace '.' with the decimal point
326      * of the current locale (for strtod)
327      * This also takes care of '\0' not necessarily being available for marking the end of the input */
328     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
329     {
330         switch (buffer_at_offset(input_buffer)[i])
331         {
332             case '0':
333             case '1':
334             case '2':
335             case '3':
336             case '4':
337             case '5':
338             case '6':
339             case '7':
340             case '8':
341             case '9':
342             case '+':
343             case '-':
344             case 'e':
345             case 'E':
346                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
347                 break;
348 
349             case '.':
350                 number_c_string[i] = decimal_point;
351                 break;
352 
353             default:
354                 goto loop_end;
355         }
356     }
357 loop_end:
358     number_c_string[i] = '\0';
359 
360     number = strtod((const char*)number_c_string, (char**)&after_end);
361     if (number_c_string == after_end)
362     {
363         return false; /* parse_error */
364     }
365 
366     item->valuedouble = number;
367 
368     /* use saturation in case of overflow */
369     if (number >= LLONG_MAX)
370     {
371         item->valueint = LLONG_MAX;
372     }
373     else if (number <= (double)LLONG_MIN)
374     {
375         item->valueint = LLONG_MIN;
376     }
377     else
378     {
379         item->valueint = (int64_t)number;
380     }
381 
382     item->type = cJSON_Number;
383 
384     input_buffer->offset += (size_t)(after_end - number_c_string);
385     return true;
386 }
387 
388 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)389 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
390 {
391     if (number >= LLONG_MAX)
392     {
393         object->valueint = LLONG_MAX;
394     }
395     else if (number <= (double)LLONG_MIN)
396     {
397         object->valueint = LLONG_MIN;
398     }
399     else
400     {
401         object->valueint = (int64_t)number;
402     }
403 
404     return object->valuedouble = number;
405 }
406 
cJSON_SetValuestring(cJSON * object,const char * valuestring)407 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
408 {
409     char *copy = NULL;
410     /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
411     if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
412     {
413         return NULL;
414     }
415     if (strlen(valuestring) <= strlen(object->valuestring))
416     {
417         strcpy(object->valuestring, valuestring);
418         return object->valuestring;
419     }
420     copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
421     if (copy == NULL)
422     {
423         return NULL;
424     }
425     if (object->valuestring != NULL)
426     {
427         cJSON_free(object->valuestring);
428     }
429     object->valuestring = copy;
430 
431     return copy;
432 }
433 
434 typedef struct
435 {
436     unsigned char *buffer;
437     size_t length;
438     size_t offset;
439     size_t depth; /* current nesting depth (for formatted printing) */
440     cJSON_bool noalloc;
441     cJSON_bool format; /* is this print a formatted print */
442     internal_hooks hooks;
443 } printbuffer;
444 
445 /* realloc printbuffer if necessary to have at least "needed" bytes more */
ensure(printbuffer * const p,size_t needed)446 static unsigned char* ensure(printbuffer * const p, size_t needed)
447 {
448     unsigned char *newbuffer = NULL;
449     size_t newsize = 0;
450 
451     if ((p == NULL) || (p->buffer == NULL))
452     {
453         return NULL;
454     }
455 
456     if ((p->length > 0) && (p->offset >= p->length))
457     {
458         /* make sure that offset is valid */
459         return NULL;
460     }
461 
462     if (needed > SIZE_MAX)
463     {
464         /* sizes bigger than SIZE_MAX are currently not supported */
465         return NULL;
466     }
467 
468     needed += p->offset + 1;
469     if (needed <= p->length)
470     {
471         return p->buffer + p->offset;
472     }
473 
474     if (p->noalloc) {
475         return NULL;
476     }
477 
478     /* calculate new buffer size */
479     if (needed > (SIZE_MAX / 2))
480     {
481         /* overflow of int, use SIZE_MAX if possible */
482         if (needed <= SIZE_MAX)
483         {
484             newsize = SIZE_MAX;
485         }
486         else
487         {
488             return NULL;
489         }
490     }
491     else
492     {
493         newsize = needed * 2;
494     }
495 
496     if (p->hooks.reallocate != NULL)
497     {
498         /* reallocate with realloc if available */
499         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
500         if (newbuffer == NULL)
501         {
502             p->hooks.deallocate(p->buffer);
503             p->length = 0;
504             p->buffer = NULL;
505 
506             return NULL;
507         }
508     }
509     else
510     {
511         /* otherwise reallocate manually */
512         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
513         if (!newbuffer)
514         {
515             p->hooks.deallocate(p->buffer);
516             p->length = 0;
517             p->buffer = NULL;
518 
519             return NULL;
520         }
521         if (newbuffer)
522         {
523             memcpy(newbuffer, p->buffer, p->offset + 1);
524         }
525         p->hooks.deallocate(p->buffer);
526     }
527     p->length = newsize;
528     p->buffer = newbuffer;
529 
530     return newbuffer + p->offset;
531 }
532 
533 /* calculate the new length of the string in a printbuffer and update the offset */
update_offset(printbuffer * const buffer)534 static void update_offset(printbuffer * const buffer)
535 {
536     const unsigned char *buffer_pointer = NULL;
537     if ((buffer == NULL) || (buffer->buffer == NULL))
538     {
539         return;
540     }
541     buffer_pointer = buffer->buffer + buffer->offset;
542 
543     buffer->offset += strlen((const char*)buffer_pointer);
544 }
545 
546 /* securely comparison of floating-point variables */
compare_double(double a,double b)547 static cJSON_bool compare_double(double a, double b)
548 {
549     double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
550     return (fabs(a - b) <= maxVal * DBL_EPSILON);
551 }
552 
553 /* Render the number nicely from the given item into a string. */
print_number(const cJSON * const item,printbuffer * const output_buffer)554 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
555 {
556     unsigned char *output_pointer = NULL;
557     double d = item->valuedouble;
558     int length = 0;
559     size_t i = 0;
560     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
561     unsigned char decimal_point = get_decimal_point();
562     double test = 0.0;
563 
564     if (output_buffer == NULL)
565     {
566         return false;
567     }
568 
569     /* This checks for NaN and Infinity */
570     if (isnan(d) || isinf(d))
571     {
572         length = sprintf((char*)number_buffer, "null");
573     }
574     else
575     {
576         /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
577         length = sprintf((char*)number_buffer, "%1.15g", d);
578 
579         /* Check whether the original double can be recovered */
580         if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
581         {
582             /* If not, print with 17 decimal places of precision */
583             length = sprintf((char*)number_buffer, "%1.17g", d);
584         }
585     }
586 
587     /* sprintf failed or buffer overrun occurred */
588     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
589     {
590         return false;
591     }
592 
593     /* reserve appropriate space in the output */
594     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
595     if (output_pointer == NULL)
596     {
597         return false;
598     }
599 
600     /* copy the printed number to the output and replace locale
601      * dependent decimal point with '.' */
602     for (i = 0; i < ((size_t)length); i++)
603     {
604         if (number_buffer[i] == decimal_point)
605         {
606             output_pointer[i] = '.';
607             continue;
608         }
609 
610         output_pointer[i] = number_buffer[i];
611     }
612     output_pointer[i] = '\0';
613 
614     output_buffer->offset += (size_t)length;
615 
616     return true;
617 }
618 
619 /* parse 4 digit hexadecimal number */
parse_hex4(const unsigned char * const input)620 static unsigned parse_hex4(const unsigned char * const input)
621 {
622     unsigned int h = 0;
623     size_t i = 0;
624 
625     for (i = 0; i < 4; i++)
626     {
627         /* parse digit */
628         if ((input[i] >= '0') && (input[i] <= '9'))
629         {
630             h += (unsigned int) input[i] - '0';
631         }
632         else if ((input[i] >= 'A') && (input[i] <= 'F'))
633         {
634             h += (unsigned int) 10 + input[i] - 'A';
635         }
636         else if ((input[i] >= 'a') && (input[i] <= 'f'))
637         {
638             h += (unsigned int) 10 + input[i] - 'a';
639         }
640         else /* invalid */
641         {
642             return 0;
643         }
644 
645         if (i < 3)
646         {
647             /* shift left to make place for the next nibble */
648             h = h << 4;
649         }
650     }
651 
652     return h;
653 }
654 
655 /* converts a UTF-16 literal to UTF-8
656  * A literal can be one or two sequences of the form \uXXXX */
utf16_literal_to_utf8(const unsigned char * const input_pointer,const unsigned char * const input_end,unsigned char ** output_pointer)657 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
658 {
659     long unsigned int codepoint = 0;
660     unsigned int first_code = 0;
661     const unsigned char *first_sequence = input_pointer;
662     unsigned char utf8_length = 0;
663     unsigned char utf8_position = 0;
664     unsigned char sequence_length = 0;
665     unsigned char first_byte_mark = 0;
666 
667     if ((input_end - first_sequence) < 6)
668     {
669         /* input ends unexpectedly */
670         goto fail;
671     }
672 
673     /* get the first utf16 sequence */
674     first_code = parse_hex4(first_sequence + 2);
675 
676     /* check that the code is valid */
677     if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
678     {
679         goto fail;
680     }
681 
682     /* UTF16 surrogate pair */
683     if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
684     {
685         const unsigned char *second_sequence = first_sequence + 6;
686         unsigned int second_code = 0;
687         sequence_length = 12; /* \uXXXX\uXXXX */
688 
689         if ((input_end - second_sequence) < 6)
690         {
691             /* input ends unexpectedly */
692             goto fail;
693         }
694 
695         if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
696         {
697             /* missing second half of the surrogate pair */
698             goto fail;
699         }
700 
701         /* get the second utf16 sequence */
702         second_code = parse_hex4(second_sequence + 2);
703         /* check that the code is valid */
704         if ((second_code < 0xDC00) || (second_code > 0xDFFF))
705         {
706             /* invalid second half of the surrogate pair */
707             goto fail;
708         }
709 
710 
711         /* calculate the unicode codepoint from the surrogate pair */
712         codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
713     }
714     else
715     {
716         sequence_length = 6; /* \uXXXX */
717         codepoint = first_code;
718     }
719 
720     /* encode as UTF-8
721      * takes at maximum 4 bytes to encode:
722      * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
723     if (codepoint < 0x80)
724     {
725         /* normal ascii, encoding 0xxxxxxx */
726         utf8_length = 1;
727     }
728     else if (codepoint < 0x800)
729     {
730         /* two bytes, encoding 110xxxxx 10xxxxxx */
731         utf8_length = 2;
732         first_byte_mark = 0xC0; /* 11000000 */
733     }
734     else if (codepoint < 0x10000)
735     {
736         /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
737         utf8_length = 3;
738         first_byte_mark = 0xE0; /* 11100000 */
739     }
740     else if (codepoint <= 0x10FFFF)
741     {
742         /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
743         utf8_length = 4;
744         first_byte_mark = 0xF0; /* 11110000 */
745     }
746     else
747     {
748         /* invalid unicode codepoint */
749         goto fail;
750     }
751 
752     /* encode as utf8 */
753     for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
754     {
755         /* 10xxxxxx */
756         (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
757         codepoint >>= 6;
758     }
759     /* encode first byte */
760     if (utf8_length > 1)
761     {
762         (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
763     }
764     else
765     {
766         (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
767     }
768 
769     *output_pointer += utf8_length;
770 
771     return sequence_length;
772 
773 fail:
774     return 0;
775 }
776 
777 /* Parse the input text into an unescaped cinput, and populate item. */
parse_string(cJSON * const item,parse_buffer * const input_buffer)778 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
779 {
780     const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
781     const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
782     unsigned char *output_pointer = NULL;
783     unsigned char *output = NULL;
784 
785     /* not a string */
786     if (buffer_at_offset(input_buffer)[0] != '\"')
787     {
788         goto fail;
789     }
790 
791     {
792         /* calculate approximate size of the output (overestimate) */
793         size_t allocation_length = 0;
794         size_t skipped_bytes = 0;
795         while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
796         {
797             /* is escape sequence */
798             if (input_end[0] == '\\')
799             {
800                 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
801                 {
802                     /* prevent buffer overflow when last input character is a backslash */
803                     goto fail;
804                 }
805                 skipped_bytes++;
806                 input_end++;
807             }
808             input_end++;
809         }
810         if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
811         {
812             goto fail; /* string ended unexpectedly */
813         }
814 
815         /* This is at most how much we need for the output */
816         allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
817         output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
818         if (output == NULL)
819         {
820             goto fail; /* allocation failure */
821         }
822     }
823 
824     output_pointer = output;
825     /* loop through the string literal */
826     while (input_pointer < input_end)
827     {
828         if (*input_pointer != '\\')
829         {
830             *output_pointer++ = *input_pointer++;
831         }
832         /* escape sequence */
833         else
834         {
835             unsigned char sequence_length = 2;
836             if ((input_end - input_pointer) < 1)
837             {
838                 goto fail;
839             }
840 
841             switch (input_pointer[1])
842             {
843                 case 'b':
844                     *output_pointer++ = '\b';
845                     break;
846                 case 'f':
847                     *output_pointer++ = '\f';
848                     break;
849                 case 'n':
850                     *output_pointer++ = '\n';
851                     break;
852                 case 'r':
853                     *output_pointer++ = '\r';
854                     break;
855                 case 't':
856                     *output_pointer++ = '\t';
857                     break;
858                 case '\"':
859                 case '\\':
860                 case '/':
861                     *output_pointer++ = input_pointer[1];
862                     break;
863 
864                 /* UTF-16 literal */
865                 case 'u':
866                     sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
867                     if (sequence_length == 0)
868                     {
869                         /* failed to convert UTF16-literal to UTF-8 */
870                         goto fail;
871                     }
872                     break;
873 
874                 default:
875                     goto fail;
876             }
877             input_pointer += sequence_length;
878         }
879     }
880 
881     /* zero terminate the output */
882     *output_pointer = '\0';
883 
884     item->type = cJSON_String;
885     item->valuestring = (char*)output;
886 
887     input_buffer->offset = (size_t) (input_end - input_buffer->content);
888     input_buffer->offset++;
889 
890     return true;
891 
892 fail:
893     if (output != NULL)
894     {
895         input_buffer->hooks.deallocate(output);
896     }
897 
898     if (input_pointer != NULL)
899     {
900         input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
901     }
902 
903     return false;
904 }
905 
906 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const unsigned char * const input,printbuffer * const output_buffer)907 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
908 {
909     const unsigned char *input_pointer = NULL;
910     unsigned char *output = NULL;
911     unsigned char *output_pointer = NULL;
912     size_t output_length = 0;
913     /* numbers of additional characters needed for escaping */
914     size_t escape_characters = 0;
915 
916     if (output_buffer == NULL)
917     {
918         return false;
919     }
920 
921     /* empty string */
922     if (input == NULL)
923     {
924         output = ensure(output_buffer, sizeof("\"\""));
925         if (output == NULL)
926         {
927             return false;
928         }
929         strcpy((char*)output, "\"\"");
930 
931         return true;
932     }
933 
934     /* set "flag" to 1 if something needs to be escaped */
935     for (input_pointer = input; *input_pointer; input_pointer++)
936     {
937         switch (*input_pointer)
938         {
939             case '\"':
940             case '\\':
941             case '\b':
942             case '\f':
943             case '\n':
944             case '\r':
945             case '\t':
946                 /* one character escape sequence */
947                 escape_characters++;
948                 break;
949             default:
950                 if (*input_pointer < 32)
951                 {
952                     /* UTF-16 escape sequence uXXXX */
953                     escape_characters += 5;
954                 }
955                 break;
956         }
957     }
958     output_length = (size_t)(input_pointer - input) + escape_characters;
959 
960     output = ensure(output_buffer, output_length + sizeof("\"\""));
961     if (output == NULL)
962     {
963         return false;
964     }
965 
966     /* no characters have to be escaped */
967     if (escape_characters == 0)
968     {
969         output[0] = '\"';
970         memcpy(output + 1, input, output_length);
971         output[output_length + 1] = '\"';
972         output[output_length + 2] = '\0';
973 
974         return true;
975     }
976 
977     output[0] = '\"';
978     output_pointer = output + 1;
979     /* copy the string */
980     for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
981     {
982         if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
983         {
984             /* normal character, copy */
985             *output_pointer = *input_pointer;
986         }
987         else
988         {
989             /* character needs to be escaped */
990             *output_pointer++ = '\\';
991             switch (*input_pointer)
992             {
993                 case '\\':
994                     *output_pointer = '\\';
995                     break;
996                 case '\"':
997                     *output_pointer = '\"';
998                     break;
999                 case '\b':
1000                     *output_pointer = 'b';
1001                     break;
1002                 case '\f':
1003                     *output_pointer = 'f';
1004                     break;
1005                 case '\n':
1006                     *output_pointer = 'n';
1007                     break;
1008                 case '\r':
1009                     *output_pointer = 'r';
1010                     break;
1011                 case '\t':
1012                     *output_pointer = 't';
1013                     break;
1014                 default:
1015                     /* escape and print as unicode codepoint */
1016                     sprintf((char*)output_pointer, "u%04x", *input_pointer);
1017                     output_pointer += 4;
1018                     break;
1019             }
1020         }
1021     }
1022     output[output_length + 1] = '\"';
1023     output[output_length + 2] = '\0';
1024 
1025     return true;
1026 }
1027 
1028 /* Invoke print_string_ptr (which is useful) on an item. */
print_string(const cJSON * const item,printbuffer * const p)1029 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1030 {
1031     return print_string_ptr((unsigned char*)item->valuestring, p);
1032 }
1033 
1034 /* Predeclare these prototypes. */
1035 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1036 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1037 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1038 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1039 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1040 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1041 
1042 /* Utility to jump whitespace and cr/lf */
buffer_skip_whitespace(parse_buffer * const buffer)1043 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1044 {
1045     if ((buffer == NULL) || (buffer->content == NULL))
1046     {
1047         return NULL;
1048     }
1049 
1050     if (cannot_access_at_index(buffer, 0))
1051     {
1052         return buffer;
1053     }
1054 
1055     while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1056     {
1057        buffer->offset++;
1058     }
1059 
1060     if (buffer->offset == buffer->length)
1061     {
1062         buffer->offset--;
1063     }
1064 
1065     return buffer;
1066 }
1067 
1068 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
skip_utf8_bom(parse_buffer * const buffer)1069 static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1070 {
1071     if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1072     {
1073         return NULL;
1074     }
1075 
1076     if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1077     {
1078         buffer->offset += 3;
1079     }
1080 
1081     return buffer;
1082 }
1083 
cJSON_ParseWithOpts(const char * value,const char ** return_parse_end,cJSON_bool require_null_terminated)1084 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1085 {
1086     size_t buffer_length;
1087 
1088     if (NULL == value)
1089     {
1090         return NULL;
1091     }
1092 
1093     /* Adding null character size due to require_null_terminated. */
1094     buffer_length = strlen(value) + sizeof("");
1095 
1096     return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1097 }
1098 
1099 /* Parse an object - create a new root, and populate. */
cJSON_ParseWithLengthOpts(const char * value,size_t buffer_length,const char ** return_parse_end,cJSON_bool require_null_terminated)1100 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1101 {
1102     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1103     cJSON *item = NULL;
1104 
1105     /* reset error position */
1106     global_error.json = NULL;
1107     global_error.position = 0;
1108 
1109     if (value == NULL || 0 == buffer_length)
1110     {
1111         goto fail;
1112     }
1113 
1114     buffer.content = (const unsigned char*)value;
1115     buffer.length = buffer_length;
1116     buffer.offset = 0;
1117     buffer.hooks = global_hooks;
1118 
1119     item = cJSON_New_Item(&global_hooks);
1120     if (item == NULL) /* memory fail */
1121     {
1122         goto fail;
1123     }
1124 
1125     if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1126     {
1127         /* parse failure. ep is set. */
1128         goto fail;
1129     }
1130 
1131     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1132     if (require_null_terminated)
1133     {
1134         buffer_skip_whitespace(&buffer);
1135         if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1136         {
1137             goto fail;
1138         }
1139     }
1140     if (return_parse_end)
1141     {
1142         *return_parse_end = (const char*)buffer_at_offset(&buffer);
1143     }
1144 
1145     return item;
1146 
1147 fail:
1148     if (item != NULL)
1149     {
1150         cJSON_Delete(item);
1151     }
1152 
1153     if (value != NULL)
1154     {
1155         error local_error;
1156         local_error.json = (const unsigned char*)value;
1157         local_error.position = 0;
1158 
1159         if (buffer.offset < buffer.length)
1160         {
1161             local_error.position = buffer.offset;
1162         }
1163         else if (buffer.length > 0)
1164         {
1165             local_error.position = buffer.length - 1;
1166         }
1167 
1168         if (return_parse_end != NULL)
1169         {
1170             *return_parse_end = (const char*)local_error.json + local_error.position;
1171         }
1172 
1173         global_error = local_error;
1174     }
1175 
1176     return NULL;
1177 }
1178 
1179 /* Default options for cJSON_Parse */
cJSON_Parse(const char * value)1180 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1181 {
1182     return cJSON_ParseWithOpts(value, 0, 0);
1183 }
1184 
cJSON_ParseWithLength(const char * value,size_t buffer_length)1185 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1186 {
1187     return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1188 }
1189 
1190 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1191 
print(const cJSON * const item,cJSON_bool format,const internal_hooks * const hooks)1192 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1193 {
1194     static const size_t default_buffer_size = 256;
1195     printbuffer buffer[1];
1196     unsigned char *printed = NULL;
1197 
1198     memset(buffer, 0, sizeof(buffer));
1199 
1200     /* create buffer */
1201     buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1202     buffer->length = default_buffer_size;
1203     buffer->format = format;
1204     buffer->hooks = *hooks;
1205     if (buffer->buffer == NULL)
1206     {
1207         goto fail;
1208     }
1209 
1210     /* print the value */
1211     if (!print_value(item, buffer))
1212     {
1213         goto fail;
1214     }
1215     update_offset(buffer);
1216 
1217     /* check if reallocate is available */
1218     if (hooks->reallocate != NULL)
1219     {
1220         printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1221         if (printed == NULL) {
1222             goto fail;
1223         }
1224         buffer->buffer = NULL;
1225     }
1226     else /* otherwise copy the JSON over to a new buffer */
1227     {
1228         printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1229         if (printed == NULL)
1230         {
1231             goto fail;
1232         }
1233         memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1234         printed[buffer->offset] = '\0'; /* just to be sure */
1235 
1236         /* free the buffer */
1237         hooks->deallocate(buffer->buffer);
1238     }
1239 
1240     return printed;
1241 
1242 fail:
1243     if (buffer->buffer != NULL)
1244     {
1245         hooks->deallocate(buffer->buffer);
1246     }
1247 
1248     if (printed != NULL)
1249     {
1250         hooks->deallocate(printed);
1251     }
1252 
1253     return NULL;
1254 }
1255 
1256 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(const cJSON * item)1257 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1258 {
1259     return (char*)print(item, true, &global_hooks);
1260 }
1261 
cJSON_PrintUnformatted(const cJSON * item)1262 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1263 {
1264     return (char*)print(item, false, &global_hooks);
1265 }
1266 
cJSON_PrintBuffered(const cJSON * item,int prebuffer,cJSON_bool fmt)1267 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1268 {
1269     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1270 
1271     if (prebuffer < 0)
1272     {
1273         return NULL;
1274     }
1275 
1276     p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1277     if (!p.buffer)
1278     {
1279         return NULL;
1280     }
1281 
1282     p.length = (size_t)prebuffer;
1283     p.offset = 0;
1284     p.noalloc = false;
1285     p.format = fmt;
1286     p.hooks = global_hooks;
1287 
1288     if (!print_value(item, &p))
1289     {
1290         global_hooks.deallocate(p.buffer);
1291         return NULL;
1292     }
1293 
1294     return (char*)p.buffer;
1295 }
1296 
cJSON_PrintPreallocated(cJSON * item,char * buffer,const int length,const cJSON_bool format)1297 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1298 {
1299     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1300 
1301     if ((length < 0) || (buffer == NULL))
1302     {
1303         return false;
1304     }
1305 
1306     p.buffer = (unsigned char*)buffer;
1307     p.length = (size_t)length;
1308     p.offset = 0;
1309     p.noalloc = true;
1310     p.format = format;
1311     p.hooks = global_hooks;
1312 
1313     return print_value(item, &p);
1314 }
1315 
1316 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * const item,parse_buffer * const input_buffer)1317 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1318 {
1319     if ((input_buffer == NULL) || (input_buffer->content == NULL))
1320     {
1321         return false; /* no input */
1322     }
1323 
1324     /* parse the different types of values */
1325     /* null */
1326     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1327     {
1328         item->type = cJSON_NULL;
1329         input_buffer->offset += 4;
1330         return true;
1331     }
1332     /* false */
1333     if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1334     {
1335         item->type = cJSON_False;
1336         input_buffer->offset += 5;
1337         return true;
1338     }
1339     /* true */
1340     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1341     {
1342         item->type = cJSON_True;
1343         item->valueint = 1;
1344         input_buffer->offset += 4;
1345         return true;
1346     }
1347     /* string */
1348     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1349     {
1350         return parse_string(item, input_buffer);
1351     }
1352     /* number */
1353     if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1354     {
1355         return parse_number(item, input_buffer);
1356     }
1357     /* array */
1358     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1359     {
1360         return parse_array(item, input_buffer);
1361     }
1362     /* object */
1363     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1364     {
1365         return parse_object(item, input_buffer);
1366     }
1367 
1368     return false;
1369 }
1370 
1371 /* Render a value to text. */
print_value(const cJSON * const item,printbuffer * const output_buffer)1372 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1373 {
1374     unsigned char *output = NULL;
1375 
1376     if ((item == NULL) || (output_buffer == NULL))
1377     {
1378         return false;
1379     }
1380 
1381     switch ((item->type) & 0xFF)
1382     {
1383         case cJSON_NULL:
1384             output = ensure(output_buffer, 5);
1385             if (output == NULL)
1386             {
1387                 return false;
1388             }
1389             strcpy((char*)output, "null");
1390             return true;
1391 
1392         case cJSON_False:
1393             output = ensure(output_buffer, 6);
1394             if (output == NULL)
1395             {
1396                 return false;
1397             }
1398             strcpy((char*)output, "false");
1399             return true;
1400 
1401         case cJSON_True:
1402             output = ensure(output_buffer, 5);
1403             if (output == NULL)
1404             {
1405                 return false;
1406             }
1407             strcpy((char*)output, "true");
1408             return true;
1409 
1410         case cJSON_Number:
1411             return print_number(item, output_buffer);
1412 
1413         case cJSON_Raw:
1414         {
1415             size_t raw_length = 0;
1416             if (item->valuestring == NULL)
1417             {
1418                 return false;
1419             }
1420 
1421             raw_length = strlen(item->valuestring) + sizeof("");
1422             output = ensure(output_buffer, raw_length);
1423             if (output == NULL)
1424             {
1425                 return false;
1426             }
1427             memcpy(output, item->valuestring, raw_length);
1428             return true;
1429         }
1430 
1431         case cJSON_String:
1432             return print_string(item, output_buffer);
1433 
1434         case cJSON_Array:
1435             return print_array(item, output_buffer);
1436 
1437         case cJSON_Object:
1438             return print_object(item, output_buffer);
1439 
1440         default:
1441             return false;
1442     }
1443 }
1444 
1445 /* Build an array from input text. */
parse_array(cJSON * const item,parse_buffer * const input_buffer)1446 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1447 {
1448     cJSON *head = NULL; /* head of the linked list */
1449     cJSON *current_item = NULL;
1450 
1451     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1452     {
1453         return false; /* to deeply nested */
1454     }
1455     input_buffer->depth++;
1456 
1457     if (buffer_at_offset(input_buffer)[0] != '[')
1458     {
1459         /* not an array */
1460         goto fail;
1461     }
1462 
1463     input_buffer->offset++;
1464     buffer_skip_whitespace(input_buffer);
1465     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1466     {
1467         /* empty array */
1468         goto success;
1469     }
1470 
1471     /* check if we skipped to the end of the buffer */
1472     if (cannot_access_at_index(input_buffer, 0))
1473     {
1474         input_buffer->offset--;
1475         goto fail;
1476     }
1477 
1478     /* step back to character in front of the first element */
1479     input_buffer->offset--;
1480     /* loop through the comma separated array elements */
1481     do
1482     {
1483         /* allocate next item */
1484         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1485         if (new_item == NULL)
1486         {
1487             goto fail; /* allocation failure */
1488         }
1489 
1490         /* attach next item to list */
1491         if (head == NULL)
1492         {
1493             /* start the linked list */
1494             current_item = head = new_item;
1495         }
1496         else
1497         {
1498             /* add to the end and advance */
1499             current_item->next = new_item;
1500             new_item->prev = current_item;
1501             current_item = new_item;
1502         }
1503 
1504         /* parse next value */
1505         input_buffer->offset++;
1506         buffer_skip_whitespace(input_buffer);
1507         if (!parse_value(current_item, input_buffer))
1508         {
1509             goto fail; /* failed to parse value */
1510         }
1511         buffer_skip_whitespace(input_buffer);
1512     }
1513     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1514 
1515     if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1516     {
1517         goto fail; /* expected end of array */
1518     }
1519 
1520 success:
1521     input_buffer->depth--;
1522 
1523     item->type = cJSON_Array;
1524     item->child = head;
1525 
1526     input_buffer->offset++;
1527 
1528     return true;
1529 
1530 fail:
1531     if (head != NULL)
1532     {
1533         cJSON_Delete(head);
1534     }
1535 
1536     return false;
1537 }
1538 
1539 /* Render an array to text */
print_array(const cJSON * const item,printbuffer * const output_buffer)1540 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1541 {
1542     unsigned char *output_pointer = NULL;
1543     size_t length = 0;
1544     cJSON *current_element = item->child;
1545 
1546     if (output_buffer == NULL)
1547     {
1548         return false;
1549     }
1550 
1551     /* Compose the output array. */
1552     /* opening square bracket */
1553     output_pointer = ensure(output_buffer, 1);
1554     if (output_pointer == NULL)
1555     {
1556         return false;
1557     }
1558 
1559     *output_pointer = '[';
1560     output_buffer->offset++;
1561     output_buffer->depth++;
1562 
1563     while (current_element != NULL)
1564     {
1565         if (!print_value(current_element, output_buffer))
1566         {
1567             return false;
1568         }
1569         update_offset(output_buffer);
1570         if (current_element->next)
1571         {
1572             length = (size_t) (output_buffer->format ? 2 : 1);
1573             output_pointer = ensure(output_buffer, length + 1);
1574             if (output_pointer == NULL)
1575             {
1576                 return false;
1577             }
1578             *output_pointer++ = ',';
1579             if(output_buffer->format)
1580             {
1581                 *output_pointer++ = ' ';
1582             }
1583             *output_pointer = '\0';
1584             output_buffer->offset += length;
1585         }
1586         current_element = current_element->next;
1587     }
1588 
1589     output_pointer = ensure(output_buffer, 2);
1590     if (output_pointer == NULL)
1591     {
1592         return false;
1593     }
1594     *output_pointer++ = ']';
1595     *output_pointer = '\0';
1596     output_buffer->depth--;
1597 
1598     return true;
1599 }
1600 
1601 /* Build an object from the text. */
parse_object(cJSON * const item,parse_buffer * const input_buffer)1602 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1603 {
1604     cJSON *head = NULL; /* linked list head */
1605     cJSON *current_item = NULL;
1606 
1607     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1608     {
1609         return false; /* to deeply nested */
1610     }
1611     input_buffer->depth++;
1612 
1613     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1614     {
1615         goto fail; /* not an object */
1616     }
1617 
1618     input_buffer->offset++;
1619     buffer_skip_whitespace(input_buffer);
1620     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1621     {
1622         goto success; /* empty object */
1623     }
1624 
1625     /* check if we skipped to the end of the buffer */
1626     if (cannot_access_at_index(input_buffer, 0))
1627     {
1628         input_buffer->offset--;
1629         goto fail;
1630     }
1631 
1632     /* step back to character in front of the first element */
1633     input_buffer->offset--;
1634     /* loop through the comma separated array elements */
1635     do
1636     {
1637         /* allocate next item */
1638         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1639         if (new_item == NULL)
1640         {
1641             goto fail; /* allocation failure */
1642         }
1643 
1644         /* attach next item to list */
1645         if (head == NULL)
1646         {
1647             /* start the linked list */
1648             current_item = head = new_item;
1649         }
1650         else
1651         {
1652             /* add to the end and advance */
1653             current_item->next = new_item;
1654             new_item->prev = current_item;
1655             current_item = new_item;
1656         }
1657 
1658         /* parse the name of the child */
1659         input_buffer->offset++;
1660         buffer_skip_whitespace(input_buffer);
1661         if (!parse_string(current_item, input_buffer))
1662         {
1663             goto fail; /* failed to parse name */
1664         }
1665         buffer_skip_whitespace(input_buffer);
1666 
1667         /* swap valuestring and string, because we parsed the name */
1668         current_item->string = current_item->valuestring;
1669         current_item->valuestring = NULL;
1670 
1671         if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1672         {
1673             goto fail; /* invalid object */
1674         }
1675 
1676         /* parse the value */
1677         input_buffer->offset++;
1678         buffer_skip_whitespace(input_buffer);
1679         if (!parse_value(current_item, input_buffer))
1680         {
1681             goto fail; /* failed to parse value */
1682         }
1683         buffer_skip_whitespace(input_buffer);
1684     }
1685     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1686 
1687     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1688     {
1689         goto fail; /* expected end of object */
1690     }
1691 
1692 success:
1693     input_buffer->depth--;
1694 
1695     item->type = cJSON_Object;
1696     item->child = head;
1697 
1698     input_buffer->offset++;
1699     return true;
1700 
1701 fail:
1702     if (head != NULL)
1703     {
1704         cJSON_Delete(head);
1705     }
1706 
1707     return false;
1708 }
1709 
1710 /* Render an object to text. */
print_object(const cJSON * const item,printbuffer * const output_buffer)1711 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1712 {
1713     unsigned char *output_pointer = NULL;
1714     size_t length = 0;
1715     cJSON *current_item = item->child;
1716 
1717     if (output_buffer == NULL)
1718     {
1719         return false;
1720     }
1721 
1722     /* Compose the output: */
1723     length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1724     output_pointer = ensure(output_buffer, length + 1);
1725     if (output_pointer == NULL)
1726     {
1727         return false;
1728     }
1729 
1730     *output_pointer++ = '{';
1731     output_buffer->depth++;
1732     if (output_buffer->format)
1733     {
1734         *output_pointer++ = '\n';
1735     }
1736     output_buffer->offset += length;
1737 
1738     while (current_item)
1739     {
1740         if (output_buffer->format)
1741         {
1742             size_t i;
1743             output_pointer = ensure(output_buffer, output_buffer->depth);
1744             if (output_pointer == NULL)
1745             {
1746                 return false;
1747             }
1748             for (i = 0; i < output_buffer->depth; i++)
1749             {
1750                 *output_pointer++ = '\t';
1751             }
1752             output_buffer->offset += output_buffer->depth;
1753         }
1754 
1755         /* print key */
1756         if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1757         {
1758             return false;
1759         }
1760         update_offset(output_buffer);
1761 
1762         length = (size_t) (output_buffer->format ? 2 : 1);
1763         output_pointer = ensure(output_buffer, length);
1764         if (output_pointer == NULL)
1765         {
1766             return false;
1767         }
1768         *output_pointer++ = ':';
1769         if (output_buffer->format)
1770         {
1771             *output_pointer++ = '\t';
1772         }
1773         output_buffer->offset += length;
1774 
1775         /* print value */
1776         if (!print_value(current_item, output_buffer))
1777         {
1778             return false;
1779         }
1780         update_offset(output_buffer);
1781 
1782         /* print comma if not last */
1783         length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1784         output_pointer = ensure(output_buffer, length + 1);
1785         if (output_pointer == NULL)
1786         {
1787             return false;
1788         }
1789         if (current_item->next)
1790         {
1791             *output_pointer++ = ',';
1792         }
1793 
1794         if (output_buffer->format)
1795         {
1796             *output_pointer++ = '\n';
1797         }
1798         *output_pointer = '\0';
1799         output_buffer->offset += length;
1800 
1801         current_item = current_item->next;
1802     }
1803 
1804     output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1805     if (output_pointer == NULL)
1806     {
1807         return false;
1808     }
1809     if (output_buffer->format)
1810     {
1811         size_t i;
1812         for (i = 0; i < (output_buffer->depth - 1); i++)
1813         {
1814             *output_pointer++ = '\t';
1815         }
1816     }
1817     *output_pointer++ = '}';
1818     *output_pointer = '\0';
1819     output_buffer->depth--;
1820 
1821     return true;
1822 }
1823 
1824 /* Get Array size/item / object item. */
cJSON_GetArraySize(const cJSON * array)1825 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1826 {
1827     cJSON *child = NULL;
1828     size_t size = 0;
1829 
1830     if (array == NULL)
1831     {
1832         return 0;
1833     }
1834 
1835     child = array->child;
1836 
1837     while(child != NULL)
1838     {
1839         size++;
1840         child = child->next;
1841     }
1842 
1843     /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1844 
1845     return (int)size;
1846 }
1847 
get_array_item(const cJSON * array,size_t index)1848 static cJSON* get_array_item(const cJSON *array, size_t index)
1849 {
1850     cJSON *current_child = NULL;
1851 
1852     if (array == NULL)
1853     {
1854         return NULL;
1855     }
1856 
1857     current_child = array->child;
1858     while ((current_child != NULL) && (index > 0))
1859     {
1860         index--;
1861         current_child = current_child->next;
1862     }
1863 
1864     return current_child;
1865 }
1866 
cJSON_GetArrayItem(const cJSON * array,int index)1867 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1868 {
1869     if (index < 0)
1870     {
1871         return NULL;
1872     }
1873 
1874     return get_array_item(array, (size_t)index);
1875 }
1876 
get_object_item(const cJSON * const object,const char * const name,const cJSON_bool case_sensitive)1877 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1878 {
1879     cJSON *current_element = NULL;
1880 
1881     if ((object == NULL) || (name == NULL))
1882     {
1883         return NULL;
1884     }
1885 
1886     current_element = object->child;
1887     if (case_sensitive)
1888     {
1889         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1890         {
1891             current_element = current_element->next;
1892         }
1893     }
1894     else
1895     {
1896         while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1897         {
1898             current_element = current_element->next;
1899         }
1900     }
1901 
1902     if ((current_element == NULL) || (current_element->string == NULL)) {
1903         return NULL;
1904     }
1905 
1906     return current_element;
1907 }
1908 
cJSON_GetObjectItem(const cJSON * const object,const char * const string)1909 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1910 {
1911     return get_object_item(object, string, false);
1912 }
1913 
cJSON_GetObjectItemCaseSensitive(const cJSON * const object,const char * const string)1914 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1915 {
1916     return get_object_item(object, string, true);
1917 }
1918 
cJSON_HasObjectItem(const cJSON * object,const char * string)1919 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1920 {
1921     return cJSON_GetObjectItem(object, string) ? 1 : 0;
1922 }
1923 
1924 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)1925 static void suffix_object(cJSON *prev, cJSON *item)
1926 {
1927     prev->next = item;
1928     item->prev = prev;
1929 }
1930 
1931 /* Utility for handling references. */
create_reference(const cJSON * item,const internal_hooks * const hooks)1932 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1933 {
1934     cJSON *reference = NULL;
1935     if (item == NULL)
1936     {
1937         return NULL;
1938     }
1939 
1940     reference = cJSON_New_Item(hooks);
1941     if (reference == NULL)
1942     {
1943         return NULL;
1944     }
1945 
1946     memcpy(reference, item, sizeof(cJSON));
1947     reference->string = NULL;
1948     reference->type |= cJSON_IsReference;
1949     reference->next = reference->prev = NULL;
1950     return reference;
1951 }
1952 
add_item_to_array(cJSON * array,cJSON * item)1953 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1954 {
1955     cJSON *child = NULL;
1956 
1957     if ((item == NULL) || (array == NULL) || (array == item))
1958     {
1959         return false;
1960     }
1961 
1962     child = array->child;
1963     /*
1964      * To find the last item in array quickly, we use prev in array
1965      */
1966     if (child == NULL)
1967     {
1968         /* list is empty, start new one */
1969         array->child = item;
1970         item->prev = item;
1971         item->next = NULL;
1972     }
1973     else
1974     {
1975         /* append to the end */
1976         if (child->prev)
1977         {
1978             suffix_object(child->prev, item);
1979             array->child->prev = item;
1980         }
1981         else
1982         {
1983             while (child->next)
1984             {
1985                 child = child->next;
1986             }
1987             suffix_object(child, item);
1988             array->child->prev = item;
1989         }
1990     }
1991 
1992     return true;
1993 }
1994 
1995 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)1996 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1997 {
1998     return add_item_to_array(array, item);
1999 }
2000 
2001 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2002     #pragma GCC diagnostic push
2003 #endif
2004 #ifdef __GNUC__
2005 #pragma GCC diagnostic ignored "-Wcast-qual"
2006 #endif
2007 /* helper function to cast away const */
cast_away_const(const void * string)2008 static void* cast_away_const(const void* string)
2009 {
2010     return (void*)string;
2011 }
2012 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2013     #pragma GCC diagnostic pop
2014 #endif
2015 
2016 
add_item_to_object(cJSON * const object,const char * const string,cJSON * const item,const internal_hooks * const hooks,const cJSON_bool constant_key)2017 static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2018 {
2019     char *new_key = NULL;
2020     int new_type = cJSON_Invalid;
2021 
2022     if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2023     {
2024         return false;
2025     }
2026 
2027     if (constant_key)
2028     {
2029         new_key = (char*)cast_away_const(string);
2030         new_type = item->type | cJSON_StringIsConst;
2031     }
2032     else
2033     {
2034         new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2035         if (new_key == NULL)
2036         {
2037             return false;
2038         }
2039 
2040         new_type = item->type & ~cJSON_StringIsConst;
2041     }
2042 
2043     if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2044     {
2045         hooks->deallocate(item->string);
2046     }
2047 
2048     item->string = new_key;
2049     item->type = new_type;
2050 
2051     return add_item_to_array(object, item);
2052 }
2053 
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)2054 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2055 {
2056     return add_item_to_object(object, string, item, &global_hooks, false);
2057 }
2058 
2059 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)2060 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2061 {
2062     return add_item_to_object(object, string, item, &global_hooks, true);
2063 }
2064 
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)2065 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2066 {
2067     if (array == NULL)
2068     {
2069         return false;
2070     }
2071 
2072     return add_item_to_array(array, create_reference(item, &global_hooks));
2073 }
2074 
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)2075 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2076 {
2077     if ((object == NULL) || (string == NULL))
2078     {
2079         return false;
2080     }
2081 
2082     return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2083 }
2084 
cJSON_AddNullToObject(cJSON * const object,const char * const name)2085 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2086 {
2087     cJSON *null = cJSON_CreateNull();
2088     if (add_item_to_object(object, name, null, &global_hooks, false))
2089     {
2090         return null;
2091     }
2092 
2093     cJSON_Delete(null);
2094     return NULL;
2095 }
2096 
cJSON_AddTrueToObject(cJSON * const object,const char * const name)2097 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2098 {
2099     cJSON *true_item = cJSON_CreateTrue();
2100     if (add_item_to_object(object, name, true_item, &global_hooks, false))
2101     {
2102         return true_item;
2103     }
2104 
2105     cJSON_Delete(true_item);
2106     return NULL;
2107 }
2108 
cJSON_AddFalseToObject(cJSON * const object,const char * const name)2109 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2110 {
2111     cJSON *false_item = cJSON_CreateFalse();
2112     if (add_item_to_object(object, name, false_item, &global_hooks, false))
2113     {
2114         return false_item;
2115     }
2116 
2117     cJSON_Delete(false_item);
2118     return NULL;
2119 }
2120 
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)2121 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2122 {
2123     cJSON *bool_item = cJSON_CreateBool(boolean);
2124     if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2125     {
2126         return bool_item;
2127     }
2128 
2129     cJSON_Delete(bool_item);
2130     return NULL;
2131 }
2132 
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2133 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2134 {
2135     cJSON *number_item = cJSON_CreateNumber(number);
2136     if (add_item_to_object(object, name, number_item, &global_hooks, false))
2137     {
2138         return number_item;
2139     }
2140 
2141     cJSON_Delete(number_item);
2142     return NULL;
2143 }
2144 
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2145 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2146 {
2147     cJSON *string_item = cJSON_CreateString(string);
2148     if (add_item_to_object(object, name, string_item, &global_hooks, false))
2149     {
2150         return string_item;
2151     }
2152 
2153     cJSON_Delete(string_item);
2154     return NULL;
2155 }
2156 
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2157 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2158 {
2159     cJSON *raw_item = cJSON_CreateRaw(raw);
2160     if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2161     {
2162         return raw_item;
2163     }
2164 
2165     cJSON_Delete(raw_item);
2166     return NULL;
2167 }
2168 
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2169 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2170 {
2171     cJSON *object_item = cJSON_CreateObject();
2172     if (add_item_to_object(object, name, object_item, &global_hooks, false))
2173     {
2174         return object_item;
2175     }
2176 
2177     cJSON_Delete(object_item);
2178     return NULL;
2179 }
2180 
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2181 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2182 {
2183     cJSON *array = cJSON_CreateArray();
2184     if (add_item_to_object(object, name, array, &global_hooks, false))
2185     {
2186         return array;
2187     }
2188 
2189     cJSON_Delete(array);
2190     return NULL;
2191 }
2192 
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2193 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2194 {
2195     if ((parent == NULL) || (item == NULL))
2196     {
2197         return NULL;
2198     }
2199 
2200     if (item != parent->child)
2201     {
2202         /* not the first element */
2203         item->prev->next = item->next;
2204     }
2205     if (item->next != NULL)
2206     {
2207         /* not the last element */
2208         item->next->prev = item->prev;
2209     }
2210 
2211     if (item == parent->child)
2212     {
2213         /* first element */
2214         parent->child = item->next;
2215     }
2216     /* make sure the detached item doesn't point anywhere anymore */
2217     item->prev = NULL;
2218     item->next = NULL;
2219 
2220     return item;
2221 }
2222 
cJSON_DetachItemFromArray(cJSON * array,int which)2223 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2224 {
2225     if (which < 0)
2226     {
2227         return NULL;
2228     }
2229 
2230     return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2231 }
2232 
cJSON_DeleteItemFromArray(cJSON * array,int which)2233 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2234 {
2235     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2236 }
2237 
cJSON_DetachItemFromObject(cJSON * object,const char * string)2238 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2239 {
2240     cJSON *to_detach = cJSON_GetObjectItem(object, string);
2241 
2242     return cJSON_DetachItemViaPointer(object, to_detach);
2243 }
2244 
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2245 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2246 {
2247     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2248 
2249     return cJSON_DetachItemViaPointer(object, to_detach);
2250 }
2251 
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2252 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2253 {
2254     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2255 }
2256 
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2257 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2258 {
2259     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2260 }
2261 
2262 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2263 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2264 {
2265     cJSON *after_inserted = NULL;
2266 
2267     if (which < 0)
2268     {
2269         return false;
2270     }
2271 
2272     after_inserted = get_array_item(array, (size_t)which);
2273     if (after_inserted == NULL)
2274     {
2275         return add_item_to_array(array, newitem);
2276     }
2277 
2278     newitem->next = after_inserted;
2279     newitem->prev = after_inserted->prev;
2280     after_inserted->prev = newitem;
2281     if (after_inserted == array->child)
2282     {
2283         array->child = newitem;
2284     }
2285     else
2286     {
2287         newitem->prev->next = newitem;
2288     }
2289     return true;
2290 }
2291 
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2292 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2293 {
2294     if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2295     {
2296         return false;
2297     }
2298 
2299     if (replacement == item)
2300     {
2301         return true;
2302     }
2303 
2304     replacement->next = item->next;
2305     replacement->prev = item->prev;
2306 
2307     if (replacement->next != NULL)
2308     {
2309         replacement->next->prev = replacement;
2310     }
2311     if (parent->child == item)
2312     {
2313         parent->child = replacement;
2314     }
2315     else
2316     {   /*
2317          * To find the last item in array quickly, we use prev in array.
2318          * We can't modify the last item's next pointer where this item was the parent's child
2319          */
2320         if (replacement->prev != NULL)
2321         {
2322             replacement->prev->next = replacement;
2323         }
2324     }
2325 
2326     item->next = NULL;
2327     item->prev = NULL;
2328     cJSON_Delete(item);
2329 
2330     return true;
2331 }
2332 
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2333 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2334 {
2335     if (which < 0)
2336     {
2337         return false;
2338     }
2339 
2340     return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2341 }
2342 
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2343 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2344 {
2345     if ((replacement == NULL) || (string == NULL))
2346     {
2347         return false;
2348     }
2349 
2350     /* replace the name in the replacement */
2351     if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2352     {
2353         cJSON_free(replacement->string);
2354     }
2355     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2356     replacement->type &= ~cJSON_StringIsConst;
2357 
2358     return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2359 }
2360 
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2361 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2362 {
2363     return replace_item_in_object(object, string, newitem, false);
2364 }
2365 
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2366 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2367 {
2368     return replace_item_in_object(object, string, newitem, true);
2369 }
2370 
2371 /* Create basic types: */
cJSON_CreateNull(void)2372 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2373 {
2374     cJSON *item = cJSON_New_Item(&global_hooks);
2375     if(item)
2376     {
2377         item->type = cJSON_NULL;
2378     }
2379 
2380     return item;
2381 }
2382 
cJSON_CreateTrue(void)2383 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2384 {
2385     cJSON *item = cJSON_New_Item(&global_hooks);
2386     if(item)
2387     {
2388         item->type = cJSON_True;
2389     }
2390 
2391     return item;
2392 }
2393 
cJSON_CreateFalse(void)2394 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2395 {
2396     cJSON *item = cJSON_New_Item(&global_hooks);
2397     if(item)
2398     {
2399         item->type = cJSON_False;
2400     }
2401 
2402     return item;
2403 }
2404 
cJSON_CreateBool(cJSON_bool boolean)2405 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2406 {
2407     cJSON *item = cJSON_New_Item(&global_hooks);
2408     if(item)
2409     {
2410         item->type = boolean ? cJSON_True : cJSON_False;
2411     }
2412 
2413     return item;
2414 }
2415 
cJSON_CreateNumber(double num)2416 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2417 {
2418     cJSON *item = cJSON_New_Item(&global_hooks);
2419     if(item)
2420     {
2421         item->type = cJSON_Number;
2422         item->valuedouble = num;
2423 
2424         /* use saturation in case of overflow */
2425         if (num >= LLONG_MAX)
2426         {
2427             item->valueint = LLONG_MAX;
2428         }
2429         else if (num <= (double)LLONG_MIN)
2430         {
2431             item->valueint = LLONG_MIN;
2432         }
2433         else
2434         {
2435             item->valueint = (int64_t)num;
2436         }
2437     }
2438 
2439     return item;
2440 }
2441 
cJSON_CreateString(const char * string)2442 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2443 {
2444     cJSON *item = cJSON_New_Item(&global_hooks);
2445     if(item)
2446     {
2447         item->type = cJSON_String;
2448         item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2449         if(!item->valuestring)
2450         {
2451             cJSON_Delete(item);
2452             return NULL;
2453         }
2454     }
2455 
2456     return item;
2457 }
2458 
cJSON_CreateStringReference(const char * string)2459 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2460 {
2461     cJSON *item = cJSON_New_Item(&global_hooks);
2462     if (item != NULL)
2463     {
2464         item->type = cJSON_String | cJSON_IsReference;
2465         item->valuestring = (char*)cast_away_const(string);
2466     }
2467 
2468     return item;
2469 }
2470 
cJSON_CreateObjectReference(const cJSON * child)2471 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2472 {
2473     cJSON *item = cJSON_New_Item(&global_hooks);
2474     if (item != NULL) {
2475         item->type = cJSON_Object | cJSON_IsReference;
2476         item->child = (cJSON*)cast_away_const(child);
2477     }
2478 
2479     return item;
2480 }
2481 
cJSON_CreateArrayReference(const cJSON * child)2482 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2483     cJSON *item = cJSON_New_Item(&global_hooks);
2484     if (item != NULL) {
2485         item->type = cJSON_Array | cJSON_IsReference;
2486         item->child = (cJSON*)cast_away_const(child);
2487     }
2488 
2489     return item;
2490 }
2491 
cJSON_CreateRaw(const char * raw)2492 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2493 {
2494     cJSON *item = cJSON_New_Item(&global_hooks);
2495     if(item)
2496     {
2497         item->type = cJSON_Raw;
2498         item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2499         if(!item->valuestring)
2500         {
2501             cJSON_Delete(item);
2502             return NULL;
2503         }
2504     }
2505 
2506     return item;
2507 }
2508 
cJSON_CreateArray(void)2509 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2510 {
2511     cJSON *item = cJSON_New_Item(&global_hooks);
2512     if(item)
2513     {
2514         item->type=cJSON_Array;
2515     }
2516 
2517     return item;
2518 }
2519 
cJSON_CreateObject(void)2520 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2521 {
2522     cJSON *item = cJSON_New_Item(&global_hooks);
2523     if (item)
2524     {
2525         item->type = cJSON_Object;
2526     }
2527 
2528     return item;
2529 }
2530 
2531 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2532 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2533 {
2534     size_t i = 0;
2535     cJSON *n = NULL;
2536     cJSON *p = NULL;
2537     cJSON *a = NULL;
2538 
2539     if ((count < 0) || (numbers == NULL))
2540     {
2541         return NULL;
2542     }
2543 
2544     a = cJSON_CreateArray();
2545     for(i = 0; a && (i < (size_t)count); i++)
2546     {
2547         n = cJSON_CreateNumber(numbers[i]);
2548         if (!n)
2549         {
2550             cJSON_Delete(a);
2551             return NULL;
2552         }
2553         if(!i)
2554         {
2555             a->child = n;
2556         }
2557         else
2558         {
2559             suffix_object(p, n);
2560         }
2561         p = n;
2562     }
2563 
2564     return a;
2565 }
2566 
cJSON_CreateFloatArray(const float * numbers,int count)2567 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2568 {
2569     size_t i = 0;
2570     cJSON *n = NULL;
2571     cJSON *p = NULL;
2572     cJSON *a = NULL;
2573 
2574     if ((count < 0) || (numbers == NULL))
2575     {
2576         return NULL;
2577     }
2578 
2579     a = cJSON_CreateArray();
2580 
2581     for(i = 0; a && (i < (size_t)count); i++)
2582     {
2583         n = cJSON_CreateNumber((double)numbers[i]);
2584         if(!n)
2585         {
2586             cJSON_Delete(a);
2587             return NULL;
2588         }
2589         if(!i)
2590         {
2591             a->child = n;
2592         }
2593         else
2594         {
2595             suffix_object(p, n);
2596         }
2597         p = n;
2598     }
2599 
2600     return a;
2601 }
2602 
cJSON_CreateDoubleArray(const double * numbers,int count)2603 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2604 {
2605     size_t i = 0;
2606     cJSON *n = NULL;
2607     cJSON *p = NULL;
2608     cJSON *a = NULL;
2609 
2610     if ((count < 0) || (numbers == NULL))
2611     {
2612         return NULL;
2613     }
2614 
2615     a = cJSON_CreateArray();
2616 
2617     for(i = 0;a && (i < (size_t)count); i++)
2618     {
2619         n = cJSON_CreateNumber(numbers[i]);
2620         if(!n)
2621         {
2622             cJSON_Delete(a);
2623             return NULL;
2624         }
2625         if(!i)
2626         {
2627             a->child = n;
2628         }
2629         else
2630         {
2631             suffix_object(p, n);
2632         }
2633         p = n;
2634     }
2635 
2636     return a;
2637 }
2638 
cJSON_CreateStringArray(const char * const * strings,int count)2639 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2640 {
2641     size_t i = 0;
2642     cJSON *n = NULL;
2643     cJSON *p = NULL;
2644     cJSON *a = NULL;
2645 
2646     if ((count < 0) || (strings == NULL))
2647     {
2648         return NULL;
2649     }
2650 
2651     a = cJSON_CreateArray();
2652 
2653     for (i = 0; a && (i < (size_t)count); i++)
2654     {
2655         n = cJSON_CreateString(strings[i]);
2656         if(!n)
2657         {
2658             cJSON_Delete(a);
2659             return NULL;
2660         }
2661         if(!i)
2662         {
2663             a->child = n;
2664         }
2665         else
2666         {
2667             suffix_object(p,n);
2668         }
2669         p = n;
2670     }
2671 
2672     return a;
2673 }
2674 
2675 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2676 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2677 {
2678     cJSON *newitem = NULL;
2679     cJSON *child = NULL;
2680     cJSON *next = NULL;
2681     cJSON *newchild = NULL;
2682 
2683     /* Bail on bad ptr */
2684     if (!item)
2685     {
2686         goto fail;
2687     }
2688     /* Create new item */
2689     newitem = cJSON_New_Item(&global_hooks);
2690     if (!newitem)
2691     {
2692         goto fail;
2693     }
2694     /* Copy over all vars */
2695     newitem->type = item->type & (~cJSON_IsReference);
2696     newitem->valueint = item->valueint;
2697     newitem->valuedouble = item->valuedouble;
2698     if (item->valuestring)
2699     {
2700         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2701         if (!newitem->valuestring)
2702         {
2703             goto fail;
2704         }
2705     }
2706     if (item->string)
2707     {
2708         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2709         if (!newitem->string)
2710         {
2711             goto fail;
2712         }
2713     }
2714     /* If non-recursive, then we're done! */
2715     if (!recurse)
2716     {
2717         return newitem;
2718     }
2719     /* Walk the ->next chain for the child. */
2720     child = item->child;
2721     while (child != NULL)
2722     {
2723         newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2724         if (!newchild)
2725         {
2726             goto fail;
2727         }
2728         if (next != NULL)
2729         {
2730             /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2731             next->next = newchild;
2732             newchild->prev = next;
2733             next = newchild;
2734         }
2735         else
2736         {
2737             /* Set newitem->child and move to it */
2738             newitem->child = newchild;
2739             next = newchild;
2740         }
2741         child = child->next;
2742     }
2743 
2744     return newitem;
2745 
2746 fail:
2747     if (newitem != NULL)
2748     {
2749         cJSON_Delete(newitem);
2750     }
2751 
2752     return NULL;
2753 }
2754 
skip_oneline_comment(char ** input)2755 static void skip_oneline_comment(char **input)
2756 {
2757     *input += static_strlen("//");
2758 
2759     for (; (*input)[0] != '\0'; ++(*input))
2760     {
2761         if ((*input)[0] == '\n') {
2762             *input += static_strlen("\n");
2763             return;
2764         }
2765     }
2766 }
2767 
skip_multiline_comment(char ** input)2768 static void skip_multiline_comment(char **input)
2769 {
2770     *input += static_strlen("/*");
2771 
2772     for (; (*input)[0] != '\0'; ++(*input))
2773     {
2774         if (((*input)[0] == '*') && ((*input)[1] == '/'))
2775         {
2776             *input += static_strlen("*/");
2777             return;
2778         }
2779     }
2780 }
2781 
minify_string(char ** input,char ** output)2782 static void minify_string(char **input, char **output) {
2783     (*output)[0] = (*input)[0];
2784     *input += static_strlen("\"");
2785     *output += static_strlen("\"");
2786 
2787 
2788     for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2789         (*output)[0] = (*input)[0];
2790 
2791         if ((*input)[0] == '\"') {
2792             (*output)[0] = '\"';
2793             *input += static_strlen("\"");
2794             *output += static_strlen("\"");
2795             return;
2796         } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2797             (*output)[1] = (*input)[1];
2798             *input += static_strlen("\"");
2799             *output += static_strlen("\"");
2800         }
2801     }
2802 }
2803 
cJSON_Minify(char * json)2804 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2805 {
2806     char *into = json;
2807 
2808     if (json == NULL)
2809     {
2810         return;
2811     }
2812 
2813     while (json[0] != '\0')
2814     {
2815         switch (json[0])
2816         {
2817             case ' ':
2818             case '\t':
2819             case '\r':
2820             case '\n':
2821                 json++;
2822                 break;
2823 
2824             case '/':
2825                 if (json[1] == '/')
2826                 {
2827                     skip_oneline_comment(&json);
2828                 }
2829                 else if (json[1] == '*')
2830                 {
2831                     skip_multiline_comment(&json);
2832                 } else {
2833                     json++;
2834                 }
2835                 break;
2836 
2837             case '\"':
2838                 minify_string(&json, (char**)&into);
2839                 break;
2840 
2841             default:
2842                 into[0] = json[0];
2843                 json++;
2844                 into++;
2845         }
2846     }
2847 
2848     /* and null-terminate. */
2849     *into = '\0';
2850 }
2851 
cJSON_IsInvalid(const cJSON * const item)2852 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2853 {
2854     if (item == NULL)
2855     {
2856         return false;
2857     }
2858 
2859     return (item->type & 0xFF) == cJSON_Invalid;
2860 }
2861 
cJSON_IsFalse(const cJSON * const item)2862 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2863 {
2864     if (item == NULL)
2865     {
2866         return false;
2867     }
2868 
2869     return (item->type & 0xFF) == cJSON_False;
2870 }
2871 
cJSON_IsTrue(const cJSON * const item)2872 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2873 {
2874     if (item == NULL)
2875     {
2876         return false;
2877     }
2878 
2879     return (item->type & 0xff) == cJSON_True;
2880 }
2881 
2882 
cJSON_IsBool(const cJSON * const item)2883 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2884 {
2885     if (item == NULL)
2886     {
2887         return false;
2888     }
2889 
2890     return (item->type & (cJSON_True | cJSON_False)) != 0;
2891 }
cJSON_IsNull(const cJSON * const item)2892 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2893 {
2894     if (item == NULL)
2895     {
2896         return false;
2897     }
2898 
2899     return (item->type & 0xFF) == cJSON_NULL;
2900 }
2901 
cJSON_IsNumber(const cJSON * const item)2902 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2903 {
2904     if (item == NULL)
2905     {
2906         return false;
2907     }
2908 
2909     return (item->type & 0xFF) == cJSON_Number;
2910 }
2911 
cJSON_IsString(const cJSON * const item)2912 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2913 {
2914     if (item == NULL)
2915     {
2916         return false;
2917     }
2918 
2919     return (item->type & 0xFF) == cJSON_String;
2920 }
2921 
cJSON_IsArray(const cJSON * const item)2922 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2923 {
2924     if (item == NULL)
2925     {
2926         return false;
2927     }
2928 
2929     return (item->type & 0xFF) == cJSON_Array;
2930 }
2931 
cJSON_IsObject(const cJSON * const item)2932 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2933 {
2934     if (item == NULL)
2935     {
2936         return false;
2937     }
2938 
2939     return (item->type & 0xFF) == cJSON_Object;
2940 }
2941 
cJSON_IsRaw(const cJSON * const item)2942 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2943 {
2944     if (item == NULL)
2945     {
2946         return false;
2947     }
2948 
2949     return (item->type & 0xFF) == cJSON_Raw;
2950 }
2951 
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2952 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2953 {
2954     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2955     {
2956         return false;
2957     }
2958 
2959     /* check if type is valid */
2960     switch (a->type & 0xFF)
2961     {
2962         case cJSON_False:
2963         case cJSON_True:
2964         case cJSON_NULL:
2965         case cJSON_Number:
2966         case cJSON_String:
2967         case cJSON_Raw:
2968         case cJSON_Array:
2969         case cJSON_Object:
2970             break;
2971 
2972         default:
2973             return false;
2974     }
2975 
2976     /* identical objects are equal */
2977     if (a == b)
2978     {
2979         return true;
2980     }
2981 
2982     switch (a->type & 0xFF)
2983     {
2984         /* in these cases and equal type is enough */
2985         case cJSON_False:
2986         case cJSON_True:
2987         case cJSON_NULL:
2988             return true;
2989 
2990         case cJSON_Number:
2991             if (compare_double(a->valuedouble, b->valuedouble))
2992             {
2993                 return true;
2994             }
2995             return false;
2996 
2997         case cJSON_String:
2998         case cJSON_Raw:
2999             if ((a->valuestring == NULL) || (b->valuestring == NULL))
3000             {
3001                 return false;
3002             }
3003             if (strcmp(a->valuestring, b->valuestring) == 0)
3004             {
3005                 return true;
3006             }
3007 
3008             return false;
3009 
3010         case cJSON_Array:
3011         {
3012             cJSON *a_element = a->child;
3013             cJSON *b_element = b->child;
3014 
3015             for (; (a_element != NULL) && (b_element != NULL);)
3016             {
3017                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3018                 {
3019                     return false;
3020                 }
3021 
3022                 a_element = a_element->next;
3023                 b_element = b_element->next;
3024             }
3025 
3026             /* one of the arrays is longer than the other */
3027             if (a_element != b_element) {
3028                 return false;
3029             }
3030 
3031             return true;
3032         }
3033 
3034         case cJSON_Object:
3035         {
3036             cJSON *a_element = NULL;
3037             cJSON *b_element = NULL;
3038             cJSON_ArrayForEach(a_element, a)
3039             {
3040                 /* TODO This has O(n^2) runtime, which is horrible! */
3041                 b_element = get_object_item(b, a_element->string, case_sensitive);
3042                 if (b_element == NULL)
3043                 {
3044                     return false;
3045                 }
3046 
3047                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3048                 {
3049                     return false;
3050                 }
3051             }
3052 
3053             /* doing this twice, once on a and b to prevent true comparison if a subset of b
3054              * TODO: Do this the proper way, this is just a fix for now */
3055             cJSON_ArrayForEach(b_element, b)
3056             {
3057                 a_element = get_object_item(a, b_element->string, case_sensitive);
3058                 if (a_element == NULL)
3059                 {
3060                     return false;
3061                 }
3062 
3063                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
3064                 {
3065                     return false;
3066                 }
3067             }
3068 
3069             return true;
3070         }
3071 
3072         default:
3073             return false;
3074     }
3075 }
3076 
cJSON_malloc(size_t size)3077 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3078 {
3079     return global_hooks.allocate(size);
3080 }
3081 
cJSON_free(void * object)3082 CJSON_PUBLIC(void) cJSON_free(void *object)
3083 {
3084     global_hooks.deallocate(object);
3085 }
3086