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