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