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
24 /* JSON parser in C. */
27 #pragma GCC visibility push(default)
40 #pragma GCC visibility pop
45 /* define our own boolean type */
46 //#define true ((cJSON_bool)1)
47 //#define false ((cJSON_bool)0)
50 const unsigned char *json;
53 static cJSON_error global_error = { NULL, 0 };
55 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
57 return (const char*) (global_error.json + global_error.position);
60 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
61 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 9)
62 #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
65 CJSON_PUBLIC(const char*) cJSON_Version(void)
67 static char version[15];
68 sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
73 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
74 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
76 if ((string1 == NULL) || (string2 == NULL))
81 if (string1 == string2)
86 for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
94 return tolower(*string1) - tolower(*string2);
97 typedef struct internal_hooks
99 void *(*allocate)(size_t size);
100 void (*deallocate)(void *pointer);
101 void *(*reallocate)(void *pointer, size_t size);
104 static internal_hooks global_hooks = { malloc, free, realloc };
106 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
109 unsigned char *copy = NULL;
116 length = strlen((const char*)string) + sizeof("");
117 if (!(copy = (unsigned char*)hooks->allocate(length)))
121 memcpy(copy, string, length);
126 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
131 global_hooks.allocate = malloc;
132 global_hooks.deallocate = free;
133 global_hooks.reallocate = realloc;
137 global_hooks.allocate = malloc;
138 if (hooks->malloc_fn != NULL)
140 global_hooks.allocate = hooks->malloc_fn;
143 global_hooks.deallocate = free;
144 if (hooks->free_fn != NULL)
146 global_hooks.deallocate = hooks->free_fn;
149 /* use realloc only if both free and malloc are used */
150 global_hooks.reallocate = NULL;
151 if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
153 global_hooks.reallocate = realloc;
157 /* Internal constructor. */
158 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
160 cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
163 memset(node, '\0', sizeof(cJSON));
169 /* Delete a cJSON structure. */
170 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
176 if (!(item->type & cJSON_IsReference) && (item->child != NULL))
178 cJSON_Delete(item->child);
180 if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
182 global_hooks.deallocate(item->valuestring);
184 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
186 global_hooks.deallocate(item->string);
188 global_hooks.deallocate(item);
193 /* get the decimal point character of the current locale */
194 static unsigned char get_decimal_point(void)
196 struct lconv *lconv = localeconv();
197 return (unsigned char) lconv->decimal_point[0];
202 const unsigned char *content;
205 size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
206 internal_hooks hooks;
209 /* check if the given size is left to read in a given parse buffer (starting with 1) */
210 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
211 #define cannot_read(buffer, size) (!can_read(buffer, size))
212 /* check if the buffer can be accessed at the given index (starting with 0) */
213 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
214 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
215 /* get a pointer to the buffer at the position */
216 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
218 /* Parse the input text to generate a number, and populate the result into item. */
219 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
222 unsigned char *after_end = NULL;
223 unsigned char number_c_string[64];
224 unsigned char decimal_point = get_decimal_point();
227 if ((input_buffer == NULL) || (input_buffer->content == NULL))
232 /* copy the number into a temporary buffer and replace '.' with the decimal point
233 * of the current locale (for strtod)
234 * This also takes care of '\0' not necessarily being available for marking the end of the input */
235 for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
237 switch (buffer_at_offset(input_buffer)[i])
253 number_c_string[i] = buffer_at_offset(input_buffer)[i];
257 number_c_string[i] = decimal_point;
265 number_c_string[i] = '\0';
267 number = strtod((const char*)number_c_string, (char**)&after_end);
268 if (number_c_string == after_end)
270 return false; /* parse_error */
273 item->valuedouble = number;
275 /* use saturation in case of overflow */
276 if (number >= INT_MAX)
278 item->valueint = INT_MAX;
280 else if (number <= INT_MIN)
282 item->valueint = INT_MIN;
286 item->valueint = (int)number;
289 item->type = cJSON_Number;
291 input_buffer->offset += (size_t)(after_end - number_c_string);
295 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
296 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
298 if (number >= INT_MAX)
300 object->valueint = INT_MAX;
302 else if (number <= INT_MIN)
304 object->valueint = INT_MIN;
308 object->valueint = (int)number;
311 return object->valuedouble = number;
316 unsigned char *buffer;
319 size_t depth; /* current nesting depth (for formatted printing) */
321 cJSON_bool format; /* is this print a formatted print */
322 internal_hooks hooks;
325 /* realloc printbuffer if necessary to have at least "needed" bytes more */
326 static unsigned char* ensure(printbuffer * const p, size_t needed)
328 unsigned char *newbuffer = NULL;
331 if ((p == NULL) || (p->buffer == NULL))
336 if ((p->length > 0) && (p->offset >= p->length))
338 /* make sure that offset is valid */
342 if (needed > INT_MAX)
344 /* sizes bigger than INT_MAX are currently not supported */
348 needed += p->offset + 1;
349 if (needed <= p->length)
351 return p->buffer + p->offset;
358 /* calculate new buffer size */
359 if (needed > (INT_MAX / 2))
361 /* overflow of int, use INT_MAX if possible */
362 if (needed <= INT_MAX)
373 newsize = needed * 2;
376 if (p->hooks.reallocate != NULL)
378 /* reallocate with realloc if available */
379 newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
380 if (newbuffer == NULL)
382 p->hooks.deallocate(p->buffer);
391 /* otherwise reallocate manually */
392 newbuffer = (unsigned char*)p->hooks.allocate(newsize);
395 p->hooks.deallocate(p->buffer);
403 memcpy(newbuffer, p->buffer, p->offset + 1);
405 p->hooks.deallocate(p->buffer);
408 p->buffer = newbuffer;
410 return newbuffer + p->offset;
413 /* calculate the new length of the string in a printbuffer and update the offset */
414 static void update_offset(printbuffer * const buffer)
416 const unsigned char *buffer_pointer = NULL;
417 if ((buffer == NULL) || (buffer->buffer == NULL))
421 buffer_pointer = buffer->buffer + buffer->offset;
423 buffer->offset += strlen((const char*)buffer_pointer);
426 /* Render the number nicely from the given item into a string. */
427 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
429 unsigned char *output_pointer = NULL;
430 double d = item->valuedouble;
433 unsigned char number_buffer[26]; /* temporary buffer to print the number into */
434 unsigned char decimal_point = get_decimal_point();
437 if (output_buffer == NULL)
442 /* This checks for NaN and Infinity */
445 length = sprintf((char*)number_buffer, "null");
449 /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
450 length = sprintf((char*)number_buffer, "%1.15g", d);
452 /* Check whether the original double can be recovered */
453 if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
455 /* If not, print with 17 decimal places of precision */
456 length = sprintf((char*)number_buffer, "%1.17g", d);
460 /* sprintf failed or buffer overrun occured */
461 if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
466 /* reserve appropriate space in the output */
467 output_pointer = ensure(output_buffer, (size_t)length);
468 if (output_pointer == NULL)
473 /* copy the printed number to the output and replace locale
474 * dependent decimal point with '.' */
475 for (i = 0; i < ((size_t)length); i++)
477 if (number_buffer[i] == decimal_point)
479 output_pointer[i] = '.';
483 output_pointer[i] = number_buffer[i];
485 output_pointer[i] = '\0';
487 output_buffer->offset += (size_t)length;
492 /* parse 4 digit hexadecimal number */
493 static unsigned parse_hex4(const unsigned char * const input)
498 for (i = 0; i < 4; i++)
501 if ((input[i] >= '0') && (input[i] <= '9'))
503 h += (unsigned int) input[i] - '0';
505 else if ((input[i] >= 'A') && (input[i] <= 'F'))
507 h += (unsigned int) 10 + input[i] - 'A';
509 else if ((input[i] >= 'a') && (input[i] <= 'f'))
511 h += (unsigned int) 10 + input[i] - 'a';
520 /* shift left to make place for the next nibble */
528 /* converts a UTF-16 literal to UTF-8
529 * A literal can be one or two sequences of the form \uXXXX */
530 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
532 long unsigned int codepoint = 0;
533 unsigned int first_code = 0;
534 const unsigned char *first_sequence = input_pointer;
535 unsigned char utf8_length = 0;
536 unsigned char utf8_position = 0;
537 unsigned char sequence_length = 0;
538 unsigned char first_byte_mark = 0;
540 if ((input_end - first_sequence) < 6)
542 /* input ends unexpectedly */
546 /* get the first utf16 sequence */
547 first_code = parse_hex4(first_sequence + 2);
549 /* check that the code is valid */
550 if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
555 /* UTF16 surrogate pair */
556 if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
558 const unsigned char *second_sequence = first_sequence + 6;
559 unsigned int second_code = 0;
560 sequence_length = 12; /* \uXXXX\uXXXX */
562 if ((input_end - second_sequence) < 6)
564 /* input ends unexpectedly */
568 if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
570 /* missing second half of the surrogate pair */
574 /* get the second utf16 sequence */
575 second_code = parse_hex4(second_sequence + 2);
576 /* check that the code is valid */
577 if ((second_code < 0xDC00) || (second_code > 0xDFFF))
579 /* invalid second half of the surrogate pair */
584 /* calculate the unicode codepoint from the surrogate pair */
585 codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
589 sequence_length = 6; /* \uXXXX */
590 codepoint = first_code;
594 * takes at maximum 4 bytes to encode:
595 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
596 if (codepoint < 0x80)
598 /* normal ascii, encoding 0xxxxxxx */
601 else if (codepoint < 0x800)
603 /* two bytes, encoding 110xxxxx 10xxxxxx */
605 first_byte_mark = 0xC0; /* 11000000 */
607 else if (codepoint < 0x10000)
609 /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
611 first_byte_mark = 0xE0; /* 11100000 */
613 else if (codepoint <= 0x10FFFF)
615 /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
617 first_byte_mark = 0xF0; /* 11110000 */
621 /* invalid unicode codepoint */
626 for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
629 (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
632 /* encode first byte */
635 (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
639 (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
642 *output_pointer += utf8_length;
644 return sequence_length;
650 /* Parse the input text into an unescaped cinput, and populate item. */
651 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
653 const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
654 const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
655 unsigned char *output_pointer = NULL;
656 unsigned char *output = NULL;
659 if (buffer_at_offset(input_buffer)[0] != '\"')
665 /* calculate approximate size of the output (overestimate) */
666 size_t allocation_length = 0;
667 size_t skipped_bytes = 0;
668 while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
670 /* is escape sequence */
671 if (input_end[0] == '\\')
673 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
675 /* prevent buffer overflow when last input character is a backslash */
683 if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
685 goto fail; /* string ended unexpectedly */
688 /* This is at most how much we need for the output */
689 allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
690 output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
693 goto fail; /* allocation failure */
697 output_pointer = output;
698 /* loop through the string literal */
699 while (input_pointer < input_end)
701 if (*input_pointer != '\\')
703 *output_pointer++ = *input_pointer++;
705 /* escape sequence */
708 unsigned char sequence_length = 2;
709 if ((input_end - input_pointer) < 1)
714 switch (input_pointer[1])
717 *output_pointer++ = '\b';
720 *output_pointer++ = '\f';
723 *output_pointer++ = '\n';
726 *output_pointer++ = '\r';
729 *output_pointer++ = '\t';
734 *output_pointer++ = input_pointer[1];
739 sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
740 if (sequence_length == 0)
742 /* failed to convert UTF16-literal to UTF-8 */
750 input_pointer += sequence_length;
754 /* zero terminate the output */
755 *output_pointer = '\0';
757 item->type = cJSON_String;
758 item->valuestring = (char*)output;
760 input_buffer->offset = (size_t) (input_end - input_buffer->content);
761 input_buffer->offset++;
768 input_buffer->hooks.deallocate(output);
771 if (input_pointer != NULL)
773 input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
779 /* Render the cstring provided to an escaped version that can be printed. */
780 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
782 const unsigned char *input_pointer = NULL;
783 unsigned char *output = NULL;
784 unsigned char *output_pointer = NULL;
785 size_t output_length = 0;
786 /* numbers of additional characters needed for escaping */
787 size_t escape_characters = 0;
789 if (output_buffer == NULL)
797 output = ensure(output_buffer, sizeof("\"\""));
802 strcpy((char*)output, "\"\"");
807 /* set "flag" to 1 if something needs to be escaped */
808 for (input_pointer = input; *input_pointer; input_pointer++)
810 switch (*input_pointer)
819 /* one character escape sequence */
823 if (*input_pointer < 32)
825 /* UTF-16 escape sequence uXXXX */
826 escape_characters += 5;
831 output_length = (size_t)(input_pointer - input) + escape_characters;
833 output = ensure(output_buffer, output_length + sizeof("\"\""));
839 /* no characters have to be escaped */
840 if (escape_characters == 0)
843 memcpy(output + 1, input, output_length);
844 output[output_length + 1] = '\"';
845 output[output_length + 2] = '\0';
851 output_pointer = output + 1;
852 /* copy the string */
853 for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
855 if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
857 /* normal character, copy */
858 *output_pointer = *input_pointer;
862 /* character needs to be escaped */
863 *output_pointer++ = '\\';
864 switch (*input_pointer)
867 *output_pointer = '\\';
870 *output_pointer = '\"';
873 *output_pointer = 'b';
876 *output_pointer = 'f';
879 *output_pointer = 'n';
882 *output_pointer = 'r';
885 *output_pointer = 't';
888 /* escape and print as unicode codepoint */
889 sprintf((char*)output_pointer, "u%04x", *input_pointer);
895 output[output_length + 1] = '\"';
896 output[output_length + 2] = '\0';
901 /* Invoke print_string_ptr (which is useful) on an item. */
902 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
904 return print_string_ptr((unsigned char*)item->valuestring, p);
907 /* Predeclare these prototypes. */
908 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
909 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
910 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
911 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
912 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
913 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
915 /* Utility to jump whitespace and cr/lf */
916 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
918 if ((buffer == NULL) || (buffer->content == NULL))
923 while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
928 if (buffer->offset == buffer->length)
936 /* Parse an object - create a new root, and populate. */
937 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
939 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
942 /* reset error position */
943 global_error.json = NULL;
944 global_error.position = 0;
951 buffer.content = (const unsigned char*)value;
952 buffer.length = strlen((const char*)value) + sizeof("");
954 buffer.hooks = global_hooks;
956 item = cJSON_New_Item(&global_hooks);
957 if (item == NULL) /* memory fail */
962 if (!parse_value(item, buffer_skip_whitespace(&buffer)))
964 /* parse failure. ep is set. */
968 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
969 if (require_null_terminated)
971 buffer_skip_whitespace(&buffer);
972 if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
977 if (return_parse_end)
979 *return_parse_end = (const char*)buffer_at_offset(&buffer);
992 cJSON_error local_error;
993 local_error.json = (const unsigned char*)value;
994 local_error.position = 0;
996 if (buffer.offset < buffer.length)
998 local_error.position = buffer.offset;
1000 else if (buffer.length > 0)
1002 local_error.position = buffer.length - 1;
1005 if (return_parse_end != NULL)
1007 *return_parse_end = (const char*)local_error.json + local_error.position;
1010 global_error = local_error;
1016 /* Default options for cJSON_Parse */
1017 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1019 return cJSON_ParseWithOpts(value, 0, 0);
1022 #define cjson_min(a, b) ((a < b) ? a : b)
1024 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1026 printbuffer buffer[1];
1027 unsigned char *printed = NULL;
1029 memset(buffer, 0, sizeof(buffer));
1032 buffer->buffer = (unsigned char*) hooks->allocate(256);
1033 buffer->format = format;
1034 buffer->hooks = *hooks;
1035 if (buffer->buffer == NULL)
1040 /* print the value */
1041 if (!print_value(item, buffer))
1045 update_offset(buffer);
1047 /* check if reallocate is available */
1048 if (hooks->reallocate != NULL)
1050 printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length);
1051 buffer->buffer = NULL;
1052 if (printed == NULL) {
1056 else /* otherwise copy the JSON over to a new buffer */
1058 printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1059 if (printed == NULL)
1063 memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1064 printed[buffer->offset] = '\0'; /* just to be sure */
1066 /* free the buffer */
1067 hooks->deallocate(buffer->buffer);
1073 if (buffer->buffer != NULL)
1075 hooks->deallocate(buffer->buffer);
1078 if (printed != NULL)
1080 hooks->deallocate(printed);
1086 /* Render a cJSON item/entity/structure to text. */
1087 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1089 return (char*)print(item, true, &global_hooks);
1092 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1094 return (char*)print(item, false, &global_hooks);
1097 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1099 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1106 p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1112 p.length = (size_t)prebuffer;
1116 p.hooks = global_hooks;
1118 if (!print_value(item, &p))
1120 global_hooks.deallocate(p.buffer);
1124 return (char*)p.buffer;
1127 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1129 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1131 if ((len < 0) || (buf == NULL))
1136 p.buffer = (unsigned char*)buf;
1137 p.length = (size_t)len;
1141 p.hooks = global_hooks;
1143 return print_value(item, &p);
1146 /* Parser core - when encountering text, process appropriately. */
1147 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1149 if ((input_buffer == NULL) || (input_buffer->content == NULL))
1151 return false; /* no input */
1154 /* parse the different types of values */
1156 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1158 item->type = cJSON_NULL;
1159 input_buffer->offset += 4;
1163 if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1165 item->type = cJSON_False;
1166 input_buffer->offset += 5;
1170 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1172 item->type = cJSON_True;
1174 input_buffer->offset += 4;
1178 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1180 return parse_string(item, input_buffer);
1183 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'))))
1185 return parse_number(item, input_buffer);
1188 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1190 return parse_array(item, input_buffer);
1193 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1195 return parse_object(item, input_buffer);
1202 /* Render a value to text. */
1203 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1205 unsigned char *output = NULL;
1207 if ((item == NULL) || (output_buffer == NULL))
1212 switch ((item->type) & 0xFF)
1215 output = ensure(output_buffer, 5);
1220 strcpy((char*)output, "null");
1224 output = ensure(output_buffer, 6);
1229 strcpy((char*)output, "false");
1233 output = ensure(output_buffer, 5);
1238 strcpy((char*)output, "true");
1242 return print_number(item, output_buffer);
1246 size_t raw_length = 0;
1247 if (item->valuestring == NULL)
1249 if (!output_buffer->noalloc)
1251 output_buffer->hooks.deallocate(output_buffer->buffer);
1256 raw_length = strlen(item->valuestring) + sizeof("");
1257 output = ensure(output_buffer, raw_length);
1262 memcpy(output, item->valuestring, raw_length);
1267 return print_string(item, output_buffer);
1270 return print_array(item, output_buffer);
1273 return print_object(item, output_buffer);
1280 /* Build an array from input text. */
1281 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1283 cJSON *head = NULL; /* head of the linked list */
1284 cJSON *current_item = NULL;
1286 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1288 return false; /* to deeply nested */
1290 input_buffer->depth++;
1292 if (buffer_at_offset(input_buffer)[0] != '[')
1298 input_buffer->offset++;
1299 buffer_skip_whitespace(input_buffer);
1300 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1306 /* check if we skipped to the end of the buffer */
1307 if (cannot_access_at_index(input_buffer, 0))
1309 input_buffer->offset--;
1313 /* step back to character in front of the first element */
1314 input_buffer->offset--;
1315 /* loop through the comma separated array elements */
1318 /* allocate next item */
1319 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1320 if (new_item == NULL)
1322 goto fail; /* allocation failure */
1325 /* attach next item to list */
1328 /* start the linked list */
1329 current_item = head = new_item;
1333 /* add to the end and advance */
1334 current_item->next = new_item;
1335 new_item->prev = current_item;
1336 current_item = new_item;
1339 /* parse next value */
1340 input_buffer->offset++;
1341 buffer_skip_whitespace(input_buffer);
1342 if (!parse_value(current_item, input_buffer))
1344 goto fail; /* failed to parse value */
1346 buffer_skip_whitespace(input_buffer);
1348 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1350 if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1352 goto fail; /* expected end of array */
1356 input_buffer->depth--;
1358 item->type = cJSON_Array;
1361 input_buffer->offset++;
1374 /* Render an array to text */
1375 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1377 unsigned char *output_pointer = NULL;
1379 cJSON *current_element = item->child;
1381 if (output_buffer == NULL)
1386 /* Compose the output array. */
1387 /* opening square bracket */
1388 output_pointer = ensure(output_buffer, 1);
1389 if (output_pointer == NULL)
1394 *output_pointer = '[';
1395 output_buffer->offset++;
1396 output_buffer->depth++;
1398 while (current_element != NULL)
1400 if (!print_value(current_element, output_buffer))
1404 update_offset(output_buffer);
1405 if (current_element->next)
1407 length = (size_t) (output_buffer->format ? 2 : 1);
1408 output_pointer = ensure(output_buffer, length + 1);
1409 if (output_pointer == NULL)
1413 *output_pointer++ = ',';
1414 if(output_buffer->format)
1416 *output_pointer++ = ' ';
1418 *output_pointer = '\0';
1419 output_buffer->offset += length;
1421 current_element = current_element->next;
1424 output_pointer = ensure(output_buffer, 2);
1425 if (output_pointer == NULL)
1429 *output_pointer++ = ']';
1430 *output_pointer = '\0';
1431 output_buffer->depth--;
1436 /* Build an object from the text. */
1437 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1439 cJSON *head = NULL; /* linked list head */
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 (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1450 goto fail; /* not an object */
1453 input_buffer->offset++;
1454 buffer_skip_whitespace(input_buffer);
1455 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1457 goto success; /* empty object */
1460 /* check if we skipped to the end of the buffer */
1461 if (cannot_access_at_index(input_buffer, 0))
1463 input_buffer->offset--;
1467 /* step back to character in front of the first element */
1468 input_buffer->offset--;
1469 /* loop through the comma separated array elements */
1472 /* allocate next item */
1473 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1474 if (new_item == NULL)
1476 goto fail; /* allocation failure */
1479 /* attach next item to list */
1482 /* start the linked list */
1483 current_item = head = new_item;
1487 /* add to the end and advance */
1488 current_item->next = new_item;
1489 new_item->prev = current_item;
1490 current_item = new_item;
1493 /* parse the name of the child */
1494 input_buffer->offset++;
1495 buffer_skip_whitespace(input_buffer);
1496 if (!parse_string(current_item, input_buffer))
1498 goto fail; /* faile to parse name */
1500 buffer_skip_whitespace(input_buffer);
1502 /* swap valuestring and string, because we parsed the name */
1503 current_item->string = current_item->valuestring;
1504 current_item->valuestring = NULL;
1506 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1508 goto fail; /* invalid object */
1511 /* parse the value */
1512 input_buffer->offset++;
1513 buffer_skip_whitespace(input_buffer);
1514 if (!parse_value(current_item, input_buffer))
1516 goto fail; /* failed to parse value */
1518 buffer_skip_whitespace(input_buffer);
1520 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1522 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1524 goto fail; /* expected end of object */
1528 input_buffer->depth--;
1530 item->type = cJSON_Object;
1533 input_buffer->offset++;
1545 /* Render an object to text. */
1546 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1548 unsigned char *output_pointer = NULL;
1550 cJSON *current_item = item->child;
1552 if (output_buffer == NULL)
1557 /* Compose the output: */
1558 length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1559 output_pointer = ensure(output_buffer, length + 1);
1560 if (output_pointer == NULL)
1565 *output_pointer++ = '{';
1566 output_buffer->depth++;
1567 if (output_buffer->format)
1569 *output_pointer++ = '\n';
1571 output_buffer->offset += length;
1573 while (current_item)
1575 if (output_buffer->format)
1578 output_pointer = ensure(output_buffer, output_buffer->depth);
1579 if (output_pointer == NULL)
1583 for (i = 0; i < output_buffer->depth; i++)
1585 *output_pointer++ = '\t';
1587 output_buffer->offset += output_buffer->depth;
1591 if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1595 update_offset(output_buffer);
1597 length = (size_t) (output_buffer->format ? 2 : 1);
1598 output_pointer = ensure(output_buffer, length);
1599 if (output_pointer == NULL)
1603 *output_pointer++ = ':';
1604 if (output_buffer->format)
1606 *output_pointer++ = '\t';
1608 output_buffer->offset += length;
1611 if (!print_value(current_item, output_buffer))
1615 update_offset(output_buffer);
1617 /* print comma if not last */
1618 length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
1619 output_pointer = ensure(output_buffer, length + 1);
1620 if (output_pointer == NULL)
1624 if (current_item->next)
1626 *output_pointer++ = ',';
1629 if (output_buffer->format)
1631 *output_pointer++ = '\n';
1633 *output_pointer = '\0';
1634 output_buffer->offset += length;
1636 current_item = current_item->next;
1639 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1640 if (output_pointer == NULL)
1644 if (output_buffer->format)
1647 for (i = 0; i < (output_buffer->depth - 1); i++)
1649 *output_pointer++ = '\t';
1652 *output_pointer++ = '}';
1653 *output_pointer = '\0';
1654 output_buffer->depth--;
1659 /* Get Array size/item / object item. */
1660 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1662 cJSON *child = NULL;
1670 child = array->child;
1672 while(child != NULL)
1675 child = child->next;
1678 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1683 static cJSON* get_array_item(const cJSON *array, size_t index)
1685 cJSON *current_child = NULL;
1692 current_child = array->child;
1693 while ((current_child != NULL) && (index > 0))
1696 current_child = current_child->next;
1699 return current_child;
1702 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1709 return get_array_item(array, (size_t)index);
1712 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1714 cJSON *current_element = NULL;
1716 if ((object == NULL) || (name == NULL))
1721 current_element = object->child;
1724 while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
1726 current_element = current_element->next;
1731 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1733 current_element = current_element->next;
1737 return current_element;
1740 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1742 return get_object_item(object, string, false);
1745 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1747 return get_object_item(object, string, true);
1750 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1752 return cJSON_GetObjectItem(object, string) ? 1 : 0;
1755 /* Utility for array list handling. */
1756 static void suffix_object(cJSON *prev, cJSON *item)
1762 /* Utility for handling references. */
1763 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1765 cJSON *reference = NULL;
1771 reference = cJSON_New_Item(hooks);
1772 if (reference == NULL)
1777 memcpy(reference, item, sizeof(cJSON));
1778 reference->string = NULL;
1779 reference->type |= cJSON_IsReference;
1780 reference->next = reference->prev = NULL;
1784 /* Add item to array/object. */
1785 CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1787 cJSON *child = NULL;
1789 if ((item == NULL) || (array == NULL))
1794 child = array->child;
1798 /* list is empty, start new one */
1799 array->child = item;
1803 /* append to the end */
1806 child = child->next;
1808 suffix_object(child, item);
1812 CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
1819 /* call cJSON_AddItemToObjectCS for code reuse */
1820 cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1821 /* remove cJSON_StringIsConst flag */
1822 item->type &= ~cJSON_StringIsConst;
1825 #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1826 #pragma GCC diagnostic push
1829 #pragma GCC diagnostic ignored "-Wcast-qual"
1832 /* Add an item to an object with constant string as key */
1833 CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1835 if ((item == NULL) || (string == NULL))
1839 if (!(item->type & cJSON_StringIsConst) && item->string)
1841 global_hooks.deallocate(item->string);
1843 item->string = (char*)string;
1844 item->type |= cJSON_StringIsConst;
1845 cJSON_AddItemToArray(object, item);
1847 #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1848 #pragma GCC diagnostic pop
1851 CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1858 cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1861 CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1863 if ((object == NULL) || (string == NULL))
1868 cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1871 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
1873 if ((parent == NULL) || (item == NULL))
1878 if (item->prev != NULL)
1880 /* not the first element */
1881 item->prev->next = item->next;
1883 if (item->next != NULL)
1885 /* not the last element */
1886 item->next->prev = item->prev;
1889 if (item == parent->child)
1892 parent->child = item->next;
1894 /* make sure the detached item doesn't point anywhere anymore */
1901 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
1908 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
1911 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1913 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
1916 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1918 cJSON *to_detach = cJSON_GetObjectItem(object, string);
1920 return cJSON_DetachItemViaPointer(object, to_detach);
1923 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
1925 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
1927 return cJSON_DetachItemViaPointer(object, to_detach);
1930 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1932 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
1935 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
1937 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
1940 /* Replace array/object items with new ones. */
1941 CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1943 cJSON *after_inserted = NULL;
1950 after_inserted = get_array_item(array, (size_t)which);
1951 if (after_inserted == NULL)
1953 cJSON_AddItemToArray(array, newitem);
1957 newitem->next = after_inserted;
1958 newitem->prev = after_inserted->prev;
1959 after_inserted->prev = newitem;
1960 if (after_inserted == array->child)
1962 array->child = newitem;
1966 newitem->prev->next = newitem;
1970 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
1972 if ((parent == NULL) || (replacement == NULL) || (item == NULL))
1977 if (replacement == item)
1982 replacement->next = item->next;
1983 replacement->prev = item->prev;
1985 if (replacement->next != NULL)
1987 replacement->next->prev = replacement;
1989 if (replacement->prev != NULL)
1991 replacement->prev->next = replacement;
1993 if (parent->child == item)
1995 parent->child = replacement;
2005 CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2012 cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2015 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2017 if ((replacement == NULL) || (string == NULL))
2022 /* replace the name in the replacement */
2023 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2025 cJSON_free(replacement->string);
2027 replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2028 replacement->type &= ~cJSON_StringIsConst;
2030 cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2035 CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2037 replace_item_in_object(object, string, newitem, false);
2040 CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2042 replace_item_in_object(object, string, newitem, true);
2045 /* Create basic types: */
2046 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2048 cJSON *item = cJSON_New_Item(&global_hooks);
2051 item->type = cJSON_NULL;
2057 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2059 cJSON *item = cJSON_New_Item(&global_hooks);
2062 item->type = cJSON_True;
2068 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2070 cJSON *item = cJSON_New_Item(&global_hooks);
2073 item->type = cJSON_False;
2079 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
2081 cJSON *item = cJSON_New_Item(&global_hooks);
2084 item->type = b ? cJSON_True : cJSON_False;
2090 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2092 cJSON *item = cJSON_New_Item(&global_hooks);
2095 item->type = cJSON_Number;
2096 item->valuedouble = num;
2098 /* use saturation in case of overflow */
2101 item->valueint = INT_MAX;
2103 else if (num <= INT_MIN)
2105 item->valueint = INT_MIN;
2109 item->valueint = (int)num;
2116 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2118 cJSON *item = cJSON_New_Item(&global_hooks);
2121 item->type = cJSON_String;
2122 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2123 if(!item->valuestring)
2133 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2135 cJSON *item = cJSON_New_Item(&global_hooks);
2138 item->type = cJSON_Raw;
2139 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2140 if(!item->valuestring)
2150 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2152 cJSON *item = cJSON_New_Item(&global_hooks);
2155 item->type=cJSON_Array;
2161 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2163 cJSON *item = cJSON_New_Item(&global_hooks);
2166 item->type = cJSON_Object;
2172 /* Create Arrays: */
2173 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2180 if ((count < 0) || (numbers == NULL))
2185 a = cJSON_CreateArray();
2186 for(i = 0; a && (i < (size_t)count); i++)
2188 n = cJSON_CreateNumber(numbers[i]);
2200 suffix_object(p, n);
2208 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2215 if ((count < 0) || (numbers == NULL))
2220 a = cJSON_CreateArray();
2222 for(i = 0; a && (i < (size_t)count); i++)
2224 n = cJSON_CreateNumber((double)numbers[i]);
2236 suffix_object(p, n);
2244 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2251 if ((count < 0) || (numbers == NULL))
2256 a = cJSON_CreateArray();
2258 for(i = 0;a && (i < (size_t)count); i++)
2260 n = cJSON_CreateNumber(numbers[i]);
2272 suffix_object(p, n);
2280 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2287 if ((count < 0) || (strings == NULL))
2292 a = cJSON_CreateArray();
2294 for (i = 0; a && (i < (size_t)count); i++)
2296 n = cJSON_CreateString(strings[i]);
2317 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2319 cJSON *newitem = NULL;
2320 cJSON *child = NULL;
2322 cJSON *newchild = NULL;
2324 /* Bail on bad ptr */
2329 /* Create new item */
2330 newitem = cJSON_New_Item(&global_hooks);
2335 /* Copy over all vars */
2336 newitem->type = item->type & (~cJSON_IsReference);
2337 newitem->valueint = item->valueint;
2338 newitem->valuedouble = item->valuedouble;
2339 if (item->valuestring)
2341 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2342 if (!newitem->valuestring)
2349 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2350 if (!newitem->string)
2355 /* If non-recursive, then we're done! */
2360 /* Walk the ->next chain for the child. */
2361 child = item->child;
2362 while (child != NULL)
2364 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2371 /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2372 next->next = newchild;
2373 newchild->prev = next;
2378 /* Set newitem->child and move to it */
2379 newitem->child = newchild;
2382 child = child->next;
2388 if (newitem != NULL)
2390 cJSON_Delete(newitem);
2396 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2398 unsigned char *into = (unsigned char*)json;
2411 else if (*json == '\t')
2413 /* Whitespace characters. */
2416 else if (*json == '\r')
2420 else if (*json=='\n')
2424 else if ((*json == '/') && (json[1] == '/'))
2426 /* double-slash comments, to end of line. */
2427 while (*json && (*json != '\n'))
2432 else if ((*json == '/') && (json[1] == '*'))
2434 /* multiline comments. */
2435 while (*json && !((*json == '*') && (json[1] == '/')))
2441 else if (*json == '\"')
2443 /* string literals, which are \" sensitive. */
2444 *into++ = (unsigned char)*json++;
2445 while (*json && (*json != '\"'))
2449 *into++ = (unsigned char)*json++;
2451 *into++ = (unsigned char)*json++;
2453 *into++ = (unsigned char)*json++;
2457 /* All other characters. */
2458 *into++ = (unsigned char)*json++;
2462 /* and null-terminate. */
2466 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2473 return (item->type & 0xFF) == cJSON_Invalid;
2476 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2483 return (item->type & 0xFF) == cJSON_False;
2486 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2493 return (item->type & 0xff) == cJSON_True;
2497 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2504 return (item->type & (cJSON_True | cJSON_False)) != 0;
2506 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2513 return (item->type & 0xFF) == cJSON_NULL;
2516 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2523 return (item->type & 0xFF) == cJSON_Number;
2526 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2533 return (item->type & 0xFF) == cJSON_String;
2536 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2543 return (item->type & 0xFF) == cJSON_Array;
2546 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2553 return (item->type & 0xFF) == cJSON_Object;
2556 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2563 return (item->type & 0xFF) == cJSON_Raw;
2566 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2568 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2573 /* check if type is valid */
2574 switch (a->type & 0xFF)
2590 /* identical objects are equal */
2596 switch (a->type & 0xFF)
2598 /* in these cases and equal type is enough */
2605 if (a->valuedouble == b->valuedouble)
2613 if ((a->valuestring == NULL) || (b->valuestring == NULL))
2617 if (strcmp(a->valuestring, b->valuestring) == 0)
2626 cJSON *a_element = a->child;
2627 cJSON *b_element = b->child;
2629 for (; (a_element != NULL) && (b_element != NULL);)
2631 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2636 a_element = a_element->next;
2637 b_element = b_element->next;
2640 /* one of the arrays is longer than the other */
2641 if (a_element != b_element) {
2650 cJSON *a_element = NULL;
2651 cJSON *b_element = NULL;
2652 cJSON_ArrayForEach(a_element, a)
2654 /* TODO This has O(n^2) runtime, which is horrible! */
2655 b_element = get_object_item(b, a_element->string, case_sensitive);
2656 if (b_element == NULL)
2661 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2667 /* doing this twice, once on a and b to prevent true comparison if a subset of b
2668 * TODO: Do this the proper way, this is just a fix for now */
2669 cJSON_ArrayForEach(b_element, b)
2671 a_element = get_object_item(a, b_element->string, case_sensitive);
2672 if (a_element == NULL)
2677 if (!cJSON_Compare(b_element, a_element, case_sensitive))
2691 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
2693 return global_hooks.allocate(size);
2696 CJSON_PUBLIC(void) cJSON_free(void *object)
2698 global_hooks.deallocate(object);