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