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