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