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