cJSON.c 67.1 KB
Newer Older
K
Kevin Branigan 已提交
1
/*
M
Max Bruckner 已提交
2
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
K
Kevin Branigan 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

/* cJSON */
/* JSON parser in C. */

26 27 28 29 30
/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
#define _CRT_SECURE_NO_DEPRECATE
#endif

31
#ifdef __GNUC__
32
#pragma GCC visibility push(default)
33
#endif
34 35 36 37 38
#if defined(_MSC_VER)
#pragma warning (push)
/* disable warning about single line comments in system headers */
#pragma warning (disable : 4001)
#endif
39

K
Kevin Branigan 已提交
40 41 42 43 44 45 46
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
47 48

#ifdef ENABLE_LOCALES
49
#include <locale.h>
50
#endif
51

52 53 54
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
55
#ifdef __GNUC__
56
#pragma GCC visibility pop
57
#endif
58

K
Kevin Branigan 已提交
59 60
#include "cJSON.h"

M
Max Bruckner 已提交
61
/* define our own boolean type */
62 63
#define true ((cJSON_bool)1)
#define false ((cJSON_bool)0)
M
Max Bruckner 已提交
64

65 66 67 68 69
typedef struct {
    const unsigned char *json;
    size_t position;
} error;
static error global_error = { NULL, 0 };
K
Kevin Branigan 已提交
70

71
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
M
Max Bruckner 已提交
72
{
73
    return (const char*) (global_error.json + global_error.position);
M
Max Bruckner 已提交
74
}
K
Kevin Branigan 已提交
75

76
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
M
Max Bruckner 已提交
77
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 6) || (CJSON_VERSION_PATCH != 0)
78 79 80
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif

81
CJSON_PUBLIC(const char*) cJSON_Version(void)
82 83 84 85 86 87 88
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

89 90
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
K
Kevin Branigan 已提交
91
{
92
    if ((string1 == NULL) || (string2 == NULL))
M
Max Bruckner 已提交
93
    {
94
        return 1;
M
Max Bruckner 已提交
95
    }
96

97
    if (string1 == string2)
M
Max Bruckner 已提交
98
    {
99
        return 0;
M
Max Bruckner 已提交
100
    }
101 102

    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
M
Max Bruckner 已提交
103
    {
104
        if (*string1 == '\0')
M
Max Bruckner 已提交
105 106 107 108 109
        {
            return 0;
        }
    }

110
    return tolower(*string1) - tolower(*string2);
K
Kevin Branigan 已提交
111 112
}

113 114 115 116 117 118 119
typedef struct internal_hooks
{
    void *(*allocate)(size_t size);
    void (*deallocate)(void *pointer);
    void *(*reallocate)(void *pointer, size_t size);
} internal_hooks;

M
Max Bruckner 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#if defined(_MSC_VER)
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
static void *internal_malloc(size_t size)
{
    return malloc(size);
}
static void internal_free(void *pointer)
{
    free(pointer);
}
static void *internal_realloc(void *pointer, size_t size)
{
    return realloc(pointer, size);
}
#else
#define internal_malloc malloc
#define internal_free free
#define internal_realloc realloc
#endif

static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
K
Kevin Branigan 已提交
141

M
Max Bruckner 已提交
142
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
143
{
M
Max Bruckner 已提交
144
    size_t length = 0;
145
    unsigned char *copy = NULL;
K
Kevin Branigan 已提交
146

M
Max Bruckner 已提交
147
    if (string == NULL)
148 149 150 151
    {
        return NULL;
    }

M
Max Bruckner 已提交
152
    length = strlen((const char*)string) + sizeof("");
153 154
    copy = (unsigned char*)hooks->allocate(length);
    if (copy == NULL)
M
Max Bruckner 已提交
155
    {
156
        return NULL;
M
Max Bruckner 已提交
157
    }
M
Max Bruckner 已提交
158
    memcpy(copy, string, length);
M
Max Bruckner 已提交
159 160

    return copy;
K
Kevin Branigan 已提交
161 162
}

163
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
K
Kevin Branigan 已提交
164
{
M
Max Bruckner 已提交
165
    if (hooks == NULL)
M
Max Bruckner 已提交
166 167
    {
        /* Reset hooks */
168 169 170
        global_hooks.allocate = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
K
Kevin Branigan 已提交
171 172 173
        return;
    }

174
    global_hooks.allocate = malloc;
M
Max Bruckner 已提交
175 176
    if (hooks->malloc_fn != NULL)
    {
177
        global_hooks.allocate = hooks->malloc_fn;
M
Max Bruckner 已提交
178 179
    }

180
    global_hooks.deallocate = free;
M
Max Bruckner 已提交
181 182
    if (hooks->free_fn != NULL)
    {
183
        global_hooks.deallocate = hooks->free_fn;
M
Max Bruckner 已提交
184 185 186
    }

    /* use realloc only if both free and malloc are used */
187 188
    global_hooks.reallocate = NULL;
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
M
Max Bruckner 已提交
189
    {
190
        global_hooks.reallocate = realloc;
M
Max Bruckner 已提交
191
    }
K
Kevin Branigan 已提交
192 193 194
}

/* Internal constructor. */
195
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
K
Kevin Branigan 已提交
196
{
197
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
M
Max Bruckner 已提交
198 199
    if (node)
    {
200
        memset(node, '\0', sizeof(cJSON));
M
Max Bruckner 已提交
201 202 203
    }

    return node;
K
Kevin Branigan 已提交
204 205 206
}

/* Delete a cJSON structure. */
M
Max Bruckner 已提交
207
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
K
Kevin Branigan 已提交
208
{
M
Max Bruckner 已提交
209
    cJSON *next = NULL;
M
Max Bruckner 已提交
210
    while (item != NULL)
M
Max Bruckner 已提交
211
    {
M
Max Bruckner 已提交
212 213
        next = item->next;
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
M
Max Bruckner 已提交
214
        {
M
Max Bruckner 已提交
215
            cJSON_Delete(item->child);
M
Max Bruckner 已提交
216
        }
M
Max Bruckner 已提交
217
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
M
Max Bruckner 已提交
218
        {
M
Max Bruckner 已提交
219
            global_hooks.deallocate(item->valuestring);
M
Max Bruckner 已提交
220
        }
M
Max Bruckner 已提交
221
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
M
Max Bruckner 已提交
222
        {
M
Max Bruckner 已提交
223
            global_hooks.deallocate(item->string);
M
Max Bruckner 已提交
224
        }
M
Max Bruckner 已提交
225 226
        global_hooks.deallocate(item);
        item = next;
M
Max Bruckner 已提交
227
    }
K
Kevin Branigan 已提交
228 229
}

230 231 232
/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
233
#ifdef ENABLE_LOCALES
234 235
    struct lconv *lconv = localeconv();
    return (unsigned char) lconv->decimal_point[0];
236
#else
237
    return '.';
238
#endif
239 240
}

M
Max Bruckner 已提交
241 242 243 244 245
typedef struct
{
    const unsigned char *content;
    size_t length;
    size_t offset;
246
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
247
    internal_hooks hooks;
M
Max Bruckner 已提交
248 249 250 251 252 253 254 255 256 257
} parse_buffer;

/* check if the given size is left to read in a given parse buffer (starting with 1) */
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
/* check if the buffer can be accessed at the given index (starting with 0) */
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
/* get a pointer to the buffer at the position */
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)

K
Kevin Branigan 已提交
258
/* Parse the input text to generate a number, and populate the result into item. */
259
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
260
{
261
    double number = 0;
262
    unsigned char *after_end = NULL;
263 264 265
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
266

M
Max Bruckner 已提交
267
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
268
    {
269
        return false;
270 271
    }

272
    /* copy the number into a temporary buffer and replace '.' with the decimal point
M
Max Bruckner 已提交
273 274 275
     * of the current locale (for strtod)
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
276
    {
M
Max Bruckner 已提交
277
        switch (buffer_at_offset(input_buffer)[i])
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case '+':
            case '-':
            case 'e':
            case 'E':
M
Max Bruckner 已提交
293
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
                break;

            case '.':
                number_c_string[i] = decimal_point;
                break;

            default:
                goto loop_end;
        }
    }
loop_end:
    number_c_string[i] = '\0';

    number = strtod((const char*)number_c_string, (char**)&after_end);
    if (number_c_string == after_end)
M
Max Bruckner 已提交
309
    {
310
        return false; /* parse_error */
M
Max Bruckner 已提交
311 312
    }

313
    item->valuedouble = number;
M
Max Bruckner 已提交
314

315
    /* use saturation in case of overflow */
316
    if (number >= INT_MAX)
317 318 319
    {
        item->valueint = INT_MAX;
    }
320
    else if (number <= INT_MIN)
321 322 323 324 325
    {
        item->valueint = INT_MIN;
    }
    else
    {
326
        item->valueint = (int)number;
327
    }
328

M
Max Bruckner 已提交
329 330
    item->type = cJSON_Number;

M
Max Bruckner 已提交
331
    input_buffer->offset += (size_t)(after_end - number_c_string);
332
    return true;
K
Kevin Branigan 已提交
333 334
}

335
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
336
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
337 338 339 340 341 342 343 344 345 346 347
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
348
        object->valueint = (int)number;
349 350 351 352 353
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
354 355
typedef struct
{
356
    unsigned char *buffer;
357 358
    size_t length;
    size_t offset;
M
Max Bruckner 已提交
359
    size_t depth; /* current nesting depth (for formatted printing) */
360
    cJSON_bool noalloc;
M
Max Bruckner 已提交
361
    cJSON_bool format; /* is this print a formatted print */
362
    internal_hooks hooks;
M
Max Bruckner 已提交
363
} printbuffer;
364

M
Max Bruckner 已提交
365
/* realloc printbuffer if necessary to have at least "needed" bytes more */
366
static unsigned char* ensure(printbuffer * const p, size_t needed)
367
{
368
    unsigned char *newbuffer = NULL;
369 370
    size_t newsize = 0;

371
    if ((p == NULL) || (p->buffer == NULL))
372 373 374 375
    {
        return NULL;
    }

M
Max Bruckner 已提交
376 377 378 379 380 381
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

382
    if (needed > INT_MAX)
M
Max Bruckner 已提交
383
    {
384
        /* sizes bigger than INT_MAX are currently not supported */
385
        return NULL;
M
Max Bruckner 已提交
386
    }
387

388
    needed += p->offset + 1;
M
Max Bruckner 已提交
389 390 391 392 393
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

394 395 396 397
    if (p->noalloc) {
        return NULL;
    }

398
    /* calculate new buffer size */
M
Max Bruckner 已提交
399
    if (needed > (INT_MAX / 2))
400 401 402 403 404 405 406 407 408 409 410
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
411 412 413 414
    else
    {
        newsize = needed * 2;
    }
415

416
    if (p->hooks.reallocate != NULL)
M
Max Bruckner 已提交
417
    {
M
Max Bruckner 已提交
418
        /* reallocate with realloc if available */
419
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
420 421 422 423 424 425 426 427
        if (newbuffer == NULL)
        {
            p->hooks.deallocate(p->buffer);
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
M
Max Bruckner 已提交
428
    }
M
Max Bruckner 已提交
429
    else
M
Max Bruckner 已提交
430
    {
M
Max Bruckner 已提交
431
        /* otherwise reallocate manually */
432
        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
M
Max Bruckner 已提交
433 434
        if (!newbuffer)
        {
435
            p->hooks.deallocate(p->buffer);
M
Max Bruckner 已提交
436 437 438 439 440 441 442
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
443
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
444
        }
445
        p->hooks.deallocate(p->buffer);
M
Max Bruckner 已提交
446 447 448 449 450
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
451 452
}

453 454
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
455
{
456 457
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
458
    {
459
        return;
M
Max Bruckner 已提交
460
    }
461
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
462

463
    buffer->offset += strlen((const char*)buffer_pointer);
464 465 466
}

/* Render the number nicely from the given item into a string. */
467
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
468
{
M
Max Bruckner 已提交
469
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
470
    double d = item->valuedouble;
471
    int length = 0;
472
    size_t i = 0;
473
    unsigned char number_buffer[26]; /* temporary buffer to print the number into */
474
    unsigned char decimal_point = get_decimal_point();
475
    double test;
M
Max Bruckner 已提交
476

M
Max Bruckner 已提交
477
    if (output_buffer == NULL)
M
Max Bruckner 已提交
478
    {
479
        return false;
M
Max Bruckner 已提交
480
    }
M
Max Bruckner 已提交
481

482 483 484
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
485
        length = sprintf((char*)number_buffer, "null");
486 487 488
    }
    else
    {
489 490 491 492 493 494 495 496 497
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
        length = sprintf((char*)number_buffer, "%1.15g", d);

        /* Check whether the original double can be recovered */
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
        {
            /* If not, print with 17 decimal places of precision */
            length = sprintf((char*)number_buffer, "%1.17g", d);
        }
M
Max Bruckner 已提交
498
    }
499

500 501
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
502
    {
503
        return false;
504 505
    }

506
    /* reserve appropriate space in the output */
507
    output_pointer = ensure(output_buffer, (size_t)length);
508 509 510
    if (output_pointer == NULL)
    {
        return false;
511 512
    }

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
    /* copy the printed number to the output and replace locale
     * dependent decimal point with '.' */
    for (i = 0; i < ((size_t)length); i++)
    {
        if (number_buffer[i] == decimal_point)
        {
            output_pointer[i] = '.';
            continue;
        }

        output_pointer[i] = number_buffer[i];
    }
    output_pointer[i] = '\0';

    output_buffer->offset += (size_t)length;

529
    return true;
K
Kevin Branigan 已提交
530 531
}

M
Max Bruckner 已提交
532
/* parse 4 digit hexadecimal number */
533
static unsigned parse_hex4(const unsigned char * const input)
534
{
M
Max Bruckner 已提交
535
    unsigned int h = 0;
536
    size_t i = 0;
M
Max Bruckner 已提交
537

538
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
539
    {
540
        /* parse digit */
541
        if ((input[i] >= '0') && (input[i] <= '9'))
542
        {
543
            h += (unsigned int) input[i] - '0';
544
        }
545
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
546
        {
547
            h += (unsigned int) 10 + input[i] - 'A';
548
        }
549
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
550
        {
551
            h += (unsigned int) 10 + input[i] - 'a';
552 553 554 555 556
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
557

558 559 560 561 562
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
563 564 565
    }

    return h;
566 567
}

568 569
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
570
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
M
Max Bruckner 已提交
571
{
572 573 574
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
575
    unsigned char utf8_length = 0;
576
    unsigned char utf8_position = 0;
577
    unsigned char sequence_length = 0;
578
    unsigned char first_byte_mark = 0;
579 580 581 582 583 584

    if ((input_end - first_sequence) < 6)
    {
        /* input ends unexpectedly */
        goto fail;
    }
M
Max Bruckner 已提交
585

586 587 588
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

589
    /* check that the code is valid */
590
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
M
Max Bruckner 已提交
591
    {
592
        goto fail;
M
Max Bruckner 已提交
593
    }
M
Max Bruckner 已提交
594

595 596
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
597
    {
598 599 600 601 602
        const unsigned char *second_sequence = first_sequence + 6;
        unsigned int second_code = 0;
        sequence_length = 12; /* \uXXXX\uXXXX */

        if ((input_end - second_sequence) < 6)
M
Max Bruckner 已提交
603
        {
604 605
            /* input ends unexpectedly */
            goto fail;
M
Max Bruckner 已提交
606
        }
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630

        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
        {
            /* missing second half of the surrogate pair */
            goto fail;
        }

        /* get the second utf16 sequence */
        second_code = parse_hex4(second_sequence + 2);
        /* check that the code is valid */
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
        {
            /* invalid second half of the surrogate pair */
            goto fail;
        }


        /* calculate the unicode codepoint from the surrogate pair */
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
    }
    else
    {
        sequence_length = 6; /* \uXXXX */
        codepoint = first_code;
M
Max Bruckner 已提交
631
    }
M
Max Bruckner 已提交
632

633 634 635 636 637 638 639 640 641 642 643 644
    /* encode as UTF-8
     * takes at maximum 4 bytes to encode:
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
    if (codepoint < 0x80)
    {
        /* normal ascii, encoding 0xxxxxxx */
        utf8_length = 1;
    }
    else if (codepoint < 0x800)
    {
        /* two bytes, encoding 110xxxxx 10xxxxxx */
        utf8_length = 2;
645
        first_byte_mark = 0xC0; /* 11000000 */
646 647 648 649 650
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
651
        first_byte_mark = 0xE0; /* 11100000 */
652 653 654 655 656
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
657
        first_byte_mark = 0xF0; /* 11110000 */
658 659
    }
    else
M
Max Bruckner 已提交
660
    {
661
        /* invalid unicode codepoint */
662
        goto fail;
M
Max Bruckner 已提交
663 664
    }

665
    /* encode as utf8 */
666 667 668 669 670
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
    {
        /* 10xxxxxx */
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
        codepoint >>= 6;
671
    }
672 673 674 675 676 677 678 679
    /* encode first byte */
    if (utf8_length > 1)
    {
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
    }
    else
    {
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
680
    }
681

682 683 684 685 686 687 688 689 690
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
691
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
692
{
M
Max Bruckner 已提交
693 694
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
695 696 697 698
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
M
Max Bruckner 已提交
699
    if (buffer_at_offset(input_buffer)[0] != '\"')
700 701 702 703 704 705 706 707
    {
        goto fail;
    }

    {
        /* calculate approximate size of the output (overestimate) */
        size_t allocation_length = 0;
        size_t skipped_bytes = 0;
708
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
709 710 711 712
        {
            /* is escape sequence */
            if (input_end[0] == '\\')
            {
M
Max Bruckner 已提交
713
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
714 715 716 717 718 719 720 721 722
                {
                    /* prevent buffer overflow when last input character is a backslash */
                    goto fail;
                }
                skipped_bytes++;
                input_end++;
            }
            input_end++;
        }
723
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
724 725 726 727 728
        {
            goto fail; /* string ended unexpectedly */
        }

        /* This is at most how much we need for the output */
M
Max Bruckner 已提交
729
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
730
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
731 732 733 734 735 736 737
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
738
    /* loop through the string literal */
739
    while (input_pointer < input_end)
M
Max Bruckner 已提交
740
    {
741
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
742
        {
743
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
744 745 746 747
        }
        /* escape sequence */
        else
        {
748
            unsigned char sequence_length = 2;
M
Max Bruckner 已提交
749 750 751 752 753
            if ((input_end - input_pointer) < 1)
            {
                goto fail;
            }

754
            switch (input_pointer[1])
M
Max Bruckner 已提交
755 756
            {
                case 'b':
757
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
758 759
                    break;
                case 'f':
760
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
761 762
                    break;
                case 'n':
763
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
764 765
                    break;
                case 'r':
766
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
767 768
                    break;
                case 't':
769
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
770
                    break;
771 772 773
                case '\"':
                case '\\':
                case '/':
774
                    *output_pointer++ = input_pointer[1];
775
                    break;
776 777

                /* UTF-16 literal */
M
Max Bruckner 已提交
778
                case 'u':
779
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
780
                    if (sequence_length == 0)
M
Max Bruckner 已提交
781
                    {
782
                        /* failed to convert UTF16-literal to UTF-8 */
783
                        goto fail;
M
Max Bruckner 已提交
784 785
                    }
                    break;
786

M
Max Bruckner 已提交
787
                default:
788
                    goto fail;
M
Max Bruckner 已提交
789
            }
790
            input_pointer += sequence_length;
M
Max Bruckner 已提交
791 792
        }
    }
793 794 795

    /* zero terminate the output */
    *output_pointer = '\0';
M
Max Bruckner 已提交
796

797
    item->type = cJSON_String;
798
    item->valuestring = (char*)output;
799

M
Max Bruckner 已提交
800 801 802
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

803
    return true;
804 805

fail:
806
    if (output != NULL)
807
    {
808
        input_buffer->hooks.deallocate(output);
809 810
    }

811 812 813 814 815
    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

816
    return false;
K
Kevin Branigan 已提交
817 818 819
}

/* Render the cstring provided to an escaped version that can be printed. */
820
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
K
Kevin Branigan 已提交
821
{
822 823 824
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
825 826 827
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
828

829
    if (output_buffer == NULL)
M
Max Bruckner 已提交
830
    {
831
        return false;
M
Max Bruckner 已提交
832 833 834
    }

    /* empty string */
835
    if (input == NULL)
M
Max Bruckner 已提交
836
    {
837
        output = ensure(output_buffer, sizeof("\"\""));
838
        if (output == NULL)
M
Max Bruckner 已提交
839
        {
840
            return false;
M
Max Bruckner 已提交
841
        }
842
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
843

844
        return true;
M
Max Bruckner 已提交
845 846 847
    }

    /* set "flag" to 1 if something needs to be escaped */
848
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
849
    {
M
Max Bruckner 已提交
850
        switch (*input_pointer)
M
Max Bruckner 已提交
851
        {
M
Max Bruckner 已提交
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
            case '\"':
            case '\\':
            case '\b':
            case '\f':
            case '\n':
            case '\r':
            case '\t':
                /* one character escape sequence */
                escape_characters++;
                break;
            default:
                if (*input_pointer < 32)
                {
                    /* UTF-16 escape sequence uXXXX */
                    escape_characters += 5;
                }
                break;
M
Max Bruckner 已提交
869 870
        }
    }
M
Max Bruckner 已提交
871
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
872

873
    output = ensure(output_buffer, output_length + sizeof("\"\""));
874
    if (output == NULL)
M
Max Bruckner 已提交
875
    {
876
        return false;
M
Max Bruckner 已提交
877 878
    }

M
Max Bruckner 已提交
879 880
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
881
    {
M
Max Bruckner 已提交
882 883 884 885 886
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

887
        return true;
M
Max Bruckner 已提交
888 889
    }

M
Max Bruckner 已提交
890 891
    output[0] = '\"';
    output_pointer = output + 1;
M
Max Bruckner 已提交
892
    /* copy the string */
M
Max Bruckner 已提交
893
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
M
Max Bruckner 已提交
894
    {
895
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
M
Max Bruckner 已提交
896 897
        {
            /* normal character, copy */
M
Max Bruckner 已提交
898
            *output_pointer = *input_pointer;
M
Max Bruckner 已提交
899 900 901 902
        }
        else
        {
            /* character needs to be escaped */
903
            *output_pointer++ = '\\';
M
Max Bruckner 已提交
904
            switch (*input_pointer)
M
Max Bruckner 已提交
905 906
            {
                case '\\':
M
Max Bruckner 已提交
907
                    *output_pointer = '\\';
M
Max Bruckner 已提交
908 909
                    break;
                case '\"':
M
Max Bruckner 已提交
910
                    *output_pointer = '\"';
M
Max Bruckner 已提交
911 912
                    break;
                case '\b':
M
Max Bruckner 已提交
913
                    *output_pointer = 'b';
M
Max Bruckner 已提交
914 915
                    break;
                case '\f':
M
Max Bruckner 已提交
916
                    *output_pointer = 'f';
M
Max Bruckner 已提交
917 918
                    break;
                case '\n':
M
Max Bruckner 已提交
919
                    *output_pointer = 'n';
M
Max Bruckner 已提交
920 921
                    break;
                case '\r':
M
Max Bruckner 已提交
922
                    *output_pointer = 'r';
M
Max Bruckner 已提交
923 924
                    break;
                case '\t':
M
Max Bruckner 已提交
925
                    *output_pointer = 't';
M
Max Bruckner 已提交
926 927 928
                    break;
                default:
                    /* escape and print as unicode codepoint */
M
Max Bruckner 已提交
929 930
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
M
Max Bruckner 已提交
931 932 933 934
                    break;
            }
        }
    }
M
Max Bruckner 已提交
935 936
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';
M
Max Bruckner 已提交
937

938
    return true;
K
Kevin Branigan 已提交
939
}
M
Max Bruckner 已提交
940

M
Max Bruckner 已提交
941
/* Invoke print_string_ptr (which is useful) on an item. */
942
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
M
Max Bruckner 已提交
943
{
944
    return print_string_ptr((unsigned char*)item->valuestring, p);
M
Max Bruckner 已提交
945
}
K
Kevin Branigan 已提交
946 947

/* Predeclare these prototypes. */
948 949 950 951 952 953
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
K
Kevin Branigan 已提交
954 955

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
956
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
M
Max Bruckner 已提交
957
{
M
Max Bruckner 已提交
958 959 960 961 962
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        return NULL;
    }

M
Max Bruckner 已提交
963 964 965 966 967 968
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
    {
       buffer->offset++;
    }

    if (buffer->offset == buffer->length)
M
Max Bruckner 已提交
969
    {
M
Max Bruckner 已提交
970
        buffer->offset--;
M
Max Bruckner 已提交
971 972
    }

M
Max Bruckner 已提交
973
    return buffer;
M
Max Bruckner 已提交
974
}
K
Kevin Branigan 已提交
975

976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
    {
        return NULL;
    }

    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
    {
        buffer->offset += 3;
    }

    return buffer;
}

K
Kevin Branigan 已提交
992
/* Parse an object - create a new root, and populate. */
993
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
994
{
995
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
996
    cJSON *item = NULL;
997 998 999 1000

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;
1001 1002

    if (value == NULL)
M
Max Bruckner 已提交
1003
    {
1004
        goto fail;
M
Max Bruckner 已提交
1005 1006
    }

M
Max Bruckner 已提交
1007 1008 1009
    buffer.content = (const unsigned char*)value;
    buffer.length = strlen((const char*)value) + sizeof("");
    buffer.offset = 0;
1010
    buffer.hooks = global_hooks;
M
Max Bruckner 已提交
1011

1012 1013 1014 1015
    item = cJSON_New_Item(&global_hooks);
    if (item == NULL) /* memory fail */
    {
        goto fail;
M
Max Bruckner 已提交
1016 1017
    }

1018
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
M
Max Bruckner 已提交
1019 1020
    {
        /* parse failure. ep is set. */
1021
        goto fail;
M
Max Bruckner 已提交
1022 1023 1024 1025 1026
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
1027 1028
        buffer_skip_whitespace(&buffer);
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
M
Max Bruckner 已提交
1029
        {
1030
            goto fail;
M
Max Bruckner 已提交
1031 1032 1033 1034
        }
    }
    if (return_parse_end)
    {
1035
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
M
Max Bruckner 已提交
1036 1037
    }

1038
    return item;
1039 1040 1041 1042 1043 1044 1045

fail:
    if (item != NULL)
    {
        cJSON_Delete(item);
    }

1046 1047
    if (value != NULL)
    {
1048 1049 1050 1051
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

1052 1053
        if (buffer.offset < buffer.length)
        {
1054
            local_error.position = buffer.offset;
1055 1056 1057
        }
        else if (buffer.length > 0)
        {
1058 1059 1060 1061 1062 1063 1064
            local_error.position = buffer.length - 1;
        }

        if (return_parse_end != NULL)
        {
            *return_parse_end = (const char*)local_error.json + local_error.position;
        }
Y
yangfl 已提交
1065

1066
        global_error = local_error;
M
Max Bruckner 已提交
1067 1068
    }

1069
    return NULL;
K
Kevin Branigan 已提交
1070
}
M
Max Bruckner 已提交
1071

1072
/* Default options for cJSON_Parse */
1073
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
1074 1075 1076
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
1077

1078
#define cjson_min(a, b) ((a < b) ? a : b)
M
Max Bruckner 已提交
1079

1080
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1081 1082 1083 1084 1085 1086 1087
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

    memset(buffer, 0, sizeof(buffer));

    /* create buffer */
1088
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
1089
    buffer->format = format;
1090
    buffer->hooks = *hooks;
M
Max Bruckner 已提交
1091 1092 1093 1094 1095 1096
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
1097
    if (!print_value(item, buffer))
M
Max Bruckner 已提交
1098 1099 1100
    {
        goto fail;
    }
1101
    update_offset(buffer);
M
Max Bruckner 已提交
1102

1103 1104
    /* check if reallocate is available */
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
1105
    {
1106 1107 1108 1109 1110
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length);
        buffer->buffer = NULL;
        if (printed == NULL) {
            goto fail;
        }
M
Max Bruckner 已提交
1111
    }
1112 1113 1114 1115 1116 1117 1118
    else /* otherwise copy the JSON over to a new buffer */
    {
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
        if (printed == NULL)
        {
            goto fail;
        }
1119
        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1120
        printed[buffer->offset] = '\0'; /* just to be sure */
M
Max Bruckner 已提交
1121

1122 1123 1124
        /* free the buffer */
        hooks->deallocate(buffer->buffer);
    }
M
Max Bruckner 已提交
1125 1126 1127 1128 1129 1130

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1131
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1132 1133 1134 1135
    }

    if (printed != NULL)
    {
1136
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1137 1138 1139 1140 1141
    }

    return NULL;
}

K
Kevin Branigan 已提交
1142
/* Render a cJSON item/entity/structure to text. */
1143
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1144
{
1145
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1146 1147
}

1148
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1149
{
1150
    return (char*)print(item, false, &global_hooks);
1151
}
1152

1153
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1154
{
1155
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
M
Max Bruckner 已提交
1156 1157 1158

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1159
        return NULL;
M
Max Bruckner 已提交
1160 1161
    }

1162
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1163 1164
    if (!p.buffer)
    {
1165
        return NULL;
1166
    }
M
Max Bruckner 已提交
1167 1168

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1169
    p.offset = 0;
1170
    p.noalloc = false;
M
Max Bruckner 已提交
1171
    p.format = fmt;
1172
    p.hooks = global_hooks;
M
Max Bruckner 已提交
1173

1174
    if (!print_value(item, &p))
1175
    {
1176
        global_hooks.deallocate(p.buffer);
1177 1178 1179 1180
        return NULL;
    }

    return (char*)p.buffer;
1181 1182
}

1183
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1184
{
1185
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
M
Max Bruckner 已提交
1186

1187
    if ((len < 0) || (buf == NULL))
M
Max Bruckner 已提交
1188 1189 1190 1191
    {
        return false;
    }

1192
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1193
    p.length = (size_t)len;
1194
    p.offset = 0;
1195
    p.noalloc = true;
M
Max Bruckner 已提交
1196
    p.format = fmt;
1197
    p.hooks = global_hooks;
M
Max Bruckner 已提交
1198

1199
    return print_value(item, &p);
1200
}
K
Kevin Branigan 已提交
1201 1202

/* Parser core - when encountering text, process appropriately. */
1203
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1204
{
M
Max Bruckner 已提交
1205
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
M
Max Bruckner 已提交
1206
    {
1207
        return false; /* no input */
M
Max Bruckner 已提交
1208 1209 1210
    }

    /* parse the different types of values */
1211
    /* null */
M
Max Bruckner 已提交
1212
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
M
Max Bruckner 已提交
1213 1214
    {
        item->type = cJSON_NULL;
M
Max Bruckner 已提交
1215
        input_buffer->offset += 4;
1216
        return true;
M
Max Bruckner 已提交
1217
    }
1218
    /* false */
M
Max Bruckner 已提交
1219
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
M
Max Bruckner 已提交
1220 1221
    {
        item->type = cJSON_False;
M
Max Bruckner 已提交
1222
        input_buffer->offset += 5;
1223
        return true;
M
Max Bruckner 已提交
1224
    }
1225
    /* true */
M
Max Bruckner 已提交
1226
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
M
Max Bruckner 已提交
1227 1228 1229
    {
        item->type = cJSON_True;
        item->valueint = 1;
M
Max Bruckner 已提交
1230
        input_buffer->offset += 4;
1231
        return true;
M
Max Bruckner 已提交
1232
    }
1233
    /* string */
M
Max Bruckner 已提交
1234
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
M
Max Bruckner 已提交
1235
    {
1236
        return parse_string(item, input_buffer);
M
Max Bruckner 已提交
1237
    }
1238
    /* number */
M
Max Bruckner 已提交
1239
    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'))))
M
Max Bruckner 已提交
1240
    {
M
Max Bruckner 已提交
1241
        return parse_number(item, input_buffer);
M
Max Bruckner 已提交
1242
    }
1243
    /* array */
M
Max Bruckner 已提交
1244
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
M
Max Bruckner 已提交
1245
    {
1246
        return parse_array(item, input_buffer);
M
Max Bruckner 已提交
1247
    }
1248
    /* object */
M
Max Bruckner 已提交
1249
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
M
Max Bruckner 已提交
1250
    {
1251
        return parse_object(item, input_buffer);
M
Max Bruckner 已提交
1252 1253
    }

1254
    return false;
K
Kevin Branigan 已提交
1255 1256 1257
}

/* Render a value to text. */
1258
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
K
Kevin Branigan 已提交
1259
{
M
Max Bruckner 已提交
1260
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1261

M
Max Bruckner 已提交
1262
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1263
    {
1264
        return false;
M
Max Bruckner 已提交
1265
    }
M
Max Bruckner 已提交
1266 1267

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1268
    {
M
Max Bruckner 已提交
1269
        case cJSON_NULL:
1270
            output = ensure(output_buffer, 5);
1271
            if (output == NULL)
M
Max Bruckner 已提交
1272
            {
1273
                return false;
M
Max Bruckner 已提交
1274
            }
1275 1276 1277
            strcpy((char*)output, "null");
            return true;

M
Max Bruckner 已提交
1278
        case cJSON_False:
1279
            output = ensure(output_buffer, 6);
1280
            if (output == NULL)
M
Max Bruckner 已提交
1281
            {
1282
                return false;
M
Max Bruckner 已提交
1283
            }
1284 1285 1286
            strcpy((char*)output, "false");
            return true;

M
Max Bruckner 已提交
1287
        case cJSON_True:
1288
            output = ensure(output_buffer, 5);
1289
            if (output == NULL)
M
Max Bruckner 已提交
1290
            {
1291
                return false;
M
Max Bruckner 已提交
1292
            }
1293 1294 1295
            strcpy((char*)output, "true");
            return true;

M
Max Bruckner 已提交
1296
        case cJSON_Number:
1297
            return print_number(item, output_buffer);
1298

M
Max Bruckner 已提交
1299
        case cJSON_Raw:
M
Max Bruckner 已提交
1300
        {
M
Max Bruckner 已提交
1301 1302
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1303
            {
M
Max Bruckner 已提交
1304
                if (!output_buffer->noalloc)
1305
                {
1306
                    output_buffer->hooks.deallocate(output_buffer->buffer);
1307
                }
1308
                return false;
M
Max Bruckner 已提交
1309
            }
1310

1311
            raw_length = strlen(item->valuestring) + sizeof("");
1312
            output = ensure(output_buffer, raw_length);
1313
            if (output == NULL)
M
Max Bruckner 已提交
1314
            {
1315
                return false;
1316
            }
1317 1318
            memcpy(output, item->valuestring, raw_length);
            return true;
M
Max Bruckner 已提交
1319
        }
1320

M
Max Bruckner 已提交
1321
        case cJSON_String:
1322
            return print_string(item, output_buffer);
1323

M
Max Bruckner 已提交
1324
        case cJSON_Array:
1325
            return print_array(item, output_buffer);
1326

M
Max Bruckner 已提交
1327
        case cJSON_Object:
1328
            return print_object(item, output_buffer);
1329

M
Max Bruckner 已提交
1330
        default:
1331
            return false;
M
Max Bruckner 已提交
1332
    }
K
Kevin Branigan 已提交
1333 1334 1335
}

/* Build an array from input text. */
1336
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1337
{
1338
    cJSON *head = NULL; /* head of the linked list */
1339 1340
    cJSON *current_item = NULL;

1341 1342 1343 1344 1345 1346
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

M
Max Bruckner 已提交
1347
    if (buffer_at_offset(input_buffer)[0] != '[')
M
Max Bruckner 已提交
1348
    {
1349
        /* not an array */
1350
        goto fail;
M
Max Bruckner 已提交
1351
    }
K
Kevin Branigan 已提交
1352

M
Max Bruckner 已提交
1353 1354 1355
    input_buffer->offset++;
    buffer_skip_whitespace(input_buffer);
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
M
Max Bruckner 已提交
1356
    {
1357
        /* empty array */
1358
        goto success;
M
Max Bruckner 已提交
1359
    }
K
Kevin Branigan 已提交
1360

M
Max Bruckner 已提交
1361 1362 1363 1364 1365 1366 1367
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1368
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1369
    input_buffer->offset--;
M
Max Bruckner 已提交
1370
    /* loop through the comma separated array elements */
1371
    do
M
Max Bruckner 已提交
1372
    {
1373
        /* allocate next item */
1374
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1375
        if (new_item == NULL)
M
Max Bruckner 已提交
1376
        {
1377
            goto fail; /* allocation failure */
M
Max Bruckner 已提交
1378
        }
1379 1380 1381

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1382
        {
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
            /* start the linked list */
            current_item = head = new_item;
        }
        else
        {
            /* add to the end and advance */
            current_item->next = new_item;
            new_item->prev = current_item;
            current_item = new_item;
        }

        /* parse next value */
M
Max Bruckner 已提交
1395 1396
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1397
        if (!parse_value(current_item, input_buffer))
1398 1399
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1400
        }
M
Max Bruckner 已提交
1401
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1402
    }
M
Max Bruckner 已提交
1403
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
M
Max Bruckner 已提交
1404

M
Max Bruckner 已提交
1405
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
M
Max Bruckner 已提交
1406
    {
1407
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1408 1409
    }

1410
success:
1411 1412
    input_buffer->depth--;

1413
    item->type = cJSON_Array;
1414
    item->child = head;
1415

M
Max Bruckner 已提交
1416 1417
    input_buffer->offset++;

1418
    return true;
K
Kevin Branigan 已提交
1419

1420
fail:
1421
    if (head != NULL)
1422
    {
1423
        cJSON_Delete(head);
1424 1425
    }

1426
    return false;
K
Kevin Branigan 已提交
1427 1428 1429
}

/* Render an array to text */
1430
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
K
Kevin Branigan 已提交
1431
{
M
Max Bruckner 已提交
1432
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1433
    size_t length = 0;
M
Max Bruckner 已提交
1434
    cJSON *current_element = item->child;
K
Kevin Branigan 已提交
1435

M
Max Bruckner 已提交
1436
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1437
    {
1438
        return false;
M
Max Bruckner 已提交
1439 1440
    }

M
Max Bruckner 已提交
1441 1442
    /* Compose the output array. */
    /* opening square bracket */
1443
    output_pointer = ensure(output_buffer, 1);
M
Max Bruckner 已提交
1444
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1445
    {
1446
        return false;
M
Max Bruckner 已提交
1447 1448
    }

M
Max Bruckner 已提交
1449 1450
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1451
    output_buffer->depth++;
M
Max Bruckner 已提交
1452

M
Max Bruckner 已提交
1453
    while (current_element != NULL)
M
Max Bruckner 已提交
1454
    {
1455
        if (!print_value(current_element, output_buffer))
M
Max Bruckner 已提交
1456
        {
1457
            return false;
M
Max Bruckner 已提交
1458
        }
1459
        update_offset(output_buffer);
M
Max Bruckner 已提交
1460
        if (current_element->next)
M
Max Bruckner 已提交
1461
        {
M
Max Bruckner 已提交
1462
            length = (size_t) (output_buffer->format ? 2 : 1);
1463
            output_pointer = ensure(output_buffer, length + 1);
M
Max Bruckner 已提交
1464
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1465
            {
1466
                return false;
M
Max Bruckner 已提交
1467
            }
M
Max Bruckner 已提交
1468
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1469
            if(output_buffer->format)
M
Max Bruckner 已提交
1470
            {
M
Max Bruckner 已提交
1471
                *output_pointer++ = ' ';
M
Max Bruckner 已提交
1472
            }
M
Max Bruckner 已提交
1473 1474
            *output_pointer = '\0';
            output_buffer->offset += length;
M
Max Bruckner 已提交
1475
        }
M
Max Bruckner 已提交
1476
        current_element = current_element->next;
M
Max Bruckner 已提交
1477 1478
    }

1479
    output_pointer = ensure(output_buffer, 2);
M
Max Bruckner 已提交
1480
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1481
    {
1482
        return false;
M
Max Bruckner 已提交
1483
    }
M
Max Bruckner 已提交
1484 1485
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1486
    output_buffer->depth--;
M
Max Bruckner 已提交
1487

1488
    return true;
K
Kevin Branigan 已提交
1489 1490 1491
}

/* Build an object from the text. */
1492
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1493
{
1494
    cJSON *head = NULL; /* linked list head */
1495 1496
    cJSON *current_item = NULL;

1497 1498 1499 1500 1501 1502
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

M
Max Bruckner 已提交
1503
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
M
Max Bruckner 已提交
1504
    {
1505
        goto fail; /* not an object */
M
Max Bruckner 已提交
1506 1507
    }

M
Max Bruckner 已提交
1508 1509 1510
    input_buffer->offset++;
    buffer_skip_whitespace(input_buffer);
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
M
Max Bruckner 已提交
1511
    {
1512
        goto success; /* empty object */
M
Max Bruckner 已提交
1513 1514
    }

M
Max Bruckner 已提交
1515 1516 1517 1518 1519 1520 1521
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1522
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1523
    input_buffer->offset--;
1524 1525
    /* loop through the comma separated array elements */
    do
M
Max Bruckner 已提交
1526
    {
1527
        /* allocate next item */
1528
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1529 1530 1531 1532
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }
M
Max Bruckner 已提交
1533

1534 1535
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1536
        {
1537 1538 1539 1540 1541 1542 1543 1544 1545
            /* start the linked list */
            current_item = head = new_item;
        }
        else
        {
            /* add to the end and advance */
            current_item->next = new_item;
            new_item->prev = current_item;
            current_item = new_item;
M
Max Bruckner 已提交
1546 1547
        }

1548
        /* parse the name of the child */
M
Max Bruckner 已提交
1549 1550
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1551
        if (!parse_string(current_item, input_buffer))
M
Max Bruckner 已提交
1552
        {
1553
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1554
        }
M
Max Bruckner 已提交
1555
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1556

1557 1558 1559
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1560

M
Max Bruckner 已提交
1561
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
M
Max Bruckner 已提交
1562
        {
1563
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1564
        }
1565 1566

        /* parse the value */
M
Max Bruckner 已提交
1567 1568
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1569
        if (!parse_value(current_item, input_buffer))
M
Max Bruckner 已提交
1570
        {
1571
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1572
        }
M
Max Bruckner 已提交
1573
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1574
    }
M
Max Bruckner 已提交
1575
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1576

M
Max Bruckner 已提交
1577
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
M
Max Bruckner 已提交
1578
    {
1579
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1580 1581
    }

1582
success:
1583 1584
    input_buffer->depth--;

1585
    item->type = cJSON_Object;
1586
    item->child = head;
1587

M
Max Bruckner 已提交
1588
    input_buffer->offset++;
1589
    return true;
1590 1591

fail:
1592
    if (head != NULL)
1593
    {
1594
        cJSON_Delete(head);
1595 1596
    }

1597
    return false;
K
Kevin Branigan 已提交
1598 1599 1600
}

/* Render an object to text. */
1601
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1602
{
M
Max Bruckner 已提交
1603
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1604
    size_t length = 0;
M
Max Bruckner 已提交
1605
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1606

M
Max Bruckner 已提交
1607
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1608
    {
1609
        return false;
M
Max Bruckner 已提交
1610 1611
    }

M
Max Bruckner 已提交
1612
    /* Compose the output: */
M
Max Bruckner 已提交
1613
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1614
    output_pointer = ensure(output_buffer, length + 1);
M
Max Bruckner 已提交
1615
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1616
    {
1617
        return false;
M
Max Bruckner 已提交
1618 1619
    }

M
Max Bruckner 已提交
1620
    *output_pointer++ = '{';
M
Max Bruckner 已提交
1621
    output_buffer->depth++;
M
Max Bruckner 已提交
1622
    if (output_buffer->format)
M
Max Bruckner 已提交
1623
    {
M
Max Bruckner 已提交
1624
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1625
    }
M
Max Bruckner 已提交
1626
    output_buffer->offset += length;
M
Max Bruckner 已提交
1627

M
Max Bruckner 已提交
1628
    while (current_item)
M
Max Bruckner 已提交
1629
    {
M
Max Bruckner 已提交
1630
        if (output_buffer->format)
M
Max Bruckner 已提交
1631
        {
M
Max Bruckner 已提交
1632
            size_t i;
1633
            output_pointer = ensure(output_buffer, output_buffer->depth);
M
Max Bruckner 已提交
1634
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1635
            {
1636
                return false;
M
Max Bruckner 已提交
1637
            }
M
Max Bruckner 已提交
1638
            for (i = 0; i < output_buffer->depth; i++)
M
Max Bruckner 已提交
1639
            {
M
Max Bruckner 已提交
1640
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1641
            }
M
Max Bruckner 已提交
1642
            output_buffer->offset += output_buffer->depth;
M
Max Bruckner 已提交
1643 1644
        }

M
Max Bruckner 已提交
1645
        /* print key */
1646
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
M
Max Bruckner 已提交
1647
        {
1648
            return false;
M
Max Bruckner 已提交
1649
        }
M
Max Bruckner 已提交
1650
        update_offset(output_buffer);
M
Max Bruckner 已提交
1651

M
Max Bruckner 已提交
1652
        length = (size_t) (output_buffer->format ? 2 : 1);
1653
        output_pointer = ensure(output_buffer, length);
M
Max Bruckner 已提交
1654
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1655
        {
1656
            return false;
M
Max Bruckner 已提交
1657
        }
M
Max Bruckner 已提交
1658
        *output_pointer++ = ':';
M
Max Bruckner 已提交
1659
        if (output_buffer->format)
M
Max Bruckner 已提交
1660
        {
M
Max Bruckner 已提交
1661
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1662
        }
M
Max Bruckner 已提交
1663
        output_buffer->offset += length;
M
Max Bruckner 已提交
1664

M
Max Bruckner 已提交
1665
        /* print value */
1666
        if (!print_value(current_item, output_buffer))
M
Max Bruckner 已提交
1667
        {
1668
            return false;
M
Max Bruckner 已提交
1669
        }
M
Max Bruckner 已提交
1670
        update_offset(output_buffer);
M
Max Bruckner 已提交
1671

M
Max Bruckner 已提交
1672
        /* print comma if not last */
M
Max Bruckner 已提交
1673
        length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
1674
        output_pointer = ensure(output_buffer, length + 1);
M
Max Bruckner 已提交
1675
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1676
        {
1677
            return false;
M
Max Bruckner 已提交
1678
        }
M
Max Bruckner 已提交
1679
        if (current_item->next)
M
Max Bruckner 已提交
1680
        {
M
Max Bruckner 已提交
1681
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1682 1683
        }

M
Max Bruckner 已提交
1684
        if (output_buffer->format)
M
Max Bruckner 已提交
1685
        {
M
Max Bruckner 已提交
1686
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1687
        }
M
Max Bruckner 已提交
1688 1689
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1690

M
Max Bruckner 已提交
1691
        current_item = current_item->next;
M
Max Bruckner 已提交
1692
    }
M
Max Bruckner 已提交
1693

1694
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
M
Max Bruckner 已提交
1695
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1696
    {
1697
        return false;
M
Max Bruckner 已提交
1698
    }
M
Max Bruckner 已提交
1699
    if (output_buffer->format)
M
Max Bruckner 已提交
1700
    {
M
Max Bruckner 已提交
1701
        size_t i;
M
Max Bruckner 已提交
1702
        for (i = 0; i < (output_buffer->depth - 1); i++)
M
Max Bruckner 已提交
1703
        {
M
Max Bruckner 已提交
1704
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1705 1706
        }
    }
M
Max Bruckner 已提交
1707 1708
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1709
    output_buffer->depth--;
M
Max Bruckner 已提交
1710

1711
    return true;
K
Kevin Branigan 已提交
1712 1713 1714
}

/* Get Array size/item / object item. */
1715
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1716
{
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
    cJSON *child = NULL;
    size_t size = 0;

    if (array == NULL)
    {
        return 0;
    }

    child = array->child;

    while(child != NULL)
M
Max Bruckner 已提交
1728
    {
1729 1730
        size++;
        child = child->next;
M
Max Bruckner 已提交
1731
    }
1732 1733 1734

    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */

1735
    return (int)size;
M
Max Bruckner 已提交
1736 1737
}

M
Max Bruckner 已提交
1738
static cJSON* get_array_item(const cJSON *array, size_t index)
M
Max Bruckner 已提交
1739
{
M
Max Bruckner 已提交
1740 1741 1742
    cJSON *current_child = NULL;

    if (array == NULL)
M
Max Bruckner 已提交
1743
    {
M
Max Bruckner 已提交
1744
        return NULL;
M
Max Bruckner 已提交
1745 1746
    }

M
Max Bruckner 已提交
1747 1748 1749 1750 1751 1752 1753 1754
    current_child = array->child;
    while ((current_child != NULL) && (index > 0))
    {
        index--;
        current_child = current_child->next;
    }

    return current_child;
M
Max Bruckner 已提交
1755 1756
}

M
Max Bruckner 已提交
1757
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
M
Max Bruckner 已提交
1758
{
M
Max Bruckner 已提交
1759
    if (index < 0)
M
Max Bruckner 已提交
1760
    {
M
Max Bruckner 已提交
1761
        return NULL;
M
Max Bruckner 已提交
1762
    }
M
Max Bruckner 已提交
1763

M
Max Bruckner 已提交
1764
    return get_array_item(array, (size_t)index);
M
Max Bruckner 已提交
1765 1766
}

1767
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1768 1769 1770
{
    cJSON *current_element = NULL;

1771
    if ((object == NULL) || (name == NULL))
1772 1773 1774 1775 1776
    {
        return NULL;
    }

    current_element = object->child;
1777
    if (case_sensitive)
1778
    {
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789
        while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
        {
            current_element = current_element->next;
        }
    }
    else
    {
        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
        {
            current_element = current_element->next;
        }
1790 1791 1792 1793 1794
    }

    return current_element;
}

1795
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1796 1797 1798 1799 1800 1801 1802 1803 1804
{
    return get_object_item(object, string, false);
}

CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
{
    return get_object_item(object, string, true);
}

1805
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1806 1807 1808
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1809 1810

/* Utility for array list handling. */
M
Max Bruckner 已提交
1811 1812 1813 1814 1815 1816
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1817
/* Utility for handling references. */
1818
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1819
{
1820 1821
    cJSON *reference = NULL;
    if (item == NULL)
M
Max Bruckner 已提交
1822
    {
1823
        return NULL;
M
Max Bruckner 已提交
1824
    }
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836

    reference = cJSON_New_Item(hooks);
    if (reference == NULL)
    {
        return NULL;
    }

    memcpy(reference, item, sizeof(cJSON));
    reference->string = NULL;
    reference->type |= cJSON_IsReference;
    reference->next = reference->prev = NULL;
    return reference;
M
Max Bruckner 已提交
1837
}
K
Kevin Branigan 已提交
1838 1839

/* Add item to array/object. */
1840
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1841
{
1842 1843 1844
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1845 1846 1847
    {
        return;
    }
1848 1849 1850 1851

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1852 1853 1854 1855 1856 1857 1858
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1859
        while (child->next)
M
Max Bruckner 已提交
1860
        {
1861
            child = child->next;
M
Max Bruckner 已提交
1862
        }
1863
        suffix_object(child, item);
M
Max Bruckner 已提交
1864 1865 1866
    }
}

1867
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1868
{
1869 1870 1871 1872 1873
    if (item == NULL)
    {
        return;
    }

1874
    /* call cJSON_AddItemToObjectCS for code reuse */
1875
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1876 1877
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1878 1879
}

1880
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1881 1882
    #pragma GCC diagnostic push
#endif
1883
#ifdef __GNUC__
1884
#pragma GCC diagnostic ignored "-Wcast-qual"
1885 1886
#endif

1887
/* Add an item to an object with constant string as key */
1888
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1889
{
1890
    if ((item == NULL) || (string == NULL))
1891 1892 1893 1894 1895
    {
        return;
    }
    if (!(item->type & cJSON_StringIsConst) && item->string)
    {
1896
        global_hooks.deallocate(item->string);
1897 1898 1899 1900 1901
    }
    item->string = (char*)string;
    item->type |= cJSON_StringIsConst;
    cJSON_AddItemToArray(object, item);
}
1902
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1903 1904
    #pragma GCC diagnostic pop
#endif
1905

1906
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1907
{
1908 1909 1910 1911 1912
    if (array == NULL)
    {
        return;
    }

1913
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1914 1915
}

1916
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1917
{
1918 1919 1920 1921 1922
    if ((object == NULL) || (string == NULL))
    {
        return;
    }

1923
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1924 1925
}

M
Max Bruckner 已提交
1926
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
1927
{
M
Max Bruckner 已提交
1928
    if ((parent == NULL) || (item == NULL))
1929
    {
1930
        return NULL;
1931
    }
M
Max Bruckner 已提交
1932 1933

    if (item->prev != NULL)
1934 1935
    {
        /* not the first element */
M
Max Bruckner 已提交
1936
        item->prev->next = item->next;
1937
    }
M
Max Bruckner 已提交
1938
    if (item->next != NULL)
1939
    {
M
Max Bruckner 已提交
1940 1941
        /* not the last element */
        item->next->prev = item->prev;
1942
    }
M
Max Bruckner 已提交
1943 1944

    if (item == parent->child)
1945
    {
M
Max Bruckner 已提交
1946 1947
        /* first element */
        parent->child = item->next;
1948 1949
    }
    /* make sure the detached item doesn't point anywhere anymore */
M
Max Bruckner 已提交
1950 1951
    item->prev = NULL;
    item->next = NULL;
1952

M
Max Bruckner 已提交
1953
    return item;
1954
}
M
Max Bruckner 已提交
1955

1956
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1957 1958 1959 1960 1961 1962
{
    if (which < 0)
    {
        return NULL;
    }

M
Max Bruckner 已提交
1963
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
M
Max Bruckner 已提交
1964
}
K
Kevin Branigan 已提交
1965

1966
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1967 1968 1969 1970
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1971
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1972
{
1973
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
1974

1975 1976 1977 1978 1979 1980
    return cJSON_DetachItemViaPointer(object, to_detach);
}

CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
1981

1982
    return cJSON_DetachItemViaPointer(object, to_detach);
1983 1984
}

1985
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1986 1987 1988
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1989

1990 1991 1992 1993 1994
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
}

K
Kevin Branigan 已提交
1995
/* Replace array/object items with new ones. */
1996
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1997
{
M
Max Bruckner 已提交
1998 1999 2000
    cJSON *after_inserted = NULL;

    if (which < 0)
2001
    {
M
Max Bruckner 已提交
2002
        return;
2003
    }
M
Max Bruckner 已提交
2004 2005 2006

    after_inserted = get_array_item(array, (size_t)which);
    if (after_inserted == NULL)
2007 2008 2009 2010
    {
        cJSON_AddItemToArray(array, newitem);
        return;
    }
M
Max Bruckner 已提交
2011 2012 2013 2014 2015

    newitem->next = after_inserted;
    newitem->prev = after_inserted->prev;
    after_inserted->prev = newitem;
    if (after_inserted == array->child)
2016 2017 2018 2019 2020 2021 2022 2023 2024
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
}

M
Max Bruckner 已提交
2025
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2026
{
2027
    if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2028
    {
M
Max Bruckner 已提交
2029
        return false;
2030
    }
M
Max Bruckner 已提交
2031

M
Max Bruckner 已提交
2032
    if (replacement == item)
2033
    {
M
Max Bruckner 已提交
2034
        return true;
2035
    }
M
Max Bruckner 已提交
2036

M
Max Bruckner 已提交
2037 2038 2039 2040
    replacement->next = item->next;
    replacement->prev = item->prev;

    if (replacement->next != NULL)
2041
    {
M
Max Bruckner 已提交
2042
        replacement->next->prev = replacement;
2043
    }
M
Max Bruckner 已提交
2044
    if (replacement->prev != NULL)
2045
    {
M
Max Bruckner 已提交
2046
        replacement->prev->next = replacement;
2047
    }
M
Max Bruckner 已提交
2048
    if (parent->child == item)
2049
    {
M
Max Bruckner 已提交
2050
        parent->child = replacement;
2051
    }
M
Max Bruckner 已提交
2052

M
Max Bruckner 已提交
2053 2054 2055
    item->next = NULL;
    item->prev = NULL;
    cJSON_Delete(item);
M
Max Bruckner 已提交
2056

M
Max Bruckner 已提交
2057
    return true;
2058
}
M
Max Bruckner 已提交
2059

2060
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
2061 2062 2063 2064 2065 2066
{
    if (which < 0)
    {
        return;
    }

M
Max Bruckner 已提交
2067
    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
M
Max Bruckner 已提交
2068
}
2069

2070 2071
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
{
2072
    if ((replacement == NULL) || (string == NULL))
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
    {
        return false;
    }

    /* replace the name in the replacement */
    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
    {
        cJSON_free(replacement->string);
    }
    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
    replacement->type &= ~cJSON_StringIsConst;

    cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);

    return true;
}

2090
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2091
{
2092
    replace_item_in_object(object, string, newitem, false);
2093
}
2094

2095 2096
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
2097
    replace_item_in_object(object, string, newitem, true);
2098
}
K
Kevin Branigan 已提交
2099 2100

/* Create basic types: */
2101
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
2102
{
2103
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2104 2105 2106 2107 2108 2109 2110 2111
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

2112
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
2113
{
2114
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2115 2116 2117 2118 2119 2120 2121 2122
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

2123
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
2124
{
2125
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2126 2127 2128 2129 2130 2131 2132 2133
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

2134
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
2135
{
2136
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2137 2138 2139 2140 2141 2142 2143 2144
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

2145
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
2146
{
2147
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2148 2149 2150 2151
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165

        /* use saturation in case of overflow */
        if (num >= INT_MAX)
        {
            item->valueint = INT_MAX;
        }
        else if (num <= INT_MIN)
        {
            item->valueint = INT_MIN;
        }
        else
        {
            item->valueint = (int)num;
        }
M
Max Bruckner 已提交
2166 2167 2168 2169 2170
    }

    return item;
}

2171
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
2172
{
2173
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2174 2175 2176
    if(item)
    {
        item->type = cJSON_String;
2177
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
2178 2179 2180
        if(!item->valuestring)
        {
            cJSON_Delete(item);
2181
            return NULL;
M
Max Bruckner 已提交
2182 2183 2184 2185 2186 2187
        }
    }

    return item;
}

2188
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
2189
{
2190
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2191 2192 2193
    if(item)
    {
        item->type = cJSON_Raw;
2194
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
2195 2196 2197 2198 2199 2200 2201 2202
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
2203 2204
}

2205
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
2206
{
2207
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2208 2209 2210 2211 2212 2213 2214 2215
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

2216
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
2217
{
2218
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2219 2220 2221 2222 2223 2224 2225
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
2226 2227

/* Create Arrays: */
2228
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
2229
{
2230
    size_t i = 0;
2231 2232
    cJSON *n = NULL;
    cJSON *p = NULL;
2233 2234
    cJSON *a = NULL;

2235
    if ((count < 0) || (numbers == NULL))
2236 2237 2238 2239 2240 2241
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2242 2243 2244 2245 2246
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
2247
            return NULL;
M
Max Bruckner 已提交
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2263
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2264
{
2265
    size_t i = 0;
2266 2267
    cJSON *n = NULL;
    cJSON *p = NULL;
2268 2269
    cJSON *a = NULL;

2270
    if ((count < 0) || (numbers == NULL))
2271 2272 2273 2274 2275 2276 2277
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2278
    {
2279
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2280 2281 2282
        if(!n)
        {
            cJSON_Delete(a);
2283
            return NULL;
M
Max Bruckner 已提交
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2299
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2300
{
2301
    size_t i = 0;
2302 2303
    cJSON *n = NULL;
    cJSON *p = NULL;
2304 2305
    cJSON *a = NULL;

2306
    if ((count < 0) || (numbers == NULL))
2307 2308 2309 2310 2311 2312 2313
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2314 2315 2316 2317 2318
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2319
            return NULL;
2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2335
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2336
{
2337
    size_t i = 0;
2338 2339
    cJSON *n = NULL;
    cJSON *p = NULL;
2340 2341
    cJSON *a = NULL;

2342
    if ((count < 0) || (strings == NULL))
2343 2344 2345 2346 2347 2348 2349
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2350 2351 2352 2353 2354
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2355
            return NULL;
2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2370 2371

/* Duplication */
2372
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2373
{
M
Max Bruckner 已提交
2374
    cJSON *newitem = NULL;
2375 2376
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2377
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2378 2379 2380 2381

    /* Bail on bad ptr */
    if (!item)
    {
2382
        goto fail;
M
Max Bruckner 已提交
2383 2384
    }
    /* Create new item */
2385
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2386 2387
    if (!newitem)
    {
2388
        goto fail;
M
Max Bruckner 已提交
2389 2390 2391 2392 2393 2394 2395
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2396
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2397 2398
        if (!newitem->valuestring)
        {
2399
            goto fail;
M
Max Bruckner 已提交
2400 2401 2402 2403
        }
    }
    if (item->string)
    {
2404
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2405 2406
        if (!newitem->string)
        {
2407
            goto fail;
M
Max Bruckner 已提交
2408 2409 2410 2411 2412 2413 2414 2415
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2416 2417
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2418
    {
2419
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2420 2421
        if (!newchild)
        {
2422
            goto fail;
M
Max Bruckner 已提交
2423
        }
2424
        if (next != NULL)
M
Max Bruckner 已提交
2425 2426
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2427 2428 2429
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2430 2431 2432 2433
        }
        else
        {
            /* Set newitem->child and move to it */
2434 2435
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2436
        }
2437
        child = child->next;
M
Max Bruckner 已提交
2438 2439 2440
    }

    return newitem;
2441 2442 2443 2444 2445 2446 2447 2448

fail:
    if (newitem != NULL)
    {
        cJSON_Delete(newitem);
    }

    return NULL;
2449
}
2450

2451
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2452
{
2453
    unsigned char *into = (unsigned char*)json;
2454 2455 2456 2457 2458 2459

    if (json == NULL)
    {
        return;
    }

M
Max Bruckner 已提交
2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
    while (*json)
    {
        if (*json == ' ')
        {
            json++;
        }
        else if (*json == '\t')
        {
            /* Whitespace characters. */
            json++;
        }
        else if (*json == '\r')
        {
            json++;
        }
        else if (*json=='\n')
        {
            json++;
        }
        else if ((*json == '/') && (json[1] == '/'))
        {
            /* double-slash comments, to end of line. */
            while (*json && (*json != '\n'))
            {
                json++;
            }
        }
        else if ((*json == '/') && (json[1] == '*'))
        {
            /* multiline comments. */
            while (*json && !((*json == '*') && (json[1] == '/')))
            {
                json++;
            }
            json += 2;
        }
        else if (*json == '\"')
        {
            /* string literals, which are \" sensitive. */
M
Max Bruckner 已提交
2499
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2500 2501 2502 2503
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2504
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2505
                }
M
Max Bruckner 已提交
2506
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2507
            }
M
Max Bruckner 已提交
2508
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2509 2510 2511 2512
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2513
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2514 2515 2516 2517 2518
        }
    }

    /* and null-terminate. */
    *into = '\0';
2519
}
2520

2521
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2522 2523 2524 2525 2526 2527 2528 2529 2530
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Invalid;
}

2531
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2532 2533 2534 2535 2536 2537 2538 2539 2540
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_False;
}

2541
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xff) == cJSON_True;
}


2552
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2553 2554 2555 2556 2557 2558 2559 2560
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2561
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2562 2563 2564 2565 2566 2567 2568 2569 2570
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_NULL;
}

2571
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2572 2573 2574 2575 2576 2577 2578 2579 2580
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Number;
}

2581
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2582 2583 2584 2585 2586 2587 2588 2589 2590
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_String;
}

2591
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2592 2593 2594 2595 2596 2597 2598 2599 2600
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Array;
}

2601
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2602 2603 2604 2605 2606 2607 2608 2609 2610
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Object;
}

2611
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2612 2613 2614 2615 2616 2617 2618 2619
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Raw;
}
2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680

CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
{
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
    {
        return false;
    }

    /* check if type is valid */
    switch (a->type & 0xFF)
    {
        case cJSON_False:
        case cJSON_True:
        case cJSON_NULL:
        case cJSON_Number:
        case cJSON_String:
        case cJSON_Raw:
        case cJSON_Array:
        case cJSON_Object:
            break;

        default:
            return false;
    }

    /* identical objects are equal */
    if (a == b)
    {
        return true;
    }

    switch (a->type & 0xFF)
    {
        /* in these cases and equal type is enough */
        case cJSON_False:
        case cJSON_True:
        case cJSON_NULL:
            return true;

        case cJSON_Number:
            if (a->valuedouble == b->valuedouble)
            {
                return true;
            }
            return false;

        case cJSON_String:
        case cJSON_Raw:
            if ((a->valuestring == NULL) || (b->valuestring == NULL))
            {
                return false;
            }
            if (strcmp(a->valuestring, b->valuestring) == 0)
            {
                return true;
            }

            return false;

        case cJSON_Array:
        {
M
Max Bruckner 已提交
2681 2682 2683 2684
            cJSON *a_element = a->child;
            cJSON *b_element = b->child;

            for (; (a_element != NULL) && (b_element != NULL);)
2685 2686 2687 2688 2689
            {
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }
M
Max Bruckner 已提交
2690 2691 2692

                a_element = a_element->next;
                b_element = b_element->next;
2693 2694
            }

2695 2696 2697 2698 2699
            /* one of the arrays is longer than the other */
            if (a_element != b_element) {
                return false;
            }

2700 2701 2702 2703 2704 2705
            return true;
        }

        case cJSON_Object:
        {
            cJSON *a_element = NULL;
2706
            cJSON *b_element = NULL;
2707 2708 2709
            cJSON_ArrayForEach(a_element, a)
            {
                /* TODO This has O(n^2) runtime, which is horrible! */
2710
                b_element = get_object_item(b, a_element->string, case_sensitive);
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721
                if (b_element == NULL)
                {
                    return false;
                }

                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }
            }

2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
             * TODO: Do this the proper way, this is just a fix for now */
            cJSON_ArrayForEach(b_element, b)
            {
                a_element = get_object_item(a, b_element->string, case_sensitive);
                if (a_element == NULL)
                {
                    return false;
                }

                if (!cJSON_Compare(b_element, a_element, case_sensitive))
                {
                    return false;
                }
            }

2738 2739 2740 2741 2742 2743 2744
            return true;
        }

        default:
            return false;
    }
}
2745 2746 2747 2748 2749 2750 2751 2752 2753 2754

CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
{
    return global_hooks.allocate(size);
}

CJSON_PUBLIC(void) cJSON_free(void *object)
{
    global_hooks.deallocate(object);
}