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 new_size, size_t old_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)
174 #define internal_malloc malloc
175 #define internal_free free
178 static void * CJSON_CDECL internal_realloc(void *pointer, size_t new_size,
181 return realloc(pointer, new_size);
185 cjson_realloc_internal (void *ptr, size_t new_size, size_t old_size);
187 /* strlen of character literals resolved at compile time */
188 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
190 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
192 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
195 unsigned char *copy = NULL;
202 length = strlen((const char*)string) + sizeof("");
203 copy = (unsigned char*)hooks->allocate(length);
208 memcpy(copy, string, length);
213 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
218 global_hooks.allocate = malloc;
219 global_hooks.deallocate = free;
220 global_hooks.reallocate = internal_realloc;
224 global_hooks.allocate = malloc;
225 if (hooks->malloc_fn != NULL)
227 global_hooks.allocate = hooks->malloc_fn;
230 global_hooks.deallocate = free;
231 if (hooks->free_fn != NULL)
233 global_hooks.deallocate = hooks->free_fn;
236 /* use realloc only if both free and malloc are used */
237 global_hooks.reallocate = NULL;
238 if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
240 global_hooks.reallocate = internal_realloc;
244 global_hooks.reallocate = cjson_realloc_internal;
248 /* Internal constructor. */
249 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
251 cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
254 memset(node, '\0', sizeof(cJSON));
260 /* Delete a cJSON structure. */
261 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
267 if (!(item->type & cJSON_IsReference) && (item->child != NULL))
269 cJSON_Delete(item->child);
271 if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
273 global_hooks.deallocate(item->valuestring);
275 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
277 global_hooks.deallocate(item->string);
279 global_hooks.deallocate(item);
284 /* get the decimal point character of the current locale */
285 static unsigned char get_decimal_point(void)
287 #ifdef ENABLE_LOCALES
288 struct lconv *lconv = localeconv();
289 return (unsigned char) lconv->decimal_point[0];
297 const unsigned char *content;
300 size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
301 internal_hooks hooks;
304 /* check if the given size is left to read in a given parse buffer (starting with 1) */
305 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
306 /* check if the buffer can be accessed at the given index (starting with 0) */
307 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
308 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
309 /* get a pointer to the buffer at the position */
310 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
312 /* Parse the input text to generate a number, and populate the result into item. */
313 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
316 unsigned char *after_end = NULL;
317 unsigned char number_c_string[64];
318 unsigned char decimal_point = get_decimal_point();
321 if ((input_buffer == NULL) || (input_buffer->content == NULL))
326 /* copy the number into a temporary buffer and replace '.' with the decimal point
327 * of the current locale (for strtod)
328 * This also takes care of '\0' not necessarily being available for marking the end of the input */
329 for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
331 switch (buffer_at_offset(input_buffer)[i])
347 number_c_string[i] = buffer_at_offset(input_buffer)[i];
351 number_c_string[i] = decimal_point;
359 number_c_string[i] = '\0';
361 number = strtod((const char*)number_c_string, (char**)&after_end);
362 if (number_c_string == after_end)
364 return false; /* parse_error */
367 item->valuedouble = number;
369 /* use saturation in case of overflow */
370 if (number >= INT_MAX)
372 item->valueint = INT_MAX;
374 else if (number <= (double)INT_MIN)
376 item->valueint = INT_MIN;
380 item->valueint = (int)number;
383 item->type = cJSON_Number;
385 input_buffer->offset += (size_t)(after_end - number_c_string);
389 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
390 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
392 if (number >= INT_MAX)
394 object->valueint = INT_MAX;
396 else if (number <= (double)INT_MIN)
398 object->valueint = INT_MIN;
402 object->valueint = (int)number;
405 return object->valuedouble = number;
408 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
411 /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
412 if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
416 if (strlen(valuestring) <= strlen(object->valuestring))
418 strcpy(object->valuestring, valuestring);
419 return object->valuestring;
421 copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
426 if (object->valuestring != NULL)
428 cJSON_free(object->valuestring);
430 object->valuestring = copy;
437 unsigned char *buffer;
440 size_t depth; /* current nesting depth (for formatted printing) */
442 cJSON_bool format; /* is this print a formatted print */
443 internal_hooks hooks;
447 cjson_realloc_internal (void *ptr, size_t new_size, size_t old_size)
450 if (old_size < new_size)
451 copy_size = old_size;
453 copy_size = new_size;
455 unsigned char *newbuffer = global_hooks.allocate(new_size);
458 global_hooks.deallocate(ptr);
462 memcpy (newbuffer, ptr, copy_size);
463 global_hooks.deallocate (ptr);
467 /* realloc printbuffer if necessary to have at least "needed" bytes more */
468 static unsigned char* ensure(printbuffer * const p, size_t needed)
470 unsigned char *newbuffer = NULL;
473 if ((p == NULL) || (p->buffer == NULL))
478 if ((p->length > 0) && (p->offset >= p->length))
480 /* make sure that offset is valid */
484 if (needed > INT_MAX)
486 /* sizes bigger than INT_MAX are currently not supported */
490 needed += p->offset + 1;
491 if (needed <= p->length)
493 return p->buffer + p->offset;
500 /* calculate new buffer size */
501 if (needed > (INT_MAX / 2))
503 /* overflow of int, use INT_MAX if possible */
504 if (needed <= INT_MAX)
515 newsize = needed * 2;
518 newbuffer = p->hooks.reallocate (p->buffer, newsize, p->length);
519 if (newbuffer == NULL)
521 p->hooks.deallocate(p->buffer);
527 p->buffer = newbuffer;
529 return newbuffer + p->offset;
532 /* calculate the new length of the string in a printbuffer and update the offset */
533 static void update_offset(printbuffer * const buffer)
535 const unsigned char *buffer_pointer = NULL;
536 if ((buffer == NULL) || (buffer->buffer == NULL))
540 buffer_pointer = buffer->buffer + buffer->offset;
542 buffer->offset += strlen((const char*)buffer_pointer);
545 /* securely comparison of floating-point variables */
546 static cJSON_bool compare_double(double a, double b)
548 double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
549 return (fabs(a - b) <= maxVal * DBL_EPSILON);
552 /* Render the number nicely from the given item into a string. */
553 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
555 unsigned char *output_pointer = NULL;
556 double d = item->valuedouble;
559 unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
560 unsigned char decimal_point = get_decimal_point();
563 if (output_buffer == NULL)
568 /* This checks for NaN and Infinity */
569 if (isnan(d) || isinf(d))
571 length = sprintf((char*)number_buffer, "null");
575 /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
576 length = sprintf((char*)number_buffer, "%1.15g", d);
578 /* Check whether the original double can be recovered */
579 if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
581 /* If not, print with 17 decimal places of precision */
582 length = sprintf((char*)number_buffer, "%1.17g", d);
586 /* sprintf failed or buffer overrun occurred */
587 if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
592 /* reserve appropriate space in the output */
593 output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
594 if (output_pointer == NULL)
599 /* copy the printed number to the output and replace locale
600 * dependent decimal point with '.' */
601 for (i = 0; i < ((size_t)length); i++)
603 if (number_buffer[i] == decimal_point)
605 output_pointer[i] = '.';
609 output_pointer[i] = number_buffer[i];
611 output_pointer[i] = '\0';
613 output_buffer->offset += (size_t)length;
618 /* parse 4 digit hexadecimal number */
619 static unsigned parse_hex4(const unsigned char * const input)
624 for (i = 0; i < 4; i++)
627 if ((input[i] >= '0') && (input[i] <= '9'))
629 h += (unsigned int) input[i] - '0';
631 else if ((input[i] >= 'A') && (input[i] <= 'F'))
633 h += (unsigned int) 10 + input[i] - 'A';
635 else if ((input[i] >= 'a') && (input[i] <= 'f'))
637 h += (unsigned int) 10 + input[i] - 'a';
646 /* shift left to make place for the next nibble */
654 /* converts a UTF-16 literal to UTF-8
655 * A literal can be one or two sequences of the form \uXXXX */
656 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
658 long unsigned int codepoint = 0;
659 unsigned int first_code = 0;
660 const unsigned char *first_sequence = input_pointer;
661 unsigned char utf8_length = 0;
662 unsigned char utf8_position = 0;
663 unsigned char sequence_length = 0;
664 unsigned char first_byte_mark = 0;
666 if ((input_end - first_sequence) < 6)
668 /* input ends unexpectedly */
672 /* get the first utf16 sequence */
673 first_code = parse_hex4(first_sequence + 2);
675 /* check that the code is valid */
676 if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
681 /* UTF16 surrogate pair */
682 if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
684 const unsigned char *second_sequence = first_sequence + 6;
685 unsigned int second_code = 0;
686 sequence_length = 12; /* \uXXXX\uXXXX */
688 if ((input_end - second_sequence) < 6)
690 /* input ends unexpectedly */
694 if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
696 /* missing second half of the surrogate pair */
700 /* get the second utf16 sequence */
701 second_code = parse_hex4(second_sequence + 2);
702 /* check that the code is valid */
703 if ((second_code < 0xDC00) || (second_code > 0xDFFF))
705 /* invalid second half of the surrogate pair */
710 /* calculate the unicode codepoint from the surrogate pair */
711 codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
715 sequence_length = 6; /* \uXXXX */
716 codepoint = first_code;
720 * takes at maximum 4 bytes to encode:
721 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
722 if (codepoint < 0x80)
724 /* normal ascii, encoding 0xxxxxxx */
727 else if (codepoint < 0x800)
729 /* two bytes, encoding 110xxxxx 10xxxxxx */
731 first_byte_mark = 0xC0; /* 11000000 */
733 else if (codepoint < 0x10000)
735 /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
737 first_byte_mark = 0xE0; /* 11100000 */
739 else if (codepoint <= 0x10FFFF)
741 /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
743 first_byte_mark = 0xF0; /* 11110000 */
747 /* invalid unicode codepoint */
752 for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
755 (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
758 /* encode first byte */
761 (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
765 (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
768 *output_pointer += utf8_length;
770 return sequence_length;
776 /* Parse the input text into an unescaped cinput, and populate item. */
777 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
779 const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
780 const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
781 unsigned char *output_pointer = NULL;
782 unsigned char *output = NULL;
785 if (buffer_at_offset(input_buffer)[0] != '\"')
791 /* calculate approximate size of the output (overestimate) */
792 size_t allocation_length = 0;
793 size_t skipped_bytes = 0;
794 while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
796 /* is escape sequence */
797 if (input_end[0] == '\\')
799 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
801 /* prevent buffer overflow when last input character is a backslash */
809 if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
811 goto fail; /* string ended unexpectedly */
814 /* This is at most how much we need for the output */
815 allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
816 output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
819 goto fail; /* allocation failure */
823 output_pointer = output;
824 /* loop through the string literal */
825 while (input_pointer < input_end)
827 if (*input_pointer != '\\')
829 *output_pointer++ = *input_pointer++;
831 /* escape sequence */
834 unsigned char sequence_length = 2;
835 if ((input_end - input_pointer) < 1)
840 switch (input_pointer[1])
843 *output_pointer++ = '\b';
846 *output_pointer++ = '\f';
849 *output_pointer++ = '\n';
852 *output_pointer++ = '\r';
855 *output_pointer++ = '\t';
860 *output_pointer++ = input_pointer[1];
865 sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
866 if (sequence_length == 0)
868 /* failed to convert UTF16-literal to UTF-8 */
876 input_pointer += sequence_length;
880 /* zero terminate the output */
881 *output_pointer = '\0';
883 item->type = cJSON_String;
884 item->valuestring = (char*)output;
886 input_buffer->offset = (size_t) (input_end - input_buffer->content);
887 input_buffer->offset++;
894 input_buffer->hooks.deallocate(output);
897 if (input_pointer != NULL)
899 input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
905 /* Render the cstring provided to an escaped version that can be printed. */
906 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
908 const unsigned char *input_pointer = NULL;
909 unsigned char *output = NULL;
910 unsigned char *output_pointer = NULL;
911 size_t output_length = 0;
912 /* numbers of additional characters needed for escaping */
913 size_t escape_characters = 0;
915 if (output_buffer == NULL)
923 output = ensure(output_buffer, sizeof("\"\""));
928 strcpy((char*)output, "\"\"");
933 /* set "flag" to 1 if something needs to be escaped */
934 for (input_pointer = input; *input_pointer; input_pointer++)
936 switch (*input_pointer)
945 /* one character escape sequence */
949 if (*input_pointer < 32)
951 /* UTF-16 escape sequence uXXXX */
952 escape_characters += 5;
957 output_length = (size_t)(input_pointer - input) + escape_characters;
959 output = ensure(output_buffer, output_length + sizeof("\"\""));
965 /* no characters have to be escaped */
966 if (escape_characters == 0)
969 memcpy(output + 1, input, output_length);
970 output[output_length + 1] = '\"';
971 output[output_length + 2] = '\0';
977 output_pointer = output + 1;
978 /* copy the string */
979 for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
981 if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
983 /* normal character, copy */
984 *output_pointer = *input_pointer;
988 /* character needs to be escaped */
989 *output_pointer++ = '\\';
990 switch (*input_pointer)
993 *output_pointer = '\\';
996 *output_pointer = '\"';
999 *output_pointer = 'b';
1002 *output_pointer = 'f';
1005 *output_pointer = 'n';
1008 *output_pointer = 'r';
1011 *output_pointer = 't';
1014 /* escape and print as unicode codepoint */
1015 sprintf((char*)output_pointer, "u%04x", *input_pointer);
1016 output_pointer += 4;
1021 output[output_length + 1] = '\"';
1022 output[output_length + 2] = '\0';
1027 /* Invoke print_string_ptr (which is useful) on an item. */
1028 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1030 return print_string_ptr((unsigned char*)item->valuestring, p);
1033 /* Predeclare these prototypes. */
1034 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1035 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1036 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1037 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1038 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1039 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1041 /* Utility to jump whitespace and cr/lf */
1042 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1044 if ((buffer == NULL) || (buffer->content == NULL))
1049 if (cannot_access_at_index(buffer, 0))
1054 while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1059 if (buffer->offset == buffer->length)
1067 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1068 static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1070 if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1075 if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1077 buffer->offset += 3;
1083 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1085 size_t buffer_length;
1092 /* Adding null character size due to require_null_terminated. */
1093 buffer_length = strlen(value) + sizeof("");
1095 return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1098 /* Parse an object - create a new root, and populate. */
1099 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1101 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1104 /* reset error position */
1105 global_error.json = NULL;
1106 global_error.position = 0;
1108 if (value == NULL || 0 == buffer_length)
1113 buffer.content = (const unsigned char*)value;
1114 buffer.length = buffer_length;
1116 buffer.hooks = global_hooks;
1118 item = cJSON_New_Item(&global_hooks);
1119 if (item == NULL) /* memory fail */
1124 if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1126 /* parse failure. ep is set. */
1130 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1131 if (require_null_terminated)
1133 buffer_skip_whitespace(&buffer);
1134 if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1139 if (return_parse_end)
1141 *return_parse_end = (const char*)buffer_at_offset(&buffer);
1155 local_error.json = (const unsigned char*)value;
1156 local_error.position = 0;
1158 if (buffer.offset < buffer.length)
1160 local_error.position = buffer.offset;
1162 else if (buffer.length > 0)
1164 local_error.position = buffer.length - 1;
1167 if (return_parse_end != NULL)
1169 *return_parse_end = (const char*)local_error.json + local_error.position;
1172 global_error = local_error;
1178 /* Default options for cJSON_Parse */
1179 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1181 return cJSON_ParseWithOpts(value, 0, 0);
1184 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1186 return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1189 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1191 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1193 static const size_t default_buffer_size = 256;
1194 printbuffer buffer[1];
1195 unsigned char *printed = NULL;
1197 memset(buffer, 0, sizeof(buffer));
1200 buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1201 buffer->length = default_buffer_size;
1202 buffer->format = format;
1203 buffer->hooks = *hooks;
1204 if (buffer->buffer == NULL)
1209 /* print the value */
1210 if (!print_value(item, buffer))
1214 update_offset(buffer);
1216 /* check if reallocate is available */
1217 if (hooks->reallocate != NULL)
1219 printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1, default_buffer_size);
1220 if (printed == NULL) {
1223 buffer->buffer = NULL;
1225 else /* otherwise copy the JSON over to a new buffer */
1227 printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1228 if (printed == NULL)
1232 memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1233 printed[buffer->offset] = '\0'; /* just to be sure */
1235 /* free the buffer */
1236 hooks->deallocate(buffer->buffer);
1242 if (buffer->buffer != NULL)
1244 hooks->deallocate(buffer->buffer);
1247 if (printed != NULL)
1249 hooks->deallocate(printed);
1255 /* Render a cJSON item/entity/structure to text. */
1256 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1258 return (char*)print(item, true, &global_hooks);
1261 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1263 return (char*)print(item, false, &global_hooks);
1266 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1268 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1275 p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1281 p.length = (size_t)prebuffer;
1285 p.hooks = global_hooks;
1287 if (!print_value(item, &p))
1289 global_hooks.deallocate(p.buffer);
1293 return (char*)p.buffer;
1296 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1298 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1300 if ((length < 0) || (buffer == NULL))
1305 p.buffer = (unsigned char*)buffer;
1306 p.length = (size_t)length;
1310 p.hooks = global_hooks;
1312 return print_value(item, &p);
1315 /* Parser core - when encountering text, process appropriately. */
1316 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1318 if ((input_buffer == NULL) || (input_buffer->content == NULL))
1320 return false; /* no input */
1323 /* parse the different types of values */
1325 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1327 item->type = cJSON_NULL;
1328 input_buffer->offset += 4;
1332 if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1334 item->type = cJSON_False;
1335 input_buffer->offset += 5;
1339 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1341 item->type = cJSON_True;
1343 input_buffer->offset += 4;
1347 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1349 return parse_string(item, input_buffer);
1352 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'))))
1354 return parse_number(item, input_buffer);
1357 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1359 return parse_array(item, input_buffer);
1362 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1364 return parse_object(item, input_buffer);
1370 /* Render a value to text. */
1371 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1373 unsigned char *output = NULL;
1375 if ((item == NULL) || (output_buffer == NULL))
1380 switch ((item->type) & 0xFF)
1383 output = ensure(output_buffer, 5);
1388 strcpy((char*)output, "null");
1392 output = ensure(output_buffer, 6);
1397 strcpy((char*)output, "false");
1401 output = ensure(output_buffer, 5);
1406 strcpy((char*)output, "true");
1410 return print_number(item, output_buffer);
1414 size_t raw_length = 0;
1415 if (item->valuestring == NULL)
1420 raw_length = strlen(item->valuestring) + sizeof("");
1421 output = ensure(output_buffer, raw_length);
1426 memcpy(output, item->valuestring, raw_length);
1431 return print_string(item, output_buffer);
1434 return print_array(item, output_buffer);
1437 return print_object(item, output_buffer);
1444 /* Build an array from input text. */
1445 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1447 cJSON *head = NULL; /* head of the linked list */
1448 cJSON *current_item = NULL;
1450 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1452 return false; /* to deeply nested */
1454 input_buffer->depth++;
1456 if (buffer_at_offset(input_buffer)[0] != '[')
1462 input_buffer->offset++;
1463 buffer_skip_whitespace(input_buffer);
1464 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1470 /* check if we skipped to the end of the buffer */
1471 if (cannot_access_at_index(input_buffer, 0))
1473 input_buffer->offset--;
1477 /* step back to character in front of the first element */
1478 input_buffer->offset--;
1479 /* loop through the comma separated array elements */
1482 /* allocate next item */
1483 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1484 if (new_item == NULL)
1486 goto fail; /* allocation failure */
1489 /* attach next item to list */
1492 /* start the linked list */
1493 current_item = head = new_item;
1497 /* add to the end and advance */
1498 current_item->next = new_item;
1499 new_item->prev = current_item;
1500 current_item = new_item;
1503 /* parse next value */
1504 input_buffer->offset++;
1505 buffer_skip_whitespace(input_buffer);
1506 if (!parse_value(current_item, input_buffer))
1508 goto fail; /* failed to parse value */
1510 buffer_skip_whitespace(input_buffer);
1512 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1514 if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1516 goto fail; /* expected end of array */
1520 input_buffer->depth--;
1523 head->prev = current_item;
1526 item->type = cJSON_Array;
1529 input_buffer->offset++;
1542 /* Render an array to text */
1543 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1545 unsigned char *output_pointer = NULL;
1547 cJSON *current_element = item->child;
1549 if (output_buffer == NULL)
1554 /* Compose the output array. */
1555 /* opening square bracket */
1556 output_pointer = ensure(output_buffer, 1);
1557 if (output_pointer == NULL)
1562 *output_pointer = '[';
1563 output_buffer->offset++;
1564 output_buffer->depth++;
1566 while (current_element != NULL)
1568 if (!print_value(current_element, output_buffer))
1572 update_offset(output_buffer);
1573 if (current_element->next)
1575 length = (size_t) (output_buffer->format ? 2 : 1);
1576 output_pointer = ensure(output_buffer, length + 1);
1577 if (output_pointer == NULL)
1581 *output_pointer++ = ',';
1582 if(output_buffer->format)
1584 *output_pointer++ = ' ';
1586 *output_pointer = '\0';
1587 output_buffer->offset += length;
1589 current_element = current_element->next;
1592 output_pointer = ensure(output_buffer, 2);
1593 if (output_pointer == NULL)
1597 *output_pointer++ = ']';
1598 *output_pointer = '\0';
1599 output_buffer->depth--;
1604 /* Build an object from the text. */
1605 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1607 cJSON *head = NULL; /* linked list head */
1608 cJSON *current_item = NULL;
1610 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1612 return false; /* to deeply nested */
1614 input_buffer->depth++;
1616 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1618 goto fail; /* not an object */
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] == '}'))
1625 goto success; /* empty object */
1628 /* check if we skipped to the end of the buffer */
1629 if (cannot_access_at_index(input_buffer, 0))
1631 input_buffer->offset--;
1635 /* step back to character in front of the first element */
1636 input_buffer->offset--;
1637 /* loop through the comma separated array elements */
1640 /* allocate next item */
1641 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1642 if (new_item == NULL)
1644 goto fail; /* allocation failure */
1647 /* attach next item to list */
1650 /* start the linked list */
1651 current_item = head = new_item;
1655 /* add to the end and advance */
1656 current_item->next = new_item;
1657 new_item->prev = current_item;
1658 current_item = new_item;
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))
1666 goto fail; /* failed to parse name */
1668 buffer_skip_whitespace(input_buffer);
1670 /* swap valuestring and string, because we parsed the name */
1671 current_item->string = current_item->valuestring;
1672 current_item->valuestring = NULL;
1674 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1676 goto fail; /* invalid object */
1679 /* parse the value */
1680 input_buffer->offset++;
1681 buffer_skip_whitespace(input_buffer);
1682 if (!parse_value(current_item, input_buffer))
1684 goto fail; /* failed to parse value */
1686 buffer_skip_whitespace(input_buffer);
1688 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1690 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1692 goto fail; /* expected end of object */
1696 input_buffer->depth--;
1699 head->prev = current_item;
1702 item->type = cJSON_Object;
1705 input_buffer->offset++;
1717 /* Render an object to text. */
1718 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1720 unsigned char *output_pointer = NULL;
1722 cJSON *current_item = item->child;
1724 if (output_buffer == NULL)
1729 /* Compose the output: */
1730 length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1731 output_pointer = ensure(output_buffer, length + 1);
1732 if (output_pointer == NULL)
1737 *output_pointer++ = '{';
1738 output_buffer->depth++;
1739 if (output_buffer->format)
1741 *output_pointer++ = '\n';
1743 output_buffer->offset += length;
1745 while (current_item)
1747 if (output_buffer->format)
1750 output_pointer = ensure(output_buffer, output_buffer->depth);
1751 if (output_pointer == NULL)
1755 for (i = 0; i < output_buffer->depth; i++)
1757 *output_pointer++ = '\t';
1759 output_buffer->offset += output_buffer->depth;
1763 if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1767 update_offset(output_buffer);
1769 length = (size_t) (output_buffer->format ? 2 : 1);
1770 output_pointer = ensure(output_buffer, length);
1771 if (output_pointer == NULL)
1775 *output_pointer++ = ':';
1776 if (output_buffer->format)
1778 *output_pointer++ = '\t';
1780 output_buffer->offset += length;
1783 if (!print_value(current_item, output_buffer))
1787 update_offset(output_buffer);
1789 /* print comma if not last */
1790 length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1791 output_pointer = ensure(output_buffer, length + 1);
1792 if (output_pointer == NULL)
1796 if (current_item->next)
1798 *output_pointer++ = ',';
1801 if (output_buffer->format)
1803 *output_pointer++ = '\n';
1805 *output_pointer = '\0';
1806 output_buffer->offset += length;
1808 current_item = current_item->next;
1811 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1812 if (output_pointer == NULL)
1816 if (output_buffer->format)
1819 for (i = 0; i < (output_buffer->depth - 1); i++)
1821 *output_pointer++ = '\t';
1824 *output_pointer++ = '}';
1825 *output_pointer = '\0';
1826 output_buffer->depth--;
1831 /* Get Array size/item / object item. */
1832 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1834 cJSON *child = NULL;
1842 child = array->child;
1844 while(child != NULL)
1847 child = child->next;
1850 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1855 static cJSON* get_array_item(const cJSON *array, size_t index)
1857 cJSON *current_child = NULL;
1864 current_child = array->child;
1865 while ((current_child != NULL) && (index > 0))
1868 current_child = current_child->next;
1871 return current_child;
1874 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1881 return get_array_item(array, (size_t)index);
1884 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1886 cJSON *current_element = NULL;
1888 if ((object == NULL) || (name == NULL))
1893 current_element = object->child;
1896 while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1898 current_element = current_element->next;
1903 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1905 current_element = current_element->next;
1909 if ((current_element == NULL) || (current_element->string == NULL)) {
1913 return current_element;
1916 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1918 return get_object_item(object, string, false);
1921 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1923 return get_object_item(object, string, true);
1926 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1928 return cJSON_GetObjectItem(object, string) ? 1 : 0;
1931 /* Utility for array list handling. */
1932 static void suffix_object(cJSON *prev, cJSON *item)
1938 /* Utility for handling references. */
1939 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1941 cJSON *reference = NULL;
1947 reference = cJSON_New_Item(hooks);
1948 if (reference == NULL)
1953 memcpy(reference, item, sizeof(cJSON));
1954 reference->string = NULL;
1955 reference->type |= cJSON_IsReference;
1956 reference->next = reference->prev = NULL;
1960 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1962 cJSON *child = NULL;
1964 if ((item == NULL) || (array == NULL) || (array == item))
1969 child = array->child;
1971 * To find the last item in array quickly, we use prev in array
1975 /* list is empty, start new one */
1976 array->child = item;
1982 /* append to the end */
1985 suffix_object(child->prev, item);
1986 array->child->prev = item;
1993 /* Add item to array/object. */
1994 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1996 return add_item_to_array(array, item);
1999 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2000 #pragma GCC diagnostic push
2003 #pragma GCC diagnostic ignored "-Wcast-qual"
2005 /* helper function to cast away const */
2006 static void* cast_away_const(const void* string)
2008 return (void*)string;
2010 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2011 #pragma GCC diagnostic pop
2015 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)
2017 char *new_key = NULL;
2018 int new_type = cJSON_Invalid;
2020 if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2027 new_key = (char*)cast_away_const(string);
2028 new_type = item->type | cJSON_StringIsConst;
2032 new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2033 if (new_key == NULL)
2038 new_type = item->type & ~cJSON_StringIsConst;
2041 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2043 hooks->deallocate(item->string);
2046 item->string = new_key;
2047 item->type = new_type;
2049 return add_item_to_array(object, item);
2052 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2054 return add_item_to_object(object, string, item, &global_hooks, false);
2057 /* Add an item to an object with constant string as key */
2058 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2060 return add_item_to_object(object, string, item, &global_hooks, true);
2063 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2070 return add_item_to_array(array, create_reference(item, &global_hooks));
2073 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2075 if ((object == NULL) || (string == NULL))
2080 return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2083 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2085 cJSON *null = cJSON_CreateNull();
2086 if (add_item_to_object(object, name, null, &global_hooks, false))
2095 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2097 cJSON *true_item = cJSON_CreateTrue();
2098 if (add_item_to_object(object, name, true_item, &global_hooks, false))
2103 cJSON_Delete(true_item);
2107 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2109 cJSON *false_item = cJSON_CreateFalse();
2110 if (add_item_to_object(object, name, false_item, &global_hooks, false))
2115 cJSON_Delete(false_item);
2119 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2121 cJSON *bool_item = cJSON_CreateBool(boolean);
2122 if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2127 cJSON_Delete(bool_item);
2131 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2133 cJSON *number_item = cJSON_CreateNumber(number);
2134 if (add_item_to_object(object, name, number_item, &global_hooks, false))
2139 cJSON_Delete(number_item);
2143 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2145 cJSON *string_item = cJSON_CreateString(string);
2146 if (add_item_to_object(object, name, string_item, &global_hooks, false))
2151 cJSON_Delete(string_item);
2155 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2157 cJSON *raw_item = cJSON_CreateRaw(raw);
2158 if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2163 cJSON_Delete(raw_item);
2167 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2169 cJSON *object_item = cJSON_CreateObject();
2170 if (add_item_to_object(object, name, object_item, &global_hooks, false))
2175 cJSON_Delete(object_item);
2179 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2181 cJSON *array = cJSON_CreateArray();
2182 if (add_item_to_object(object, name, array, &global_hooks, false))
2187 cJSON_Delete(array);
2191 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2193 if ((parent == NULL) || (item == NULL))
2198 if (item != parent->child)
2200 /* not the first element */
2201 item->prev->next = item->next;
2203 if (item->next != NULL)
2205 /* not the last element */
2206 item->next->prev = item->prev;
2209 if (item == parent->child)
2212 parent->child = item->next;
2214 else if (item->next == NULL)
2217 parent->child->prev = item->prev;
2220 /* make sure the detached item doesn't point anywhere anymore */
2227 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2234 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2237 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2239 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2242 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2244 cJSON *to_detach = cJSON_GetObjectItem(object, string);
2246 return cJSON_DetachItemViaPointer(object, to_detach);
2249 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2251 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2253 return cJSON_DetachItemViaPointer(object, to_detach);
2256 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2258 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2261 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2263 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2266 /* Replace array/object items with new ones. */
2267 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2269 cJSON *after_inserted = NULL;
2276 after_inserted = get_array_item(array, (size_t)which);
2277 if (after_inserted == NULL)
2279 return add_item_to_array(array, newitem);
2282 newitem->next = after_inserted;
2283 newitem->prev = after_inserted->prev;
2284 after_inserted->prev = newitem;
2285 if (after_inserted == array->child)
2287 array->child = newitem;
2291 newitem->prev->next = newitem;
2296 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2298 if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2303 if (replacement == item)
2308 replacement->next = item->next;
2309 replacement->prev = item->prev;
2311 if (replacement->next != NULL)
2313 replacement->next->prev = replacement;
2315 if (parent->child == item)
2317 if (parent->child->prev == parent->child)
2319 replacement->prev = replacement;
2321 parent->child = replacement;
2325 * To find the last item in array quickly, we use prev in array.
2326 * We can't modify the last item's next pointer where this item was the parent's child
2328 if (replacement->prev != NULL)
2330 replacement->prev->next = replacement;
2332 if (replacement->next == NULL)
2334 parent->child->prev = replacement;
2345 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2352 return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2355 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2357 if ((replacement == NULL) || (string == NULL))
2362 /* replace the name in the replacement */
2363 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2365 cJSON_free(replacement->string);
2367 replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2368 replacement->type &= ~cJSON_StringIsConst;
2370 return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2373 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2375 return replace_item_in_object(object, string, newitem, false);
2378 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2380 return replace_item_in_object(object, string, newitem, true);
2383 /* Create basic types: */
2384 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2386 cJSON *item = cJSON_New_Item(&global_hooks);
2389 item->type = cJSON_NULL;
2395 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2397 cJSON *item = cJSON_New_Item(&global_hooks);
2400 item->type = cJSON_True;
2406 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2408 cJSON *item = cJSON_New_Item(&global_hooks);
2411 item->type = cJSON_False;
2417 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2419 cJSON *item = cJSON_New_Item(&global_hooks);
2422 item->type = boolean ? cJSON_True : cJSON_False;
2428 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2430 cJSON *item = cJSON_New_Item(&global_hooks);
2433 item->type = cJSON_Number;
2434 item->valuedouble = num;
2436 /* use saturation in case of overflow */
2439 item->valueint = INT_MAX;
2441 else if (num <= (double)INT_MIN)
2443 item->valueint = INT_MIN;
2447 item->valueint = (int)num;
2454 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2456 cJSON *item = cJSON_New_Item(&global_hooks);
2459 item->type = cJSON_String;
2460 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2461 if(!item->valuestring)
2471 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2473 cJSON *item = cJSON_New_Item(&global_hooks);
2476 item->type = cJSON_String | cJSON_IsReference;
2477 item->valuestring = (char*)cast_away_const(string);
2483 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2485 cJSON *item = cJSON_New_Item(&global_hooks);
2487 item->type = cJSON_Object | cJSON_IsReference;
2488 item->child = (cJSON*)cast_away_const(child);
2494 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2495 cJSON *item = cJSON_New_Item(&global_hooks);
2497 item->type = cJSON_Array | cJSON_IsReference;
2498 item->child = (cJSON*)cast_away_const(child);
2504 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2506 cJSON *item = cJSON_New_Item(&global_hooks);
2509 item->type = cJSON_Raw;
2510 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2511 if(!item->valuestring)
2521 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2523 cJSON *item = cJSON_New_Item(&global_hooks);
2526 item->type=cJSON_Array;
2532 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2534 cJSON *item = cJSON_New_Item(&global_hooks);
2537 item->type = cJSON_Object;
2543 /* Create Arrays: */
2544 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2551 if ((count < 0) || (numbers == NULL))
2556 a = cJSON_CreateArray();
2558 for(i = 0; a && (i < (size_t)count); i++)
2560 n = cJSON_CreateNumber(numbers[i]);
2572 suffix_object(p, n);
2585 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2592 if ((count < 0) || (numbers == NULL))
2597 a = cJSON_CreateArray();
2599 for(i = 0; a && (i < (size_t)count); i++)
2601 n = cJSON_CreateNumber((double)numbers[i]);
2613 suffix_object(p, n);
2626 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2633 if ((count < 0) || (numbers == NULL))
2638 a = cJSON_CreateArray();
2640 for (i = 0; a && (i < (size_t) count); i++)
2642 n = cJSON_CreateNumber(numbers[i]);
2654 suffix_object(p, n);
2667 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2674 if ((count < 0) || (strings == NULL))
2679 a = cJSON_CreateArray();
2681 for (i = 0; a && (i < (size_t)count); i++)
2683 n = cJSON_CreateString(strings[i]);
2709 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2711 cJSON *newitem = NULL;
2712 cJSON *child = NULL;
2714 cJSON *newchild = NULL;
2716 /* Bail on bad ptr */
2721 /* Create new item */
2722 newitem = cJSON_New_Item(&global_hooks);
2727 /* Copy over all vars */
2728 newitem->type = item->type & (~cJSON_IsReference);
2729 newitem->valueint = item->valueint;
2730 newitem->valuedouble = item->valuedouble;
2731 if (item->valuestring)
2733 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2734 if (!newitem->valuestring)
2741 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2742 if (!newitem->string)
2747 /* If non-recursive, then we're done! */
2752 /* Walk the ->next chain for the child. */
2753 child = item->child;
2754 while (child != NULL)
2756 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2763 /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2764 next->next = newchild;
2765 newchild->prev = next;
2770 /* Set newitem->child and move to it */
2771 newitem->child = newchild;
2774 child = child->next;
2776 if (newitem && newitem->child)
2778 newitem->child->prev = newchild;
2784 if (newitem != NULL)
2786 cJSON_Delete(newitem);
2792 static void skip_oneline_comment(char **input)
2794 *input += static_strlen("//");
2796 for (; (*input)[0] != '\0'; ++(*input))
2798 if ((*input)[0] == '\n') {
2799 *input += static_strlen("\n");
2805 static void skip_multiline_comment(char **input)
2807 *input += static_strlen("/*");
2809 for (; (*input)[0] != '\0'; ++(*input))
2811 if (((*input)[0] == '*') && ((*input)[1] == '/'))
2813 *input += static_strlen("*/");
2819 static void minify_string(char **input, char **output) {
2820 (*output)[0] = (*input)[0];
2821 *input += static_strlen("\"");
2822 *output += static_strlen("\"");
2825 for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2826 (*output)[0] = (*input)[0];
2828 if ((*input)[0] == '\"') {
2829 (*output)[0] = '\"';
2830 *input += static_strlen("\"");
2831 *output += static_strlen("\"");
2833 } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2834 (*output)[1] = (*input)[1];
2835 *input += static_strlen("\"");
2836 *output += static_strlen("\"");
2841 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2850 while (json[0] != '\0')
2864 skip_oneline_comment(&json);
2866 else if (json[1] == '*')
2868 skip_multiline_comment(&json);
2875 minify_string(&json, (char**)&into);
2885 /* and null-terminate. */
2889 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2896 return (item->type & 0xFF) == cJSON_Invalid;
2899 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2906 return (item->type & 0xFF) == cJSON_False;
2909 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2916 return (item->type & 0xff) == cJSON_True;
2920 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2927 return (item->type & (cJSON_True | cJSON_False)) != 0;
2929 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2936 return (item->type & 0xFF) == cJSON_NULL;
2939 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2946 return (item->type & 0xFF) == cJSON_Number;
2949 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2956 return (item->type & 0xFF) == cJSON_String;
2959 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2966 return (item->type & 0xFF) == cJSON_Array;
2969 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2976 return (item->type & 0xFF) == cJSON_Object;
2979 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2986 return (item->type & 0xFF) == cJSON_Raw;
2989 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2991 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2996 /* check if type is valid */
2997 switch (a->type & 0xFF)
3013 /* identical objects are equal */
3019 switch (a->type & 0xFF)
3021 /* in these cases and equal type is enough */
3028 if (compare_double(a->valuedouble, b->valuedouble))
3036 if ((a->valuestring == NULL) || (b->valuestring == NULL))
3040 if (strcmp(a->valuestring, b->valuestring) == 0)
3049 cJSON *a_element = a->child;
3050 cJSON *b_element = b->child;
3052 for (; (a_element != NULL) && (b_element != NULL);)
3054 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3059 a_element = a_element->next;
3060 b_element = b_element->next;
3063 /* one of the arrays is longer than the other */
3064 if (a_element != b_element) {
3073 cJSON *a_element = NULL;
3074 cJSON *b_element = NULL;
3075 cJSON_ArrayForEach(a_element, a)
3077 /* TODO This has O(n^2) runtime, which is horrible! */
3078 b_element = get_object_item(b, a_element->string, case_sensitive);
3079 if (b_element == NULL)
3084 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3090 /* doing this twice, once on a and b to prevent true comparison if a subset of b
3091 * TODO: Do this the proper way, this is just a fix for now */
3092 cJSON_ArrayForEach(b_element, b)
3094 a_element = get_object_item(a, b_element->string, case_sensitive);
3095 if (a_element == NULL)
3100 if (!cJSON_Compare(b_element, a_element, case_sensitive))
3114 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3116 return global_hooks.allocate(size);
3119 CJSON_PUBLIC(void) cJSON_free(void *object)
3121 global_hooks.deallocate(object);
3124 CJSON_PUBLIC(void *) cJSON_realloc(void *object, size_t new_size, size_t old_size)
3126 return global_hooks.reallocate(object, new_size, old_size);