2 Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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
22 /* clang-format off */
24 /* JSON parser in C. */
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
32 #pragma GCC visibility push(default)
35 #pragma warning (push)
36 /* disable warning about single line comments in system headers */
37 #pragma warning (disable : 4001)
56 #pragma GCC visibility pop
61 /* define our own boolean type */
65 #define true ((cJSON_bool)1)
70 #define false ((cJSON_bool)0)
72 /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
74 #define isinf(d) (isnan((d - d)) && !isnan(d))
77 #define isnan(d) (d != d)
82 #define NAN sqrt (-1.0)
89 const unsigned char *json;
92 static error global_error = { NULL, 0 };
94 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
96 return (const char*) (global_error.json + global_error.position);
99 CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
101 if (!cJSON_IsString(item))
106 return item->valuestring;
109 CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
111 if (!cJSON_IsNumber(item))
116 return item->valuedouble;
119 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 14)
121 #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
124 CJSON_PUBLIC(const char*) cJSON_Version(void)
126 static char version[15];
127 sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
132 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
135 if ((string1 == NULL) || (string2 == NULL))
140 if (string1 == string2)
145 for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
147 if (*string1 == '\0')
153 return tolower(*string1) - tolower(*string2);
156 typedef struct internal_hooks
158 void *(CJSON_CDECL *allocate)(size_t size);
159 void (CJSON_CDECL *deallocate)(void *pointer);
160 void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
163 #if defined(_MSC_VER)
164 /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165 static void * CJSON_CDECL internal_malloc(size_t size)
169 static void CJSON_CDECL internal_free(void *pointer)
173 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
175 return realloc(pointer, size);
178 #define internal_malloc malloc
179 #define internal_free free
180 #define internal_realloc realloc
183 /* strlen of character literals resolved at compile time */
184 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
186 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
188 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
191 unsigned char *copy = NULL;
198 length = strlen((const char*)string) + sizeof("");
199 copy = (unsigned char*)hooks->allocate(length);
204 memcpy(copy, string, length);
209 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
214 global_hooks.allocate = malloc;
215 global_hooks.deallocate = free;
216 global_hooks.reallocate = realloc;
220 global_hooks.allocate = malloc;
221 if (hooks->malloc_fn != NULL)
223 global_hooks.allocate = hooks->malloc_fn;
226 global_hooks.deallocate = free;
227 if (hooks->free_fn != NULL)
229 global_hooks.deallocate = hooks->free_fn;
232 /* use realloc only if both free and malloc are used */
233 global_hooks.reallocate = NULL;
234 if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
236 global_hooks.reallocate = realloc;
240 /* Internal constructor. */
241 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
243 cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
246 memset(node, '\0', sizeof(cJSON));
252 /* Delete a cJSON structure. */
253 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
259 if (!(item->type & cJSON_IsReference) && (item->child != NULL))
261 cJSON_Delete(item->child);
263 if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
265 global_hooks.deallocate(item->valuestring);
267 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269 global_hooks.deallocate(item->string);
271 global_hooks.deallocate(item);
276 /* get the decimal point character of the current locale */
277 static unsigned char get_decimal_point(void)
279 #ifdef ENABLE_LOCALES
280 struct lconv *lconv = localeconv();
281 return (unsigned char) lconv->decimal_point[0];
289 const unsigned char *content;
292 size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
293 internal_hooks hooks;
296 /* check if the given size is left to read in a given parse buffer (starting with 1) */
297 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
298 /* check if the buffer can be accessed at the given index (starting with 0) */
299 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
300 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
301 /* get a pointer to the buffer at the position */
302 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
304 /* Parse the input text to generate a number, and populate the result into item. */
305 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308 unsigned char *after_end = NULL;
309 unsigned char number_c_string[64];
310 unsigned char decimal_point = get_decimal_point();
313 if ((input_buffer == NULL) || (input_buffer->content == NULL))
318 /* copy the number into a temporary buffer and replace '.' with the decimal point
319 * of the current locale (for strtod)
320 * This also takes care of '\0' not necessarily being available for marking the end of the input */
321 for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
323 switch (buffer_at_offset(input_buffer)[i])
339 number_c_string[i] = buffer_at_offset(input_buffer)[i];
343 number_c_string[i] = decimal_point;
351 number_c_string[i] = '\0';
353 number = strtod((const char*)number_c_string, (char**)&after_end);
354 if (number_c_string == after_end)
356 return false; /* parse_error */
359 item->valuedouble = number;
361 /* use saturation in case of overflow */
362 if (number >= INT_MAX)
364 item->valueint = INT_MAX;
366 else if (number <= (double)INT_MIN)
368 item->valueint = INT_MIN;
372 item->valueint = (int)number;
375 item->type = cJSON_Number;
377 input_buffer->offset += (size_t)(after_end - number_c_string);
381 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
382 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
384 if (number >= INT_MAX)
386 object->valueint = INT_MAX;
388 else if (number <= (double)INT_MIN)
390 object->valueint = INT_MIN;
394 object->valueint = (int)number;
397 return object->valuedouble = number;
400 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
403 /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
404 if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
408 if (strlen(valuestring) <= strlen(object->valuestring))
410 strcpy(object->valuestring, valuestring);
411 return object->valuestring;
413 copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
418 if (object->valuestring != NULL)
420 cJSON_free(object->valuestring);
422 object->valuestring = copy;
429 unsigned char *buffer;
432 size_t depth; /* current nesting depth (for formatted printing) */
434 cJSON_bool format; /* is this print a formatted print */
435 internal_hooks hooks;
438 /* realloc printbuffer if necessary to have at least "needed" bytes more */
439 static unsigned char* ensure(printbuffer * const p, size_t needed)
441 unsigned char *newbuffer = NULL;
444 if ((p == NULL) || (p->buffer == NULL))
449 if ((p->length > 0) && (p->offset >= p->length))
451 /* make sure that offset is valid */
455 if (needed > INT_MAX)
457 /* sizes bigger than INT_MAX are currently not supported */
461 needed += p->offset + 1;
462 if (needed <= p->length)
464 return p->buffer + p->offset;
471 /* calculate new buffer size */
472 if (needed > (INT_MAX / 2))
474 /* overflow of int, use INT_MAX if possible */
475 if (needed <= INT_MAX)
486 newsize = needed * 2;
489 if (p->hooks.reallocate != NULL)
491 /* reallocate with realloc if available */
492 newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
493 if (newbuffer == NULL)
495 p->hooks.deallocate(p->buffer);
504 /* otherwise reallocate manually */
505 newbuffer = (unsigned char*)p->hooks.allocate(newsize);
508 p->hooks.deallocate(p->buffer);
515 memcpy (newbuffer, p->buffer, p->offset + 1);
516 p->hooks.deallocate (p->buffer);
519 p->buffer = newbuffer;
521 return newbuffer + p->offset;
524 /* calculate the new length of the string in a printbuffer and update the offset */
525 static void update_offset(printbuffer * const buffer)
527 const unsigned char *buffer_pointer = NULL;
528 if ((buffer == NULL) || (buffer->buffer == NULL))
532 buffer_pointer = buffer->buffer + buffer->offset;
534 buffer->offset += strlen((const char*)buffer_pointer);
537 /* securely comparison of floating-point variables */
538 static cJSON_bool compare_double(double a, double b)
540 double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
541 return (fabs(a - b) <= maxVal * DBL_EPSILON);
544 /* Render the number nicely from the given item into a string. */
545 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
547 unsigned char *output_pointer = NULL;
548 double d = item->valuedouble;
551 unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
552 unsigned char decimal_point = get_decimal_point();
555 if (output_buffer == NULL)
560 /* This checks for NaN and Infinity */
561 if (isnan(d) || isinf(d))
563 length = sprintf((char*)number_buffer, "null");
567 /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
568 length = sprintf((char*)number_buffer, "%1.15g", d);
570 /* Check whether the original double can be recovered */
571 if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
573 /* If not, print with 17 decimal places of precision */
574 length = sprintf((char*)number_buffer, "%1.17g", d);
578 /* sprintf failed or buffer overrun occurred */
579 if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
584 /* reserve appropriate space in the output */
585 output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
586 if (output_pointer == NULL)
591 /* copy the printed number to the output and replace locale
592 * dependent decimal point with '.' */
593 for (i = 0; i < ((size_t)length); i++)
595 if (number_buffer[i] == decimal_point)
597 output_pointer[i] = '.';
601 output_pointer[i] = number_buffer[i];
603 output_pointer[i] = '\0';
605 output_buffer->offset += (size_t)length;
610 /* parse 4 digit hexadecimal number */
611 static unsigned parse_hex4(const unsigned char * const input)
616 for (i = 0; i < 4; i++)
619 if ((input[i] >= '0') && (input[i] <= '9'))
621 h += (unsigned int) input[i] - '0';
623 else if ((input[i] >= 'A') && (input[i] <= 'F'))
625 h += (unsigned int) 10 + input[i] - 'A';
627 else if ((input[i] >= 'a') && (input[i] <= 'f'))
629 h += (unsigned int) 10 + input[i] - 'a';
638 /* shift left to make place for the next nibble */
646 /* converts a UTF-16 literal to UTF-8
647 * A literal can be one or two sequences of the form \uXXXX */
648 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
650 long unsigned int codepoint = 0;
651 unsigned int first_code = 0;
652 const unsigned char *first_sequence = input_pointer;
653 unsigned char utf8_length = 0;
654 unsigned char utf8_position = 0;
655 unsigned char sequence_length = 0;
656 unsigned char first_byte_mark = 0;
658 if ((input_end - first_sequence) < 6)
660 /* input ends unexpectedly */
664 /* get the first utf16 sequence */
665 first_code = parse_hex4(first_sequence + 2);
667 /* check that the code is valid */
668 if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
673 /* UTF16 surrogate pair */
674 if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
676 const unsigned char *second_sequence = first_sequence + 6;
677 unsigned int second_code = 0;
678 sequence_length = 12; /* \uXXXX\uXXXX */
680 if ((input_end - second_sequence) < 6)
682 /* input ends unexpectedly */
686 if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
688 /* missing second half of the surrogate pair */
692 /* get the second utf16 sequence */
693 second_code = parse_hex4(second_sequence + 2);
694 /* check that the code is valid */
695 if ((second_code < 0xDC00) || (second_code > 0xDFFF))
697 /* invalid second half of the surrogate pair */
702 /* calculate the unicode codepoint from the surrogate pair */
703 codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
707 sequence_length = 6; /* \uXXXX */
708 codepoint = first_code;
712 * takes at maximum 4 bytes to encode:
713 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
714 if (codepoint < 0x80)
716 /* normal ascii, encoding 0xxxxxxx */
719 else if (codepoint < 0x800)
721 /* two bytes, encoding 110xxxxx 10xxxxxx */
723 first_byte_mark = 0xC0; /* 11000000 */
725 else if (codepoint < 0x10000)
727 /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
729 first_byte_mark = 0xE0; /* 11100000 */
731 else if (codepoint <= 0x10FFFF)
733 /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
735 first_byte_mark = 0xF0; /* 11110000 */
739 /* invalid unicode codepoint */
744 for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
747 (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
750 /* encode first byte */
753 (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
757 (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
760 *output_pointer += utf8_length;
762 return sequence_length;
768 /* Parse the input text into an unescaped cinput, and populate item. */
769 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
771 const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
772 const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
773 unsigned char *output_pointer = NULL;
774 unsigned char *output = NULL;
777 if (buffer_at_offset(input_buffer)[0] != '\"')
783 /* calculate approximate size of the output (overestimate) */
784 size_t allocation_length = 0;
785 size_t skipped_bytes = 0;
786 while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
788 /* is escape sequence */
789 if (input_end[0] == '\\')
791 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
793 /* prevent buffer overflow when last input character is a backslash */
801 if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
803 goto fail; /* string ended unexpectedly */
806 /* This is at most how much we need for the output */
807 allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
808 output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
811 goto fail; /* allocation failure */
815 output_pointer = output;
816 /* loop through the string literal */
817 while (input_pointer < input_end)
819 if (*input_pointer != '\\')
821 *output_pointer++ = *input_pointer++;
823 /* escape sequence */
826 unsigned char sequence_length = 2;
827 if ((input_end - input_pointer) < 1)
832 switch (input_pointer[1])
835 *output_pointer++ = '\b';
838 *output_pointer++ = '\f';
841 *output_pointer++ = '\n';
844 *output_pointer++ = '\r';
847 *output_pointer++ = '\t';
852 *output_pointer++ = input_pointer[1];
857 sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
858 if (sequence_length == 0)
860 /* failed to convert UTF16-literal to UTF-8 */
868 input_pointer += sequence_length;
872 /* zero terminate the output */
873 *output_pointer = '\0';
875 item->type = cJSON_String;
876 item->valuestring = (char*)output;
878 input_buffer->offset = (size_t) (input_end - input_buffer->content);
879 input_buffer->offset++;
886 input_buffer->hooks.deallocate(output);
889 if (input_pointer != NULL)
891 input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
897 /* Render the cstring provided to an escaped version that can be printed. */
898 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
900 const unsigned char *input_pointer = NULL;
901 unsigned char *output = NULL;
902 unsigned char *output_pointer = NULL;
903 size_t output_length = 0;
904 /* numbers of additional characters needed for escaping */
905 size_t escape_characters = 0;
907 if (output_buffer == NULL)
915 output = ensure(output_buffer, sizeof("\"\""));
920 strcpy((char*)output, "\"\"");
925 /* set "flag" to 1 if something needs to be escaped */
926 for (input_pointer = input; *input_pointer; input_pointer++)
928 switch (*input_pointer)
937 /* one character escape sequence */
941 if (*input_pointer < 32)
943 /* UTF-16 escape sequence uXXXX */
944 escape_characters += 5;
949 output_length = (size_t)(input_pointer - input) + escape_characters;
951 output = ensure(output_buffer, output_length + sizeof("\"\""));
957 /* no characters have to be escaped */
958 if (escape_characters == 0)
961 memcpy(output + 1, input, output_length);
962 output[output_length + 1] = '\"';
963 output[output_length + 2] = '\0';
969 output_pointer = output + 1;
970 /* copy the string */
971 for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
973 if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
975 /* normal character, copy */
976 *output_pointer = *input_pointer;
980 /* character needs to be escaped */
981 *output_pointer++ = '\\';
982 switch (*input_pointer)
985 *output_pointer = '\\';
988 *output_pointer = '\"';
991 *output_pointer = 'b';
994 *output_pointer = 'f';
997 *output_pointer = 'n';
1000 *output_pointer = 'r';
1003 *output_pointer = 't';
1006 /* escape and print as unicode codepoint */
1007 sprintf((char*)output_pointer, "u%04x", *input_pointer);
1008 output_pointer += 4;
1013 output[output_length + 1] = '\"';
1014 output[output_length + 2] = '\0';
1019 /* Invoke print_string_ptr (which is useful) on an item. */
1020 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1022 return print_string_ptr((unsigned char*)item->valuestring, p);
1025 /* Predeclare these prototypes. */
1026 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1027 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1028 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1029 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1030 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1031 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1033 /* Utility to jump whitespace and cr/lf */
1034 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1036 if ((buffer == NULL) || (buffer->content == NULL))
1041 if (cannot_access_at_index(buffer, 0))
1046 while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1051 if (buffer->offset == buffer->length)
1059 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1060 static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1062 if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1067 if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1069 buffer->offset += 3;
1075 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1077 size_t buffer_length;
1084 /* Adding null character size due to require_null_terminated. */
1085 buffer_length = strlen(value) + sizeof("");
1087 return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1090 /* Parse an object - create a new root, and populate. */
1091 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1093 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1096 /* reset error position */
1097 global_error.json = NULL;
1098 global_error.position = 0;
1100 if (value == NULL || 0 == buffer_length)
1105 buffer.content = (const unsigned char*)value;
1106 buffer.length = buffer_length;
1108 buffer.hooks = global_hooks;
1110 item = cJSON_New_Item(&global_hooks);
1111 if (item == NULL) /* memory fail */
1116 if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1118 /* parse failure. ep is set. */
1122 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1123 if (require_null_terminated)
1125 buffer_skip_whitespace(&buffer);
1126 if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1131 if (return_parse_end)
1133 *return_parse_end = (const char*)buffer_at_offset(&buffer);
1147 local_error.json = (const unsigned char*)value;
1148 local_error.position = 0;
1150 if (buffer.offset < buffer.length)
1152 local_error.position = buffer.offset;
1154 else if (buffer.length > 0)
1156 local_error.position = buffer.length - 1;
1159 if (return_parse_end != NULL)
1161 *return_parse_end = (const char*)local_error.json + local_error.position;
1164 global_error = local_error;
1170 /* Default options for cJSON_Parse */
1171 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1173 return cJSON_ParseWithOpts(value, 0, 0);
1176 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1178 return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1181 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1183 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1185 static const size_t default_buffer_size = 256;
1186 printbuffer buffer[1];
1187 unsigned char *printed = NULL;
1189 memset(buffer, 0, sizeof(buffer));
1192 buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1193 buffer->length = default_buffer_size;
1194 buffer->format = format;
1195 buffer->hooks = *hooks;
1196 if (buffer->buffer == NULL)
1201 /* print the value */
1202 if (!print_value(item, buffer))
1206 update_offset(buffer);
1208 /* check if reallocate is available */
1209 if (hooks->reallocate != NULL)
1211 printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1212 if (printed == NULL) {
1215 buffer->buffer = NULL;
1217 else /* otherwise copy the JSON over to a new buffer */
1219 printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1220 if (printed == NULL)
1224 memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1225 printed[buffer->offset] = '\0'; /* just to be sure */
1227 /* free the buffer */
1228 hooks->deallocate(buffer->buffer);
1234 if (buffer->buffer != NULL)
1236 hooks->deallocate(buffer->buffer);
1239 if (printed != NULL)
1241 hooks->deallocate(printed);
1247 /* Render a cJSON item/entity/structure to text. */
1248 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1250 return (char*)print(item, true, &global_hooks);
1253 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1255 return (char*)print(item, false, &global_hooks);
1258 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1260 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1267 p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1273 p.length = (size_t)prebuffer;
1277 p.hooks = global_hooks;
1279 if (!print_value(item, &p))
1281 global_hooks.deallocate(p.buffer);
1285 return (char*)p.buffer;
1288 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1290 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1292 if ((length < 0) || (buffer == NULL))
1297 p.buffer = (unsigned char*)buffer;
1298 p.length = (size_t)length;
1302 p.hooks = global_hooks;
1304 return print_value(item, &p);
1307 /* Parser core - when encountering text, process appropriately. */
1308 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1310 if ((input_buffer == NULL) || (input_buffer->content == NULL))
1312 return false; /* no input */
1315 /* parse the different types of values */
1317 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1319 item->type = cJSON_NULL;
1320 input_buffer->offset += 4;
1324 if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1326 item->type = cJSON_False;
1327 input_buffer->offset += 5;
1331 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1333 item->type = cJSON_True;
1335 input_buffer->offset += 4;
1339 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1341 return parse_string(item, input_buffer);
1344 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'))))
1346 return parse_number(item, input_buffer);
1349 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1351 return parse_array(item, input_buffer);
1354 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1356 return parse_object(item, input_buffer);
1362 /* Render a value to text. */
1363 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1365 unsigned char *output = NULL;
1367 if ((item == NULL) || (output_buffer == NULL))
1372 switch ((item->type) & 0xFF)
1375 output = ensure(output_buffer, 5);
1380 strcpy((char*)output, "null");
1384 output = ensure(output_buffer, 6);
1389 strcpy((char*)output, "false");
1393 output = ensure(output_buffer, 5);
1398 strcpy((char*)output, "true");
1402 return print_number(item, output_buffer);
1406 size_t raw_length = 0;
1407 if (item->valuestring == NULL)
1412 raw_length = strlen(item->valuestring) + sizeof("");
1413 output = ensure(output_buffer, raw_length);
1418 memcpy(output, item->valuestring, raw_length);
1423 return print_string(item, output_buffer);
1426 return print_array(item, output_buffer);
1429 return print_object(item, output_buffer);
1436 /* Build an array from input text. */
1437 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1439 cJSON *head = NULL; /* head of the linked list */
1440 cJSON *current_item = NULL;
1442 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1444 return false; /* to deeply nested */
1446 input_buffer->depth++;
1448 if (buffer_at_offset(input_buffer)[0] != '[')
1454 input_buffer->offset++;
1455 buffer_skip_whitespace(input_buffer);
1456 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1462 /* check if we skipped to the end of the buffer */
1463 if (cannot_access_at_index(input_buffer, 0))
1465 input_buffer->offset--;
1469 /* step back to character in front of the first element */
1470 input_buffer->offset--;
1471 /* loop through the comma separated array elements */
1474 /* allocate next item */
1475 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1476 if (new_item == NULL)
1478 goto fail; /* allocation failure */
1481 /* attach next item to list */
1484 /* start the linked list */
1485 current_item = head = new_item;
1489 /* add to the end and advance */
1490 current_item->next = new_item;
1491 new_item->prev = current_item;
1492 current_item = new_item;
1495 /* parse next value */
1496 input_buffer->offset++;
1497 buffer_skip_whitespace(input_buffer);
1498 if (!parse_value(current_item, input_buffer))
1500 goto fail; /* failed to parse value */
1502 buffer_skip_whitespace(input_buffer);
1504 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1506 if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1508 goto fail; /* expected end of array */
1512 input_buffer->depth--;
1515 head->prev = current_item;
1518 item->type = cJSON_Array;
1521 input_buffer->offset++;
1534 /* Render an array to text */
1535 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1537 unsigned char *output_pointer = NULL;
1539 cJSON *current_element = item->child;
1541 if (output_buffer == NULL)
1546 /* Compose the output array. */
1547 /* opening square bracket */
1548 output_pointer = ensure(output_buffer, 1);
1549 if (output_pointer == NULL)
1554 *output_pointer = '[';
1555 output_buffer->offset++;
1556 output_buffer->depth++;
1558 while (current_element != NULL)
1560 if (!print_value(current_element, output_buffer))
1564 update_offset(output_buffer);
1565 if (current_element->next)
1567 length = (size_t) (output_buffer->format ? 2 : 1);
1568 output_pointer = ensure(output_buffer, length + 1);
1569 if (output_pointer == NULL)
1573 *output_pointer++ = ',';
1574 if(output_buffer->format)
1576 *output_pointer++ = ' ';
1578 *output_pointer = '\0';
1579 output_buffer->offset += length;
1581 current_element = current_element->next;
1584 output_pointer = ensure(output_buffer, 2);
1585 if (output_pointer == NULL)
1589 *output_pointer++ = ']';
1590 *output_pointer = '\0';
1591 output_buffer->depth--;
1596 /* Build an object from the text. */
1597 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1599 cJSON *head = NULL; /* linked list head */
1600 cJSON *current_item = NULL;
1602 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1604 return false; /* to deeply nested */
1606 input_buffer->depth++;
1608 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1610 goto fail; /* not an object */
1613 input_buffer->offset++;
1614 buffer_skip_whitespace(input_buffer);
1615 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1617 goto success; /* empty object */
1620 /* check if we skipped to the end of the buffer */
1621 if (cannot_access_at_index(input_buffer, 0))
1623 input_buffer->offset--;
1627 /* step back to character in front of the first element */
1628 input_buffer->offset--;
1629 /* loop through the comma separated array elements */
1632 /* allocate next item */
1633 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1634 if (new_item == NULL)
1636 goto fail; /* allocation failure */
1639 /* attach next item to list */
1642 /* start the linked list */
1643 current_item = head = new_item;
1647 /* add to the end and advance */
1648 current_item->next = new_item;
1649 new_item->prev = current_item;
1650 current_item = new_item;
1653 /* parse the name of the child */
1654 input_buffer->offset++;
1655 buffer_skip_whitespace(input_buffer);
1656 if (!parse_string(current_item, input_buffer))
1658 goto fail; /* failed to parse name */
1660 buffer_skip_whitespace(input_buffer);
1662 /* swap valuestring and string, because we parsed the name */
1663 current_item->string = current_item->valuestring;
1664 current_item->valuestring = NULL;
1666 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1668 goto fail; /* invalid object */
1671 /* parse the value */
1672 input_buffer->offset++;
1673 buffer_skip_whitespace(input_buffer);
1674 if (!parse_value(current_item, input_buffer))
1676 goto fail; /* failed to parse value */
1678 buffer_skip_whitespace(input_buffer);
1680 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1682 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1684 goto fail; /* expected end of object */
1688 input_buffer->depth--;
1691 head->prev = current_item;
1694 item->type = cJSON_Object;
1697 input_buffer->offset++;
1709 /* Render an object to text. */
1710 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1712 unsigned char *output_pointer = NULL;
1714 cJSON *current_item = item->child;
1716 if (output_buffer == NULL)
1721 /* Compose the output: */
1722 length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1723 output_pointer = ensure(output_buffer, length + 1);
1724 if (output_pointer == NULL)
1729 *output_pointer++ = '{';
1730 output_buffer->depth++;
1731 if (output_buffer->format)
1733 *output_pointer++ = '\n';
1735 output_buffer->offset += length;
1737 while (current_item)
1739 if (output_buffer->format)
1742 output_pointer = ensure(output_buffer, output_buffer->depth);
1743 if (output_pointer == NULL)
1747 for (i = 0; i < output_buffer->depth; i++)
1749 *output_pointer++ = '\t';
1751 output_buffer->offset += output_buffer->depth;
1755 if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1759 update_offset(output_buffer);
1761 length = (size_t) (output_buffer->format ? 2 : 1);
1762 output_pointer = ensure(output_buffer, length);
1763 if (output_pointer == NULL)
1767 *output_pointer++ = ':';
1768 if (output_buffer->format)
1770 *output_pointer++ = '\t';
1772 output_buffer->offset += length;
1775 if (!print_value(current_item, output_buffer))
1779 update_offset(output_buffer);
1781 /* print comma if not last */
1782 length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1783 output_pointer = ensure(output_buffer, length + 1);
1784 if (output_pointer == NULL)
1788 if (current_item->next)
1790 *output_pointer++ = ',';
1793 if (output_buffer->format)
1795 *output_pointer++ = '\n';
1797 *output_pointer = '\0';
1798 output_buffer->offset += length;
1800 current_item = current_item->next;
1803 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1804 if (output_pointer == NULL)
1808 if (output_buffer->format)
1811 for (i = 0; i < (output_buffer->depth - 1); i++)
1813 *output_pointer++ = '\t';
1816 *output_pointer++ = '}';
1817 *output_pointer = '\0';
1818 output_buffer->depth--;
1823 /* Get Array size/item / object item. */
1824 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1826 cJSON *child = NULL;
1834 child = array->child;
1836 while(child != NULL)
1839 child = child->next;
1842 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1847 static cJSON* get_array_item(const cJSON *array, size_t index)
1849 cJSON *current_child = NULL;
1856 current_child = array->child;
1857 while ((current_child != NULL) && (index > 0))
1860 current_child = current_child->next;
1863 return current_child;
1866 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1873 return get_array_item(array, (size_t)index);
1876 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1878 cJSON *current_element = NULL;
1880 if ((object == NULL) || (name == NULL))
1885 current_element = object->child;
1888 while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1890 current_element = current_element->next;
1895 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1897 current_element = current_element->next;
1901 if ((current_element == NULL) || (current_element->string == NULL)) {
1905 return current_element;
1908 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1910 return get_object_item(object, string, false);
1913 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1915 return get_object_item(object, string, true);
1918 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1920 return cJSON_GetObjectItem(object, string) ? 1 : 0;
1923 /* Utility for array list handling. */
1924 static void suffix_object(cJSON *prev, cJSON *item)
1930 /* Utility for handling references. */
1931 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1933 cJSON *reference = NULL;
1939 reference = cJSON_New_Item(hooks);
1940 if (reference == NULL)
1945 memcpy(reference, item, sizeof(cJSON));
1946 reference->string = NULL;
1947 reference->type |= cJSON_IsReference;
1948 reference->next = reference->prev = NULL;
1952 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1954 cJSON *child = NULL;
1956 if ((item == NULL) || (array == NULL) || (array == item))
1961 child = array->child;
1963 * To find the last item in array quickly, we use prev in array
1967 /* list is empty, start new one */
1968 array->child = item;
1974 /* append to the end */
1977 suffix_object(child->prev, item);
1978 array->child->prev = item;
1985 /* Add item to array/object. */
1986 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1988 return add_item_to_array(array, item);
1991 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1992 #pragma GCC diagnostic push
1995 #pragma GCC diagnostic ignored "-Wcast-qual"
1997 /* helper function to cast away const */
1998 static void* cast_away_const(const void* string)
2000 return (void*)string;
2002 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2003 #pragma GCC diagnostic pop
2007 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)
2009 char *new_key = NULL;
2010 int new_type = cJSON_Invalid;
2012 if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2019 new_key = (char*)cast_away_const(string);
2020 new_type = item->type | cJSON_StringIsConst;
2024 new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2025 if (new_key == NULL)
2030 new_type = item->type & ~cJSON_StringIsConst;
2033 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2035 hooks->deallocate(item->string);
2038 item->string = new_key;
2039 item->type = new_type;
2041 return add_item_to_array(object, item);
2044 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2046 return add_item_to_object(object, string, item, &global_hooks, false);
2049 /* Add an item to an object with constant string as key */
2050 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2052 return add_item_to_object(object, string, item, &global_hooks, true);
2055 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2062 return add_item_to_array(array, create_reference(item, &global_hooks));
2065 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2067 if ((object == NULL) || (string == NULL))
2072 return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2075 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2077 cJSON *null = cJSON_CreateNull();
2078 if (add_item_to_object(object, name, null, &global_hooks, false))
2087 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2089 cJSON *true_item = cJSON_CreateTrue();
2090 if (add_item_to_object(object, name, true_item, &global_hooks, false))
2095 cJSON_Delete(true_item);
2099 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2101 cJSON *false_item = cJSON_CreateFalse();
2102 if (add_item_to_object(object, name, false_item, &global_hooks, false))
2107 cJSON_Delete(false_item);
2111 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2113 cJSON *bool_item = cJSON_CreateBool(boolean);
2114 if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2119 cJSON_Delete(bool_item);
2123 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2125 cJSON *number_item = cJSON_CreateNumber(number);
2126 if (add_item_to_object(object, name, number_item, &global_hooks, false))
2131 cJSON_Delete(number_item);
2135 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2137 cJSON *string_item = cJSON_CreateString(string);
2138 if (add_item_to_object(object, name, string_item, &global_hooks, false))
2143 cJSON_Delete(string_item);
2147 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2149 cJSON *raw_item = cJSON_CreateRaw(raw);
2150 if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2155 cJSON_Delete(raw_item);
2159 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2161 cJSON *object_item = cJSON_CreateObject();
2162 if (add_item_to_object(object, name, object_item, &global_hooks, false))
2167 cJSON_Delete(object_item);
2171 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2173 cJSON *array = cJSON_CreateArray();
2174 if (add_item_to_object(object, name, array, &global_hooks, false))
2179 cJSON_Delete(array);
2183 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2185 if ((parent == NULL) || (item == NULL))
2190 if (item != parent->child)
2192 /* not the first element */
2193 item->prev->next = item->next;
2195 if (item->next != NULL)
2197 /* not the last element */
2198 item->next->prev = item->prev;
2201 if (item == parent->child)
2204 parent->child = item->next;
2206 else if (item->next == NULL)
2209 parent->child->prev = item->prev;
2212 /* make sure the detached item doesn't point anywhere anymore */
2219 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2226 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2229 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2231 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2234 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2236 cJSON *to_detach = cJSON_GetObjectItem(object, string);
2238 return cJSON_DetachItemViaPointer(object, to_detach);
2241 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2243 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2245 return cJSON_DetachItemViaPointer(object, to_detach);
2248 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2250 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2253 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2255 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2258 /* Replace array/object items with new ones. */
2259 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2261 cJSON *after_inserted = NULL;
2268 after_inserted = get_array_item(array, (size_t)which);
2269 if (after_inserted == NULL)
2271 return add_item_to_array(array, newitem);
2274 newitem->next = after_inserted;
2275 newitem->prev = after_inserted->prev;
2276 after_inserted->prev = newitem;
2277 if (after_inserted == array->child)
2279 array->child = newitem;
2283 newitem->prev->next = newitem;
2288 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2290 if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2295 if (replacement == item)
2300 replacement->next = item->next;
2301 replacement->prev = item->prev;
2303 if (replacement->next != NULL)
2305 replacement->next->prev = replacement;
2307 if (parent->child == item)
2309 if (parent->child->prev == parent->child)
2311 replacement->prev = replacement;
2313 parent->child = replacement;
2317 * To find the last item in array quickly, we use prev in array.
2318 * We can't modify the last item's next pointer where this item was the parent's child
2320 if (replacement->prev != NULL)
2322 replacement->prev->next = replacement;
2324 if (replacement->next == NULL)
2326 parent->child->prev = replacement;
2337 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2344 return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2347 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2349 if ((replacement == NULL) || (string == NULL))
2354 /* replace the name in the replacement */
2355 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2357 cJSON_free(replacement->string);
2359 replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2360 replacement->type &= ~cJSON_StringIsConst;
2362 return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2365 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2367 return replace_item_in_object(object, string, newitem, false);
2370 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2372 return replace_item_in_object(object, string, newitem, true);
2375 /* Create basic types: */
2376 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2378 cJSON *item = cJSON_New_Item(&global_hooks);
2381 item->type = cJSON_NULL;
2387 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2389 cJSON *item = cJSON_New_Item(&global_hooks);
2392 item->type = cJSON_True;
2398 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2400 cJSON *item = cJSON_New_Item(&global_hooks);
2403 item->type = cJSON_False;
2409 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2411 cJSON *item = cJSON_New_Item(&global_hooks);
2414 item->type = boolean ? cJSON_True : cJSON_False;
2420 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2422 cJSON *item = cJSON_New_Item(&global_hooks);
2425 item->type = cJSON_Number;
2426 item->valuedouble = num;
2428 /* use saturation in case of overflow */
2431 item->valueint = INT_MAX;
2433 else if (num <= (double)INT_MIN)
2435 item->valueint = INT_MIN;
2439 item->valueint = (int)num;
2446 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2448 cJSON *item = cJSON_New_Item(&global_hooks);
2451 item->type = cJSON_String;
2452 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2453 if(!item->valuestring)
2463 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2465 cJSON *item = cJSON_New_Item(&global_hooks);
2468 item->type = cJSON_String | cJSON_IsReference;
2469 item->valuestring = (char*)cast_away_const(string);
2475 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2477 cJSON *item = cJSON_New_Item(&global_hooks);
2479 item->type = cJSON_Object | cJSON_IsReference;
2480 item->child = (cJSON*)cast_away_const(child);
2486 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2487 cJSON *item = cJSON_New_Item(&global_hooks);
2489 item->type = cJSON_Array | cJSON_IsReference;
2490 item->child = (cJSON*)cast_away_const(child);
2496 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2498 cJSON *item = cJSON_New_Item(&global_hooks);
2501 item->type = cJSON_Raw;
2502 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2503 if(!item->valuestring)
2513 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2515 cJSON *item = cJSON_New_Item(&global_hooks);
2518 item->type=cJSON_Array;
2524 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2526 cJSON *item = cJSON_New_Item(&global_hooks);
2529 item->type = cJSON_Object;
2535 /* Create Arrays: */
2536 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2543 if ((count < 0) || (numbers == NULL))
2548 a = cJSON_CreateArray();
2550 for(i = 0; a && (i < (size_t)count); i++)
2552 n = cJSON_CreateNumber(numbers[i]);
2564 suffix_object(p, n);
2577 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2584 if ((count < 0) || (numbers == NULL))
2589 a = cJSON_CreateArray();
2591 for(i = 0; a && (i < (size_t)count); i++)
2593 n = cJSON_CreateNumber((double)numbers[i]);
2605 suffix_object(p, n);
2618 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2625 if ((count < 0) || (numbers == NULL))
2630 a = cJSON_CreateArray();
2632 for (i = 0; a && (i < (size_t) count); i++)
2634 n = cJSON_CreateNumber(numbers[i]);
2646 suffix_object(p, n);
2659 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2666 if ((count < 0) || (strings == NULL))
2671 a = cJSON_CreateArray();
2673 for (i = 0; a && (i < (size_t)count); i++)
2675 n = cJSON_CreateString(strings[i]);
2701 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2703 cJSON *newitem = NULL;
2704 cJSON *child = NULL;
2706 cJSON *newchild = NULL;
2708 /* Bail on bad ptr */
2713 /* Create new item */
2714 newitem = cJSON_New_Item(&global_hooks);
2719 /* Copy over all vars */
2720 newitem->type = item->type & (~cJSON_IsReference);
2721 newitem->valueint = item->valueint;
2722 newitem->valuedouble = item->valuedouble;
2723 if (item->valuestring)
2725 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2726 if (!newitem->valuestring)
2733 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2734 if (!newitem->string)
2739 /* If non-recursive, then we're done! */
2744 /* Walk the ->next chain for the child. */
2745 child = item->child;
2746 while (child != NULL)
2748 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2755 /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2756 next->next = newchild;
2757 newchild->prev = next;
2762 /* Set newitem->child and move to it */
2763 newitem->child = newchild;
2766 child = child->next;
2768 if (newitem && newitem->child)
2770 newitem->child->prev = newchild;
2776 if (newitem != NULL)
2778 cJSON_Delete(newitem);
2784 static void skip_oneline_comment(char **input)
2786 *input += static_strlen("//");
2788 for (; (*input)[0] != '\0'; ++(*input))
2790 if ((*input)[0] == '\n') {
2791 *input += static_strlen("\n");
2797 static void skip_multiline_comment(char **input)
2799 *input += static_strlen("/*");
2801 for (; (*input)[0] != '\0'; ++(*input))
2803 if (((*input)[0] == '*') && ((*input)[1] == '/'))
2805 *input += static_strlen("*/");
2811 static void minify_string(char **input, char **output) {
2812 (*output)[0] = (*input)[0];
2813 *input += static_strlen("\"");
2814 *output += static_strlen("\"");
2817 for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2818 (*output)[0] = (*input)[0];
2820 if ((*input)[0] == '\"') {
2821 (*output)[0] = '\"';
2822 *input += static_strlen("\"");
2823 *output += static_strlen("\"");
2825 } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2826 (*output)[1] = (*input)[1];
2827 *input += static_strlen("\"");
2828 *output += static_strlen("\"");
2833 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2842 while (json[0] != '\0')
2856 skip_oneline_comment(&json);
2858 else if (json[1] == '*')
2860 skip_multiline_comment(&json);
2867 minify_string(&json, (char**)&into);
2877 /* and null-terminate. */
2881 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2888 return (item->type & 0xFF) == cJSON_Invalid;
2891 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2898 return (item->type & 0xFF) == cJSON_False;
2901 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2908 return (item->type & 0xff) == cJSON_True;
2912 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2919 return (item->type & (cJSON_True | cJSON_False)) != 0;
2921 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2928 return (item->type & 0xFF) == cJSON_NULL;
2931 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2938 return (item->type & 0xFF) == cJSON_Number;
2941 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2948 return (item->type & 0xFF) == cJSON_String;
2951 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2958 return (item->type & 0xFF) == cJSON_Array;
2961 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2968 return (item->type & 0xFF) == cJSON_Object;
2971 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2978 return (item->type & 0xFF) == cJSON_Raw;
2981 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2983 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2988 /* check if type is valid */
2989 switch (a->type & 0xFF)
3005 /* identical objects are equal */
3011 switch (a->type & 0xFF)
3013 /* in these cases and equal type is enough */
3020 if (compare_double(a->valuedouble, b->valuedouble))
3028 if ((a->valuestring == NULL) || (b->valuestring == NULL))
3032 if (strcmp(a->valuestring, b->valuestring) == 0)
3041 cJSON *a_element = a->child;
3042 cJSON *b_element = b->child;
3044 for (; (a_element != NULL) && (b_element != NULL);)
3046 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3051 a_element = a_element->next;
3052 b_element = b_element->next;
3055 /* one of the arrays is longer than the other */
3056 if (a_element != b_element) {
3065 cJSON *a_element = NULL;
3066 cJSON *b_element = NULL;
3067 cJSON_ArrayForEach(a_element, a)
3069 /* TODO This has O(n^2) runtime, which is horrible! */
3070 b_element = get_object_item(b, a_element->string, case_sensitive);
3071 if (b_element == NULL)
3076 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3082 /* doing this twice, once on a and b to prevent true comparison if a subset of b
3083 * TODO: Do this the proper way, this is just a fix for now */
3084 cJSON_ArrayForEach(b_element, b)
3086 a_element = get_object_item(a, b_element->string, case_sensitive);
3087 if (a_element == NULL)
3092 if (!cJSON_Compare(b_element, a_element, case_sensitive))
3106 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3108 return global_hooks.allocate(size);
3111 CJSON_PUBLIC(void) cJSON_free(void *object)
3113 global_hooks.deallocate(object);