xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/iq_parser_v2/j2s/cJSON.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
48 #ifdef ENABLE_LOCALES
49 #include <locale.h>
50 #endif
51 
52 #if defined(_MSC_VER)
53 #pragma warning (pop)
54 #endif
55 #ifdef __GNUC__
56 #pragma GCC visibility pop
57 #endif
58 
59 #include "cJSON.h"
60 
61 /* define our own boolean type */
62 #ifdef true
63 #undef true
64 #endif
65 #define true ((cJSON_bool)1)
66 
67 #ifdef false
68 #undef false
69 #endif
70 #define false ((cJSON_bool)0)
71 
72 /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73 #ifndef isinf
74 #define isinf(d) (isnan((d - d)) && !isnan(d))
75 #endif
76 #ifndef isnan
77 #define isnan(d) (d != d)
78 #endif
79 
80 #ifndef NAN
81 #ifdef _WIN32
82 #define NAN sqrt(-1.0)
83 #else
84 #define NAN 0.0/0.0
85 #endif
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 namespace RkCam {
95 
cJSON_GetErrorPtr(void)96 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
97 {
98     return (const char*) (global_error.json + global_error.position);
99 }
100 
cJSON_GetStringValue(const cJSON * const item)101 CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
102 {
103     if (!cJSON_IsString(item))
104     {
105         return NULL;
106     }
107 
108     return item->valuestring;
109 }
110 
cJSON_GetNumberValue(const cJSON * const item)111 CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
112 {
113     if (!cJSON_IsNumber(item))
114     {
115         return (double) NAN;
116     }
117 
118     return item->valuedouble;
119 }
120 
121 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
122 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 14)
123     #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
124 #endif
125 
cJSON_Version(void)126 CJSON_PUBLIC(const char*) cJSON_Version(void)
127 {
128     static char version[15];
129     sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
130 
131     return version;
132 }
133 
134 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
case_insensitive_strcmp(const unsigned char * string1,const unsigned char * string2)135 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
136 {
137     if ((string1 == NULL) || (string2 == NULL))
138     {
139         return 1;
140     }
141 
142     if (string1 == string2)
143     {
144         return 0;
145     }
146 
147     for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
148     {
149         if (*string1 == '\0')
150         {
151             return 0;
152         }
153     }
154 
155     return tolower(*string1) - tolower(*string2);
156 }
157 
158 typedef struct internal_hooks
159 {
160     void *(CJSON_CDECL *allocate)(size_t size);
161     void (CJSON_CDECL *deallocate)(void *pointer);
162     void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
163 } internal_hooks;
164 
165 #if defined(_MSC_VER)
166 /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
internal_malloc(size_t size)167 static void * CJSON_CDECL internal_malloc(size_t size)
168 {
169     return malloc(size);
170 }
internal_free(void * pointer)171 static void CJSON_CDECL internal_free(void *pointer)
172 {
173     free(pointer);
174 }
internal_realloc(void * pointer,size_t size)175 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
176 {
177     return realloc(pointer, size);
178 }
179 #else
180 #define internal_malloc malloc
181 #define internal_free free
182 #define internal_realloc realloc
183 #endif
184 
185 /* strlen of character literals resolved at compile time */
186 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
187 
188 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
189 
cJSON_strdup(const unsigned char * string,const internal_hooks * const hooks)190 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
191 {
192     size_t length = 0;
193     unsigned char *copy = NULL;
194 
195     if (string == NULL)
196     {
197         return NULL;
198     }
199 
200     length = strlen((const char*)string) + sizeof("");
201     copy = (unsigned char*)hooks->allocate(length);
202     if (copy == NULL)
203     {
204         return NULL;
205     }
206     memcpy(copy, string, length);
207 
208     return copy;
209 }
210 
cJSON_InitHooks(cJSON_Hooks * hooks)211 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
212 {
213     if (hooks == NULL)
214     {
215         /* Reset hooks */
216         global_hooks.allocate = malloc;
217         global_hooks.deallocate = free;
218         global_hooks.reallocate = realloc;
219         return;
220     }
221 
222     global_hooks.allocate = malloc;
223     if (hooks->malloc_fn != NULL)
224     {
225         global_hooks.allocate = hooks->malloc_fn;
226     }
227 
228     global_hooks.deallocate = free;
229     if (hooks->free_fn != NULL)
230     {
231         global_hooks.deallocate = hooks->free_fn;
232     }
233 
234     /* use realloc only if both free and malloc are used */
235     global_hooks.reallocate = NULL;
236     if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
237     {
238         global_hooks.reallocate = realloc;
239     }
240 }
241 
242 /* Internal constructor. */
cJSON_New_Item(const internal_hooks * const hooks)243 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
244 {
245     cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
246     if (node)
247     {
248         memset(node, '\0', sizeof(cJSON));
249     }
250 
251     return node;
252 }
253 
254 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * item)255 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
256 {
257     cJSON *next = NULL;
258     while (item != NULL)
259     {
260         next = item->next;
261         if (!(item->type & cJSON_IsReference) && (item->child != NULL))
262         {
263             cJSON_Delete(item->child);
264         }
265         if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
266         {
267             global_hooks.deallocate(item->valuestring);
268         }
269         if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
270         {
271             global_hooks.deallocate(item->string);
272         }
273         global_hooks.deallocate(item);
274         item = next;
275     }
276 }
277 
278 /* get the decimal point character of the current locale */
get_decimal_point(void)279 static unsigned char get_decimal_point(void)
280 {
281 #ifdef ENABLE_LOCALES
282     struct lconv *lconv = localeconv();
283     return (unsigned char) lconv->decimal_point[0];
284 #else
285     return '.';
286 #endif
287 }
288 
289 typedef struct
290 {
291     const unsigned char *content;
292     size_t length;
293     size_t offset;
294     size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
295     internal_hooks hooks;
296 } parse_buffer;
297 
298 /* check if the given size is left to read in a given parse buffer (starting with 1) */
299 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300 /* check if the buffer can be accessed at the given index (starting with 0) */
301 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303 /* get a pointer to the buffer at the position */
304 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
305 
306 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)307 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308 {
309     double number = 0;
310     unsigned char *after_end = NULL;
311     unsigned char number_c_string[64];
312     unsigned char decimal_point = get_decimal_point();
313     size_t i = 0;
314 
315     if ((input_buffer == NULL) || (input_buffer->content == NULL))
316     {
317         return false;
318     }
319 
320     /* copy the number into a temporary buffer and replace '.' with the decimal point
321      * of the current locale (for strtod)
322      * This also takes care of '\0' not necessarily being available for marking the end of the input */
323     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
324     {
325         switch (buffer_at_offset(input_buffer)[i])
326         {
327             case '0':
328             case '1':
329             case '2':
330             case '3':
331             case '4':
332             case '5':
333             case '6':
334             case '7':
335             case '8':
336             case '9':
337             case '+':
338             case '-':
339             case 'e':
340             case 'E':
341                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
342                 break;
343 
344             case '.':
345                 number_c_string[i] = decimal_point;
346                 break;
347 
348             default:
349                 goto loop_end;
350         }
351     }
352 loop_end:
353     number_c_string[i] = '\0';
354 
355     number = strtod((const char*)number_c_string, (char**)&after_end);
356     if (number_c_string == after_end)
357     {
358         return false; /* parse_error */
359     }
360 
361     item->valuedouble = number;
362 
363     /* use saturation in case of overflow */
364     if (number >= INT_MAX)
365     {
366         item->valueint = INT_MAX;
367     }
368     else if (number <= (double)INT_MIN)
369     {
370         item->valueint = INT_MIN;
371     }
372     else
373     {
374         item->valueint = (int)number;
375     }
376 
377     item->type = cJSON_Number;
378 
379     input_buffer->offset += (size_t)(after_end - number_c_string);
380     return true;
381 }
382 
383 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)384 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
385 {
386     if (number >= INT_MAX)
387     {
388         object->valueint = INT_MAX;
389     }
390     else if (number <= (double)INT_MIN)
391     {
392         object->valueint = INT_MIN;
393     }
394     else
395     {
396         object->valueint = (int)number;
397     }
398 
399     return object->valuedouble = number;
400 }
401 
cJSON_SetValuestring(cJSON * object,const char * valuestring)402 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
403 {
404     char *copy = NULL;
405     /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
406     if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
407     {
408         return NULL;
409     }
410     if (strlen(valuestring) <= strlen(object->valuestring))
411     {
412         strcpy(object->valuestring, valuestring);
413         return object->valuestring;
414     }
415     copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
416     if (copy == NULL)
417     {
418         return NULL;
419     }
420     if (object->valuestring != NULL)
421     {
422         cJSON_free(object->valuestring);
423     }
424     object->valuestring = copy;
425 
426     return copy;
427 }
428 
429 typedef struct
430 {
431     unsigned char *buffer;
432     size_t length;
433     size_t offset;
434     size_t depth; /* current nesting depth (for formatted printing) */
435     cJSON_bool noalloc;
436     cJSON_bool format; /* is this print a formatted print */
437     internal_hooks hooks;
438 } printbuffer;
439 
440 /* realloc printbuffer if necessary to have at least "needed" bytes more */
ensure(printbuffer * const p,size_t needed)441 static unsigned char* ensure(printbuffer * const p, size_t needed)
442 {
443     unsigned char *newbuffer = NULL;
444     size_t newsize = 0;
445 
446     if ((p == NULL) || (p->buffer == NULL))
447     {
448         return NULL;
449     }
450 
451     if ((p->length > 0) && (p->offset >= p->length))
452     {
453         /* make sure that offset is valid */
454         return NULL;
455     }
456 
457     if (needed > INT_MAX)
458     {
459         /* sizes bigger than INT_MAX are currently not supported */
460         return NULL;
461     }
462 
463     needed += p->offset + 1;
464     if (needed <= p->length)
465     {
466         return p->buffer + p->offset;
467     }
468 
469     if (p->noalloc) {
470         return NULL;
471     }
472 
473     /* calculate new buffer size */
474     if (needed > (INT_MAX / 2))
475     {
476         /* overflow of int, use INT_MAX if possible */
477         if (needed <= INT_MAX)
478         {
479             newsize = INT_MAX;
480         }
481         else
482         {
483             return NULL;
484         }
485     }
486     else
487     {
488         newsize = needed * 2;
489     }
490 
491     if (p->hooks.reallocate != NULL)
492     {
493         /* reallocate with realloc if available */
494         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
495         if (newbuffer == NULL)
496         {
497             p->hooks.deallocate(p->buffer);
498             p->length = 0;
499             p->buffer = NULL;
500 
501             return NULL;
502         }
503     }
504     else
505     {
506         /* otherwise reallocate manually */
507         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
508         if (!newbuffer)
509         {
510             p->hooks.deallocate(p->buffer);
511             p->length = 0;
512             p->buffer = NULL;
513 
514             return NULL;
515         }
516         if (newbuffer)
517         {
518             memcpy(newbuffer, p->buffer, p->offset + 1);
519         }
520         p->hooks.deallocate(p->buffer);
521     }
522     p->length = newsize;
523     p->buffer = newbuffer;
524 
525     return newbuffer + p->offset;
526 }
527 
528 /* calculate the new length of the string in a printbuffer and update the offset */
update_offset(printbuffer * const buffer)529 static void update_offset(printbuffer * const buffer)
530 {
531     const unsigned char *buffer_pointer = NULL;
532     if ((buffer == NULL) || (buffer->buffer == NULL))
533     {
534         return;
535     }
536     buffer_pointer = buffer->buffer + buffer->offset;
537 
538     buffer->offset += strlen((const char*)buffer_pointer);
539 }
540 
541 /* securely comparison of floating-point variables */
compare_double(double a,double b)542 static cJSON_bool compare_double(double a, double b)
543 {
544     double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
545     return (fabs(a - b) <= maxVal * DBL_EPSILON);
546 }
547 
548 /* Render the number nicely from the given item into a string. */
print_number(const cJSON * const item,printbuffer * const output_buffer)549 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
550 {
551     unsigned char *output_pointer = NULL;
552     double d = item->valuedouble;
553     int length = 0;
554     size_t i = 0;
555     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
556     unsigned char decimal_point = get_decimal_point();
557     double test = 0.0;
558 
559     if (output_buffer == NULL)
560     {
561         return false;
562     }
563 
564     /* This checks for NaN and Infinity */
565     if (isnan(d) || isinf(d))
566     {
567         length = sprintf((char*)number_buffer, "null");
568     }
569     else
570     {
571 #if 0
572         /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
573         length = sprintf((char*)number_buffer, "%1.15g", d);
574 
575         /* Check whether the original double can be recovered */
576         if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
577         {
578             /* If not, print with 17 decimal places of precision */
579             length = sprintf((char*)number_buffer, "%1.17g", d);
580         }
581 #else
582 	/* HACK: Force use 6 decimal places of precision */
583         length = sprintf((char*)number_buffer, "%1.6g", d);
584 #endif
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     if (head != NULL) {
1524         head->prev = current_item;
1525     }
1526 
1527     item->type = cJSON_Array;
1528     item->child = head;
1529 
1530     input_buffer->offset++;
1531 
1532     return true;
1533 
1534 fail:
1535     if (head != NULL)
1536     {
1537         cJSON_Delete(head);
1538     }
1539 
1540     return false;
1541 }
1542 
1543 /* Render an array to text */
print_array(const cJSON * const item,printbuffer * const output_buffer)1544 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1545 {
1546     unsigned char *output_pointer = NULL;
1547     size_t length = 0;
1548     cJSON *current_element = item->child;
1549 
1550     if (output_buffer == NULL)
1551     {
1552         return false;
1553     }
1554 
1555     /* Compose the output array. */
1556     /* opening square bracket */
1557     output_pointer = ensure(output_buffer, 1);
1558     if (output_pointer == NULL)
1559     {
1560         return false;
1561     }
1562 
1563     *output_pointer = '[';
1564     output_buffer->offset++;
1565     output_buffer->depth++;
1566 
1567     while (current_element != NULL)
1568     {
1569         if (!print_value(current_element, output_buffer))
1570         {
1571             return false;
1572         }
1573         update_offset(output_buffer);
1574         if (current_element->next)
1575         {
1576             length = (size_t) (output_buffer->format ? 2 : 1);
1577             output_pointer = ensure(output_buffer, length + 1);
1578             if (output_pointer == NULL)
1579             {
1580                 return false;
1581             }
1582             *output_pointer++ = ',';
1583             if(output_buffer->format)
1584             {
1585                 *output_pointer++ = ' ';
1586             }
1587             *output_pointer = '\0';
1588             output_buffer->offset += length;
1589         }
1590         current_element = current_element->next;
1591     }
1592 
1593     output_pointer = ensure(output_buffer, 2);
1594     if (output_pointer == NULL)
1595     {
1596         return false;
1597     }
1598     *output_pointer++ = ']';
1599     *output_pointer = '\0';
1600     output_buffer->depth--;
1601 
1602     return true;
1603 }
1604 
1605 /* Build an object from the text. */
parse_object(cJSON * const item,parse_buffer * const input_buffer)1606 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1607 {
1608     cJSON *head = NULL; /* linked list head */
1609     cJSON *current_item = NULL;
1610 
1611     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1612     {
1613         return false; /* to deeply nested */
1614     }
1615     input_buffer->depth++;
1616 
1617     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1618     {
1619         goto fail; /* not an object */
1620     }
1621 
1622     input_buffer->offset++;
1623     buffer_skip_whitespace(input_buffer);
1624     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1625     {
1626         goto success; /* empty object */
1627     }
1628 
1629     /* check if we skipped to the end of the buffer */
1630     if (cannot_access_at_index(input_buffer, 0))
1631     {
1632         input_buffer->offset--;
1633         goto fail;
1634     }
1635 
1636     /* step back to character in front of the first element */
1637     input_buffer->offset--;
1638     /* loop through the comma separated array elements */
1639     do
1640     {
1641         /* allocate next item */
1642         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1643         if (new_item == NULL)
1644         {
1645             goto fail; /* allocation failure */
1646         }
1647 
1648         /* attach next item to list */
1649         if (head == NULL)
1650         {
1651             /* start the linked list */
1652             current_item = head = new_item;
1653         }
1654         else
1655         {
1656             /* add to the end and advance */
1657             current_item->next = new_item;
1658             new_item->prev = current_item;
1659             current_item = new_item;
1660         }
1661 
1662         /* parse the name of the child */
1663         input_buffer->offset++;
1664         buffer_skip_whitespace(input_buffer);
1665         if (!parse_string(current_item, input_buffer))
1666         {
1667             goto fail; /* failed to parse name */
1668         }
1669         buffer_skip_whitespace(input_buffer);
1670 
1671         /* swap valuestring and string, because we parsed the name */
1672         current_item->string = current_item->valuestring;
1673         current_item->valuestring = NULL;
1674 
1675         if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1676         {
1677             goto fail; /* invalid object */
1678         }
1679 
1680         /* parse the value */
1681         input_buffer->offset++;
1682         buffer_skip_whitespace(input_buffer);
1683         if (!parse_value(current_item, input_buffer))
1684         {
1685             goto fail; /* failed to parse value */
1686         }
1687         buffer_skip_whitespace(input_buffer);
1688     }
1689     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1690 
1691     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1692     {
1693         goto fail; /* expected end of object */
1694     }
1695 
1696 success:
1697     input_buffer->depth--;
1698 
1699     if (head != NULL) {
1700         head->prev = current_item;
1701     }
1702 
1703     item->type = cJSON_Object;
1704     item->child = head;
1705 
1706     input_buffer->offset++;
1707     return true;
1708 
1709 fail:
1710     if (head != NULL)
1711     {
1712         cJSON_Delete(head);
1713     }
1714 
1715     return false;
1716 }
1717 
1718 /* Render an object to text. */
print_object(const cJSON * const item,printbuffer * const output_buffer)1719 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1720 {
1721     unsigned char *output_pointer = NULL;
1722     size_t length = 0;
1723     cJSON *current_item = item->child;
1724 
1725     if (output_buffer == NULL)
1726     {
1727         return false;
1728     }
1729 
1730     /* Compose the output: */
1731     length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1732     output_pointer = ensure(output_buffer, length + 1);
1733     if (output_pointer == NULL)
1734     {
1735         return false;
1736     }
1737 
1738     *output_pointer++ = '{';
1739     output_buffer->depth++;
1740     if (output_buffer->format)
1741     {
1742         *output_pointer++ = '\n';
1743     }
1744     output_buffer->offset += length;
1745 
1746     while (current_item)
1747     {
1748         if (output_buffer->format)
1749         {
1750             size_t i;
1751             output_pointer = ensure(output_buffer, output_buffer->depth);
1752             if (output_pointer == NULL)
1753             {
1754                 return false;
1755             }
1756             for (i = 0; i < output_buffer->depth; i++)
1757             {
1758                 *output_pointer++ = '\t';
1759             }
1760             output_buffer->offset += output_buffer->depth;
1761         }
1762 
1763         /* print key */
1764         if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1765         {
1766             return false;
1767         }
1768         update_offset(output_buffer);
1769 
1770         length = (size_t) (output_buffer->format ? 2 : 1);
1771         output_pointer = ensure(output_buffer, length);
1772         if (output_pointer == NULL)
1773         {
1774             return false;
1775         }
1776         *output_pointer++ = ':';
1777         if (output_buffer->format)
1778         {
1779             *output_pointer++ = '\t';
1780         }
1781         output_buffer->offset += length;
1782 
1783         /* print value */
1784         if (!print_value(current_item, output_buffer))
1785         {
1786             return false;
1787         }
1788         update_offset(output_buffer);
1789 
1790         /* print comma if not last */
1791         length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1792         output_pointer = ensure(output_buffer, length + 1);
1793         if (output_pointer == NULL)
1794         {
1795             return false;
1796         }
1797         if (current_item->next)
1798         {
1799             *output_pointer++ = ',';
1800         }
1801 
1802         if (output_buffer->format)
1803         {
1804             *output_pointer++ = '\n';
1805         }
1806         *output_pointer = '\0';
1807         output_buffer->offset += length;
1808 
1809         current_item = current_item->next;
1810     }
1811 
1812     output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1813     if (output_pointer == NULL)
1814     {
1815         return false;
1816     }
1817     if (output_buffer->format)
1818     {
1819         size_t i;
1820         for (i = 0; i < (output_buffer->depth - 1); i++)
1821         {
1822             *output_pointer++ = '\t';
1823         }
1824     }
1825     *output_pointer++ = '}';
1826     *output_pointer = '\0';
1827     output_buffer->depth--;
1828 
1829     return true;
1830 }
1831 
1832 /* Get Array size/item / object item. */
cJSON_GetArraySize(const cJSON * array)1833 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1834 {
1835     cJSON *child = NULL;
1836     size_t size = 0;
1837 
1838     if (array == NULL)
1839     {
1840         return 0;
1841     }
1842 
1843     child = array->child;
1844 
1845     while(child != NULL)
1846     {
1847         size++;
1848         child = child->next;
1849     }
1850 
1851     /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1852 
1853     return (int)size;
1854 }
1855 
get_array_item(const cJSON * array,size_t index)1856 static cJSON* get_array_item(const cJSON *array, size_t index)
1857 {
1858     cJSON *current_child = NULL;
1859 
1860     if (array == NULL)
1861     {
1862         return NULL;
1863     }
1864 
1865     current_child = array->child;
1866     while ((current_child != NULL) && (index > 0))
1867     {
1868         index--;
1869         current_child = current_child->next;
1870     }
1871 
1872     return current_child;
1873 }
1874 
cJSON_GetArrayItem(const cJSON * array,int index)1875 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1876 {
1877     if (index < 0)
1878     {
1879         return NULL;
1880     }
1881 
1882     return get_array_item(array, (size_t)index);
1883 }
1884 
get_object_item(const cJSON * const object,const char * const name,const cJSON_bool case_sensitive)1885 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1886 {
1887     cJSON *current_element = NULL;
1888 
1889     if ((object == NULL) || (name == NULL))
1890     {
1891         return NULL;
1892     }
1893 
1894     current_element = object->child;
1895     if (case_sensitive)
1896     {
1897         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1898         {
1899             current_element = current_element->next;
1900         }
1901     }
1902     else
1903     {
1904         while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1905         {
1906             current_element = current_element->next;
1907         }
1908     }
1909 
1910     if ((current_element == NULL) || (current_element->string == NULL)) {
1911         return NULL;
1912     }
1913 
1914     return current_element;
1915 }
1916 
cJSON_GetObjectItem(const cJSON * const object,const char * const string)1917 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1918 {
1919     return get_object_item(object, string, false);
1920 }
1921 
cJSON_GetObjectItemCaseSensitive(const cJSON * const object,const char * const string)1922 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1923 {
1924     return get_object_item(object, string, true);
1925 }
1926 
cJSON_HasObjectItem(const cJSON * object,const char * string)1927 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1928 {
1929     return cJSON_GetObjectItem(object, string) ? 1 : 0;
1930 }
1931 
1932 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)1933 static void suffix_object(cJSON *prev, cJSON *item)
1934 {
1935     prev->next = item;
1936     item->prev = prev;
1937 }
1938 
1939 /* Utility for handling references. */
create_reference(const cJSON * item,const internal_hooks * const hooks)1940 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1941 {
1942     cJSON *reference = NULL;
1943     if (item == NULL)
1944     {
1945         return NULL;
1946     }
1947 
1948     reference = cJSON_New_Item(hooks);
1949     if (reference == NULL)
1950     {
1951         return NULL;
1952     }
1953 
1954     memcpy(reference, item, sizeof(cJSON));
1955     reference->string = NULL;
1956     reference->type |= cJSON_IsReference;
1957     reference->next = reference->prev = NULL;
1958     return reference;
1959 }
1960 
add_item_to_array(cJSON * array,cJSON * item)1961 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1962 {
1963     cJSON *child = NULL;
1964 
1965     if ((item == NULL) || (array == NULL) || (array == item))
1966     {
1967         return false;
1968     }
1969 
1970     child = array->child;
1971     /*
1972      * To find the last item in array quickly, we use prev in array
1973      */
1974     if (child == NULL)
1975     {
1976         /* list is empty, start new one */
1977         array->child = item;
1978         item->prev = item;
1979         item->next = NULL;
1980     }
1981     else
1982     {
1983         /* append to the end */
1984         if (child->prev)
1985         {
1986             suffix_object(child->prev, item);
1987             array->child->prev = item;
1988         }
1989     }
1990 
1991     return true;
1992 }
1993 
1994 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)1995 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1996 {
1997     return add_item_to_array(array, item);
1998 }
1999 
2000 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2001     #pragma GCC diagnostic push
2002 #endif
2003 #ifdef __GNUC__
2004 #pragma GCC diagnostic ignored "-Wcast-qual"
2005 #endif
2006 /* helper function to cast away const */
cast_away_const(const void * string)2007 static void* cast_away_const(const void* string)
2008 {
2009     return (void*)string;
2010 }
2011 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2012     #pragma GCC diagnostic pop
2013 #endif
2014 
2015 
add_item_to_object(cJSON * const object,const char * const string,cJSON * const item,const internal_hooks * const hooks,const cJSON_bool constant_key)2016 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)
2017 {
2018     char *new_key = NULL;
2019     int new_type = cJSON_Invalid;
2020 
2021     if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2022     {
2023         return false;
2024     }
2025 
2026     if (constant_key)
2027     {
2028         new_key = (char*)cast_away_const(string);
2029         new_type = item->type | cJSON_StringIsConst;
2030     }
2031     else
2032     {
2033         new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2034         if (new_key == NULL)
2035         {
2036             return false;
2037         }
2038 
2039         new_type = item->type & ~cJSON_StringIsConst;
2040     }
2041 
2042     if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2043     {
2044         hooks->deallocate(item->string);
2045     }
2046 
2047     item->string = new_key;
2048     item->type = new_type;
2049 
2050     return add_item_to_array(object, item);
2051 }
2052 
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)2053 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2054 {
2055     return add_item_to_object(object, string, item, &global_hooks, false);
2056 }
2057 
2058 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)2059 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2060 {
2061     return add_item_to_object(object, string, item, &global_hooks, true);
2062 }
2063 
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)2064 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2065 {
2066     if (array == NULL)
2067     {
2068         return false;
2069     }
2070 
2071     return add_item_to_array(array, create_reference(item, &global_hooks));
2072 }
2073 
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)2074 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2075 {
2076     if ((object == NULL) || (string == NULL))
2077     {
2078         return false;
2079     }
2080 
2081     return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2082 }
2083 
cJSON_AddNullToObject(cJSON * const object,const char * const name)2084 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2085 {
2086     cJSON *null = cJSON_CreateNull();
2087     if (add_item_to_object(object, name, null, &global_hooks, false))
2088     {
2089         return null;
2090     }
2091 
2092     cJSON_Delete(null);
2093     return NULL;
2094 }
2095 
cJSON_AddTrueToObject(cJSON * const object,const char * const name)2096 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2097 {
2098     cJSON *true_item = cJSON_CreateTrue();
2099     if (add_item_to_object(object, name, true_item, &global_hooks, false))
2100     {
2101         return true_item;
2102     }
2103 
2104     cJSON_Delete(true_item);
2105     return NULL;
2106 }
2107 
cJSON_AddFalseToObject(cJSON * const object,const char * const name)2108 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2109 {
2110     cJSON *false_item = cJSON_CreateFalse();
2111     if (add_item_to_object(object, name, false_item, &global_hooks, false))
2112     {
2113         return false_item;
2114     }
2115 
2116     cJSON_Delete(false_item);
2117     return NULL;
2118 }
2119 
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)2120 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2121 {
2122     cJSON *bool_item = cJSON_CreateBool(boolean);
2123     if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2124     {
2125         return bool_item;
2126     }
2127 
2128     cJSON_Delete(bool_item);
2129     return NULL;
2130 }
2131 
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2132 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2133 {
2134     cJSON *number_item = cJSON_CreateNumber(number);
2135     if (add_item_to_object(object, name, number_item, &global_hooks, false))
2136     {
2137         return number_item;
2138     }
2139 
2140     cJSON_Delete(number_item);
2141     return NULL;
2142 }
2143 
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2144 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2145 {
2146     cJSON *string_item = cJSON_CreateString(string);
2147     if (add_item_to_object(object, name, string_item, &global_hooks, false))
2148     {
2149         return string_item;
2150     }
2151 
2152     cJSON_Delete(string_item);
2153     return NULL;
2154 }
2155 
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2156 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2157 {
2158     cJSON *raw_item = cJSON_CreateRaw(raw);
2159     if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2160     {
2161         return raw_item;
2162     }
2163 
2164     cJSON_Delete(raw_item);
2165     return NULL;
2166 }
2167 
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2168 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2169 {
2170     cJSON *object_item = cJSON_CreateObject();
2171     if (add_item_to_object(object, name, object_item, &global_hooks, false))
2172     {
2173         return object_item;
2174     }
2175 
2176     cJSON_Delete(object_item);
2177     return NULL;
2178 }
2179 
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2180 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2181 {
2182     cJSON *array = cJSON_CreateArray();
2183     if (add_item_to_object(object, name, array, &global_hooks, false))
2184     {
2185         return array;
2186     }
2187 
2188     cJSON_Delete(array);
2189     return NULL;
2190 }
2191 
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2192 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2193 {
2194     if ((parent == NULL) || (item == NULL))
2195     {
2196         return NULL;
2197     }
2198 
2199     if (item != parent->child)
2200     {
2201         /* not the first element */
2202         item->prev->next = item->next;
2203     }
2204     if (item->next != NULL)
2205     {
2206         /* not the last element */
2207         item->next->prev = item->prev;
2208     }
2209 
2210     if (item == parent->child)
2211     {
2212         /* first element */
2213         parent->child = item->next;
2214     }
2215     else if (item->next == NULL)
2216     {
2217         /* last element */
2218         parent->child->prev = item->prev;
2219     }
2220 
2221     /* make sure the detached item doesn't point anywhere anymore */
2222     item->prev = NULL;
2223     item->next = NULL;
2224 
2225     return item;
2226 }
2227 
cJSON_DetachItemFromArray(cJSON * array,int which)2228 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2229 {
2230     if (which < 0)
2231     {
2232         return NULL;
2233     }
2234 
2235     return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2236 }
2237 
cJSON_DeleteItemFromArray(cJSON * array,int which)2238 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2239 {
2240     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2241 }
2242 
cJSON_DetachItemFromObject(cJSON * object,const char * string)2243 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2244 {
2245     cJSON *to_detach = cJSON_GetObjectItem(object, string);
2246 
2247     return cJSON_DetachItemViaPointer(object, to_detach);
2248 }
2249 
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2250 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2251 {
2252     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2253 
2254     return cJSON_DetachItemViaPointer(object, to_detach);
2255 }
2256 
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2257 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2258 {
2259     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2260 }
2261 
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2262 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2263 {
2264     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2265 }
2266 
2267 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2268 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2269 {
2270     cJSON *after_inserted = NULL;
2271 
2272     if (which < 0)
2273     {
2274         return false;
2275     }
2276 
2277     after_inserted = get_array_item(array, (size_t)which);
2278     if (after_inserted == NULL)
2279     {
2280         return add_item_to_array(array, newitem);
2281     }
2282 
2283     newitem->next = after_inserted;
2284     newitem->prev = after_inserted->prev;
2285     after_inserted->prev = newitem;
2286     if (after_inserted == array->child)
2287     {
2288         array->child = newitem;
2289     }
2290     else
2291     {
2292         newitem->prev->next = newitem;
2293     }
2294     return true;
2295 }
2296 
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2297 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2298 {
2299     if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2300     {
2301         return false;
2302     }
2303 
2304     if (replacement == item)
2305     {
2306         return true;
2307     }
2308 
2309     replacement->next = item->next;
2310     replacement->prev = item->prev;
2311 
2312     if (replacement->next != NULL)
2313     {
2314         replacement->next->prev = replacement;
2315     }
2316     if (parent->child == item)
2317     {
2318         if (parent->child->prev == parent->child)
2319         {
2320             replacement->prev = replacement;
2321         }
2322         parent->child = replacement;
2323     }
2324     else
2325     {   /*
2326          * To find the last item in array quickly, we use prev in array.
2327          * We can't modify the last item's next pointer where this item was the parent's child
2328          */
2329         if (replacement->prev != NULL)
2330         {
2331             replacement->prev->next = replacement;
2332         }
2333         if (replacement->next == NULL)
2334         {
2335             parent->child->prev = replacement;
2336         }
2337     }
2338 
2339     item->next = NULL;
2340     item->prev = NULL;
2341     cJSON_Delete(item);
2342 
2343     return true;
2344 }
2345 
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2346 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2347 {
2348     if (which < 0)
2349     {
2350         return false;
2351     }
2352 
2353     return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2354 }
2355 
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2356 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2357 {
2358     if ((replacement == NULL) || (string == NULL))
2359     {
2360         return false;
2361     }
2362 
2363     /* replace the name in the replacement */
2364     if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2365     {
2366         cJSON_free(replacement->string);
2367     }
2368     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2369     replacement->type &= ~cJSON_StringIsConst;
2370 
2371     return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2372 }
2373 
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2374 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2375 {
2376     return replace_item_in_object(object, string, newitem, false);
2377 }
2378 
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2379 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2380 {
2381     return replace_item_in_object(object, string, newitem, true);
2382 }
2383 
2384 /* Create basic types: */
cJSON_CreateNull(void)2385 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2386 {
2387     cJSON *item = cJSON_New_Item(&global_hooks);
2388     if(item)
2389     {
2390         item->type = cJSON_NULL;
2391     }
2392 
2393     return item;
2394 }
2395 
cJSON_CreateTrue(void)2396 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2397 {
2398     cJSON *item = cJSON_New_Item(&global_hooks);
2399     if(item)
2400     {
2401         item->type = cJSON_True;
2402     }
2403 
2404     return item;
2405 }
2406 
cJSON_CreateFalse(void)2407 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2408 {
2409     cJSON *item = cJSON_New_Item(&global_hooks);
2410     if(item)
2411     {
2412         item->type = cJSON_False;
2413     }
2414 
2415     return item;
2416 }
2417 
cJSON_CreateBool(cJSON_bool boolean)2418 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2419 {
2420     cJSON *item = cJSON_New_Item(&global_hooks);
2421     if(item)
2422     {
2423         item->type = boolean ? cJSON_True : cJSON_False;
2424     }
2425 
2426     return item;
2427 }
2428 
cJSON_CreateNumber(double num)2429 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2430 {
2431     cJSON *item = cJSON_New_Item(&global_hooks);
2432     if(item)
2433     {
2434         item->type = cJSON_Number;
2435         item->valuedouble = num;
2436 
2437         /* use saturation in case of overflow */
2438         if (num >= INT_MAX)
2439         {
2440             item->valueint = INT_MAX;
2441         }
2442         else if (num <= (double)INT_MIN)
2443         {
2444             item->valueint = INT_MIN;
2445         }
2446         else
2447         {
2448             item->valueint = (int)num;
2449         }
2450     }
2451 
2452     return item;
2453 }
2454 
cJSON_CreateString(const char * string)2455 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2456 {
2457     cJSON *item = cJSON_New_Item(&global_hooks);
2458     if(item)
2459     {
2460         item->type = cJSON_String;
2461         item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2462         if(!item->valuestring)
2463         {
2464             cJSON_Delete(item);
2465             return NULL;
2466         }
2467     }
2468 
2469     return item;
2470 }
2471 
cJSON_CreateStringReference(const char * string)2472 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2473 {
2474     cJSON *item = cJSON_New_Item(&global_hooks);
2475     if (item != NULL)
2476     {
2477         item->type = cJSON_String | cJSON_IsReference;
2478         item->valuestring = (char*)cast_away_const(string);
2479     }
2480 
2481     return item;
2482 }
2483 
cJSON_CreateObjectReference(const cJSON * child)2484 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2485 {
2486     cJSON *item = cJSON_New_Item(&global_hooks);
2487     if (item != NULL) {
2488         item->type = cJSON_Object | cJSON_IsReference;
2489         item->child = (cJSON*)cast_away_const(child);
2490     }
2491 
2492     return item;
2493 }
2494 
cJSON_CreateArrayReference(const cJSON * child)2495 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2496     cJSON *item = cJSON_New_Item(&global_hooks);
2497     if (item != NULL) {
2498         item->type = cJSON_Array | cJSON_IsReference;
2499         item->child = (cJSON*)cast_away_const(child);
2500     }
2501 
2502     return item;
2503 }
2504 
cJSON_CreateRaw(const char * raw)2505 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2506 {
2507     cJSON *item = cJSON_New_Item(&global_hooks);
2508     if(item)
2509     {
2510         item->type = cJSON_Raw;
2511         item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2512         if(!item->valuestring)
2513         {
2514             cJSON_Delete(item);
2515             return NULL;
2516         }
2517     }
2518 
2519     return item;
2520 }
2521 
cJSON_CreateArray(void)2522 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2523 {
2524     cJSON *item = cJSON_New_Item(&global_hooks);
2525     if(item)
2526     {
2527         item->type=cJSON_Array;
2528     }
2529 
2530     return item;
2531 }
2532 
cJSON_CreateObject(void)2533 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2534 {
2535     cJSON *item = cJSON_New_Item(&global_hooks);
2536     if (item)
2537     {
2538         item->type = cJSON_Object;
2539     }
2540 
2541     return item;
2542 }
2543 
2544 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2545 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2546 {
2547     size_t i = 0;
2548     cJSON *n = NULL;
2549     cJSON *p = NULL;
2550     cJSON *a = NULL;
2551 
2552     if ((count < 0) || (numbers == NULL))
2553     {
2554         return NULL;
2555     }
2556 
2557     a = cJSON_CreateArray();
2558     if (!a)
2559     {
2560         return NULL;
2561     }
2562 
2563     for(i = 0; i < (size_t)count; i++)
2564     {
2565         n = cJSON_CreateNumber(numbers[i]);
2566         if (!n)
2567         {
2568             cJSON_Delete(a);
2569             return NULL;
2570         }
2571         if(!i)
2572         {
2573             a->child = n;
2574         }
2575         else
2576         {
2577             suffix_object(p, n);
2578         }
2579         p = n;
2580     }
2581     a->child->prev = n;
2582 
2583     return a;
2584 }
2585 
cJSON_CreateFloatArray(const float * numbers,int count)2586 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2587 {
2588     size_t i = 0;
2589     cJSON *n = NULL;
2590     cJSON *p = NULL;
2591     cJSON *a = NULL;
2592 
2593     if ((count < 0) || (numbers == NULL))
2594     {
2595         return NULL;
2596     }
2597 
2598     a = cJSON_CreateArray();
2599     if (!a)
2600     {
2601         return NULL;
2602     }
2603 
2604     for(i = 0; i < (size_t)count; i++)
2605     {
2606         n = cJSON_CreateNumber((double)numbers[i]);
2607         if(!n)
2608         {
2609             cJSON_Delete(a);
2610             return NULL;
2611         }
2612         if(!i)
2613         {
2614             a->child = n;
2615         }
2616         else
2617         {
2618             suffix_object(p, n);
2619         }
2620         p = n;
2621     }
2622     a->child->prev = n;
2623 
2624     return a;
2625 }
2626 
cJSON_CreateDoubleArray(const double * numbers,int count)2627 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2628 {
2629     size_t i = 0;
2630     cJSON *n = NULL;
2631     cJSON *p = NULL;
2632     cJSON *a = NULL;
2633 
2634     if ((count < 0) || (numbers == NULL))
2635     {
2636         return NULL;
2637     }
2638 
2639     a = cJSON_CreateArray();
2640     if (!a)
2641     {
2642         return NULL;
2643     }
2644 
2645     for(i = 0; i < (size_t)count; i++)
2646     {
2647         n = cJSON_CreateNumber(numbers[i]);
2648         if(!n)
2649         {
2650             cJSON_Delete(a);
2651             return NULL;
2652         }
2653         if(!i)
2654         {
2655             a->child = n;
2656         }
2657         else
2658         {
2659             suffix_object(p, n);
2660         }
2661         p = n;
2662     }
2663     a->child->prev = n;
2664 
2665     return a;
2666 }
2667 
cJSON_CreateStringArray(const char * const * strings,int count)2668 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2669 {
2670     size_t i = 0;
2671     cJSON *n = NULL;
2672     cJSON *p = NULL;
2673     cJSON *a = NULL;
2674 
2675     if ((count < 0) || (strings == NULL))
2676     {
2677         return NULL;
2678     }
2679 
2680     a = cJSON_CreateArray();
2681     if (!a)
2682     {
2683         return NULL;
2684     }
2685 
2686     for (i = 0; i < (size_t)count; i++)
2687     {
2688         n = cJSON_CreateString(strings[i]);
2689         if(!n)
2690         {
2691             cJSON_Delete(a);
2692             return NULL;
2693         }
2694         if(!i)
2695         {
2696             a->child = n;
2697         }
2698         else
2699         {
2700             suffix_object(p,n);
2701         }
2702         p = n;
2703     }
2704     a->child->prev = n;
2705 
2706     return a;
2707 }
2708 
2709 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2710 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2711 {
2712     cJSON *newitem = NULL;
2713     cJSON *child = NULL;
2714     cJSON *next = NULL;
2715     cJSON *newchild = NULL;
2716 
2717     /* Bail on bad ptr */
2718     if (!item)
2719     {
2720         goto fail;
2721     }
2722     /* Create new item */
2723     newitem = cJSON_New_Item(&global_hooks);
2724     if (!newitem)
2725     {
2726         goto fail;
2727     }
2728     /* Copy over all vars */
2729     newitem->type = item->type & (~cJSON_IsReference);
2730     newitem->valueint = item->valueint;
2731     newitem->valuedouble = item->valuedouble;
2732     if (item->valuestring)
2733     {
2734         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2735         if (!newitem->valuestring)
2736         {
2737             goto fail;
2738         }
2739     }
2740     if (item->string)
2741     {
2742         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2743         if (!newitem->string)
2744         {
2745             goto fail;
2746         }
2747     }
2748     /* If non-recursive, then we're done! */
2749     if (!recurse)
2750     {
2751         return newitem;
2752     }
2753     /* Walk the ->next chain for the child. */
2754     child = item->child;
2755     while (child != NULL)
2756     {
2757         newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2758         if (!newchild)
2759         {
2760             goto fail;
2761         }
2762         if (next != NULL)
2763         {
2764             /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2765             next->next = newchild;
2766             newchild->prev = next;
2767             next = newchild;
2768         }
2769         else
2770         {
2771             /* Set newitem->child and move to it */
2772             newitem->child = newchild;
2773             next = newchild;
2774         }
2775         child = child->next;
2776     }
2777     if (newitem && newitem->child)
2778     {
2779         newitem->child->prev = newchild;
2780     }
2781 
2782     return newitem;
2783 
2784 fail:
2785     if (newitem != NULL)
2786     {
2787         cJSON_Delete(newitem);
2788     }
2789 
2790     return NULL;
2791 }
2792 
skip_oneline_comment(char ** input)2793 static void skip_oneline_comment(char **input)
2794 {
2795     *input += static_strlen("//");
2796 
2797     for (; (*input)[0] != '\0'; ++(*input))
2798     {
2799         if ((*input)[0] == '\n') {
2800             *input += static_strlen("\n");
2801             return;
2802         }
2803     }
2804 }
2805 
skip_multiline_comment(char ** input)2806 static void skip_multiline_comment(char **input)
2807 {
2808     *input += static_strlen("/*");
2809 
2810     for (; (*input)[0] != '\0'; ++(*input))
2811     {
2812         if (((*input)[0] == '*') && ((*input)[1] == '/'))
2813         {
2814             *input += static_strlen("*/");
2815             return;
2816         }
2817     }
2818 }
2819 
minify_string(char ** input,char ** output)2820 static void minify_string(char **input, char **output) {
2821     (*output)[0] = (*input)[0];
2822     *input += static_strlen("\"");
2823     *output += static_strlen("\"");
2824 
2825 
2826     for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2827         (*output)[0] = (*input)[0];
2828 
2829         if ((*input)[0] == '\"') {
2830             (*output)[0] = '\"';
2831             *input += static_strlen("\"");
2832             *output += static_strlen("\"");
2833             return;
2834         } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2835             (*output)[1] = (*input)[1];
2836             *input += static_strlen("\"");
2837             *output += static_strlen("\"");
2838         }
2839     }
2840 }
2841 
cJSON_Minify(char * json)2842 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2843 {
2844     char *into = json;
2845 
2846     if (json == NULL)
2847     {
2848         return;
2849     }
2850 
2851     while (json[0] != '\0')
2852     {
2853         switch (json[0])
2854         {
2855             case ' ':
2856             case '\t':
2857             case '\r':
2858             case '\n':
2859                 json++;
2860                 break;
2861 
2862             case '/':
2863                 if (json[1] == '/')
2864                 {
2865                     skip_oneline_comment(&json);
2866                 }
2867                 else if (json[1] == '*')
2868                 {
2869                     skip_multiline_comment(&json);
2870                 } else {
2871                     json++;
2872                 }
2873                 break;
2874 
2875             case '\"':
2876                 minify_string(&json, (char**)&into);
2877                 break;
2878 
2879             default:
2880                 into[0] = json[0];
2881                 json++;
2882                 into++;
2883         }
2884     }
2885 
2886     /* and null-terminate. */
2887     *into = '\0';
2888 }
2889 
cJSON_IsInvalid(const cJSON * const item)2890 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2891 {
2892     if (item == NULL)
2893     {
2894         return false;
2895     }
2896 
2897     return (item->type & 0xFF) == cJSON_Invalid;
2898 }
2899 
cJSON_IsFalse(const cJSON * const item)2900 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2901 {
2902     if (item == NULL)
2903     {
2904         return false;
2905     }
2906 
2907     return (item->type & 0xFF) == cJSON_False;
2908 }
2909 
cJSON_IsTrue(const cJSON * const item)2910 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2911 {
2912     if (item == NULL)
2913     {
2914         return false;
2915     }
2916 
2917     return (item->type & 0xff) == cJSON_True;
2918 }
2919 
2920 
cJSON_IsBool(const cJSON * const item)2921 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2922 {
2923     if (item == NULL)
2924     {
2925         return false;
2926     }
2927 
2928     return (item->type & (cJSON_True | cJSON_False)) != 0;
2929 }
cJSON_IsNull(const cJSON * const item)2930 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2931 {
2932     if (item == NULL)
2933     {
2934         return false;
2935     }
2936 
2937     return (item->type & 0xFF) == cJSON_NULL;
2938 }
2939 
cJSON_IsNumber(const cJSON * const item)2940 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2941 {
2942     if (item == NULL)
2943     {
2944         return false;
2945     }
2946 
2947     return (item->type & 0xFF) == cJSON_Number;
2948 }
2949 
cJSON_IsString(const cJSON * const item)2950 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2951 {
2952     if (item == NULL)
2953     {
2954         return false;
2955     }
2956 
2957     return (item->type & 0xFF) == cJSON_String;
2958 }
2959 
cJSON_IsArray(const cJSON * const item)2960 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2961 {
2962     if (item == NULL)
2963     {
2964         return false;
2965     }
2966 
2967     return (item->type & 0xFF) == cJSON_Array;
2968 }
2969 
cJSON_IsObject(const cJSON * const item)2970 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2971 {
2972     if (item == NULL)
2973     {
2974         return false;
2975     }
2976 
2977     return (item->type & 0xFF) == cJSON_Object;
2978 }
2979 
cJSON_IsRaw(const cJSON * const item)2980 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2981 {
2982     if (item == NULL)
2983     {
2984         return false;
2985     }
2986 
2987     return (item->type & 0xFF) == cJSON_Raw;
2988 }
2989 
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2990 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2991 {
2992     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2993     {
2994         return false;
2995     }
2996 
2997     /* check if type is valid */
2998     switch (a->type & 0xFF)
2999     {
3000         case cJSON_False:
3001         case cJSON_True:
3002         case cJSON_NULL:
3003         case cJSON_Number:
3004         case cJSON_String:
3005         case cJSON_Raw:
3006         case cJSON_Array:
3007         case cJSON_Object:
3008             break;
3009 
3010         default:
3011             return false;
3012     }
3013 
3014     /* identical objects are equal */
3015     if (a == b)
3016     {
3017         return true;
3018     }
3019 
3020     switch (a->type & 0xFF)
3021     {
3022         /* in these cases and equal type is enough */
3023         case cJSON_False:
3024         case cJSON_True:
3025         case cJSON_NULL:
3026             return true;
3027 
3028         case cJSON_Number:
3029             if (compare_double(a->valuedouble, b->valuedouble))
3030             {
3031                 return true;
3032             }
3033             return false;
3034 
3035         case cJSON_String:
3036         case cJSON_Raw:
3037             if ((a->valuestring == NULL) || (b->valuestring == NULL))
3038             {
3039                 return false;
3040             }
3041             if (strcmp(a->valuestring, b->valuestring) == 0)
3042             {
3043                 return true;
3044             }
3045 
3046             return false;
3047 
3048         case cJSON_Array:
3049         {
3050             cJSON *a_element = a->child;
3051             cJSON *b_element = b->child;
3052 
3053             for (; (a_element != NULL) && (b_element != NULL);)
3054             {
3055                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3056                 {
3057                     return false;
3058                 }
3059 
3060                 a_element = a_element->next;
3061                 b_element = b_element->next;
3062             }
3063 
3064             /* one of the arrays is longer than the other */
3065             if (a_element != b_element) {
3066                 return false;
3067             }
3068 
3069             return true;
3070         }
3071 
3072         case cJSON_Object:
3073         {
3074             cJSON *a_element = NULL;
3075             cJSON *b_element = NULL;
3076             cJSON_ArrayForEach(a_element, a)
3077             {
3078                 /* TODO This has O(n^2) runtime, which is horrible! */
3079                 b_element = get_object_item(b, a_element->string, case_sensitive);
3080                 if (b_element == NULL)
3081                 {
3082                     return false;
3083                 }
3084 
3085                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3086                 {
3087                     return false;
3088                 }
3089             }
3090 
3091             /* doing this twice, once on a and b to prevent true comparison if a subset of b
3092              * TODO: Do this the proper way, this is just a fix for now */
3093             cJSON_ArrayForEach(b_element, b)
3094             {
3095                 a_element = get_object_item(a, b_element->string, case_sensitive);
3096                 if (a_element == NULL)
3097                 {
3098                     return false;
3099                 }
3100 
3101                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
3102                 {
3103                     return false;
3104                 }
3105             }
3106 
3107             return true;
3108         }
3109 
3110         default:
3111             return false;
3112     }
3113 }
3114 
cJSON_malloc(size_t size)3115 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3116 {
3117     return global_hooks.allocate(size);
3118 }
3119 
cJSON_free(void * object)3120 CJSON_PUBLIC(void) cJSON_free(void *object)
3121 {
3122     global_hooks.deallocate(object);
3123 }
3124 
3125 }
3126