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