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