• 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 #ifdef S210
41 #include <app/cli/string.h>
42 #include <common/type.h>
43 #include <common/print/console.h>
44 #include <common/mem/memctrl.h>
45 #include <stdint.h>
46 #include "securec.h"
47 
48 #define BUFFER_SIZE 26
49 #else
50 #include <string.h>
51 #include <stdio.h>
52 #include <math.h>
53 #include <stdlib.h>
54 #include <limits.h>
55 #include <ctype.h>
56 #include <float.h>
57 #endif
58 
59 #ifdef ENABLE_LOCALES
60 #include <locale.h>
61 #endif
62 
63 #if defined(_MSC_VER)
64 #pragma warning (pop)
65 #endif
66 #ifdef __GNUC__
67 #pragma GCC visibility pop
68 #endif
69 
70 #include "cJSON.h"
71 
72 /* define our own boolean type */
73 #ifdef true
74 #undef true
75 #endif
76 #define true ((cJSON_bool)1)
77 
78 #ifdef false
79 #undef false
80 #endif
81 #define false ((cJSON_bool)0)
82 
83 /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
84 #ifndef isinf
85 #define isinf(d) (isnan((d - d)) && !isnan(d))
86 #endif
87 #ifndef isnan
88 #define isnan(d) (d != d)
89 #endif
90 
91 #ifndef NAN
92 #ifdef _WIN32
93 #define NAN sqrt(-1.0)
94 #else
95 #define NAN 0.0/0.0
96 #endif
97 #endif
98 
99 /* The arm 1620 server product is customized and modified with BIOS_CJSON macro definition isolation.
100    If other products open this macro definition, compilation may fail.
101 */
102 #ifdef BIOS_CJSON
103 #include <Library/BaseLib.h>
104 #include <Library/DebugLib.h>
105 #include <Library/HwSafeMemOpWrapper.h>
106 #include <Library/HwSafePrint.h>
107 #include <Library/PrintLib.h>
108 
109 #define MAX_STRING_SIZE  0x6000
110 #define NUMBER_BUFFER_SIZE 26
111 #define VERSION_BUFFER_SIZE 15
112 #define strncmp(string1,string2,count) (int)(AsciiStrnCmp(string1,string2,(UINTN)(count)))
113 
114 /* This function can only handle integer types. If decimal or scientific counting methods are passed in,
115    it can only return the value corresponding to a continuous integer string.
116 */
AtoI2(char * string)117 unsigned int AtoI2(char *string)
118 {
119     unsigned int   data = 0;
120     char           character;
121     unsigned int   integerNumber;
122     unsigned int   remainder;
123 
124     integerNumber = ((unsigned int)-1) / 10;
125     remainder = ((unsigned int)-1) % 10;
126 
127     if (string != NULL) {
128         /* convert digits */
129         character = *(string++);
130         while (character) {
131             if (character >= '0' && character <= '9') {
132                 if (data > integerNumber || (data == integerNumber && (character - '0') > remainder)) {
133                     return (unsigned int)-1;
134                 }
135                 data = (data * 10) + character - '0';
136             } else {
137                 break;
138             }
139             character = *(string++);
140         }
141         return data;
142     } else {
143         return data;
144     }
145 }
146 #endif
147 typedef struct {
148     const unsigned char *json;
149     size_t position;
150 } error;
151 static error global_error = { NULL, 0 };
152 
cJSON_GetErrorPtr(void)153 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
154 {
155     return (const char*) (global_error.json + global_error.position);
156 }
157 
cJSON_GetStringValue(const cJSON * const item)158 CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
159 {
160     if (!cJSON_IsString(item))
161     {
162         return NULL;
163     }
164 
165     return item->valuestring;
166 }
167 
168 #ifdef __CJSON_USE_INT64
cJSON_GetInt64NumberValue(cJSON * const item)169 CJSON_PUBLIC(long long *) cJSON_GetInt64NumberValue(cJSON * const item)
170 {
171     if (!cJSON_IsInt64Number(item))
172     {
173         return NULL;
174     }
175 
176     return &(item->valueint);
177 }
178 #endif
179 #ifdef S210
cJSON_GetNumberValue(const cJSON * const item)180 CJSON_PUBLIC(int64) cJSON_GetNumberValue(const cJSON *const item)
181 {
182     if (!cJSON_IsNumber(item))
183     {
184         return 0;
185     }
186 
187     return item->valueint;
188 }
189 
cJSON_GetFloatValue(const cJSON * const item)190 CJSON_PUBLIC(double) cJSON_GetFloatValue(const cJSON *const item)
191 {
192     if (!cJSON_IsNumber(item)) {
193         return (double)0.0;
194     }
195 
196     return item->valuedouble;
197 }
198 #else
cJSON_GetNumberValue(const cJSON * const item)199 CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
200 {
201     if (!cJSON_IsNumber(item))
202     {
203         return (double) NAN;
204     }
205 
206     return item->valuedouble;
207 }
208 #endif
209 
210 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
211 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
212     #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
213 #endif
214 
cJSON_Version(void)215 CJSON_PUBLIC(const char*) cJSON_Version(void)
216 {
217     static char version[15];
218 #ifdef BIOS_CJSON
219     AsciiSPrintS(version, VERSION_BUFFER_SIZE, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
220 #else
221     sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
222 #endif
223 
224     return version;
225 }
226 
227 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
case_insensitive_strcmp(const unsigned char * string1,const unsigned char * string2)228 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
229 {
230     if ((string1 == NULL) || (string2 == NULL))
231     {
232         return 1;
233     }
234 
235     if (string1 == string2)
236     {
237         return 0;
238     }
239 
240     for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
241     {
242         if (*string1 == '\0')
243         {
244             return 0;
245         }
246     }
247 
248     return tolower(*string1) - tolower(*string2);
249 }
250 
251 typedef struct internal_hooks
252 {
253     void *(CJSON_CDECL *allocate)(size_t size);
254     void (CJSON_CDECL *deallocate)(void *pointer);
255     void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
256 } internal_hooks;
257 
258 #if defined(_MSC_VER)
259 /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
internal_malloc(size_t size)260 static void * CJSON_CDECL internal_malloc(size_t size)
261 {
262     return malloc(size);
263 }
internal_free(void * pointer)264 static void CJSON_CDECL internal_free(void *pointer)
265 {
266     free(pointer);
267 }
internal_realloc(void * pointer,size_t size)268 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
269 {
270     return realloc(pointer, size);
271 }
272 #else
273 #ifdef S210
274 #define internal_malloc cj_malloc
275 #define internal_free cj_free
276 #define internal_realloc NULL
277 #else
278 #define internal_malloc malloc
279 #define internal_free free
280 #define internal_realloc realloc
281 #endif
282 #endif
283 
284 /* strlen of character literals resolved at compile time */
285 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
286 
287 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
288 
cJSON_strdup(const unsigned char * string,const internal_hooks * const hooks)289 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
290 {
291     size_t length = 0;
292     unsigned char *copy = NULL;
293 
294     if (string == NULL)
295     {
296         return NULL;
297     }
298 #ifdef BIOS_CJSON
299     length = (size_t)(AsciiStrnLenS((const char*)string, MAX_STRING_SIZE)) + sizeof("");
300 #else
301     length = strlen((const char*)string) + sizeof("");
302 #endif
303     copy = (unsigned char*)hooks->allocate(length);
304     if (copy == NULL)
305     {
306         return NULL;
307     }
308     memcpy(copy, string, length);
309 
310     return copy;
311 }
312 #ifdef S210
cJSON_InitHooks(cJSON_Hooks * hooks)313 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks)
314 {
315     if (hooks == NULL) {
316         /* Reset hooks */
317         return;
318     }
319 
320     if (hooks->malloc_fn != NULL)
321     {
322         global_hooks.allocate = hooks->malloc_fn;
323     }
324 
325     if (hooks->free_fn != NULL)
326     {
327         global_hooks.deallocate = hooks->free_fn;
328     }
329 
330     /* use realloc only if both free and malloc are used */
331     global_hooks.reallocate = NULL;
332 }
333 #else
cJSON_InitHooks(cJSON_Hooks * hooks)334 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
335 {
336     if (hooks == NULL)
337     {
338         /* Reset hooks */
339         global_hooks.allocate = malloc;
340         global_hooks.deallocate = free;
341         global_hooks.reallocate = realloc;
342         return;
343     }
344 
345     global_hooks.allocate = malloc;
346     if (hooks->malloc_fn != NULL)
347     {
348         global_hooks.allocate = hooks->malloc_fn;
349     }
350 
351     global_hooks.deallocate = free;
352     if (hooks->free_fn != NULL)
353     {
354         global_hooks.deallocate = hooks->free_fn;
355     }
356 
357     /* use realloc only if both free and malloc are used */
358     global_hooks.reallocate = NULL;
359     if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
360     {
361         global_hooks.reallocate = realloc;
362     }
363 }
364 #endif
365 /* Internal constructor. */
366 #ifdef S210
cJSON_New_Item(const internal_hooks * const hooks)367 static cJSON *cJSON_New_Item(const internal_hooks *const hooks)
368 {
369     cJSON *node = cjson_data_new();
370     if (node)
371     {
372         memset(node, '\0', sizeof(cJSON));
373         node->type |= cJSON_Allocated;
374     }
375 
376     return node;
377 }
378 #else
cJSON_New_Item(const internal_hooks * const hooks)379 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
380 {
381     cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
382     if (node)
383     {
384         memset(node, '\0', sizeof(cJSON));
385     }
386 
387     return node;
388 }
389 #endif
390 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * item)391 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
392 {
393     cJSON *next = NULL;
394     while (item != NULL)
395     {
396         next = item->next;
397         if (!(item->type & cJSON_IsReference) && (item->child != NULL))
398         {
399             cJSON_Delete(item->child);
400         }
401         if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
402         {
403             global_hooks.deallocate(item->valuestring);
404         }
405         if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
406         {
407             global_hooks.deallocate(item->string);
408         }
409         global_hooks.deallocate(item);
410         item = next;
411     }
412 }
413 
414 #ifndef BIOS_CJSON
415 /* get the decimal point character of the current locale */
get_decimal_point(void)416 static unsigned char get_decimal_point(void)
417 {
418 #ifdef ENABLE_LOCALES
419     struct lconv *lconv = localeconv();
420     return (unsigned char) lconv->decimal_point[0];
421 #else
422     return '.';
423 #endif
424 }
425 #endif
426 
427 typedef struct
428 {
429     const unsigned char *content;
430     size_t length;
431     size_t offset;
432     size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
433 #ifdef RESTRICT_RESOURCE
434     size_t item_count; /* item count. */
435 #endif
436     internal_hooks hooks;
437 } parse_buffer;
438 
439 /* check if the given size is left to read in a given parse buffer (starting with 1) */
440 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
441 /* check if the buffer can be accessed at the given index (starting with 0) */
442 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
443 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
444 /* get a pointer to the buffer at the position */
445 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
446 
447 /* Parse the input text to generate a number, and populate the result into item. */
448 #ifdef S210
parse_number(cJSON * const item,parse_buffer * const input_buffer)449 static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer)
450 {
451     int64 numberInt = 0;
452     double numberFloat = 0.0;
453     int numberLength = 0;
454     unsigned char number_c_string[64];
455     unsigned char decimal_point = get_decimal_point();
456     int isFloat = 0;
457     size_t i = 0;
458 
459     if ((input_buffer == NULL) || (input_buffer->content == NULL))
460     {
461         return false;
462     }
463 
464     /* copy the number into a temporary buffer and replace '.' with the decimal point
465      * of the current locale (for strtod)
466      * This also takes care of '\0' not necessarily being available for marking the end of the input */
467     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
468     {
469         switch (buffer_at_offset(input_buffer)[i]) {
470             case '0':
471             case '1':
472             case '2':
473             case '3':
474             case '4':
475             case '5':
476             case '6':
477             case '7':
478             case '8':
479             case '9':
480             case '+':
481             case '-':
482                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
483                 break;
484             case 'e':
485             case 'E':
486                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
487                 isFloat = 1;
488                 break;
489             case '.':
490                 number_c_string[i] = decimal_point;
491                 isFloat = 1;
492                 break;
493 
494             default:
495                 goto loop_end;
496         }
497     }
498 loop_end:
499     number_c_string[i] = 'X';  // 用于标记数字后面第一个字符
500 
501     if (!isFloat)
502     {
503         if (sscanf_s((const char *)number_c_string, "%lld", &numberInt) != 1)
504         {
505             return false;
506         }
507         item->valueint = numberInt;
508         item->type = cJSON_Number;
509     } else {
510         if (sscanf_s((const char *)number_c_string, "%lf", &numberFloat) != 1)
511         {
512             return false;
513         }
514         item->valuedouble = numberFloat;
515         item->type = cJSON_Float;
516     }
517 
518     i = 0;
519     while (i < 64 && number_c_string[i] != 'X')
520     {
521         i++;
522         numberLength++;
523     }
524 
525     input_buffer->offset += (size_t)numberLength;
526 
527     return true;
528 }
529 #else
530 #ifdef __CJSON_USE_INT64
531 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)532 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
533 {
534     double number = 0;
535     long long integer = 0;
536     unsigned char *after_end = NULL;
537     unsigned char number_c_string[64];
538     unsigned char decimal_point = get_decimal_point();
539     size_t i = 0;
540     cJSON_bool is_integer = true;
541 
542     if ((input_buffer == NULL) || (input_buffer->content == NULL))
543     {
544         return false;
545     }
546 
547     /* copy the number into a temporary buffer and replace '.' with the decimal point
548      * of the current locale (for strtod)
549      * This also takes care of '\0' not necessarily being available for marking the end of the input */
550     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
551     {
552         switch (buffer_at_offset(input_buffer)[i])
553         {
554             case '0':
555             case '1':
556             case '2':
557             case '3':
558             case '4':
559             case '5':
560             case '6':
561             case '7':
562             case '8':
563             case '9':
564             case '+':
565             case '-':
566                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
567                 break;
568             case 'e':
569             case 'E':
570                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
571                 is_integer = false;
572                 break;
573 
574             case '.':
575                 number_c_string[i] = decimal_point;
576                 is_integer = false;
577                 break;
578 
579             default:
580                 goto loop_end;
581         }
582     }
583 loop_end:
584     number_c_string[i] = '\0';
585 
586     /* use guard clause to process the int64 case first */
587     if (is_integer)
588     {
589         /* for int64 values, cJSON_IsInt64 */
590         item->type = cJSON_Number | cJSON_IsInt64;
591         integer = strtoll((const char*)number_c_string, (char**)&after_end, 10);
592         if (number_c_string == after_end)
593         {
594             return false; /* parse_error */
595         }
596         item->valueint = integer;
597         item->valuedouble = (double)integer;
598         goto parse_end;
599     }
600 
601     number = strtod((const char*)number_c_string, (char**)&after_end);
602     if (number_c_string == after_end)
603     {
604         return false; /* parse_error */
605     }
606 
607     item->valuedouble = number;
608 
609     /* use saturation in case of overflow */
610     if (number >= (double)LLONG_MAX)
611     {
612         item->valueint = LLONG_MAX;
613     }
614     else if (number <= (double)LLONG_MIN)
615     {
616         item->valueint = LLONG_MIN;
617     }
618     else
619     {
620         item->valueint = (long long)number;
621     }
622 
623     item->type = cJSON_Number;
624 
625 parse_end:
626     input_buffer->offset += (size_t)(after_end - number_c_string);
627     return true;
628 }
629 #else
630 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)631 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
632 {
633     double number = 0;
634     unsigned char number_c_string[64];
635 #ifndef BIOS_CJSON
636     unsigned char *after_end = NULL;
637     unsigned char decimal_point = get_decimal_point();
638 #else
639     size_t length = 0;
640 #endif
641     size_t i = 0;
642 
643     if ((input_buffer == NULL) || (input_buffer->content == NULL))
644     {
645         return false;
646     }
647 
648     /* copy the number into a temporary buffer and replace '.' with the decimal point
649      * of the current locale (for strtod)
650      * This also takes care of '\0' not necessarily being available for marking the end of the input */
651     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
652     {
653         switch (buffer_at_offset(input_buffer)[i])
654         {
655             case '0':
656             case '1':
657             case '2':
658             case '3':
659             case '4':
660             case '5':
661             case '6':
662             case '7':
663             case '8':
664             case '9':
665             case '+':
666             case '-':
667             case 'e':
668             case 'E':
669                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
670                 break;
671 #ifndef BIOS_CJSON
672             case '.':
673                 number_c_string[i] = decimal_point;
674                 break;
675 #endif
676             default:
677                 goto loop_end;
678         }
679     }
680 loop_end:
681     number_c_string[i] = '\0';
682 #ifndef BIOS_CJSON
683     number = strtod((const char*)number_c_string, (char**)&after_end);
684     if (number_c_string == after_end)
685     {
686         return false; /* parse_error */
687     }
688 #else
689     for (i = 0; number_c_string[i] != '\0'; i++) {
690         length++;
691     }
692     number = AtoI2((char*)number_c_string);
693 #endif
694     item->valuedouble = number;
695 
696     /* use saturation in case of overflow */
697     if (number >= INT_MAX)
698     {
699         item->valueint = INT_MAX;
700     }
701     else if (number <= (double)INT_MIN)
702     {
703         item->valueint = INT_MIN;
704     }
705     else
706     {
707         item->valueint = (int)number;
708     }
709 
710     item->type = cJSON_Number;
711 #ifndef BIOS_CJSON
712     input_buffer->offset += (size_t)(after_end - number_c_string);
713 #else
714     input_buffer->offset += length;
715 #endif
716     return true;
717 }
718 #endif
719 #endif
720 
721 #ifdef __CJSON_USE_INT64
cJSON_SetInt64NumberValue(cJSON * const object,const long long integer)722 CJSON_PUBLIC(long long) cJSON_SetInt64NumberValue(cJSON * const object, const long long integer)
723 {
724     if (object == NULL)
725     {
726         return integer;
727     }
728 
729     /* check the type before setting values */
730     if (!(object->type & cJSON_Number) || !(object->type & cJSON_IsInt64))
731     {
732         return integer;
733     }
734 
735     object->valueint = integer;
736     object->valuedouble = (double)integer;
737 
738     return integer;
739 }
740 #endif
741 
742 #ifdef S210
743 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)744 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
745 {
746     return number;
747 }
748 #else
749 #ifdef __CJSON_USE_INT64
750 /* note that double max(DBL_MAX) is bigger than long long max(LLONG_MAX) */
cJSON_SetNumberHelper(cJSON * object,double number)751 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
752 {
753     if (number >= (double)LLONG_MAX)
754     {
755         object->valueint = LLONG_MAX;
756     }
757     else if (number <= (double)LLONG_MIN)
758     {
759         object->valueint = LLONG_MIN;
760     }
761     else
762     {
763         object->valueint = (long long)number;
764     }
765 
766     return object->valuedouble = number;
767 }
768 #else
769 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)770 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
771 {
772     if (number >= INT_MAX)
773     {
774         object->valueint = INT_MAX;
775     }
776     else if (number <= (double)INT_MIN)
777     {
778         object->valueint = INT_MIN;
779     }
780     else
781     {
782         object->valueint = (int)number;
783     }
784 
785     return object->valuedouble = number;
786 }
787 #endif
788 #endif
789 
cJSON_SetValuestring(cJSON * object,const char * valuestring)790 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
791 {
792     char *copy = NULL;
793     /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
794     if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
795     {
796         return NULL;
797     }
798     /* return NULL if the object is corrupted */
799     if (object->valuestring == NULL)
800     {
801         return NULL;
802     }
803 #ifdef BIOS_CJSON
804     if ((size_t)(AsciiStrnLenS(valuestring, MAX_STRING_SIZE)) <= (size_t)(AsciiStrnLenS(object->valuestring, MAX_STRING_SIZE)))
805     {
806         unsigned int returnError = AsciiStrCpyS(object->valuestring, MAX_STRING_SIZE, valuestring);
807         if (returnError != 0)
808         {
809             return NULL;
810         }
811 #else
812     if (strlen(valuestring) <= strlen(object->valuestring))
813     {
814         strcpy(object->valuestring, valuestring);
815 #endif
816         return object->valuestring;
817     }
818     copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
819     if (copy == NULL)
820     {
821         return NULL;
822     }
823     if (object->valuestring != NULL)
824     {
825         cJSON_free(object->valuestring);
826     }
827     object->valuestring = copy;
828 
829     return copy;
830 }
831 
832 typedef struct
833 {
834     unsigned char *buffer;
835     size_t length;
836     size_t offset;
837     size_t depth; /* current nesting depth (for formatted printing) */
838     cJSON_bool noalloc;
839     cJSON_bool format; /* is this print a formatted print */
840     internal_hooks hooks;
841 } printbuffer;
842 
843 #ifdef S210
844 /* realloc printbuffer if necessary to have at least "needed" bytes more */
845 static unsigned char* ensure(printbuffer * const p, size_t needed)
846 {
847     unsigned char *newbuffer = NULL;
848     size_t newsize = 0;
849 
850     if ((p == NULL) || (p->buffer == NULL))
851     {
852         return NULL;
853     }
854 
855     if ((p->length > 0) && (p->offset >= p->length))
856     {
857         /* make sure that offset is valid */
858         return NULL;
859     }
860 
861     if (needed > INT32_MAX)
862     {
863         /* sizes bigger than INT32_MAX are currently not supported */
864         return NULL;
865     }
866 
867     needed += p->offset + 1;
868     if (needed <= p->length)
869     {
870         return p->buffer + p->offset;
871     }
872 
873     if (p->noalloc) {
874         return NULL;
875     }
876 
877     /* calculate new buffer size */
878     if (needed > (INT32_MAX / 2))
879     {
880         /* overflow of int, use INT32_MAX if possible */
881         if (needed <= INT32_MAX)
882         {
883             newsize = INT32_MAX;
884         }
885         else
886         {
887             return NULL;
888         }
889     }
890     else
891     {
892         newsize = needed * 2;
893     }
894 
895     if (p->hooks.reallocate != NULL)
896     {
897         /* reallocate with realloc if available */
898         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
899         if (newbuffer == NULL)
900         {
901             p->hooks.deallocate(p->buffer);
902             p->length = 0;
903             p->buffer = NULL;
904 
905             return NULL;
906         }
907     }
908     else
909     {
910         /* otherwise reallocate manually */
911         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
912         if (!newbuffer)
913         {
914             p->hooks.deallocate(p->buffer);
915             p->length = 0;
916             p->buffer = NULL;
917 
918             return NULL;
919         }
920         if (newbuffer)
921         {
922             memcpy(newbuffer, p->buffer, p->offset + 1);
923         }
924         p->hooks.deallocate(p->buffer);
925     }
926     p->length = newsize;
927     p->buffer = newbuffer;
928 
929     return newbuffer + p->offset;
930 }
931 #else
932 /* realloc printbuffer if necessary to have at least "needed" bytes more */
933 static unsigned char* ensure(printbuffer * const p, size_t needed)
934 {
935     unsigned char *newbuffer = NULL;
936     size_t newsize = 0;
937 
938     if ((p == NULL) || (p->buffer == NULL))
939     {
940         return NULL;
941     }
942 
943     if ((p->length > 0) && (p->offset >= p->length))
944     {
945         /* make sure that offset is valid */
946         return NULL;
947     }
948 
949     if (needed > INT_MAX)
950     {
951         /* sizes bigger than INT_MAX are currently not supported */
952         return NULL;
953     }
954 
955     needed += p->offset + 1;
956     if (needed <= p->length)
957     {
958         return p->buffer + p->offset;
959     }
960 
961     if (p->noalloc) {
962         return NULL;
963     }
964 
965     /* calculate new buffer size */
966     if (needed > (INT_MAX / 2))
967     {
968         /* overflow of int, use INT_MAX if possible */
969         if (needed <= INT_MAX)
970         {
971             newsize = INT_MAX;
972         }
973         else
974         {
975             return NULL;
976         }
977     }
978     else
979     {
980         newsize = needed * 2;
981     }
982 
983     if (p->hooks.reallocate != NULL)
984     {
985         /* reallocate with realloc if available */
986         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
987         if (newbuffer == NULL)
988         {
989             p->hooks.deallocate(p->buffer);
990             p->length = 0;
991             p->buffer = NULL;
992 
993             return NULL;
994         }
995     }
996     else
997     {
998         /* otherwise reallocate manually */
999         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
1000         if (!newbuffer)
1001         {
1002             p->hooks.deallocate(p->buffer);
1003             p->length = 0;
1004             p->buffer = NULL;
1005 
1006             return NULL;
1007         }
1008 
1009         memcpy(newbuffer, p->buffer, p->offset + 1);
1010         p->hooks.deallocate(p->buffer);
1011     }
1012     p->length = newsize;
1013     p->buffer = newbuffer;
1014 
1015     return newbuffer + p->offset;
1016 }
1017 #endif
1018 
1019 /* calculate the new length of the string in a printbuffer and update the offset */
1020 static void update_offset(printbuffer * const buffer)
1021 {
1022     const unsigned char *buffer_pointer = NULL;
1023     if ((buffer == NULL) || (buffer->buffer == NULL))
1024     {
1025         return;
1026     }
1027     buffer_pointer = buffer->buffer + buffer->offset;
1028 
1029 #ifdef BIOS_CJSON
1030     buffer->offset += (size_t)AsciiStrnLenS((const char*)buffer_pointer, MAX_STRING_SIZE);
1031 #else
1032     buffer->offset += strlen((const char*)buffer_pointer);
1033 #endif
1034 }
1035 
1036 #ifndef S210
1037 /* securely comparison of floating-point variables */
1038 static cJSON_bool compare_double(double a, double b)
1039 {
1040     double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
1041     return (fabs(a - b) <= maxVal * DBL_EPSILON);
1042 }
1043 #endif
1044 
1045 #ifdef S210
1046 /* Render the number nicely from the given item into a string. */
1047 static cJSON_bool print_float(const cJSON *const item, printbuffer *const output_buffer)
1048 {
1049     unsigned char *output_pointer = NULL;
1050     double d = item->valuedouble;
1051     int length = 0;
1052     size_t i = 0;
1053     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
1054     unsigned char decimal_point = get_decimal_point();
1055 
1056     if (output_buffer == NULL) {
1057         return false;
1058     }
1059 
1060     // WARNING: 基于当前设备环境没有浮点数运行时库,未对d值做校验
1061     length = sprintf_s((char *)number_buffer, BUFFER_SIZE, "%lf", d);  // 不支持float
1062 
1063     /* sprintf failed or buffer overrun occurred */
1064     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
1065         return false;
1066     }
1067 
1068     /* reserve appropriate space in the output */
1069     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
1070     if (output_pointer == NULL) {
1071         return false;
1072     }
1073 
1074     /* copy the printed number to the output and replace locale
1075      * dependent decimal point with '.' */
1076     for (i = 0; i < ((size_t)length); i++) {
1077         if (number_buffer[i] == decimal_point) {
1078             output_pointer[i] = '.';
1079             continue;
1080         }
1081 
1082         output_pointer[i] = number_buffer[i];
1083     }
1084     output_pointer[i] = '\0';
1085 
1086     output_buffer->offset += (size_t)length;
1087 
1088     return true;
1089 }
1090 #endif
1091 
1092 #ifdef S210
1093 /* Render the number nicely from the given item into a string. */
1094 static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer)
1095 {
1096     unsigned char *output_pointer = NULL;
1097     int64 d = item->valueint;
1098     int length = 0;
1099     size_t i = 0;
1100     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
1101 
1102     if (output_buffer == NULL)
1103     {
1104         return false;
1105     }
1106 
1107     length = sprintf_s((char *)number_buffer, BUFFER_SIZE, "%lld", d);
1108 
1109     /* sprintf failed or buffer overrun occurred */
1110     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
1111     {
1112         return false;
1113     }
1114 
1115     /* reserve appropriate space in the output */
1116     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
1117     if (output_pointer == NULL)
1118     {
1119         return false;
1120     }
1121 
1122     /* copy the printed number to the output and replace locale
1123      * dependent decimal point with '.' */
1124     for (i = 0; i < ((size_t)length); i++)
1125     {
1126         output_pointer[i] = number_buffer[i];
1127     }
1128 
1129     output_pointer[i] = '\0';
1130 
1131     output_buffer->offset += (size_t)length;
1132 
1133     return true;
1134 }
1135 #else
1136 #ifdef __CJSON_USE_INT64
1137 /* Render the number nicely from the given item into a string. */
1138 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
1139 {
1140     unsigned char *output_pointer = NULL;
1141     double d = item->valuedouble;
1142     long long integer = item->valueint;
1143     int length = 0;
1144     size_t i = 0;
1145     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
1146     unsigned char decimal_point = get_decimal_point();
1147     double test = 0.0;
1148 
1149     if (output_buffer == NULL)
1150     {
1151         return false;
1152     }
1153 
1154     if (item->type & cJSON_IsInt64)
1155     {
1156         /* use lld to print the long long integer */
1157 #ifdef BIOS_CJSON
1158         length = AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE, "%lld", integer);
1159 #else
1160         length = sprintf((char*)number_buffer, "%lld", integer);
1161 #endif
1162     }
1163     else /* item-type == cJSON_Number */
1164     {
1165         /* This checks for NaN and Infinity */
1166         if (isnan(d) || isinf(d))
1167         {
1168 #ifdef BIOS_CJSON
1169             length = AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE, "null");
1170 #else
1171             length = sprintf((char*)number_buffer, "null");
1172 #endif
1173         }
1174         else
1175         {
1176             /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
1177 #ifdef BIOS_CJSON
1178             length = AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE, "%1.15g", d);
1179 #else
1180             length = sprintf((char*)number_buffer, "%1.15g", d);
1181 #endif
1182 
1183             /* Check whether the original double can be recovered */
1184             if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
1185             {
1186                 /* If not, print with 17 decimal places of precision */
1187 #ifdef BIOS_CJSON
1188                 length = AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE, "%1.17g", d);
1189 #else
1190                 length = sprintf((char*)number_buffer, "%1.17g", d);
1191 #endif
1192             }
1193         }
1194     }
1195 
1196     /* sprintf failed or buffer overrun occurred */
1197     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
1198     {
1199         return false;
1200     }
1201 
1202     /* reserve appropriate space in the output */
1203     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
1204     if (output_pointer == NULL)
1205     {
1206         return false;
1207     }
1208 
1209     /* copy the printed number to the output and replace locale
1210      * dependent decimal point with '.' */
1211     for (i = 0; i < ((size_t)length); i++)
1212     {
1213         if (number_buffer[i] == decimal_point)
1214         {
1215             output_pointer[i] = '.';
1216             continue;
1217         }
1218 
1219         output_pointer[i] = number_buffer[i];
1220     }
1221     output_pointer[i] = '\0';
1222 
1223     output_buffer->offset += (size_t)length;
1224 
1225     return true;
1226 }
1227 #else
1228 /* Render the number nicely from the given item into a string. */
1229 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
1230 {
1231     unsigned char *output_pointer = NULL;
1232     int length = 0;
1233     size_t i = 0;
1234     unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
1235 #ifndef BIOS_CJSON
1236     double d = item->valuedouble;
1237     unsigned char decimal_point = get_decimal_point();
1238     double test = 0.0;
1239 #else
1240     int d = item->valueint;
1241 #endif
1242     if (output_buffer == NULL)
1243     {
1244         return false;
1245     }
1246 #ifndef BIOS_CJSON
1247     /* This checks for NaN and Infinity */
1248     if (isnan(d) || isinf(d))
1249     {
1250         length = sprintf((char*)number_buffer, "null");
1251     }
1252     else
1253     {
1254         /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
1255         length = sprintf((char*)number_buffer, "%1.15g", d);
1256 
1257         /* Check whether the original double can be recovered */
1258         if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
1259         {
1260             /* If not, print with 17 decimal places of precision */
1261             length = sprintf((char*)number_buffer, "%1.17g", d);
1262         }
1263     }
1264 #else
1265     if ((d * 0) != 0)
1266     {
1267         length = (int)AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE, "null");
1268     }
1269     else
1270     {
1271         length = (int)AsciiSPrintS((char*)number_buffer, NUMBER_BUFFER_SIZE,"%d", d);
1272     }
1273 #endif
1274     /* sprintf failed or buffer overrun occurred */
1275     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
1276     {
1277         return false;
1278     }
1279 
1280     /* reserve appropriate space in the output */
1281 #ifndef BIOS_CJSON
1282     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
1283 #else
1284     output_pointer = ensure(output_buffer, (size_t)length);
1285 #endif
1286     if (output_pointer == NULL)
1287     {
1288         return false;
1289     }
1290 
1291     /* copy the printed number to the output and replace locale
1292      * dependent decimal point with '.' */
1293     for (i = 0; i < ((size_t)length); i++)
1294     {
1295 #ifndef BIOS_CJSON
1296         if (number_buffer[i] == decimal_point)
1297         {
1298             output_pointer[i] = '.';
1299             continue;
1300         }
1301 #endif
1302         output_pointer[i] = number_buffer[i];
1303     }
1304     output_pointer[i] = '\0';
1305 
1306     output_buffer->offset += (size_t)length;
1307 
1308     return true;
1309 }
1310 #endif
1311 #endif
1312 
1313 /* parse 4 digit hexadecimal number */
1314 static unsigned parse_hex4(const unsigned char * const input)
1315 {
1316     unsigned int h = 0;
1317     size_t i = 0;
1318 
1319     for (i = 0; i < 4; i++)
1320     {
1321         /* parse digit */
1322         if ((input[i] >= '0') && (input[i] <= '9'))
1323         {
1324             h += (unsigned int) input[i] - '0';
1325         }
1326         else if ((input[i] >= 'A') && (input[i] <= 'F'))
1327         {
1328             h += (unsigned int) 10 + input[i] - 'A';
1329         }
1330         else if ((input[i] >= 'a') && (input[i] <= 'f'))
1331         {
1332             h += (unsigned int) 10 + input[i] - 'a';
1333         }
1334         else /* invalid */
1335         {
1336             return 0;
1337         }
1338 
1339         if (i < 3)
1340         {
1341             /* shift left to make place for the next nibble */
1342             h = h << 4;
1343         }
1344     }
1345 
1346     return h;
1347 }
1348 
1349 /* converts a UTF-16 literal to UTF-8
1350  * A literal can be one or two sequences of the form \uXXXX */
1351 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
1352 {
1353     long unsigned int codepoint = 0;
1354     unsigned int first_code = 0;
1355     const unsigned char *first_sequence = input_pointer;
1356     unsigned char utf8_length = 0;
1357     unsigned char utf8_position = 0;
1358     unsigned char sequence_length = 0;
1359     unsigned char first_byte_mark = 0;
1360 
1361     if ((input_end - first_sequence) < 6)
1362     {
1363         /* input ends unexpectedly */
1364         goto fail;
1365     }
1366 
1367     /* get the first utf16 sequence */
1368     first_code = parse_hex4(first_sequence + 2);
1369 
1370     /* check that the code is valid */
1371     if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
1372     {
1373         goto fail;
1374     }
1375 
1376     /* UTF16 surrogate pair */
1377     if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
1378     {
1379         const unsigned char *second_sequence = first_sequence + 6;
1380         unsigned int second_code = 0;
1381         sequence_length = 12; /* \uXXXX\uXXXX */
1382 
1383         if ((input_end - second_sequence) < 6)
1384         {
1385             /* input ends unexpectedly */
1386             goto fail;
1387         }
1388 
1389         if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
1390         {
1391             /* missing second half of the surrogate pair */
1392             goto fail;
1393         }
1394 
1395         /* get the second utf16 sequence */
1396         second_code = parse_hex4(second_sequence + 2);
1397         /* check that the code is valid */
1398         if ((second_code < 0xDC00) || (second_code > 0xDFFF))
1399         {
1400             /* invalid second half of the surrogate pair */
1401             goto fail;
1402         }
1403 
1404 
1405         /* calculate the unicode codepoint from the surrogate pair */
1406         codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
1407     }
1408     else
1409     {
1410         sequence_length = 6; /* \uXXXX */
1411         codepoint = first_code;
1412     }
1413 
1414     /* encode as UTF-8
1415      * takes at maximum 4 bytes to encode:
1416      * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
1417     if (codepoint < 0x80)
1418     {
1419         /* normal ascii, encoding 0xxxxxxx */
1420         utf8_length = 1;
1421     }
1422     else if (codepoint < 0x800)
1423     {
1424         /* two bytes, encoding 110xxxxx 10xxxxxx */
1425         utf8_length = 2;
1426         first_byte_mark = 0xC0; /* 11000000 */
1427     }
1428     else if (codepoint < 0x10000)
1429     {
1430         /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
1431         utf8_length = 3;
1432         first_byte_mark = 0xE0; /* 11100000 */
1433     }
1434     else if (codepoint <= 0x10FFFF)
1435     {
1436         /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
1437         utf8_length = 4;
1438         first_byte_mark = 0xF0; /* 11110000 */
1439     }
1440     else
1441     {
1442         /* invalid unicode codepoint */
1443         goto fail;
1444     }
1445 
1446     /* encode as utf8 */
1447     for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
1448     {
1449         /* 10xxxxxx */
1450         (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
1451         codepoint >>= 6;
1452     }
1453     /* encode first byte */
1454     if (utf8_length > 1)
1455     {
1456         (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
1457     }
1458     else
1459     {
1460         (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
1461     }
1462 
1463     *output_pointer += utf8_length;
1464 
1465     return sequence_length;
1466 
1467 fail:
1468     return 0;
1469 }
1470 
1471 /* Parse the input text into an unescaped cinput, and populate item. */
1472 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
1473 {
1474     const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
1475     const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
1476     unsigned char *output_pointer = NULL;
1477     unsigned char *output = NULL;
1478 
1479     /* not a string */
1480     if (buffer_at_offset(input_buffer)[0] != '\"')
1481     {
1482         goto fail;
1483     }
1484 
1485     {
1486         /* calculate approximate size of the output (overestimate) */
1487         size_t allocation_length = 0;
1488         size_t skipped_bytes = 0;
1489         while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
1490         {
1491             /* is escape sequence */
1492             if (input_end[0] == '\\')
1493             {
1494                 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
1495                 {
1496                     /* prevent buffer overflow when last input character is a backslash */
1497                     goto fail;
1498                 }
1499                 skipped_bytes++;
1500                 input_end++;
1501             }
1502             input_end++;
1503         }
1504         if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
1505         {
1506             goto fail; /* string ended unexpectedly */
1507         }
1508 
1509         /* This is at most how much we need for the output */
1510         allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
1511         output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
1512         if (output == NULL)
1513         {
1514             goto fail; /* allocation failure */
1515         }
1516     }
1517 
1518     output_pointer = output;
1519     /* loop through the string literal */
1520     while (input_pointer < input_end)
1521     {
1522         if (*input_pointer != '\\')
1523         {
1524             *output_pointer++ = *input_pointer++;
1525         }
1526         /* escape sequence */
1527         else
1528         {
1529             unsigned char sequence_length = 2;
1530             if ((input_end - input_pointer) < 1)
1531             {
1532                 goto fail;
1533             }
1534 
1535             switch (input_pointer[1])
1536             {
1537                 case 'b':
1538                     *output_pointer++ = '\b';
1539                     break;
1540                 case 'f':
1541                     *output_pointer++ = '\f';
1542                     break;
1543                 case 'n':
1544                     *output_pointer++ = '\n';
1545                     break;
1546                 case 'r':
1547                     *output_pointer++ = '\r';
1548                     break;
1549                 case 't':
1550                     *output_pointer++ = '\t';
1551                     break;
1552                 case '\"':
1553                 case '\\':
1554                 case '/':
1555                     *output_pointer++ = input_pointer[1];
1556                     break;
1557 
1558                 /* UTF-16 literal */
1559                 case 'u':
1560                     sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
1561                     if (sequence_length == 0)
1562                     {
1563                         /* failed to convert UTF16-literal to UTF-8 */
1564                         goto fail;
1565                     }
1566                     break;
1567 
1568                 default:
1569                     goto fail;
1570             }
1571             input_pointer += sequence_length;
1572         }
1573     }
1574 
1575     /* zero terminate the output */
1576     *output_pointer = '\0';
1577 
1578     item->type = cJSON_String;
1579     item->valuestring = (char*)output;
1580 
1581     input_buffer->offset = (size_t) (input_end - input_buffer->content);
1582     input_buffer->offset++;
1583 
1584     return true;
1585 
1586 fail:
1587     if (output != NULL)
1588     {
1589         input_buffer->hooks.deallocate(output);
1590     }
1591 
1592     if (input_pointer != NULL)
1593     {
1594         input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
1595     }
1596 
1597     return false;
1598 }
1599 
1600 /* Render the cstring provided to an escaped version that can be printed. */
1601 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
1602 {
1603     const unsigned char *input_pointer = NULL;
1604     unsigned char *output = NULL;
1605     unsigned char *output_pointer = NULL;
1606     size_t output_length = 0;
1607     /* numbers of additional characters needed for escaping */
1608     size_t escape_characters = 0;
1609 
1610     if (output_buffer == NULL)
1611     {
1612         return false;
1613     }
1614 
1615     /* empty string */
1616     if (input == NULL)
1617     {
1618         output = ensure(output_buffer, sizeof("\"\""));
1619         if (output == NULL)
1620         {
1621             return false;
1622         }
1623 #ifdef BIOS_CJSON
1624         unsigned int returnError = AsciiStrCpyS((char*)output, MAX_STRING_SIZE, "\"\"");
1625         if (returnError != 0)
1626         {
1627             return false;
1628         }
1629 #else
1630         strcpy((char*)output, "\"\"");
1631 #endif
1632 
1633         return true;
1634     }
1635 
1636     /* set "flag" to 1 if something needs to be escaped */
1637     for (input_pointer = input; *input_pointer; input_pointer++)
1638     {
1639         switch (*input_pointer)
1640         {
1641             case '\"':
1642             case '\\':
1643             case '\b':
1644             case '\f':
1645             case '\n':
1646             case '\r':
1647             case '\t':
1648                 /* one character escape sequence */
1649                 escape_characters++;
1650                 break;
1651             default:
1652                 if (*input_pointer < 32)
1653                 {
1654                     /* UTF-16 escape sequence uXXXX */
1655                     escape_characters += 5;
1656                 }
1657                 break;
1658         }
1659     }
1660     output_length = (size_t)(input_pointer - input) + escape_characters;
1661 
1662     output = ensure(output_buffer, output_length + sizeof("\"\""));
1663     if (output == NULL)
1664     {
1665         return false;
1666     }
1667 
1668     /* no characters have to be escaped */
1669     if (escape_characters == 0)
1670     {
1671         output[0] = '\"';
1672         memcpy(output + 1, input, output_length);
1673         output[output_length + 1] = '\"';
1674         output[output_length + 2] = '\0';
1675 
1676         return true;
1677     }
1678 
1679     output[0] = '\"';
1680     output_pointer = output + 1;
1681     /* copy the string */
1682     for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1683     {
1684         if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1685         {
1686             /* normal character, copy */
1687             *output_pointer = *input_pointer;
1688         }
1689         else
1690         {
1691             /* character needs to be escaped */
1692             *output_pointer++ = '\\';
1693             switch (*input_pointer)
1694             {
1695                 case '\\':
1696                     *output_pointer = '\\';
1697                     break;
1698                 case '\"':
1699                     *output_pointer = '\"';
1700                     break;
1701                 case '\b':
1702                     *output_pointer = 'b';
1703                     break;
1704                 case '\f':
1705                     *output_pointer = 'f';
1706                     break;
1707                 case '\n':
1708                     *output_pointer = 'n';
1709                     break;
1710                 case '\r':
1711                     *output_pointer = 'r';
1712                     break;
1713                 case '\t':
1714                     *output_pointer = 't';
1715                     break;
1716                 default:
1717                     /* escape and print as unicode codepoint */
1718 #ifdef BIOS_CJSON
1719                     AsciiSPrintS((char*)output_pointer, MAX_STRING_SIZE, "u%04x", *input_pointer);
1720 #else
1721                     sprintf((char*)output_pointer, "u%04x", *input_pointer);
1722 #endif
1723                     output_pointer += 4;
1724                     break;
1725             }
1726         }
1727     }
1728     output[output_length + 1] = '\"';
1729     output[output_length + 2] = '\0';
1730 
1731     return true;
1732 }
1733 
1734 /* Invoke print_string_ptr (which is useful) on an item. */
1735 static cJSON_bool print_string(const cJSON *const item, printbuffer *const p)
1736 {
1737     return print_string_ptr((unsigned char *)item->valuestring, p);
1738 }
1739 
1740 /* Predeclare these prototypes. */
1741 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1742 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1743 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1744 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1745 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1746 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1747 
1748 /* Utility to jump whitespace and cr/lf */
1749 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1750 {
1751     if ((buffer == NULL) || (buffer->content == NULL))
1752     {
1753         return NULL;
1754     }
1755 
1756     if (cannot_access_at_index(buffer, 0))
1757     {
1758         return buffer;
1759     }
1760 
1761     while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1762     {
1763        buffer->offset++;
1764     }
1765 
1766     if (buffer->offset == buffer->length)
1767     {
1768         buffer->offset--;
1769     }
1770 
1771     return buffer;
1772 }
1773 
1774 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1775 static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1776 {
1777     if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1778     {
1779         return NULL;
1780     }
1781 
1782     if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1783     {
1784         buffer->offset += 3;
1785     }
1786 
1787     return buffer;
1788 }
1789 
1790 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1791 {
1792     size_t buffer_length;
1793 
1794     if (NULL == value)
1795     {
1796         return NULL;
1797     }
1798 
1799     /* Adding null character size due to require_null_terminated. */
1800 #ifdef BIOS_CJSON
1801     buffer_length = (size_t)AsciiStrnLenS(value, MAX_STRING_SIZE) + sizeof("");
1802 #else
1803     buffer_length = strlen(value) + sizeof("");
1804 #endif
1805 
1806     return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1807 }
1808 
1809 /* Parse an object - create a new root, and populate. */
1810 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1811 {
1812 #ifdef RESTRICT_RESOURCE
1813     parse_buffer buffer = { 0, 0, 0, 0, 0, { 0, 0, 0 } };
1814 #else
1815     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1816 #endif
1817     cJSON *item = NULL;
1818 
1819     /* reset error position */
1820     global_error.json = NULL;
1821     global_error.position = 0;
1822 
1823     if (value == NULL || 0 == buffer_length)
1824     {
1825         goto fail;
1826     }
1827 
1828     buffer.content = (const unsigned char*)value;
1829     buffer.length = buffer_length;
1830     buffer.offset = 0;
1831     buffer.hooks = global_hooks;
1832 
1833 #ifdef RESTRICT_RESOURCE
1834     buffer.item_count = 0;
1835 
1836     if (buffer_length > STR_LENGTH_LIMIT)
1837     {
1838         return NULL;
1839     }
1840 #endif
1841 
1842     item = cJSON_New_Item(&global_hooks);
1843     if (item == NULL) /* memory fail */
1844     {
1845         goto fail;
1846     }
1847 
1848     if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1849     {
1850         /* parse failure. ep is set. */
1851         goto fail;
1852     }
1853 
1854     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1855     if (require_null_terminated)
1856     {
1857         buffer_skip_whitespace(&buffer);
1858         if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1859         {
1860             goto fail;
1861         }
1862     }
1863     if (return_parse_end)
1864     {
1865         *return_parse_end = (const char*)buffer_at_offset(&buffer);
1866     }
1867 
1868     return item;
1869 
1870 fail:
1871     if (item != NULL)
1872     {
1873         cJSON_Delete(item);
1874     }
1875 
1876     if (value != NULL)
1877     {
1878         error local_error;
1879         local_error.json = (const unsigned char*)value;
1880         local_error.position = 0;
1881 
1882         if (buffer.offset < buffer.length)
1883         {
1884             local_error.position = buffer.offset;
1885         }
1886         else if (buffer.length > 0)
1887         {
1888             local_error.position = buffer.length - 1;
1889         }
1890 
1891         if (return_parse_end != NULL)
1892         {
1893             *return_parse_end = (const char*)local_error.json + local_error.position;
1894         }
1895 
1896         global_error = local_error;
1897     }
1898 
1899     return NULL;
1900 }
1901 
1902 /* Default options for cJSON_Parse */
1903 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1904 {
1905     return cJSON_ParseWithOpts(value, 0, 0);
1906 }
1907 
1908 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1909 {
1910     return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1911 }
1912 
1913 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1914 
1915 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1916 {
1917     static const size_t default_buffer_size = 256;
1918     printbuffer buffer[1];
1919     unsigned char *printed = NULL;
1920 
1921     memset(buffer, 0, sizeof(buffer));
1922 
1923     /* create buffer */
1924     buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1925     buffer->length = default_buffer_size;
1926     buffer->format = format;
1927     buffer->hooks = *hooks;
1928     if (buffer->buffer == NULL)
1929     {
1930         goto fail;
1931     }
1932 
1933     /* print the value */
1934     if (!print_value(item, buffer))
1935     {
1936         goto fail;
1937     }
1938     update_offset(buffer);
1939 
1940     /* check if reallocate is available */
1941     if (hooks->reallocate != NULL)
1942     {
1943         printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1944         if (printed == NULL) {
1945             goto fail;
1946         }
1947         buffer->buffer = NULL;
1948     }
1949     else /* otherwise copy the JSON over to a new buffer */
1950     {
1951         printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1952         if (printed == NULL)
1953         {
1954             goto fail;
1955         }
1956         memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1957         printed[buffer->offset] = '\0'; /* just to be sure */
1958 
1959         /* free the buffer */
1960         hooks->deallocate(buffer->buffer);
1961     }
1962 
1963     return printed;
1964 
1965 fail:
1966     if (buffer->buffer != NULL)
1967     {
1968         hooks->deallocate(buffer->buffer);
1969     }
1970 
1971     if (printed != NULL)
1972     {
1973         hooks->deallocate(printed);
1974     }
1975 
1976     return NULL;
1977 }
1978 
1979 /* Render a cJSON item/entity/structure to text. */
1980 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1981 {
1982     return (char*)print(item, true, &global_hooks);
1983 }
1984 
1985 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1986 {
1987     return (char*)print(item, false, &global_hooks);
1988 }
1989 
1990 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1991 {
1992     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1993 
1994     if (prebuffer < 0)
1995     {
1996         return NULL;
1997     }
1998 
1999     p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
2000     if (!p.buffer)
2001     {
2002         return NULL;
2003     }
2004 
2005     p.length = (size_t)prebuffer;
2006     p.offset = 0;
2007     p.noalloc = false;
2008     p.format = fmt;
2009     p.hooks = global_hooks;
2010 
2011     if (!print_value(item, &p))
2012     {
2013         global_hooks.deallocate(p.buffer);
2014         return NULL;
2015     }
2016 
2017     return (char*)p.buffer;
2018 }
2019 
2020 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
2021 {
2022     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
2023 
2024     if ((length < 0) || (buffer == NULL))
2025     {
2026         return false;
2027     }
2028 
2029     p.buffer = (unsigned char*)buffer;
2030     p.length = (size_t)length;
2031     p.offset = 0;
2032     p.noalloc = true;
2033     p.format = format;
2034     p.hooks = global_hooks;
2035 
2036     return print_value(item, &p);
2037 }
2038 
2039 
2040 /* Parser core - when encountering text, process appropriately. */
2041 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
2042 {
2043     if ((input_buffer == NULL) || (input_buffer->content == NULL))
2044     {
2045         return false; /* no input */
2046     }
2047 
2048 #ifdef RESTRICT_RESOURCE
2049     input_buffer->item_count++;
2050     if (input_buffer->item_count > ITEM_COUNT_LIMIT)
2051     {
2052         return false;
2053     }
2054 #endif
2055 
2056     /* parse the different types of values */
2057     /* null */
2058     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
2059     {
2060         item->type = cJSON_NULL;
2061         input_buffer->offset += 4;
2062         return true;
2063     }
2064     /* false */
2065     if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
2066     {
2067         item->type = cJSON_False;
2068         input_buffer->offset += 5;
2069         return true;
2070     }
2071     /* true */
2072     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
2073     {
2074         item->type = cJSON_True;
2075         item->valueint = 1;
2076         input_buffer->offset += 4;
2077         return true;
2078     }
2079     /* string */
2080     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
2081     {
2082         return parse_string(item, input_buffer);
2083     }
2084     /* number */
2085     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'))))
2086     {
2087         return parse_number(item, input_buffer);
2088     }
2089     /* array */
2090     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
2091     {
2092         return parse_array(item, input_buffer);
2093     }
2094     /* object */
2095     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
2096     {
2097         return parse_object(item, input_buffer);
2098     }
2099 
2100     return false;
2101 }
2102 
2103 #ifdef S210
2104 /* Render a value to text. */
2105 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
2106 {
2107     unsigned char *output = NULL;
2108 
2109     if ((item == NULL) || (output_buffer == NULL))
2110     {
2111         return false;
2112     }
2113 
2114     switch ((item->type) & 0xFFFF)
2115     {
2116         case cJSON_NULL:
2117             output = ensure(output_buffer, 5);
2118             if (output == NULL)
2119             {
2120                 return false;
2121             }
2122             strcpy((char*)output, "null");
2123             return true;
2124 
2125         case cJSON_False:
2126             output = ensure(output_buffer, 6);
2127             if (output == NULL)
2128             {
2129                 return false;
2130             }
2131             strcpy((char*)output, "false");
2132             return true;
2133 
2134         case cJSON_True:
2135             output = ensure(output_buffer, 5);
2136             if (output == NULL)
2137             {
2138                 return false;
2139             }
2140             strcpy((char*)output, "true");
2141             return true;
2142 
2143         case cJSON_Number:
2144             return print_number(item, output_buffer);
2145 
2146         case cJSON_Float:
2147             return print_float(item, output_buffer);
2148 
2149         case cJSON_Raw: {
2150             size_t raw_length = 0;
2151             if (item->valuestring == NULL)
2152             {
2153                 return false;
2154             }
2155 
2156             raw_length = strlen(item->valuestring) + sizeof("");
2157             output = ensure(output_buffer, raw_length);
2158             if (output == NULL)
2159             {
2160                 return false;
2161             }
2162             memcpy(output, item->valuestring, raw_length);
2163             return true;
2164         }
2165 
2166         case cJSON_String:
2167             return print_string(item, output_buffer);
2168 
2169         case cJSON_Array:
2170             return print_array(item, output_buffer);
2171 
2172         case cJSON_Object:
2173             return print_object(item, output_buffer);
2174 
2175         default:
2176             return false;
2177     }
2178 }
2179 #else
2180 /* Render a value to text. */
2181 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
2182 {
2183     unsigned char *output = NULL;
2184 #ifdef BIOS_CJSON
2185     unsigned int returnError;
2186 #endif
2187 
2188     if ((item == NULL) || (output_buffer == NULL))
2189     {
2190         return false;
2191     }
2192 
2193     switch ((item->type) & 0xFF)
2194     {
2195         case cJSON_NULL:
2196             output = ensure(output_buffer, 5);
2197             if (output == NULL)
2198             {
2199                 return false;
2200             }
2201 #ifdef BIOS_CJSON
2202             returnError = AsciiStrCpyS((char*)output, MAX_STRING_SIZE, "null");
2203             if (returnError != 0)
2204             {
2205                 return false;
2206             }
2207 #else
2208             strcpy((char*)output, "null");
2209 #endif
2210             return true;
2211 
2212         case cJSON_False:
2213             output = ensure(output_buffer, 6);
2214             if (output == NULL)
2215             {
2216                 return false;
2217             }
2218 #ifdef BIOS_CJSON
2219             returnError = AsciiStrCpyS((char*)output, MAX_STRING_SIZE, "false");
2220             if (returnError != 0)
2221             {
2222                 return false;
2223             }
2224 #else
2225             strcpy((char*)output, "false");
2226 #endif
2227             return true;
2228 
2229         case cJSON_True:
2230             output = ensure(output_buffer, 5);
2231             if (output == NULL)
2232             {
2233                 return false;
2234             }
2235 #ifdef BIOS_CJSON
2236             returnError = AsciiStrCpyS((char*)output, MAX_STRING_SIZE, "true");
2237             if (returnError != 0)
2238             {
2239                 return false;
2240             }
2241 #else
2242             strcpy((char*)output, "true");
2243 #endif
2244             return true;
2245 
2246         case cJSON_Number:
2247             return print_number(item, output_buffer);
2248 
2249         case cJSON_Raw:
2250         {
2251             size_t raw_length = 0;
2252             if (item->valuestring == NULL)
2253             {
2254                 return false;
2255             }
2256 
2257 #ifdef BIOS_CJSON
2258             raw_length = (size_t)AsciiStrnLenS(item->valuestring, MAX_STRING_SIZE) + sizeof("");
2259 #else
2260             raw_length = strlen(item->valuestring) + sizeof("");
2261 #endif
2262             output = ensure(output_buffer, raw_length);
2263             if (output == NULL)
2264             {
2265                 return false;
2266             }
2267             memcpy(output, item->valuestring, raw_length);
2268             return true;
2269         }
2270 
2271         case cJSON_String:
2272             return print_string(item, output_buffer);
2273 
2274         case cJSON_Array:
2275             return print_array(item, output_buffer);
2276 
2277         case cJSON_Object:
2278             return print_object(item, output_buffer);
2279 
2280         default:
2281             return false;
2282     }
2283 }
2284 #endif
2285 /* Build an array from input text. */
2286 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
2287 {
2288     cJSON *head = NULL; /* head of the linked list */
2289     cJSON *current_item = NULL;
2290 
2291     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
2292     {
2293         return false; /* to deeply nested */
2294     }
2295     input_buffer->depth++;
2296 
2297     if (buffer_at_offset(input_buffer)[0] != '[')
2298     {
2299         /* not an array */
2300         goto fail;
2301     }
2302 
2303     input_buffer->offset++;
2304     buffer_skip_whitespace(input_buffer);
2305     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
2306     {
2307         /* empty array */
2308         goto success;
2309     }
2310 
2311     /* check if we skipped to the end of the buffer */
2312     if (cannot_access_at_index(input_buffer, 0))
2313     {
2314         input_buffer->offset--;
2315         goto fail;
2316     }
2317 
2318     /* step back to character in front of the first element */
2319     input_buffer->offset--;
2320     /* loop through the comma separated array elements */
2321     do
2322     {
2323         /* allocate next item */
2324         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
2325         if (new_item == NULL)
2326         {
2327             goto fail; /* allocation failure */
2328         }
2329 
2330         /* attach next item to list */
2331         if (head == NULL)
2332         {
2333             /* start the linked list */
2334             current_item = head = new_item;
2335         }
2336         else
2337         {
2338             /* add to the end and advance */
2339             current_item->next = new_item;
2340             new_item->prev = current_item;
2341             current_item = new_item;
2342         }
2343 
2344         /* parse next value */
2345         input_buffer->offset++;
2346         buffer_skip_whitespace(input_buffer);
2347         if (!parse_value(current_item, input_buffer))
2348         {
2349             goto fail; /* failed to parse value */
2350         }
2351         buffer_skip_whitespace(input_buffer);
2352     }
2353     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
2354 
2355     if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
2356     {
2357         goto fail; /* expected end of array */
2358     }
2359 
2360 success:
2361     input_buffer->depth--;
2362 
2363     if (head != NULL) {
2364         head->prev = current_item;
2365     }
2366 
2367     item->type = cJSON_Array;
2368     item->child = head;
2369 
2370     input_buffer->offset++;
2371 
2372     return true;
2373 
2374 fail:
2375     if (head != NULL)
2376     {
2377         cJSON_Delete(head);
2378     }
2379 
2380     return false;
2381 }
2382 
2383 /* Render an array to text */
2384 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
2385 {
2386     unsigned char *output_pointer = NULL;
2387     size_t length = 0;
2388     cJSON *current_element = item->child;
2389 
2390     if (output_buffer == NULL)
2391     {
2392         return false;
2393     }
2394 
2395     /* Compose the output array. */
2396     /* opening square bracket */
2397     output_pointer = ensure(output_buffer, 1);
2398     if (output_pointer == NULL)
2399     {
2400         return false;
2401     }
2402 
2403     *output_pointer = '[';
2404     output_buffer->offset++;
2405     output_buffer->depth++;
2406 
2407     while (current_element != NULL)
2408     {
2409         if (!print_value(current_element, output_buffer))
2410         {
2411             return false;
2412         }
2413         update_offset(output_buffer);
2414         if (current_element->next)
2415         {
2416             length = (size_t) (output_buffer->format ? 2 : 1);
2417             output_pointer = ensure(output_buffer, length + 1);
2418             if (output_pointer == NULL)
2419             {
2420                 return false;
2421             }
2422             *output_pointer++ = ',';
2423             if(output_buffer->format)
2424             {
2425                 *output_pointer++ = ' ';
2426             }
2427             *output_pointer = '\0';
2428             output_buffer->offset += length;
2429         }
2430         current_element = current_element->next;
2431     }
2432 
2433     output_pointer = ensure(output_buffer, 2);
2434     if (output_pointer == NULL)
2435     {
2436         return false;
2437     }
2438     *output_pointer++ = ']';
2439     *output_pointer = '\0';
2440     output_buffer->depth--;
2441 
2442     return true;
2443 }
2444 
2445 /* Build an object from the text. */
2446 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
2447 {
2448     cJSON *head = NULL; /* linked list head */
2449     cJSON *current_item = NULL;
2450 
2451     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
2452     {
2453         return false; /* to deeply nested */
2454     }
2455     input_buffer->depth++;
2456 
2457     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
2458     {
2459         goto fail; /* not an object */
2460     }
2461 
2462     input_buffer->offset++;
2463     buffer_skip_whitespace(input_buffer);
2464     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
2465     {
2466         goto success; /* empty object */
2467     }
2468 
2469     /* check if we skipped to the end of the buffer */
2470     if (cannot_access_at_index(input_buffer, 0))
2471     {
2472         input_buffer->offset--;
2473         goto fail;
2474     }
2475 
2476     /* step back to character in front of the first element */
2477     input_buffer->offset--;
2478     /* loop through the comma separated array elements */
2479     do
2480     {
2481         /* allocate next item */
2482         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
2483         if (new_item == NULL)
2484         {
2485             goto fail; /* allocation failure */
2486         }
2487 
2488         /* attach next item to list */
2489         if (head == NULL)
2490         {
2491             /* start the linked list */
2492             current_item = head = new_item;
2493         }
2494         else
2495         {
2496             /* add to the end and advance */
2497             current_item->next = new_item;
2498             new_item->prev = current_item;
2499             current_item = new_item;
2500         }
2501 
2502         /* parse the name of the child */
2503         input_buffer->offset++;
2504         buffer_skip_whitespace(input_buffer);
2505         if (!parse_string(current_item, input_buffer))
2506         {
2507             goto fail; /* failed to parse name */
2508         }
2509         buffer_skip_whitespace(input_buffer);
2510 
2511         /* swap valuestring and string, because we parsed the name */
2512         current_item->string = current_item->valuestring;
2513         current_item->valuestring = NULL;
2514 
2515         if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
2516         {
2517             goto fail; /* invalid object */
2518         }
2519 
2520         /* parse the value */
2521         input_buffer->offset++;
2522         buffer_skip_whitespace(input_buffer);
2523         if (!parse_value(current_item, input_buffer))
2524         {
2525             goto fail; /* failed to parse value */
2526         }
2527         buffer_skip_whitespace(input_buffer);
2528     }
2529     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
2530 
2531     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
2532     {
2533         goto fail; /* expected end of object */
2534     }
2535 
2536 success:
2537     input_buffer->depth--;
2538 
2539     if (head != NULL) {
2540         head->prev = current_item;
2541     }
2542 
2543     item->type = cJSON_Object;
2544     item->child = head;
2545 
2546     input_buffer->offset++;
2547     return true;
2548 
2549 fail:
2550     if (head != NULL)
2551     {
2552         cJSON_Delete(head);
2553     }
2554 
2555     return false;
2556 }
2557 
2558 /* Render an object to text. */
2559 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
2560 {
2561     unsigned char *output_pointer = NULL;
2562     size_t length = 0;
2563     cJSON *current_item = item->child;
2564 
2565     if (output_buffer == NULL)
2566     {
2567         return false;
2568     }
2569 
2570     /* Compose the output: */
2571     length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
2572     output_pointer = ensure(output_buffer, length + 1);
2573     if (output_pointer == NULL)
2574     {
2575         return false;
2576     }
2577 
2578     *output_pointer++ = '{';
2579     output_buffer->depth++;
2580     if (output_buffer->format)
2581     {
2582         *output_pointer++ = '\n';
2583     }
2584     output_buffer->offset += length;
2585 
2586     while (current_item)
2587     {
2588         if (output_buffer->format)
2589         {
2590             size_t i;
2591             output_pointer = ensure(output_buffer, output_buffer->depth);
2592             if (output_pointer == NULL)
2593             {
2594                 return false;
2595             }
2596             for (i = 0; i < output_buffer->depth; i++)
2597             {
2598                 *output_pointer++ = '\t';
2599             }
2600             output_buffer->offset += output_buffer->depth;
2601         }
2602 
2603         /* print key */
2604         if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
2605         {
2606             return false;
2607         }
2608         update_offset(output_buffer);
2609 
2610         length = (size_t) (output_buffer->format ? 2 : 1);
2611         output_pointer = ensure(output_buffer, length);
2612         if (output_pointer == NULL)
2613         {
2614             return false;
2615         }
2616         *output_pointer++ = ':';
2617         if (output_buffer->format)
2618         {
2619             *output_pointer++ = '\t';
2620         }
2621         output_buffer->offset += length;
2622 
2623         /* print value */
2624         if (!print_value(current_item, output_buffer))
2625         {
2626             return false;
2627         }
2628         update_offset(output_buffer);
2629 
2630         /* print comma if not last */
2631         length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
2632         output_pointer = ensure(output_buffer, length + 1);
2633         if (output_pointer == NULL)
2634         {
2635             return false;
2636         }
2637         if (current_item->next)
2638         {
2639             *output_pointer++ = ',';
2640         }
2641 
2642         if (output_buffer->format)
2643         {
2644             *output_pointer++ = '\n';
2645         }
2646         *output_pointer = '\0';
2647         output_buffer->offset += length;
2648 
2649         current_item = current_item->next;
2650     }
2651 
2652     output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
2653     if (output_pointer == NULL)
2654     {
2655         return false;
2656     }
2657     if (output_buffer->format)
2658     {
2659         size_t i;
2660         for (i = 0; i < (output_buffer->depth - 1); i++)
2661         {
2662             *output_pointer++ = '\t';
2663         }
2664     }
2665     *output_pointer++ = '}';
2666     *output_pointer = '\0';
2667     output_buffer->depth--;
2668 
2669     return true;
2670 }
2671 
2672 /* Get Array size/item / object item. */
2673 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
2674 {
2675     cJSON *child = NULL;
2676     size_t size = 0;
2677 
2678     if (array == NULL)
2679     {
2680         return 0;
2681     }
2682 
2683     child = array->child;
2684 
2685     while(child != NULL)
2686     {
2687         size++;
2688         child = child->next;
2689     }
2690 
2691     /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
2692 
2693     return (int)size;
2694 }
2695 
2696 static cJSON* get_array_item(const cJSON *array, size_t index)
2697 {
2698     cJSON *current_child = NULL;
2699 
2700     if (array == NULL)
2701     {
2702         return NULL;
2703     }
2704 
2705     current_child = array->child;
2706     while ((current_child != NULL) && (index > 0))
2707     {
2708         index--;
2709         current_child = current_child->next;
2710     }
2711 
2712     return current_child;
2713 }
2714 
2715 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
2716 {
2717     if (index < 0)
2718     {
2719         return NULL;
2720     }
2721 
2722     return get_array_item(array, (size_t)index);
2723 }
2724 
2725 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
2726 {
2727     cJSON *current_element = NULL;
2728 
2729     if ((object == NULL) || (name == NULL))
2730     {
2731         return NULL;
2732     }
2733 
2734     current_element = object->child;
2735     if (case_sensitive)
2736     {
2737         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
2738         {
2739             current_element = current_element->next;
2740         }
2741     }
2742     else
2743     {
2744         while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
2745         {
2746             current_element = current_element->next;
2747         }
2748     }
2749 
2750     if ((current_element == NULL) || (current_element->string == NULL)) {
2751         return NULL;
2752     }
2753 
2754     return current_element;
2755 }
2756 
2757 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
2758 {
2759     return get_object_item(object, string, false);
2760 }
2761 
2762 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
2763 {
2764     return get_object_item(object, string, true);
2765 }
2766 
2767 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
2768 {
2769     return cJSON_GetObjectItem(object, string) ? 1 : 0;
2770 }
2771 
2772 /* Utility for array list handling. */
2773 static void suffix_object(cJSON *prev, cJSON *item)
2774 {
2775     prev->next = item;
2776     item->prev = prev;
2777 }
2778 
2779 /* Utility for handling references. */
2780 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
2781 {
2782     cJSON *reference = NULL;
2783     if (item == NULL)
2784     {
2785         return NULL;
2786     }
2787 
2788     reference = cJSON_New_Item(hooks);
2789     if (reference == NULL)
2790     {
2791         return NULL;
2792     }
2793 
2794     memcpy(reference, item, sizeof(cJSON));
2795     reference->string = NULL;
2796     reference->type |= cJSON_IsReference;
2797     reference->next = reference->prev = NULL;
2798     return reference;
2799 }
2800 
2801 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2802 {
2803     cJSON *child = NULL;
2804 
2805     if ((item == NULL) || (array == NULL) || (array == item))
2806     {
2807         return false;
2808     }
2809 
2810     child = array->child;
2811     /*
2812      * To find the last item in array quickly, we use prev in array
2813      */
2814     if (child == NULL)
2815     {
2816         /* list is empty, start new one */
2817         array->child = item;
2818         item->prev = item;
2819         item->next = NULL;
2820     }
2821     else
2822     {
2823         /* append to the end */
2824         if (child->prev)
2825         {
2826             suffix_object(child->prev, item);
2827             array->child->prev = item;
2828         }
2829         else
2830         {
2831             while (child->next)
2832             {
2833                 child = child->next;
2834             }
2835             suffix_object(child, item);
2836             array->child->prev = item;
2837         }
2838     }
2839 
2840     return true;
2841 }
2842 
2843 /* Add item to array/object. */
2844 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2845 {
2846     return add_item_to_array(array, item);
2847 }
2848 
2849 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2850     #pragma GCC diagnostic push
2851 #endif
2852 #ifdef __GNUC__
2853 #pragma GCC diagnostic ignored "-Wcast-qual"
2854 #endif
2855 /* helper function to cast away const */
2856 static void* cast_away_const(const void* string)
2857 {
2858     return (void*)string;
2859 }
2860 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2861     #pragma GCC diagnostic pop
2862 #endif
2863 
2864 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)
2865 {
2866     char *new_key = NULL;
2867     int new_type = cJSON_Invalid;
2868 
2869     if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2870     {
2871         return false;
2872     }
2873 
2874     if (constant_key)
2875     {
2876         new_key = (char*)cast_away_const(string);
2877         new_type = item->type | cJSON_StringIsConst;
2878     }
2879     else
2880     {
2881         new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2882         if (new_key == NULL)
2883         {
2884             return false;
2885         }
2886 
2887         new_type = item->type & ~cJSON_StringIsConst;
2888     }
2889 
2890     if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2891     {
2892         hooks->deallocate(item->string);
2893     }
2894 
2895     item->string = new_key;
2896     item->type = new_type;
2897 
2898     return add_item_to_array(object, item);
2899 }
2900 
2901 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2902 {
2903     return add_item_to_object(object, string, item, &global_hooks, false);
2904 }
2905 
2906 /* Add an item to an object with constant string as key */
2907 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2908 {
2909     return add_item_to_object(object, string, item, &global_hooks, true);
2910 }
2911 
2912 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2913 {
2914     if (array == NULL)
2915     {
2916         return false;
2917     }
2918 
2919     return add_item_to_array(array, create_reference(item, &global_hooks));
2920 }
2921 
2922 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2923 {
2924     if ((object == NULL) || (string == NULL))
2925     {
2926         return false;
2927     }
2928 
2929     return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2930 }
2931 
2932 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2933 {
2934     cJSON *null = cJSON_CreateNull();
2935     if (add_item_to_object(object, name, null, &global_hooks, false))
2936     {
2937         return null;
2938     }
2939 
2940     cJSON_Delete(null);
2941     return NULL;
2942 }
2943 
2944 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2945 {
2946     cJSON *true_item = cJSON_CreateTrue();
2947     if (add_item_to_object(object, name, true_item, &global_hooks, false))
2948     {
2949         return true_item;
2950     }
2951 
2952     cJSON_Delete(true_item);
2953     return NULL;
2954 }
2955 
2956 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2957 {
2958     cJSON *false_item = cJSON_CreateFalse();
2959     if (add_item_to_object(object, name, false_item, &global_hooks, false))
2960     {
2961         return false_item;
2962     }
2963 
2964     cJSON_Delete(false_item);
2965     return NULL;
2966 }
2967 
2968 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2969 {
2970     cJSON *bool_item = cJSON_CreateBool(boolean);
2971     if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2972     {
2973         return bool_item;
2974     }
2975 
2976     cJSON_Delete(bool_item);
2977     return NULL;
2978 }
2979 
2980 #ifdef __CJSON_USE_INT64
2981 CJSON_PUBLIC(cJSON*) cJSON_AddInt64NumberToObject(cJSON * const object, const char * const name, const long long integer)
2982 {
2983     cJSON *int_item = cJSON_CreateInt64Number(integer);
2984     if (add_item_to_object(object, name, int_item, &global_hooks, false))
2985     {
2986         return int_item;
2987     }
2988 
2989     cJSON_Delete(int_item);
2990     return NULL;
2991 }
2992 #endif
2993 
2994 #ifdef S210
2995 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const int64 number)
2996 {
2997     cJSON *number_item = cJSON_CreateNumber(number);
2998     if (add_item_to_object(object, name, number_item, &global_hooks, false))
2999     {
3000         return number_item;
3001     }
3002 
3003     cJSON_Delete(number_item);
3004     return NULL;
3005 }
3006 #else
3007 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
3008 {
3009     cJSON *number_item = cJSON_CreateNumber(number);
3010     if (add_item_to_object(object, name, number_item, &global_hooks, false))
3011     {
3012         return number_item;
3013     }
3014 
3015     cJSON_Delete(number_item);
3016     return NULL;
3017 }
3018 #endif
3019 
3020 #ifdef S210
3021 CJSON_PUBLIC(cJSON *) cJSON_AddFloatToObject(cJSON *const object, const char *const name, const double number)
3022 {
3023     cJSON *number_item = cJSON_CreateFloat(number);
3024     if (add_item_to_object(object, name, number_item, &global_hooks, false)) {
3025         return number_item;
3026     }
3027 
3028     cJSON_Delete(number_item);
3029     return NULL;
3030 }
3031 #endif
3032 
3033 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
3034 {
3035     cJSON *string_item = cJSON_CreateString(string);
3036     if (add_item_to_object(object, name, string_item, &global_hooks, false))
3037     {
3038         return string_item;
3039     }
3040 
3041     cJSON_Delete(string_item);
3042     return NULL;
3043 }
3044 
3045 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
3046 {
3047     cJSON *raw_item = cJSON_CreateRaw(raw);
3048     if (add_item_to_object(object, name, raw_item, &global_hooks, false))
3049     {
3050         return raw_item;
3051     }
3052 
3053     cJSON_Delete(raw_item);
3054     return NULL;
3055 }
3056 
3057 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
3058 {
3059     cJSON *object_item = cJSON_CreateObject();
3060     if (add_item_to_object(object, name, object_item, &global_hooks, false))
3061     {
3062         return object_item;
3063     }
3064 
3065     cJSON_Delete(object_item);
3066     return NULL;
3067 }
3068 
3069 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
3070 {
3071     cJSON *array = cJSON_CreateArray();
3072     if (add_item_to_object(object, name, array, &global_hooks, false))
3073     {
3074         return array;
3075     }
3076 
3077     cJSON_Delete(array);
3078     return NULL;
3079 }
3080 
3081 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
3082 {
3083     if ((parent == NULL) || (item == NULL))
3084     {
3085         return NULL;
3086     }
3087 
3088     if (item != parent->child)
3089     {
3090         /* not the first element */
3091         item->prev->next = item->next;
3092     }
3093     if (item->next != NULL)
3094     {
3095         /* not the last element */
3096         item->next->prev = item->prev;
3097     }
3098 
3099     if (item == parent->child)
3100     {
3101         /* first element */
3102         parent->child = item->next;
3103     }
3104     else if (item->next == NULL)
3105     {
3106         /* last element */
3107         parent->child->prev = item->prev;
3108     }
3109 
3110     /* make sure the detached item doesn't point anywhere anymore */
3111     item->prev = NULL;
3112     item->next = NULL;
3113 
3114     return item;
3115 }
3116 
3117 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
3118 {
3119     if (which < 0)
3120     {
3121         return NULL;
3122     }
3123 
3124     return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
3125 }
3126 
3127 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
3128 {
3129     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
3130 }
3131 
3132 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
3133 {
3134     cJSON *to_detach = cJSON_GetObjectItem(object, string);
3135 
3136     return cJSON_DetachItemViaPointer(object, to_detach);
3137 }
3138 
3139 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
3140 {
3141     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
3142 
3143     return cJSON_DetachItemViaPointer(object, to_detach);
3144 }
3145 
3146 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
3147 {
3148     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
3149 }
3150 
3151 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
3152 {
3153     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
3154 }
3155 
3156 /* Replace array/object items with new ones. */
3157 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
3158 {
3159     cJSON *after_inserted = NULL;
3160 
3161     if (which < 0 || newitem == NULL)
3162     {
3163         return false;
3164     }
3165 
3166     after_inserted = get_array_item(array, (size_t)which);
3167     if (after_inserted == NULL)
3168     {
3169         return add_item_to_array(array, newitem);
3170     }
3171 
3172     if (after_inserted != array->child && after_inserted->prev == NULL) {
3173         /* return false if after_inserted is a corrupted array item */
3174         return false;
3175     }
3176 
3177     newitem->next = after_inserted;
3178     newitem->prev = after_inserted->prev;
3179     after_inserted->prev = newitem;
3180     if (after_inserted == array->child)
3181     {
3182         array->child = newitem;
3183     }
3184     else
3185     {
3186         newitem->prev->next = newitem;
3187     }
3188     return true;
3189 }
3190 
3191 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
3192 {
3193     if ((parent == NULL) || (replacement == NULL) || (item == NULL))
3194     {
3195         return false;
3196     }
3197 
3198     if (replacement == item)
3199     {
3200         return true;
3201     }
3202 
3203     replacement->next = item->next;
3204     replacement->prev = item->prev;
3205 
3206     if (replacement->next != NULL)
3207     {
3208         replacement->next->prev = replacement;
3209     }
3210     if (parent->child == item)
3211     {
3212         if (parent->child->prev == parent->child)
3213         {
3214             replacement->prev = replacement;
3215         }
3216         parent->child = replacement;
3217     }
3218     else
3219     {   /*
3220          * To find the last item in array quickly, we use prev in array.
3221          * We can't modify the last item's next pointer where this item was the parent's child
3222          */
3223         if (replacement->prev != NULL)
3224         {
3225             replacement->prev->next = replacement;
3226         }
3227         if (replacement->next == NULL)
3228         {
3229             parent->child->prev = replacement;
3230         }
3231     }
3232 
3233     item->next = NULL;
3234     item->prev = NULL;
3235     cJSON_Delete(item);
3236 
3237     return true;
3238 }
3239 
3240 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
3241 {
3242     if (which < 0)
3243     {
3244         return false;
3245     }
3246 
3247     return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
3248 }
3249 
3250 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
3251 {
3252     if ((replacement == NULL) || (string == NULL))
3253     {
3254         return false;
3255     }
3256 
3257     /* replace the name in the replacement */
3258     if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
3259     {
3260         cJSON_free(replacement->string);
3261     }
3262     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
3263     replacement->type &= ~cJSON_StringIsConst;
3264 
3265     return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
3266 }
3267 
3268 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
3269 {
3270     return replace_item_in_object(object, string, newitem, false);
3271 }
3272 
3273 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
3274 {
3275     return replace_item_in_object(object, string, newitem, true);
3276 }
3277 
3278 /* Create basic types: */
3279 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
3280 {
3281     cJSON *item = cJSON_New_Item(&global_hooks);
3282     if(item)
3283     {
3284         item->type = cJSON_NULL;
3285     }
3286 
3287     return item;
3288 }
3289 
3290 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
3291 {
3292     cJSON *item = cJSON_New_Item(&global_hooks);
3293     if(item)
3294     {
3295         item->type = cJSON_True;
3296     }
3297 
3298     return item;
3299 }
3300 
3301 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
3302 {
3303     cJSON *item = cJSON_New_Item(&global_hooks);
3304     if(item)
3305     {
3306         item->type = cJSON_False;
3307     }
3308 
3309     return item;
3310 }
3311 
3312 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
3313 {
3314     cJSON *item = cJSON_New_Item(&global_hooks);
3315     if(item)
3316     {
3317         item->type = boolean ? cJSON_True : cJSON_False;
3318     }
3319 
3320     return item;
3321 }
3322 
3323 #ifdef __CJSON_USE_INT64
3324 CJSON_PUBLIC(cJSON *) cJSON_CreateInt64Number(long long integer)
3325 {
3326     cJSON *item = cJSON_New_Item(&global_hooks);
3327     if(item)
3328     {
3329         item->type = cJSON_Number | cJSON_IsInt64;
3330         item->valueint = integer;
3331         item->valuedouble = (double)integer;
3332     }
3333 
3334     return item;
3335 }
3336 #endif
3337 
3338 #ifdef S210
3339 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(int64 num)
3340 {
3341     cJSON *item = cJSON_New_Item(&global_hooks);
3342     if (item)
3343     {
3344         item->type = cJSON_Number;
3345         item->valueint = num;
3346     }
3347 
3348     return item;
3349 }
3350 #else
3351 #ifdef __CJSON_USE_INT64
3352 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
3353 {
3354     cJSON *item = cJSON_New_Item(&global_hooks);
3355     if(item)
3356     {
3357         item->type = cJSON_Number;
3358         item->valuedouble = num;
3359 
3360         /* use saturation in case of overflow */
3361         /* note that double max(DBL_MAX) is bigger than long long max(LLONG_MAX) */
3362         if (num >= (double)LLONG_MAX)
3363         {
3364             item->valueint = LLONG_MAX;
3365         }
3366         else if (num <= (double)LLONG_MIN)
3367         {
3368             item->valueint = LLONG_MIN;
3369         }
3370         else
3371         {
3372             item->valueint = (long long)num;
3373         }
3374     }
3375 
3376     return item;
3377 }
3378 #else
3379 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
3380 {
3381     cJSON *item = cJSON_New_Item(&global_hooks);
3382     if(item)
3383     {
3384         item->type = cJSON_Number;
3385         item->valuedouble = num;
3386 
3387         /* use saturation in case of overflow */
3388         if (num >= INT_MAX)
3389         {
3390             item->valueint = INT_MAX;
3391         }
3392         else if (num <= (double)INT_MIN)
3393         {
3394             item->valueint = INT_MIN;
3395         }
3396         else
3397         {
3398             item->valueint = (int)num;
3399         }
3400     }
3401 
3402     return item;
3403 }
3404 #endif
3405 #endif
3406 
3407 #ifdef S210
3408 CJSON_PUBLIC(cJSON *) cJSON_CreateFloat(double num)
3409 {
3410     cJSON *item = cJSON_New_Item(&global_hooks);
3411     if (item) {
3412         item->type = cJSON_Float;
3413         item->valuedouble = num;
3414     }
3415 
3416     return item;
3417 }
3418 #endif
3419 
3420 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
3421 {
3422     cJSON *item = cJSON_New_Item(&global_hooks);
3423     if(item)
3424     {
3425         item->type = cJSON_String;
3426         item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
3427         if(!item->valuestring)
3428         {
3429             cJSON_Delete(item);
3430             return NULL;
3431         }
3432     }
3433 
3434     return item;
3435 }
3436 
3437 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
3438 {
3439     cJSON *item = cJSON_New_Item(&global_hooks);
3440     if (item != NULL)
3441     {
3442         item->type = cJSON_String | cJSON_IsReference;
3443         item->valuestring = (char*)cast_away_const(string);
3444     }
3445 
3446     return item;
3447 }
3448 
3449 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
3450 {
3451     cJSON *item = cJSON_New_Item(&global_hooks);
3452     if (item != NULL) {
3453         item->type = cJSON_Object | cJSON_IsReference;
3454         item->child = (cJSON*)cast_away_const(child);
3455     }
3456 
3457     return item;
3458 }
3459 
3460 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
3461     cJSON *item = cJSON_New_Item(&global_hooks);
3462     if (item != NULL) {
3463         item->type = cJSON_Array | cJSON_IsReference;
3464         item->child = (cJSON*)cast_away_const(child);
3465     }
3466 
3467     return item;
3468 }
3469 
3470 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
3471 {
3472     cJSON *item = cJSON_New_Item(&global_hooks);
3473     if(item)
3474     {
3475         item->type = cJSON_Raw;
3476         item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
3477         if(!item->valuestring)
3478         {
3479             cJSON_Delete(item);
3480             return NULL;
3481         }
3482     }
3483 
3484     return item;
3485 }
3486 
3487 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
3488 {
3489     cJSON *item = cJSON_New_Item(&global_hooks);
3490     if(item)
3491     {
3492         item->type=cJSON_Array;
3493     }
3494 
3495     return item;
3496 }
3497 
3498 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
3499 {
3500     cJSON *item = cJSON_New_Item(&global_hooks);
3501     if (item)
3502     {
3503         item->type = cJSON_Object;
3504     }
3505 
3506     return item;
3507 }
3508 
3509 /* Create Arrays: */
3510 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
3511 {
3512     size_t i = 0;
3513     cJSON *n = NULL;
3514     cJSON *p = NULL;
3515     cJSON *a = NULL;
3516 
3517     if ((count < 0) || (numbers == NULL))
3518     {
3519         return NULL;
3520     }
3521 
3522     a = cJSON_CreateArray();
3523 
3524     for(i = 0; a && (i < (size_t)count); i++)
3525     {
3526         n = cJSON_CreateNumber(numbers[i]);
3527         if (!n)
3528         {
3529             cJSON_Delete(a);
3530             return NULL;
3531         }
3532         if(!i)
3533         {
3534             a->child = n;
3535         }
3536         else
3537         {
3538             suffix_object(p, n);
3539         }
3540         p = n;
3541     }
3542 
3543     if (a && a->child) {
3544         a->child->prev = n;
3545     }
3546 
3547     return a;
3548 }
3549 
3550 #ifdef S210
3551 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const double *numbers, int count)
3552 {
3553     size_t i = 0;
3554     cJSON *n = NULL;
3555     cJSON *p = NULL;
3556     cJSON *a = NULL;
3557 
3558     if ((count < 0) || (numbers == NULL))
3559     {
3560         return NULL;
3561     }
3562 
3563     a = cJSON_CreateArray();
3564 
3565     for (i = 0; a && (i < (size_t)count); i++)
3566     {
3567         n = cJSON_CreateFloat(numbers[i]);
3568         if (!n)
3569         {
3570             cJSON_Delete(a);
3571             return NULL;
3572         }
3573         if (!i)
3574         {
3575             a->child = n;
3576         }
3577         else
3578         {
3579             suffix_object(p, n);
3580         }
3581         p = n;
3582     }
3583     if (a && a->child) {
3584         a->child->prev = n;
3585     }
3586 
3587     return a;
3588 }
3589 #else
3590 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
3591 {
3592     size_t i = 0;
3593     cJSON *n = NULL;
3594     cJSON *p = NULL;
3595     cJSON *a = NULL;
3596 
3597     if ((count < 0) || (numbers == NULL))
3598     {
3599         return NULL;
3600     }
3601 
3602     a = cJSON_CreateArray();
3603 
3604     for(i = 0; a && (i < (size_t)count); i++)
3605     {
3606         n = cJSON_CreateNumber((double)numbers[i]);
3607         if(!n)
3608         {
3609             cJSON_Delete(a);
3610             return NULL;
3611         }
3612         if(!i)
3613         {
3614             a->child = n;
3615         }
3616         else
3617         {
3618             suffix_object(p, n);
3619         }
3620         p = n;
3621     }
3622 
3623     if (a && a->child) {
3624         a->child->prev = n;
3625     }
3626 
3627     return a;
3628 }
3629 #endif
3630 
3631 #ifdef S210
3632 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
3633 {
3634     size_t i = 0;
3635     cJSON *n = NULL;
3636     cJSON *p = NULL;
3637     cJSON *a = NULL;
3638 
3639     if ((count < 0) || (numbers == NULL))
3640     {
3641         return NULL;
3642     }
3643 
3644     a = cJSON_CreateArray();
3645 
3646     for (i = 0; a && (i < (size_t)count); i++)
3647     {
3648         n = cJSON_CreateFloat(numbers[i]);
3649         if (!n)
3650         {
3651             cJSON_Delete(a);
3652             return NULL;
3653         }
3654         if(!i)
3655         {
3656             a->child = n;
3657         }
3658         else
3659         {
3660             suffix_object(p, n);
3661         }
3662         p = n;
3663     }
3664     if (a && a->child) {
3665         a->child->prev = n;
3666     }
3667 
3668     return a;
3669 }
3670 #else
3671 
3672 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
3673 {
3674     size_t i = 0;
3675     cJSON *n = NULL;
3676     cJSON *p = NULL;
3677     cJSON *a = NULL;
3678 
3679     if ((count < 0) || (numbers == NULL))
3680     {
3681         return NULL;
3682     }
3683 
3684     a = cJSON_CreateArray();
3685 
3686     for(i = 0; a && (i < (size_t)count); i++)
3687     {
3688         n = cJSON_CreateNumber(numbers[i]);
3689         if(!n)
3690         {
3691             cJSON_Delete(a);
3692             return NULL;
3693         }
3694         if(!i)
3695         {
3696             a->child = n;
3697         }
3698         else
3699         {
3700             suffix_object(p, n);
3701         }
3702         p = n;
3703     }
3704 
3705     if (a && a->child) {
3706         a->child->prev = n;
3707     }
3708 
3709     return a;
3710 }
3711 #endif
3712 
3713 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
3714 {
3715     size_t i = 0;
3716     cJSON *n = NULL;
3717     cJSON *p = NULL;
3718     cJSON *a = NULL;
3719 
3720     if ((count < 0) || (strings == NULL))
3721     {
3722         return NULL;
3723     }
3724 
3725     a = cJSON_CreateArray();
3726 
3727     for (i = 0; a && (i < (size_t)count); i++)
3728     {
3729         n = cJSON_CreateString(strings[i]);
3730         if(!n)
3731         {
3732             cJSON_Delete(a);
3733             return NULL;
3734         }
3735         if(!i)
3736         {
3737             a->child = n;
3738         }
3739         else
3740         {
3741             suffix_object(p,n);
3742         }
3743         p = n;
3744     }
3745 
3746     if (a && a->child) {
3747         a->child->prev = n;
3748     }
3749 
3750     return a;
3751 }
3752 
3753 /* Duplication */
3754 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
3755 {
3756     cJSON *newitem = NULL;
3757     cJSON *child = NULL;
3758     cJSON *next = NULL;
3759     cJSON *newchild = NULL;
3760 
3761     /* Bail on bad ptr */
3762     if (!item)
3763     {
3764         goto fail;
3765     }
3766     /* Create new item */
3767     newitem = cJSON_New_Item(&global_hooks);
3768     if (!newitem)
3769     {
3770         goto fail;
3771     }
3772     /* Copy over all vars */
3773     newitem->type = item->type & (~cJSON_IsReference);
3774     newitem->valueint = item->valueint;
3775     newitem->valuedouble = item->valuedouble;
3776     if (item->valuestring)
3777     {
3778         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
3779         if (!newitem->valuestring)
3780         {
3781             goto fail;
3782         }
3783     }
3784     if (item->string)
3785     {
3786         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
3787         if (!newitem->string)
3788         {
3789             goto fail;
3790         }
3791     }
3792     /* If non-recursive, then we're done! */
3793     if (!recurse)
3794     {
3795         return newitem;
3796     }
3797     /* Walk the ->next chain for the child. */
3798     child = item->child;
3799     while (child != NULL)
3800     {
3801         newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
3802         if (!newchild)
3803         {
3804             goto fail;
3805         }
3806         if (next != NULL)
3807         {
3808             /* If newitem->child already set, then crosswire ->prev and ->next and move on */
3809             next->next = newchild;
3810             newchild->prev = next;
3811             next = newchild;
3812         }
3813         else
3814         {
3815             /* Set newitem->child and move to it */
3816             newitem->child = newchild;
3817             next = newchild;
3818         }
3819         child = child->next;
3820     }
3821     if (newitem && newitem->child)
3822     {
3823         newitem->child->prev = newchild;
3824     }
3825 
3826     return newitem;
3827 
3828 fail:
3829     if (newitem != NULL)
3830     {
3831         cJSON_Delete(newitem);
3832     }
3833 
3834     return NULL;
3835 }
3836 
3837 static void skip_oneline_comment(char **input)
3838 {
3839     *input += static_strlen("//");
3840 
3841     for (; (*input)[0] != '\0'; ++(*input))
3842     {
3843         if ((*input)[0] == '\n') {
3844             *input += static_strlen("\n");
3845             return;
3846         }
3847     }
3848 }
3849 
3850 static void skip_multiline_comment(char **input)
3851 {
3852     *input += static_strlen("/*");
3853 
3854     for (; (*input)[0] != '\0'; ++(*input))
3855     {
3856         if (((*input)[0] == '*') && ((*input)[1] == '/'))
3857         {
3858             *input += static_strlen("*/");
3859             return;
3860         }
3861     }
3862 }
3863 
3864 static void minify_string(char **input, char **output) {
3865     (*output)[0] = (*input)[0];
3866     *input += static_strlen("\"");
3867     *output += static_strlen("\"");
3868 
3869 
3870     for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
3871         (*output)[0] = (*input)[0];
3872 
3873         if ((*input)[0] == '\"') {
3874             (*output)[0] = '\"';
3875             *input += static_strlen("\"");
3876             *output += static_strlen("\"");
3877             return;
3878         } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
3879             (*output)[1] = (*input)[1];
3880             *input += static_strlen("\"");
3881             *output += static_strlen("\"");
3882         }
3883     }
3884 }
3885 
3886 CJSON_PUBLIC(void) cJSON_Minify(char *json)
3887 {
3888     char *into = json;
3889 
3890     if (json == NULL)
3891     {
3892         return;
3893     }
3894 
3895     while (json[0] != '\0')
3896     {
3897         switch (json[0])
3898         {
3899             case ' ':
3900             case '\t':
3901             case '\r':
3902             case '\n':
3903                 json++;
3904                 break;
3905 
3906             case '/':
3907                 if (json[1] == '/')
3908                 {
3909                     skip_oneline_comment(&json);
3910                 }
3911                 else if (json[1] == '*')
3912                 {
3913                     skip_multiline_comment(&json);
3914                 } else {
3915                     json++;
3916                 }
3917                 break;
3918 
3919             case '\"':
3920                 minify_string(&json, (char**)&into);
3921                 break;
3922 
3923             default:
3924                 into[0] = json[0];
3925                 json++;
3926                 into++;
3927         }
3928     }
3929 
3930     /* and null-terminate. */
3931     *into = '\0';
3932 }
3933 
3934 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
3935 {
3936     if (item == NULL)
3937     {
3938         return false;
3939     }
3940 
3941     return (item->type & 0xFF) == cJSON_Invalid;
3942 }
3943 
3944 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
3945 {
3946     if (item == NULL)
3947     {
3948         return false;
3949     }
3950 
3951     return (item->type & 0xFF) == cJSON_False;
3952 }
3953 
3954 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
3955 {
3956     if (item == NULL)
3957     {
3958         return false;
3959     }
3960 
3961     return (item->type & 0xff) == cJSON_True;
3962 }
3963 
3964 
3965 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
3966 {
3967     if (item == NULL)
3968     {
3969         return false;
3970     }
3971 
3972     return (item->type & (cJSON_True | cJSON_False)) != 0;
3973 }
3974 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
3975 {
3976     if (item == NULL)
3977     {
3978         return false;
3979     }
3980 
3981     return (item->type & 0xFF) == cJSON_NULL;
3982 }
3983 
3984 #ifdef __CJSON_USE_INT64
3985 CJSON_PUBLIC(cJSON_bool) cJSON_IsInt64Number(const cJSON * const item)
3986 {
3987     if (item == NULL)
3988     {
3989         return false;
3990     }
3991 
3992     return cJSON_IsNumber(item) && (item->type & cJSON_IsInt64);
3993 }
3994 #endif
3995 
3996 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
3997 {
3998     if (item == NULL)
3999     {
4000         return false;
4001     }
4002 
4003     return (item->type & 0xFF) == cJSON_Number;
4004 }
4005 
4006 #ifdef S210
4007 CJSON_PUBLIC(cJSON_bool) cJSON_IsFLoat(const cJSON *const item)
4008 {
4009     if (item == NULL) {
4010         return false;
4011     }
4012 
4013     return (item->type & 0xFF) == cJSON_Float;
4014 }
4015 #endif
4016 
4017 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
4018 {
4019     if (item == NULL)
4020     {
4021         return false;
4022     }
4023 
4024     return (item->type & 0xFF) == cJSON_String;
4025 }
4026 
4027 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
4028 {
4029     if (item == NULL)
4030     {
4031         return false;
4032     }
4033 
4034     return (item->type & 0xFF) == cJSON_Array;
4035 }
4036 
4037 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
4038 {
4039     if (item == NULL)
4040     {
4041         return false;
4042     }
4043 
4044     return (item->type & 0xFF) == cJSON_Object;
4045 }
4046 
4047 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
4048 {
4049     if (item == NULL)
4050     {
4051         return false;
4052     }
4053 
4054     return (item->type & 0xFF) == cJSON_Raw;
4055 }
4056 
4057 #ifdef S210
4058 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
4059 {
4060     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
4061     {
4062         return false;
4063     }
4064 
4065     /* check if type is valid */
4066     switch (a->type & 0xFF)
4067     {
4068         case cJSON_False:
4069         case cJSON_True:
4070         case cJSON_NULL:
4071         case cJSON_Number:
4072         case cJSON_String:
4073         case cJSON_Raw:
4074         case cJSON_Array:
4075         case cJSON_Object:
4076             break;
4077 
4078         default:
4079             return false;
4080     }
4081 
4082     /* identical objects are equal */
4083     if (a == b)
4084     {
4085         return true;
4086     }
4087 
4088     switch (a->type & 0xFF)
4089     {
4090         /* in these cases and equal type is enough */
4091         case cJSON_False:
4092         case cJSON_True:
4093         case cJSON_NULL:
4094             return true;
4095         case cJSON_Number:
4096             if (a->valueint == b->valueint)
4097             {
4098                 return true;
4099             }
4100             return false;
4101 
4102         case cJSON_Float:
4103             // float 数据默认不相等
4104             return false;
4105 
4106         case cJSON_String:
4107         case cJSON_Raw:
4108             if ((a->valuestring == NULL) || (b->valuestring == NULL))
4109             {
4110                 return false;
4111             }
4112             if (strcmp(a->valuestring, b->valuestring) == 0)
4113             {
4114                 return true;
4115             }
4116 
4117             return false;
4118 
4119         case cJSON_Array:
4120         {
4121             cJSON *a_element = a->child;
4122             cJSON *b_element = b->child;
4123 
4124             for (; (a_element != NULL) && (b_element != NULL);)
4125             {
4126                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
4127                 {
4128                     return false;
4129                 }
4130 
4131                 a_element = a_element->next;
4132                 b_element = b_element->next;
4133             }
4134 
4135             /* one of the arrays is longer than the other */
4136             if (a_element != b_element) {
4137                 return false;
4138             }
4139 
4140             return true;
4141         }
4142 
4143         case cJSON_Object:
4144         {
4145             cJSON *a_element = NULL;
4146             cJSON *b_element = NULL;
4147             cJSON_ArrayForEach(a_element, a)
4148             {
4149                 /* TODO This has O(n^2) runtime, which is horrible! */
4150                 b_element = get_object_item(b, a_element->string, case_sensitive);
4151                 if (b_element == NULL)
4152                 {
4153                     return false;
4154                 }
4155 
4156                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
4157                 {
4158                     return false;
4159                 }
4160             }
4161 
4162             /* doing this twice, once on a and b to prevent true comparison if a subset of b
4163              * TODO: Do this the proper way, this is just a fix for now */
4164             cJSON_ArrayForEach(b_element, b)
4165             {
4166                 a_element = get_object_item(a, b_element->string, case_sensitive);
4167                 if (a_element == NULL)
4168                 {
4169                     return false;
4170                 }
4171 
4172                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
4173                 {
4174                     return false;
4175                 }
4176             }
4177 
4178             return true;
4179         }
4180 
4181         default:
4182             return false;
4183     }
4184 }
4185 #else
4186 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
4187 {
4188     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
4189     {
4190         return false;
4191     }
4192 
4193     /* check if type is valid */
4194     switch (a->type & 0xFF)
4195     {
4196         case cJSON_False:
4197         case cJSON_True:
4198         case cJSON_NULL:
4199         case cJSON_Number:
4200         case cJSON_String:
4201         case cJSON_Raw:
4202         case cJSON_Array:
4203         case cJSON_Object:
4204             break;
4205 
4206         default:
4207             return false;
4208     }
4209 
4210     /* identical objects are equal */
4211     if (a == b)
4212     {
4213         return true;
4214     }
4215 
4216     switch (a->type & 0xFF)
4217     {
4218         /* in these cases and equal type is enough */
4219         case cJSON_False:
4220         case cJSON_True:
4221         case cJSON_NULL:
4222             return true;
4223 #ifdef __CJSON_USE_INT64
4224         case cJSON_Number:
4225             if (!compare_double(a->valuedouble, b->valuedouble))
4226             {
4227                 return false;
4228             }
4229 
4230             if ((a->type & cJSON_IsInt64) != (b->type & cJSON_IsInt64))
4231             {
4232                 /* cJSON_IsInt64 should also be considered */
4233                 return false;
4234             }
4235 
4236             if ((a->type & cJSON_IsInt64) && (b->type & cJSON_IsInt64))
4237             {
4238                 /* compare valueint if both of them are int64 */
4239                 return a->valueint == b->valueint;
4240             }
4241 
4242             return true;
4243 #else
4244         case cJSON_Number:
4245             if (compare_double(a->valuedouble, b->valuedouble))
4246             {
4247                 return true;
4248             }
4249             return false;
4250 #endif
4251 
4252         case cJSON_String:
4253         case cJSON_Raw:
4254             if ((a->valuestring == NULL) || (b->valuestring == NULL))
4255             {
4256                 return false;
4257             }
4258             if (strcmp(a->valuestring, b->valuestring) == 0)
4259             {
4260                 return true;
4261             }
4262 
4263             return false;
4264 
4265         case cJSON_Array:
4266         {
4267             cJSON *a_element = a->child;
4268             cJSON *b_element = b->child;
4269 
4270             for (; (a_element != NULL) && (b_element != NULL);)
4271             {
4272                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
4273                 {
4274                     return false;
4275                 }
4276 
4277                 a_element = a_element->next;
4278                 b_element = b_element->next;
4279             }
4280 
4281             /* one of the arrays is longer than the other */
4282             if (a_element != b_element) {
4283                 return false;
4284             }
4285 
4286             return true;
4287         }
4288 
4289         case cJSON_Object:
4290         {
4291             cJSON *a_element = NULL;
4292             cJSON *b_element = NULL;
4293             cJSON_ArrayForEach(a_element, a)
4294             {
4295                 /* TODO This has O(n^2) runtime, which is horrible! */
4296                 b_element = get_object_item(b, a_element->string, case_sensitive);
4297                 if (b_element == NULL)
4298                 {
4299                     return false;
4300                 }
4301 
4302                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
4303                 {
4304                     return false;
4305                 }
4306             }
4307 
4308             /* doing this twice, once on a and b to prevent true comparison if a subset of b
4309              * TODO: Do this the proper way, this is just a fix for now */
4310             cJSON_ArrayForEach(b_element, b)
4311             {
4312                 a_element = get_object_item(a, b_element->string, case_sensitive);
4313                 if (a_element == NULL)
4314                 {
4315                     return false;
4316                 }
4317 
4318                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
4319                 {
4320                     return false;
4321                 }
4322             }
4323 
4324             return true;
4325         }
4326 
4327         default:
4328             return false;
4329     }
4330 }
4331 #endif
4332 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
4333 {
4334     return global_hooks.allocate(size);
4335 }
4336 
4337 CJSON_PUBLIC(void) cJSON_free(void *object)
4338 {
4339     global_hooks.deallocate(object);
4340 }
4341