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