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 != 3)
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 if ((object == NULL) || (string == NULL) || (item == NULL))
1899 {
1900 return false;
1901 }
1902
1903 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
1904 {
1905 hooks->deallocate(item->string);
1906 }
1907
1908 if (constant_key)
1909 {
1910 item->string = (char*)cast_away_const(string);
1911 item->type |= cJSON_StringIsConst;
1912 }
1913 else
1914 {
1915 char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
1916 if (key == NULL)
1917 {
1918 return false;
1919 }
1920
1921 item->string = key;
1922 item->type &= ~cJSON_StringIsConst;
1923 }
1924
1925 return add_item_to_array(object, item);
1926 }
1927
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)1928 CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
1929 {
1930 add_item_to_object(object, string, item, &global_hooks, false);
1931 }
1932
1933 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)1934 CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1935 {
1936 add_item_to_object(object, string, item, &global_hooks, true);
1937 }
1938
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)1939 CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1940 {
1941 if (array == NULL)
1942 {
1943 return;
1944 }
1945
1946 add_item_to_array(array, create_reference(item, &global_hooks));
1947 }
1948
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)1949 CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1950 {
1951 if ((object == NULL) || (string == NULL))
1952 {
1953 return;
1954 }
1955
1956 add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1957 }
1958
cJSON_AddNullToObject(cJSON * const object,const char * const name)1959 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
1960 {
1961 cJSON *null = cJSON_CreateNull();
1962 if (add_item_to_object(object, name, null, &global_hooks, false))
1963 {
1964 return null;
1965 }
1966
1967 cJSON_Delete(null);
1968 return NULL;
1969 }
1970
cJSON_AddTrueToObject(cJSON * const object,const char * const name)1971 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
1972 {
1973 cJSON *true_item = cJSON_CreateTrue();
1974 if (add_item_to_object(object, name, true_item, &global_hooks, false))
1975 {
1976 return true_item;
1977 }
1978
1979 cJSON_Delete(true_item);
1980 return NULL;
1981 }
1982
cJSON_AddFalseToObject(cJSON * const object,const char * const name)1983 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
1984 {
1985 cJSON *false_item = cJSON_CreateFalse();
1986 if (add_item_to_object(object, name, false_item, &global_hooks, false))
1987 {
1988 return false_item;
1989 }
1990
1991 cJSON_Delete(false_item);
1992 return NULL;
1993 }
1994
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)1995 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
1996 {
1997 cJSON *bool_item = cJSON_CreateBool(boolean);
1998 if (add_item_to_object(object, name, bool_item, &global_hooks, false))
1999 {
2000 return bool_item;
2001 }
2002
2003 cJSON_Delete(bool_item);
2004 return NULL;
2005 }
2006
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2007 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2008 {
2009 cJSON *number_item = cJSON_CreateNumber(number);
2010 if (add_item_to_object(object, name, number_item, &global_hooks, false))
2011 {
2012 return number_item;
2013 }
2014
2015 cJSON_Delete(number_item);
2016 return NULL;
2017 }
2018
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2019 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2020 {
2021 cJSON *string_item = cJSON_CreateString(string);
2022 if (add_item_to_object(object, name, string_item, &global_hooks, false))
2023 {
2024 return string_item;
2025 }
2026
2027 cJSON_Delete(string_item);
2028 return NULL;
2029 }
2030
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2031 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2032 {
2033 cJSON *raw_item = cJSON_CreateRaw(raw);
2034 if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2035 {
2036 return raw_item;
2037 }
2038
2039 cJSON_Delete(raw_item);
2040 return NULL;
2041 }
2042
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2043 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2044 {
2045 cJSON *object_item = cJSON_CreateObject();
2046 if (add_item_to_object(object, name, object_item, &global_hooks, false))
2047 {
2048 return object_item;
2049 }
2050
2051 cJSON_Delete(object_item);
2052 return NULL;
2053 }
2054
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2055 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2056 {
2057 cJSON *array = cJSON_CreateArray();
2058 if (add_item_to_object(object, name, array, &global_hooks, false))
2059 {
2060 return array;
2061 }
2062
2063 cJSON_Delete(array);
2064 return NULL;
2065 }
2066
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2067 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2068 {
2069 if ((parent == NULL) || (item == NULL))
2070 {
2071 return NULL;
2072 }
2073
2074 if (item->prev != NULL)
2075 {
2076 /* not the first element */
2077 item->prev->next = item->next;
2078 }
2079 if (item->next != NULL)
2080 {
2081 /* not the last element */
2082 item->next->prev = item->prev;
2083 }
2084
2085 if (item == parent->child)
2086 {
2087 /* first element */
2088 parent->child = item->next;
2089 }
2090 /* make sure the detached item doesn't point anywhere anymore */
2091 item->prev = NULL;
2092 item->next = NULL;
2093
2094 return item;
2095 }
2096
cJSON_DetachItemFromArray(cJSON * array,int which)2097 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2098 {
2099 if (which < 0)
2100 {
2101 return NULL;
2102 }
2103
2104 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2105 }
2106
cJSON_DeleteItemFromArray(cJSON * array,int which)2107 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2108 {
2109 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2110 }
2111
cJSON_DetachItemFromObject(cJSON * object,const char * string)2112 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2113 {
2114 cJSON *to_detach = cJSON_GetObjectItem(object, string);
2115
2116 return cJSON_DetachItemViaPointer(object, to_detach);
2117 }
2118
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2119 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2120 {
2121 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2122
2123 return cJSON_DetachItemViaPointer(object, to_detach);
2124 }
2125
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2126 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2127 {
2128 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2129 }
2130
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2131 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2132 {
2133 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2134 }
2135
2136 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2137 CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2138 {
2139 cJSON *after_inserted = NULL;
2140
2141 if (which < 0)
2142 {
2143 return;
2144 }
2145
2146 after_inserted = get_array_item(array, (size_t)which);
2147 if (after_inserted == NULL)
2148 {
2149 add_item_to_array(array, newitem);
2150 return;
2151 }
2152
2153 newitem->next = after_inserted;
2154 newitem->prev = after_inserted->prev;
2155 after_inserted->prev = newitem;
2156 if (after_inserted == array->child)
2157 {
2158 array->child = newitem;
2159 }
2160 else
2161 {
2162 newitem->prev->next = newitem;
2163 }
2164 }
2165
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2166 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2167 {
2168 if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2169 {
2170 return false;
2171 }
2172
2173 if (replacement == item)
2174 {
2175 return true;
2176 }
2177
2178 replacement->next = item->next;
2179 replacement->prev = item->prev;
2180
2181 if (replacement->next != NULL)
2182 {
2183 replacement->next->prev = replacement;
2184 }
2185 if (replacement->prev != NULL)
2186 {
2187 replacement->prev->next = replacement;
2188 }
2189 if (parent->child == item)
2190 {
2191 parent->child = replacement;
2192 }
2193
2194 item->next = NULL;
2195 item->prev = NULL;
2196 cJSON_Delete(item);
2197
2198 return true;
2199 }
2200
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2201 CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2202 {
2203 if (which < 0)
2204 {
2205 return;
2206 }
2207
2208 cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2209 }
2210
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2211 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2212 {
2213 if ((replacement == NULL) || (string == NULL))
2214 {
2215 return false;
2216 }
2217
2218 /* replace the name in the replacement */
2219 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2220 {
2221 cJSON_free(replacement->string);
2222 }
2223 replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2224 replacement->type &= ~cJSON_StringIsConst;
2225
2226 cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2227
2228 return true;
2229 }
2230
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2231 CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2232 {
2233 replace_item_in_object(object, string, newitem, false);
2234 }
2235
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2236 CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2237 {
2238 replace_item_in_object(object, string, newitem, true);
2239 }
2240
2241 /* Create basic types: */
cJSON_CreateNull(void)2242 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2243 {
2244 cJSON *item = cJSON_New_Item(&global_hooks);
2245 if(item)
2246 {
2247 item->type = cJSON_NULL;
2248 }
2249
2250 return item;
2251 }
2252
cJSON_CreateTrue(void)2253 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2254 {
2255 cJSON *item = cJSON_New_Item(&global_hooks);
2256 if(item)
2257 {
2258 item->type = cJSON_True;
2259 }
2260
2261 return item;
2262 }
2263
cJSON_CreateFalse(void)2264 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2265 {
2266 cJSON *item = cJSON_New_Item(&global_hooks);
2267 if(item)
2268 {
2269 item->type = cJSON_False;
2270 }
2271
2272 return item;
2273 }
2274
cJSON_CreateBool(cJSON_bool b)2275 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
2276 {
2277 cJSON *item = cJSON_New_Item(&global_hooks);
2278 if(item)
2279 {
2280 item->type = b ? cJSON_True : cJSON_False;
2281 }
2282
2283 return item;
2284 }
2285
cJSON_CreateNumber(double num)2286 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2287 {
2288 cJSON *item = cJSON_New_Item(&global_hooks);
2289 if(item)
2290 {
2291 item->type = cJSON_Number;
2292 item->valuedouble = num;
2293
2294 /* use saturation in case of overflow */
2295 if (num >= INT_MAX)
2296 {
2297 item->valueint = INT_MAX;
2298 }
2299 else if (num <= INT_MIN)
2300 {
2301 item->valueint = INT_MIN;
2302 }
2303 else
2304 {
2305 item->valueint = (int)num;
2306 }
2307 }
2308
2309 return item;
2310 }
2311
cJSON_CreateString(const char * string)2312 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2313 {
2314 cJSON *item = cJSON_New_Item(&global_hooks);
2315 if(item)
2316 {
2317 item->type = cJSON_String;
2318 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2319 if(!item->valuestring)
2320 {
2321 cJSON_Delete(item);
2322 return NULL;
2323 }
2324 }
2325
2326 return item;
2327 }
2328
cJSON_CreateStringReference(const char * string)2329 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2330 {
2331 cJSON *item = cJSON_New_Item(&global_hooks);
2332 if (item != NULL)
2333 {
2334 item->type = cJSON_String | cJSON_IsReference;
2335 item->valuestring = (char*)cast_away_const(string);
2336 }
2337
2338 return item;
2339 }
2340
cJSON_CreateObjectReference(const cJSON * child)2341 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2342 {
2343 cJSON *item = cJSON_New_Item(&global_hooks);
2344 if (item != NULL) {
2345 item->type = cJSON_Object | cJSON_IsReference;
2346 item->child = (cJSON*)cast_away_const(child);
2347 }
2348
2349 return item;
2350 }
2351
cJSON_CreateArrayReference(const cJSON * child)2352 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2353 cJSON *item = cJSON_New_Item(&global_hooks);
2354 if (item != NULL) {
2355 item->type = cJSON_Array | cJSON_IsReference;
2356 item->child = (cJSON*)cast_away_const(child);
2357 }
2358
2359 return item;
2360 }
2361
cJSON_CreateRaw(const char * raw)2362 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2363 {
2364 cJSON *item = cJSON_New_Item(&global_hooks);
2365 if(item)
2366 {
2367 item->type = cJSON_Raw;
2368 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2369 if(!item->valuestring)
2370 {
2371 cJSON_Delete(item);
2372 return NULL;
2373 }
2374 }
2375
2376 return item;
2377 }
2378
cJSON_CreateArray(void)2379 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2380 {
2381 cJSON *item = cJSON_New_Item(&global_hooks);
2382 if(item)
2383 {
2384 item->type=cJSON_Array;
2385 }
2386
2387 return item;
2388 }
2389
cJSON_CreateObject(void)2390 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2391 {
2392 cJSON *item = cJSON_New_Item(&global_hooks);
2393 if (item)
2394 {
2395 item->type = cJSON_Object;
2396 }
2397
2398 return item;
2399 }
2400
2401 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2402 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2403 {
2404 size_t i = 0;
2405 cJSON *n = NULL;
2406 cJSON *p = NULL;
2407 cJSON *a = NULL;
2408
2409 if ((count < 0) || (numbers == NULL))
2410 {
2411 return NULL;
2412 }
2413
2414 a = cJSON_CreateArray();
2415 for(i = 0; a && (i < (size_t)count); i++)
2416 {
2417 n = cJSON_CreateNumber(numbers[i]);
2418 if (!n)
2419 {
2420 cJSON_Delete(a);
2421 return NULL;
2422 }
2423 if(!i)
2424 {
2425 a->child = n;
2426 }
2427 else
2428 {
2429 suffix_object(p, n);
2430 }
2431 p = n;
2432 }
2433
2434 return a;
2435 }
2436
cJSON_CreateFloatArray(const float * numbers,int count)2437 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2438 {
2439 size_t i = 0;
2440 cJSON *n = NULL;
2441 cJSON *p = NULL;
2442 cJSON *a = NULL;
2443
2444 if ((count < 0) || (numbers == NULL))
2445 {
2446 return NULL;
2447 }
2448
2449 a = cJSON_CreateArray();
2450
2451 for(i = 0; a && (i < (size_t)count); i++)
2452 {
2453 n = cJSON_CreateNumber((double)numbers[i]);
2454 if(!n)
2455 {
2456 cJSON_Delete(a);
2457 return NULL;
2458 }
2459 if(!i)
2460 {
2461 a->child = n;
2462 }
2463 else
2464 {
2465 suffix_object(p, n);
2466 }
2467 p = n;
2468 }
2469
2470 return a;
2471 }
2472
cJSON_CreateDoubleArray(const double * numbers,int count)2473 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2474 {
2475 size_t i = 0;
2476 cJSON *n = NULL;
2477 cJSON *p = NULL;
2478 cJSON *a = NULL;
2479
2480 if ((count < 0) || (numbers == NULL))
2481 {
2482 return NULL;
2483 }
2484
2485 a = cJSON_CreateArray();
2486
2487 for(i = 0;a && (i < (size_t)count); i++)
2488 {
2489 n = cJSON_CreateNumber(numbers[i]);
2490 if(!n)
2491 {
2492 cJSON_Delete(a);
2493 return NULL;
2494 }
2495 if(!i)
2496 {
2497 a->child = n;
2498 }
2499 else
2500 {
2501 suffix_object(p, n);
2502 }
2503 p = n;
2504 }
2505
2506 return a;
2507 }
2508
cJSON_CreateStringArray(const char ** strings,int count)2509 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2510 {
2511 size_t i = 0;
2512 cJSON *n = NULL;
2513 cJSON *p = NULL;
2514 cJSON *a = NULL;
2515
2516 if ((count < 0) || (strings == NULL))
2517 {
2518 return NULL;
2519 }
2520
2521 a = cJSON_CreateArray();
2522
2523 for (i = 0; a && (i < (size_t)count); i++)
2524 {
2525 n = cJSON_CreateString(strings[i]);
2526 if(!n)
2527 {
2528 cJSON_Delete(a);
2529 return NULL;
2530 }
2531 if(!i)
2532 {
2533 a->child = n;
2534 }
2535 else
2536 {
2537 suffix_object(p,n);
2538 }
2539 p = n;
2540 }
2541
2542 return a;
2543 }
2544
2545 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2546 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2547 {
2548 cJSON *newitem = NULL;
2549 cJSON *child = NULL;
2550 cJSON *next = NULL;
2551 cJSON *newchild = NULL;
2552
2553 /* Bail on bad ptr */
2554 if (!item)
2555 {
2556 goto fail;
2557 }
2558 /* Create new item */
2559 newitem = cJSON_New_Item(&global_hooks);
2560 if (!newitem)
2561 {
2562 goto fail;
2563 }
2564 /* Copy over all vars */
2565 newitem->type = item->type & (~cJSON_IsReference);
2566 newitem->valueint = item->valueint;
2567 newitem->valuedouble = item->valuedouble;
2568 if (item->valuestring)
2569 {
2570 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2571 if (!newitem->valuestring)
2572 {
2573 goto fail;
2574 }
2575 }
2576 if (item->string)
2577 {
2578 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2579 if (!newitem->string)
2580 {
2581 goto fail;
2582 }
2583 }
2584 /* If non-recursive, then we're done! */
2585 if (!recurse)
2586 {
2587 return newitem;
2588 }
2589 /* Walk the ->next chain for the child. */
2590 child = item->child;
2591 while (child != NULL)
2592 {
2593 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2594 if (!newchild)
2595 {
2596 goto fail;
2597 }
2598 if (next != NULL)
2599 {
2600 /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2601 next->next = newchild;
2602 newchild->prev = next;
2603 next = newchild;
2604 }
2605 else
2606 {
2607 /* Set newitem->child and move to it */
2608 newitem->child = newchild;
2609 next = newchild;
2610 }
2611 child = child->next;
2612 }
2613
2614 return newitem;
2615
2616 fail:
2617 if (newitem != NULL)
2618 {
2619 cJSON_Delete(newitem);
2620 }
2621
2622 return NULL;
2623 }
2624
cJSON_Minify(char * json)2625 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2626 {
2627 unsigned char *into = (unsigned char*)json;
2628
2629 if (json == NULL)
2630 {
2631 return;
2632 }
2633
2634 while (*json)
2635 {
2636 if (*json == ' ')
2637 {
2638 json++;
2639 }
2640 else if (*json == '\t')
2641 {
2642 /* Whitespace characters. */
2643 json++;
2644 }
2645 else if (*json == '\r')
2646 {
2647 json++;
2648 }
2649 else if (*json=='\n')
2650 {
2651 json++;
2652 }
2653 else if ((*json == '/') && (json[1] == '/'))
2654 {
2655 /* double-slash comments, to end of line. */
2656 while (*json && (*json != '\n'))
2657 {
2658 json++;
2659 }
2660 }
2661 else if ((*json == '/') && (json[1] == '*'))
2662 {
2663 /* multiline comments. */
2664 while (*json && !((*json == '*') && (json[1] == '/')))
2665 {
2666 json++;
2667 }
2668 json += 2;
2669 }
2670 else if (*json == '\"')
2671 {
2672 /* string literals, which are \" sensitive. */
2673 *into++ = (unsigned char)*json++;
2674 while (*json && (*json != '\"'))
2675 {
2676 if (*json == '\\')
2677 {
2678 *into++ = (unsigned char)*json++;
2679 }
2680 *into++ = (unsigned char)*json++;
2681 }
2682 *into++ = (unsigned char)*json++;
2683 }
2684 else
2685 {
2686 /* All other characters. */
2687 *into++ = (unsigned char)*json++;
2688 }
2689 }
2690
2691 /* and null-terminate. */
2692 *into = '\0';
2693 }
2694
cJSON_IsInvalid(const cJSON * const item)2695 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2696 {
2697 if (item == NULL)
2698 {
2699 return false;
2700 }
2701
2702 return (item->type & 0xFF) == cJSON_Invalid;
2703 }
2704
cJSON_IsFalse(const cJSON * const item)2705 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2706 {
2707 if (item == NULL)
2708 {
2709 return false;
2710 }
2711
2712 return (item->type & 0xFF) == cJSON_False;
2713 }
2714
cJSON_IsTrue(const cJSON * const item)2715 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2716 {
2717 if (item == NULL)
2718 {
2719 return false;
2720 }
2721
2722 return (item->type & 0xff) == cJSON_True;
2723 }
2724
2725
cJSON_IsBool(const cJSON * const item)2726 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2727 {
2728 if (item == NULL)
2729 {
2730 return false;
2731 }
2732
2733 return (item->type & (cJSON_True | cJSON_False)) != 0;
2734 }
cJSON_IsNull(const cJSON * const item)2735 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2736 {
2737 if (item == NULL)
2738 {
2739 return false;
2740 }
2741
2742 return (item->type & 0xFF) == cJSON_NULL;
2743 }
2744
cJSON_IsNumber(const cJSON * const item)2745 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2746 {
2747 if (item == NULL)
2748 {
2749 return false;
2750 }
2751
2752 return (item->type & 0xFF) == cJSON_Number;
2753 }
2754
cJSON_IsString(const cJSON * const item)2755 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2756 {
2757 if (item == NULL)
2758 {
2759 return false;
2760 }
2761
2762 return (item->type & 0xFF) == cJSON_String;
2763 }
2764
cJSON_IsArray(const cJSON * const item)2765 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2766 {
2767 if (item == NULL)
2768 {
2769 return false;
2770 }
2771
2772 return (item->type & 0xFF) == cJSON_Array;
2773 }
2774
cJSON_IsObject(const cJSON * const item)2775 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2776 {
2777 if (item == NULL)
2778 {
2779 return false;
2780 }
2781
2782 return (item->type & 0xFF) == cJSON_Object;
2783 }
2784
cJSON_IsRaw(const cJSON * const item)2785 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2786 {
2787 if (item == NULL)
2788 {
2789 return false;
2790 }
2791
2792 return (item->type & 0xFF) == cJSON_Raw;
2793 }
2794
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2795 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2796 {
2797 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2798 {
2799 return false;
2800 }
2801
2802 /* check if type is valid */
2803 switch (a->type & 0xFF)
2804 {
2805 case cJSON_False:
2806 case cJSON_True:
2807 case cJSON_NULL:
2808 case cJSON_Number:
2809 case cJSON_String:
2810 case cJSON_Raw:
2811 case cJSON_Array:
2812 case cJSON_Object:
2813 break;
2814
2815 default:
2816 return false;
2817 }
2818
2819 /* identical objects are equal */
2820 if (a == b)
2821 {
2822 return true;
2823 }
2824
2825 switch (a->type & 0xFF)
2826 {
2827 /* in these cases and equal type is enough */
2828 case cJSON_False:
2829 case cJSON_True:
2830 case cJSON_NULL:
2831 return true;
2832
2833 case cJSON_Number:
2834 if (a->valuedouble == b->valuedouble)
2835 {
2836 return true;
2837 }
2838 return false;
2839
2840 case cJSON_String:
2841 case cJSON_Raw:
2842 if ((a->valuestring == NULL) || (b->valuestring == NULL))
2843 {
2844 return false;
2845 }
2846 if (strcmp(a->valuestring, b->valuestring) == 0)
2847 {
2848 return true;
2849 }
2850
2851 return false;
2852
2853 case cJSON_Array:
2854 {
2855 cJSON *a_element = a->child;
2856 cJSON *b_element = b->child;
2857
2858 for (; (a_element != NULL) && (b_element != NULL);)
2859 {
2860 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2861 {
2862 return false;
2863 }
2864
2865 a_element = a_element->next;
2866 b_element = b_element->next;
2867 }
2868
2869 /* one of the arrays is longer than the other */
2870 if (a_element != b_element) {
2871 return false;
2872 }
2873
2874 return true;
2875 }
2876
2877 case cJSON_Object:
2878 {
2879 cJSON *a_element = NULL;
2880 cJSON *b_element = NULL;
2881 cJSON_ArrayForEach(a_element, a)
2882 {
2883 /* TODO This has O(n^2) runtime, which is horrible! */
2884 b_element = get_object_item(b, a_element->string, case_sensitive);
2885 if (b_element == NULL)
2886 {
2887 return false;
2888 }
2889
2890 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2891 {
2892 return false;
2893 }
2894 }
2895
2896 /* doing this twice, once on a and b to prevent true comparison if a subset of b
2897 * TODO: Do this the proper way, this is just a fix for now */
2898 cJSON_ArrayForEach(b_element, b)
2899 {
2900 a_element = get_object_item(a, b_element->string, case_sensitive);
2901 if (a_element == NULL)
2902 {
2903 return false;
2904 }
2905
2906 if (!cJSON_Compare(b_element, a_element, case_sensitive))
2907 {
2908 return false;
2909 }
2910 }
2911
2912 return true;
2913 }
2914
2915 default:
2916 return false;
2917 }
2918 }
2919
cJSON_malloc(size_t size)2920 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
2921 {
2922 return global_hooks.allocate(size);
2923 }
2924
cJSON_free(void * object)2925 CJSON_PUBLIC(void) cJSON_free(void *object)
2926 {
2927 global_hooks.deallocate(object);
2928 }
2929