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