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