cJSON.c 71.5 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
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
46 47

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

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

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

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

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

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

M
Max Bruckner 已提交
75 76 77 78 79 80 81 82
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
    if (!cJSON_IsString(item)) {
        return NULL;
    }

    return item->valuestring;
}

83
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
M
Max Bruckner 已提交
84
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 7)
85 86 87
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif

88
CJSON_PUBLIC(const char*) cJSON_Version(void)
89 90 91 92 93 94 95
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

96 97
/* 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 已提交
98
{
99
    if ((string1 == NULL) || (string2 == NULL))
M
Max Bruckner 已提交
100
    {
101
        return 1;
M
Max Bruckner 已提交
102
    }
103

104
    if (string1 == string2)
M
Max Bruckner 已提交
105
    {
106
        return 0;
M
Max Bruckner 已提交
107
    }
108 109

    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
M
Max Bruckner 已提交
110
    {
111
        if (*string1 == '\0')
M
Max Bruckner 已提交
112 113 114 115 116
        {
            return 0;
        }
    }

117
    return tolower(*string1) - tolower(*string2);
K
Kevin Branigan 已提交
118 119
}

120 121 122 123 124 125 126
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 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
#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 已提交
148

M
Max Bruckner 已提交
149
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
150
{
M
Max Bruckner 已提交
151
    size_t length = 0;
152
    unsigned char *copy = NULL;
K
Kevin Branigan 已提交
153

M
Max Bruckner 已提交
154
    if (string == NULL)
155 156 157 158
    {
        return NULL;
    }

M
Max Bruckner 已提交
159
    length = strlen((const char*)string) + sizeof("");
160 161
    copy = (unsigned char*)hooks->allocate(length);
    if (copy == NULL)
M
Max Bruckner 已提交
162
    {
163
        return NULL;
M
Max Bruckner 已提交
164
    }
M
Max Bruckner 已提交
165
    memcpy(copy, string, length);
M
Max Bruckner 已提交
166 167

    return copy;
K
Kevin Branigan 已提交
168 169
}

170
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
K
Kevin Branigan 已提交
171
{
M
Max Bruckner 已提交
172
    if (hooks == NULL)
M
Max Bruckner 已提交
173 174
    {
        /* Reset hooks */
175 176 177
        global_hooks.allocate = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
K
Kevin Branigan 已提交
178 179 180
        return;
    }

181
    global_hooks.allocate = malloc;
M
Max Bruckner 已提交
182 183
    if (hooks->malloc_fn != NULL)
    {
184
        global_hooks.allocate = hooks->malloc_fn;
M
Max Bruckner 已提交
185 186
    }

187
    global_hooks.deallocate = free;
M
Max Bruckner 已提交
188 189
    if (hooks->free_fn != NULL)
    {
190
        global_hooks.deallocate = hooks->free_fn;
M
Max Bruckner 已提交
191 192 193
    }

    /* use realloc only if both free and malloc are used */
194 195
    global_hooks.reallocate = NULL;
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
M
Max Bruckner 已提交
196
    {
197
        global_hooks.reallocate = realloc;
M
Max Bruckner 已提交
198
    }
K
Kevin Branigan 已提交
199 200 201
}

/* Internal constructor. */
202
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
K
Kevin Branigan 已提交
203
{
204
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
M
Max Bruckner 已提交
205 206
    if (node)
    {
207
        memset(node, '\0', sizeof(cJSON));
M
Max Bruckner 已提交
208 209 210
    }

    return node;
K
Kevin Branigan 已提交
211 212 213
}

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

237 238 239
/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
240
#ifdef ENABLE_LOCALES
241 242
    struct lconv *lconv = localeconv();
    return (unsigned char) lconv->decimal_point[0];
243
#else
244
    return '.';
245
#endif
246 247
}

M
Max Bruckner 已提交
248 249 250 251 252
typedef struct
{
    const unsigned char *content;
    size_t length;
    size_t offset;
253
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
254
    internal_hooks hooks;
M
Max Bruckner 已提交
255 256 257 258 259 260 261 262 263 264
} 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 已提交
265
/* Parse the input text to generate a number, and populate the result into item. */
266
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
267
{
268
    double number = 0;
269
    unsigned char *after_end = NULL;
270 271 272
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
273

M
Max Bruckner 已提交
274
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
275
    {
276
        return false;
277 278
    }

279
    /* copy the number into a temporary buffer and replace '.' with the decimal point
M
Max Bruckner 已提交
280 281 282
     * 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++)
283
    {
M
Max Bruckner 已提交
284
        switch (buffer_at_offset(input_buffer)[i])
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
        {
            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 已提交
300
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
                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 已提交
316
    {
317
        return false; /* parse_error */
M
Max Bruckner 已提交
318 319
    }

320
    item->valuedouble = number;
M
Max Bruckner 已提交
321

322
    /* use saturation in case of overflow */
323
    if (number >= INT_MAX)
324 325 326
    {
        item->valueint = INT_MAX;
    }
327
    else if (number <= INT_MIN)
328 329 330 331 332
    {
        item->valueint = INT_MIN;
    }
    else
    {
333
        item->valueint = (int)number;
334
    }
335

M
Max Bruckner 已提交
336 337
    item->type = cJSON_Number;

M
Max Bruckner 已提交
338
    input_buffer->offset += (size_t)(after_end - number_c_string);
339
    return true;
K
Kevin Branigan 已提交
340 341
}

342
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
343
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
344 345 346 347 348 349 350 351 352 353 354
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
355
        object->valueint = (int)number;
356 357 358 359 360
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
361 362
typedef struct
{
363
    unsigned char *buffer;
364 365
    size_t length;
    size_t offset;
M
Max Bruckner 已提交
366
    size_t depth; /* current nesting depth (for formatted printing) */
367
    cJSON_bool noalloc;
M
Max Bruckner 已提交
368
    cJSON_bool format; /* is this print a formatted print */
369
    internal_hooks hooks;
M
Max Bruckner 已提交
370
} printbuffer;
371

M
Max Bruckner 已提交
372
/* realloc printbuffer if necessary to have at least "needed" bytes more */
373
static unsigned char* ensure(printbuffer * const p, size_t needed)
374
{
375
    unsigned char *newbuffer = NULL;
376 377
    size_t newsize = 0;

378
    if ((p == NULL) || (p->buffer == NULL))
379 380 381 382
    {
        return NULL;
    }

M
Max Bruckner 已提交
383 384 385 386 387 388
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

389
    if (needed > INT_MAX)
M
Max Bruckner 已提交
390
    {
391
        /* sizes bigger than INT_MAX are currently not supported */
392
        return NULL;
M
Max Bruckner 已提交
393
    }
394

395
    needed += p->offset + 1;
M
Max Bruckner 已提交
396 397 398 399 400
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

401 402 403 404
    if (p->noalloc) {
        return NULL;
    }

405
    /* calculate new buffer size */
M
Max Bruckner 已提交
406
    if (needed > (INT_MAX / 2))
407 408 409 410 411 412 413 414 415 416 417
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
418 419 420 421
    else
    {
        newsize = needed * 2;
    }
422

423
    if (p->hooks.reallocate != NULL)
M
Max Bruckner 已提交
424
    {
M
Max Bruckner 已提交
425
        /* reallocate with realloc if available */
426
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
427 428 429 430 431 432 433 434
        if (newbuffer == NULL)
        {
            p->hooks.deallocate(p->buffer);
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
M
Max Bruckner 已提交
435
    }
M
Max Bruckner 已提交
436
    else
M
Max Bruckner 已提交
437
    {
M
Max Bruckner 已提交
438
        /* otherwise reallocate manually */
439
        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
M
Max Bruckner 已提交
440 441
        if (!newbuffer)
        {
442
            p->hooks.deallocate(p->buffer);
M
Max Bruckner 已提交
443 444 445 446 447 448 449
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
450
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
451
        }
452
        p->hooks.deallocate(p->buffer);
M
Max Bruckner 已提交
453 454 455 456 457
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
458 459
}

460 461
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
462
{
463 464
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
465
    {
466
        return;
M
Max Bruckner 已提交
467
    }
468
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
469

470
    buffer->offset += strlen((const char*)buffer_pointer);
471 472 473
}

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

M
Max Bruckner 已提交
484
    if (output_buffer == NULL)
M
Max Bruckner 已提交
485
    {
486
        return false;
M
Max Bruckner 已提交
487
    }
M
Max Bruckner 已提交
488

489 490 491
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
492
        length = sprintf((char*)number_buffer, "null");
493 494 495
    }
    else
    {
496 497 498 499 500 501 502 503 504
        /* 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 已提交
505
    }
506

507 508
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
509
    {
510
        return false;
511 512
    }

513
    /* reserve appropriate space in the output */
514
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
515 516 517
    if (output_pointer == NULL)
    {
        return false;
518 519
    }

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
    /* 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;

536
    return true;
K
Kevin Branigan 已提交
537 538
}

M
Max Bruckner 已提交
539
/* parse 4 digit hexadecimal number */
540
static unsigned parse_hex4(const unsigned char * const input)
541
{
M
Max Bruckner 已提交
542
    unsigned int h = 0;
543
    size_t i = 0;
M
Max Bruckner 已提交
544

545
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
546
    {
547
        /* parse digit */
548
        if ((input[i] >= '0') && (input[i] <= '9'))
549
        {
550
            h += (unsigned int) input[i] - '0';
551
        }
552
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
553
        {
554
            h += (unsigned int) 10 + input[i] - 'A';
555
        }
556
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
557
        {
558
            h += (unsigned int) 10 + input[i] - 'a';
559 560 561 562 563
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
564

565 566 567 568 569
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
570 571 572
    }

    return h;
573 574
}

575 576
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
577
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 已提交
578
{
579 580 581
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
582
    unsigned char utf8_length = 0;
583
    unsigned char utf8_position = 0;
584
    unsigned char sequence_length = 0;
585
    unsigned char first_byte_mark = 0;
586 587 588 589 590 591

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

593 594 595
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

596
    /* check that the code is valid */
597
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
M
Max Bruckner 已提交
598
    {
599
        goto fail;
M
Max Bruckner 已提交
600
    }
M
Max Bruckner 已提交
601

602 603
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
604
    {
605 606 607 608 609
        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 已提交
610
        {
611 612
            /* input ends unexpectedly */
            goto fail;
M
Max Bruckner 已提交
613
        }
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637

        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 已提交
638
    }
M
Max Bruckner 已提交
639

640 641 642 643 644 645 646 647 648 649 650 651
    /* 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;
652
        first_byte_mark = 0xC0; /* 11000000 */
653 654 655 656 657
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
658
        first_byte_mark = 0xE0; /* 11100000 */
659 660 661 662 663
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
664
        first_byte_mark = 0xF0; /* 11110000 */
665 666
    }
    else
M
Max Bruckner 已提交
667
    {
668
        /* invalid unicode codepoint */
669
        goto fail;
M
Max Bruckner 已提交
670 671
    }

672
    /* encode as utf8 */
673 674 675 676 677
    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;
678
    }
679 680 681 682 683 684 685 686
    /* 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);
687
    }
688

689 690 691 692 693 694 695 696 697
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
698
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
699
{
M
Max Bruckner 已提交
700 701
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
702 703 704 705
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
M
Max Bruckner 已提交
706
    if (buffer_at_offset(input_buffer)[0] != '\"')
707 708 709 710 711 712 713 714
    {
        goto fail;
    }

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

        /* This is at most how much we need for the output */
M
Max Bruckner 已提交
736
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
737
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
738 739 740 741 742 743 744
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
745
    /* loop through the string literal */
746
    while (input_pointer < input_end)
M
Max Bruckner 已提交
747
    {
748
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
749
        {
750
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
751 752 753 754
        }
        /* escape sequence */
        else
        {
755
            unsigned char sequence_length = 2;
M
Max Bruckner 已提交
756 757 758 759 760
            if ((input_end - input_pointer) < 1)
            {
                goto fail;
            }

761
            switch (input_pointer[1])
M
Max Bruckner 已提交
762 763
            {
                case 'b':
764
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
765 766
                    break;
                case 'f':
767
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
768 769
                    break;
                case 'n':
770
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
771 772
                    break;
                case 'r':
773
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
774 775
                    break;
                case 't':
776
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
777
                    break;
778 779 780
                case '\"':
                case '\\':
                case '/':
781
                    *output_pointer++ = input_pointer[1];
782
                    break;
783 784

                /* UTF-16 literal */
M
Max Bruckner 已提交
785
                case 'u':
786
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
787
                    if (sequence_length == 0)
M
Max Bruckner 已提交
788
                    {
789
                        /* failed to convert UTF16-literal to UTF-8 */
790
                        goto fail;
M
Max Bruckner 已提交
791 792
                    }
                    break;
793

M
Max Bruckner 已提交
794
                default:
795
                    goto fail;
M
Max Bruckner 已提交
796
            }
797
            input_pointer += sequence_length;
M
Max Bruckner 已提交
798 799
        }
    }
800 801 802

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

804
    item->type = cJSON_String;
805
    item->valuestring = (char*)output;
806

M
Max Bruckner 已提交
807 808 809
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

810
    return true;
811 812

fail:
813
    if (output != NULL)
814
    {
815
        input_buffer->hooks.deallocate(output);
816 817
    }

818 819 820 821 822
    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

823
    return false;
K
Kevin Branigan 已提交
824 825 826
}

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

836
    if (output_buffer == NULL)
M
Max Bruckner 已提交
837
    {
838
        return false;
M
Max Bruckner 已提交
839 840 841
    }

    /* empty string */
842
    if (input == NULL)
M
Max Bruckner 已提交
843
    {
844
        output = ensure(output_buffer, sizeof("\"\""));
845
        if (output == NULL)
M
Max Bruckner 已提交
846
        {
847
            return false;
M
Max Bruckner 已提交
848
        }
849
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
850

851
        return true;
M
Max Bruckner 已提交
852 853 854
    }

    /* set "flag" to 1 if something needs to be escaped */
855
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
856
    {
M
Max Bruckner 已提交
857
        switch (*input_pointer)
M
Max Bruckner 已提交
858
        {
M
Max Bruckner 已提交
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
            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 已提交
876 877
        }
    }
M
Max Bruckner 已提交
878
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
879

880
    output = ensure(output_buffer, output_length + sizeof("\"\""));
881
    if (output == NULL)
M
Max Bruckner 已提交
882
    {
883
        return false;
M
Max Bruckner 已提交
884 885
    }

M
Max Bruckner 已提交
886 887
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
888
    {
M
Max Bruckner 已提交
889 890 891 892 893
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

894
        return true;
M
Max Bruckner 已提交
895 896
    }

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

945
    return true;
K
Kevin Branigan 已提交
946
}
M
Max Bruckner 已提交
947

M
Max Bruckner 已提交
948
/* Invoke print_string_ptr (which is useful) on an item. */
949
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
M
Max Bruckner 已提交
950
{
951
    return print_string_ptr((unsigned char*)item->valuestring, p);
M
Max Bruckner 已提交
952
}
K
Kevin Branigan 已提交
953 954

/* Predeclare these prototypes. */
955 956 957 958 959 960
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 已提交
961 962

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
963
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
M
Max Bruckner 已提交
964
{
M
Max Bruckner 已提交
965 966 967 968 969
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        return NULL;
    }

M
Max Bruckner 已提交
970 971 972 973 974 975
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
    {
       buffer->offset++;
    }

    if (buffer->offset == buffer->length)
M
Max Bruckner 已提交
976
    {
M
Max Bruckner 已提交
977
        buffer->offset--;
M
Max Bruckner 已提交
978 979
    }

M
Max Bruckner 已提交
980
    return buffer;
M
Max Bruckner 已提交
981
}
K
Kevin Branigan 已提交
982

983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
/* 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 已提交
999
/* Parse an object - create a new root, and populate. */
1000
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
1001
{
1002
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1003
    cJSON *item = NULL;
1004 1005 1006 1007

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;
1008 1009

    if (value == NULL)
M
Max Bruckner 已提交
1010
    {
1011
        goto fail;
M
Max Bruckner 已提交
1012 1013
    }

M
Max Bruckner 已提交
1014 1015 1016
    buffer.content = (const unsigned char*)value;
    buffer.length = strlen((const char*)value) + sizeof("");
    buffer.offset = 0;
1017
    buffer.hooks = global_hooks;
M
Max Bruckner 已提交
1018

1019 1020 1021 1022
    item = cJSON_New_Item(&global_hooks);
    if (item == NULL) /* memory fail */
    {
        goto fail;
M
Max Bruckner 已提交
1023 1024
    }

1025
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
M
Max Bruckner 已提交
1026 1027
    {
        /* parse failure. ep is set. */
1028
        goto fail;
M
Max Bruckner 已提交
1029 1030 1031 1032 1033
    }

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

1045
    return item;
1046 1047 1048 1049 1050 1051 1052

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

1053 1054
    if (value != NULL)
    {
1055 1056 1057 1058
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

1059 1060
        if (buffer.offset < buffer.length)
        {
1061
            local_error.position = buffer.offset;
1062 1063 1064
        }
        else if (buffer.length > 0)
        {
1065 1066 1067 1068 1069 1070 1071
            local_error.position = buffer.length - 1;
        }

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

1073
        global_error = local_error;
M
Max Bruckner 已提交
1074 1075
    }

1076
    return NULL;
K
Kevin Branigan 已提交
1077
}
M
Max Bruckner 已提交
1078

1079
/* Default options for cJSON_Parse */
1080
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
1081 1082 1083
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
1084

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

1087
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1088
{
1089
    static const size_t default_buffer_size = 256;
M
Max Bruckner 已提交
1090 1091 1092 1093 1094 1095
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
1096 1097
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
    buffer->length = default_buffer_size;
M
Max Bruckner 已提交
1098
    buffer->format = format;
1099
    buffer->hooks = *hooks;
M
Max Bruckner 已提交
1100 1101 1102 1103 1104 1105
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
1106
    if (!print_value(item, buffer))
M
Max Bruckner 已提交
1107 1108 1109
    {
        goto fail;
    }
1110
    update_offset(buffer);
M
Max Bruckner 已提交
1111

1112 1113
    /* check if reallocate is available */
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
1114
    {
1115
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1116 1117 1118
        if (printed == NULL) {
            goto fail;
        }
1119
        buffer->buffer = NULL;
M
Max Bruckner 已提交
1120
    }
1121 1122 1123 1124 1125 1126 1127
    else /* otherwise copy the JSON over to a new buffer */
    {
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
        if (printed == NULL)
        {
            goto fail;
        }
1128
        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1129
        printed[buffer->offset] = '\0'; /* just to be sure */
M
Max Bruckner 已提交
1130

1131 1132 1133
        /* free the buffer */
        hooks->deallocate(buffer->buffer);
    }
M
Max Bruckner 已提交
1134 1135 1136 1137 1138 1139

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1140
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1141 1142 1143 1144
    }

    if (printed != NULL)
    {
1145
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1146 1147 1148 1149 1150
    }

    return NULL;
}

K
Kevin Branigan 已提交
1151
/* Render a cJSON item/entity/structure to text. */
1152
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1153
{
1154
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1155 1156
}

1157
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1158
{
1159
    return (char*)print(item, false, &global_hooks);
1160
}
1161

1162
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1163
{
1164
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
M
Max Bruckner 已提交
1165 1166 1167

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1168
        return NULL;
M
Max Bruckner 已提交
1169 1170
    }

1171
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1172 1173
    if (!p.buffer)
    {
1174
        return NULL;
1175
    }
M
Max Bruckner 已提交
1176 1177

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1178
    p.offset = 0;
1179
    p.noalloc = false;
M
Max Bruckner 已提交
1180
    p.format = fmt;
1181
    p.hooks = global_hooks;
M
Max Bruckner 已提交
1182

1183
    if (!print_value(item, &p))
1184
    {
1185
        global_hooks.deallocate(p.buffer);
1186 1187 1188 1189
        return NULL;
    }

    return (char*)p.buffer;
1190 1191
}

1192
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1193
{
1194
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
M
Max Bruckner 已提交
1195

1196
    if ((len < 0) || (buf == NULL))
M
Max Bruckner 已提交
1197 1198 1199 1200
    {
        return false;
    }

1201
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1202
    p.length = (size_t)len;
1203
    p.offset = 0;
1204
    p.noalloc = true;
M
Max Bruckner 已提交
1205
    p.format = fmt;
1206
    p.hooks = global_hooks;
M
Max Bruckner 已提交
1207

1208
    return print_value(item, &p);
1209
}
K
Kevin Branigan 已提交
1210 1211

/* Parser core - when encountering text, process appropriately. */
1212
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1213
{
M
Max Bruckner 已提交
1214
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
M
Max Bruckner 已提交
1215
    {
1216
        return false; /* no input */
M
Max Bruckner 已提交
1217 1218 1219
    }

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

1263
    return false;
K
Kevin Branigan 已提交
1264 1265 1266
}

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

M
Max Bruckner 已提交
1271
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1272
    {
1273
        return false;
M
Max Bruckner 已提交
1274
    }
M
Max Bruckner 已提交
1275 1276

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1277
    {
M
Max Bruckner 已提交
1278
        case cJSON_NULL:
1279
            output = ensure(output_buffer, 5);
1280
            if (output == NULL)
M
Max Bruckner 已提交
1281
            {
1282
                return false;
M
Max Bruckner 已提交
1283
            }
1284 1285 1286
            strcpy((char*)output, "null");
            return true;

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

M
Max Bruckner 已提交
1296
        case cJSON_True:
1297
            output = ensure(output_buffer, 5);
1298
            if (output == NULL)
M
Max Bruckner 已提交
1299
            {
1300
                return false;
M
Max Bruckner 已提交
1301
            }
1302 1303 1304
            strcpy((char*)output, "true");
            return true;

M
Max Bruckner 已提交
1305
        case cJSON_Number:
1306
            return print_number(item, output_buffer);
1307

M
Max Bruckner 已提交
1308
        case cJSON_Raw:
M
Max Bruckner 已提交
1309
        {
M
Max Bruckner 已提交
1310 1311
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1312
            {
1313
                return false;
M
Max Bruckner 已提交
1314
            }
1315

1316
            raw_length = strlen(item->valuestring) + sizeof("");
1317
            output = ensure(output_buffer, raw_length);
1318
            if (output == NULL)
M
Max Bruckner 已提交
1319
            {
1320
                return false;
1321
            }
1322 1323
            memcpy(output, item->valuestring, raw_length);
            return true;
M
Max Bruckner 已提交
1324
        }
1325

M
Max Bruckner 已提交
1326
        case cJSON_String:
1327
            return print_string(item, output_buffer);
1328

M
Max Bruckner 已提交
1329
        case cJSON_Array:
1330
            return print_array(item, output_buffer);
1331

M
Max Bruckner 已提交
1332
        case cJSON_Object:
1333
            return print_object(item, output_buffer);
1334

M
Max Bruckner 已提交
1335
        default:
1336
            return false;
M
Max Bruckner 已提交
1337
    }
K
Kevin Branigan 已提交
1338 1339 1340
}

/* Build an array from input text. */
1341
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1342
{
1343
    cJSON *head = NULL; /* head of the linked list */
1344 1345
    cJSON *current_item = NULL;

1346 1347 1348 1349 1350 1351
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

M
Max Bruckner 已提交
1352
    if (buffer_at_offset(input_buffer)[0] != '[')
M
Max Bruckner 已提交
1353
    {
1354
        /* not an array */
1355
        goto fail;
M
Max Bruckner 已提交
1356
    }
K
Kevin Branigan 已提交
1357

M
Max Bruckner 已提交
1358 1359 1360
    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 已提交
1361
    {
1362
        /* empty array */
1363
        goto success;
M
Max Bruckner 已提交
1364
    }
K
Kevin Branigan 已提交
1365

M
Max Bruckner 已提交
1366 1367 1368 1369 1370 1371 1372
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

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

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1387
        {
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
            /* 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 已提交
1400 1401
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1402
        if (!parse_value(current_item, input_buffer))
1403 1404
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1405
        }
M
Max Bruckner 已提交
1406
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1407
    }
M
Max Bruckner 已提交
1408
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
M
Max Bruckner 已提交
1409

M
Max Bruckner 已提交
1410
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
M
Max Bruckner 已提交
1411
    {
1412
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1413 1414
    }

1415
success:
1416 1417
    input_buffer->depth--;

1418
    item->type = cJSON_Array;
1419
    item->child = head;
1420

M
Max Bruckner 已提交
1421 1422
    input_buffer->offset++;

1423
    return true;
K
Kevin Branigan 已提交
1424

1425
fail:
1426
    if (head != NULL)
1427
    {
1428
        cJSON_Delete(head);
1429 1430
    }

1431
    return false;
K
Kevin Branigan 已提交
1432 1433 1434
}

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

M
Max Bruckner 已提交
1441
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1442
    {
1443
        return false;
M
Max Bruckner 已提交
1444 1445
    }

M
Max Bruckner 已提交
1446 1447
    /* Compose the output array. */
    /* opening square bracket */
1448
    output_pointer = ensure(output_buffer, 1);
M
Max Bruckner 已提交
1449
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1450
    {
1451
        return false;
M
Max Bruckner 已提交
1452 1453
    }

M
Max Bruckner 已提交
1454 1455
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1456
    output_buffer->depth++;
M
Max Bruckner 已提交
1457

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

1484
    output_pointer = ensure(output_buffer, 2);
M
Max Bruckner 已提交
1485
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1486
    {
1487
        return false;
M
Max Bruckner 已提交
1488
    }
M
Max Bruckner 已提交
1489 1490
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1491
    output_buffer->depth--;
M
Max Bruckner 已提交
1492

1493
    return true;
K
Kevin Branigan 已提交
1494 1495 1496
}

/* Build an object from the text. */
1497
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
1498
{
1499
    cJSON *head = NULL; /* linked list head */
1500 1501
    cJSON *current_item = NULL;

1502 1503 1504 1505 1506 1507
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

M
Max Bruckner 已提交
1508
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
M
Max Bruckner 已提交
1509
    {
1510
        goto fail; /* not an object */
M
Max Bruckner 已提交
1511 1512
    }

M
Max Bruckner 已提交
1513 1514 1515
    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 已提交
1516
    {
1517
        goto success; /* empty object */
M
Max Bruckner 已提交
1518 1519
    }

M
Max Bruckner 已提交
1520 1521 1522 1523 1524 1525 1526
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

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

1539 1540
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1541
        {
1542 1543 1544 1545 1546 1547 1548 1549 1550
            /* 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 已提交
1551 1552
        }

1553
        /* parse the name of the child */
M
Max Bruckner 已提交
1554 1555
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1556
        if (!parse_string(current_item, input_buffer))
M
Max Bruckner 已提交
1557
        {
1558
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1559
        }
M
Max Bruckner 已提交
1560
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1561

1562 1563 1564
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1565

M
Max Bruckner 已提交
1566
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
M
Max Bruckner 已提交
1567
        {
1568
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1569
        }
1570 1571

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

M
Max Bruckner 已提交
1582
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
M
Max Bruckner 已提交
1583
    {
1584
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1585 1586
    }

1587
success:
1588 1589
    input_buffer->depth--;

1590
    item->type = cJSON_Object;
1591
    item->child = head;
1592

M
Max Bruckner 已提交
1593
    input_buffer->offset++;
1594
    return true;
1595 1596

fail:
1597
    if (head != NULL)
1598
    {
1599
        cJSON_Delete(head);
1600 1601
    }

1602
    return false;
K
Kevin Branigan 已提交
1603 1604 1605
}

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

M
Max Bruckner 已提交
1612
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1613
    {
1614
        return false;
M
Max Bruckner 已提交
1615 1616
    }

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

M
Max Bruckner 已提交
1625
    *output_pointer++ = '{';
M
Max Bruckner 已提交
1626
    output_buffer->depth++;
M
Max Bruckner 已提交
1627
    if (output_buffer->format)
M
Max Bruckner 已提交
1628
    {
M
Max Bruckner 已提交
1629
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1630
    }
M
Max Bruckner 已提交
1631
    output_buffer->offset += length;
M
Max Bruckner 已提交
1632

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

M
Max Bruckner 已提交
1650
        /* print key */
1651
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
M
Max Bruckner 已提交
1652
        {
1653
            return false;
M
Max Bruckner 已提交
1654
        }
M
Max Bruckner 已提交
1655
        update_offset(output_buffer);
M
Max Bruckner 已提交
1656

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

M
Max Bruckner 已提交
1670
        /* print value */
1671
        if (!print_value(current_item, output_buffer))
M
Max Bruckner 已提交
1672
        {
1673
            return false;
M
Max Bruckner 已提交
1674
        }
M
Max Bruckner 已提交
1675
        update_offset(output_buffer);
M
Max Bruckner 已提交
1676

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

M
Max Bruckner 已提交
1689
        if (output_buffer->format)
M
Max Bruckner 已提交
1690
        {
M
Max Bruckner 已提交
1691
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1692
        }
M
Max Bruckner 已提交
1693 1694
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1695

M
Max Bruckner 已提交
1696
        current_item = current_item->next;
M
Max Bruckner 已提交
1697
    }
M
Max Bruckner 已提交
1698

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

1716
    return true;
K
Kevin Branigan 已提交
1717 1718 1719
}

/* Get Array size/item / object item. */
1720
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1721
{
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732
    cJSON *child = NULL;
    size_t size = 0;

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

    child = array->child;

    while(child != NULL)
M
Max Bruckner 已提交
1733
    {
1734 1735
        size++;
        child = child->next;
M
Max Bruckner 已提交
1736
    }
1737 1738 1739

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

1740
    return (int)size;
M
Max Bruckner 已提交
1741 1742
}

M
Max Bruckner 已提交
1743
static cJSON* get_array_item(const cJSON *array, size_t index)
M
Max Bruckner 已提交
1744
{
M
Max Bruckner 已提交
1745 1746 1747
    cJSON *current_child = NULL;

    if (array == NULL)
M
Max Bruckner 已提交
1748
    {
M
Max Bruckner 已提交
1749
        return NULL;
M
Max Bruckner 已提交
1750 1751
    }

M
Max Bruckner 已提交
1752 1753 1754 1755 1756 1757 1758 1759
    current_child = array->child;
    while ((current_child != NULL) && (index > 0))
    {
        index--;
        current_child = current_child->next;
    }

    return current_child;
M
Max Bruckner 已提交
1760 1761
}

M
Max Bruckner 已提交
1762
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
M
Max Bruckner 已提交
1763
{
M
Max Bruckner 已提交
1764
    if (index < 0)
M
Max Bruckner 已提交
1765
    {
M
Max Bruckner 已提交
1766
        return NULL;
M
Max Bruckner 已提交
1767
    }
M
Max Bruckner 已提交
1768

M
Max Bruckner 已提交
1769
    return get_array_item(array, (size_t)index);
M
Max Bruckner 已提交
1770 1771
}

1772
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1773 1774 1775
{
    cJSON *current_element = NULL;

1776
    if ((object == NULL) || (name == NULL))
1777 1778 1779 1780 1781
    {
        return NULL;
    }

    current_element = object->child;
1782
    if (case_sensitive)
1783
    {
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
        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;
        }
1795 1796 1797 1798 1799
    }

    return current_element;
}

1800
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1801 1802 1803 1804 1805 1806 1807 1808 1809
{
    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);
}

1810
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1811 1812 1813
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1814 1815

/* Utility for array list handling. */
M
Max Bruckner 已提交
1816 1817 1818 1819 1820 1821
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

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

    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 已提交
1842
}
K
Kevin Branigan 已提交
1843

1844
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1845
{
1846 1847 1848
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1849
    {
1850
        return false;
M
Max Bruckner 已提交
1851
    }
1852 1853 1854 1855

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1856 1857 1858 1859 1860 1861 1862
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1863
        while (child->next)
M
Max Bruckner 已提交
1864
        {
1865
            child = child->next;
M
Max Bruckner 已提交
1866
        }
1867
        suffix_object(child, item);
M
Max Bruckner 已提交
1868
    }
1869 1870 1871 1872 1873 1874 1875 1876

    return true;
}

/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
    add_item_to_array(array, item);
M
Max Bruckner 已提交
1877 1878
}

1879
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1880 1881
    #pragma GCC diagnostic push
#endif
1882
#ifdef __GNUC__
1883
#pragma GCC diagnostic ignored "-Wcast-qual"
1884
#endif
1885
/* helper function to cast away const */
1886
static void* cast_away_const(const void* string)
1887
{
1888
    return (void*)string;
1889 1890 1891 1892
}
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic pop
#endif
1893

1894 1895

static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
1896
{
1897 1898 1899
    char *new_key = NULL;
    int new_type = cJSON_Invalid;

1900
    if ((object == NULL) || (string == NULL) || (item == NULL))
1901
    {
1902
        return false;
1903
    }
1904 1905

    if (constant_key)
1906
    {
1907 1908
        new_key = (char*)cast_away_const(string);
        new_type = item->type | cJSON_StringIsConst;
1909
    }
1910 1911
    else
    {
1912 1913
        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
        if (new_key == NULL)
1914 1915 1916 1917
        {
            return false;
        }

1918
        new_type = item->type & ~cJSON_StringIsConst;
1919 1920
    }

1921 1922 1923 1924 1925 1926 1927 1928
    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
    {
        hooks->deallocate(item->string);
    }

    item->string = new_key;
    item->type = new_type;

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940
    return add_item_to_array(object, item);
}

CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
    add_item_to_object(object, string, item, &global_hooks, false);
}

/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
    add_item_to_object(object, string, item, &global_hooks, true);
1941 1942
}

1943
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1944
{
1945 1946 1947 1948 1949
    if (array == NULL)
    {
        return;
    }

1950
    add_item_to_array(array, create_reference(item, &global_hooks));
1951 1952
}

1953
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1954
{
1955 1956 1957 1958 1959
    if ((object == NULL) || (string == NULL))
    {
        return;
    }

1960
    add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1961 1962
}

1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
{
    cJSON *null = cJSON_CreateNull();
    if (add_item_to_object(object, name, null, &global_hooks, false))
    {
        return null;
    }

    cJSON_Delete(null);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
{
    cJSON *true_item = cJSON_CreateTrue();
    if (add_item_to_object(object, name, true_item, &global_hooks, false))
    {
        return true_item;
    }

    cJSON_Delete(true_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
{
    cJSON *false_item = cJSON_CreateFalse();
    if (add_item_to_object(object, name, false_item, &global_hooks, false))
    {
        return false_item;
    }

    cJSON_Delete(false_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
{
    cJSON *bool_item = cJSON_CreateBool(boolean);
    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
    {
        return bool_item;
    }

    cJSON_Delete(bool_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
{
    cJSON *number_item = cJSON_CreateNumber(number);
    if (add_item_to_object(object, name, number_item, &global_hooks, false))
    {
        return number_item;
    }

    cJSON_Delete(number_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
{
    cJSON *string_item = cJSON_CreateString(string);
    if (add_item_to_object(object, name, string_item, &global_hooks, false))
    {
        return string_item;
    }

    cJSON_Delete(string_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
{
    cJSON *raw_item = cJSON_CreateRaw(raw);
    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
    {
        return raw_item;
    }

    cJSON_Delete(raw_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
{
    cJSON *object_item = cJSON_CreateObject();
    if (add_item_to_object(object, name, object_item, &global_hooks, false))
    {
        return object_item;
    }

    cJSON_Delete(object_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
{
    cJSON *array = cJSON_CreateArray();
    if (add_item_to_object(object, name, array, &global_hooks, false))
    {
        return array;
    }

    cJSON_Delete(array);
    return NULL;
}

M
Max Bruckner 已提交
2071
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2072
{
M
Max Bruckner 已提交
2073
    if ((parent == NULL) || (item == NULL))
2074
    {
2075
        return NULL;
2076
    }
M
Max Bruckner 已提交
2077 2078

    if (item->prev != NULL)
2079 2080
    {
        /* not the first element */
M
Max Bruckner 已提交
2081
        item->prev->next = item->next;
2082
    }
M
Max Bruckner 已提交
2083
    if (item->next != NULL)
2084
    {
M
Max Bruckner 已提交
2085 2086
        /* not the last element */
        item->next->prev = item->prev;
2087
    }
M
Max Bruckner 已提交
2088 2089

    if (item == parent->child)
2090
    {
M
Max Bruckner 已提交
2091 2092
        /* first element */
        parent->child = item->next;
2093 2094
    }
    /* make sure the detached item doesn't point anywhere anymore */
M
Max Bruckner 已提交
2095 2096
    item->prev = NULL;
    item->next = NULL;
2097

M
Max Bruckner 已提交
2098
    return item;
2099
}
M
Max Bruckner 已提交
2100

2101
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
2102 2103 2104 2105 2106 2107
{
    if (which < 0)
    {
        return NULL;
    }

M
Max Bruckner 已提交
2108
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
M
Max Bruckner 已提交
2109
}
K
Kevin Branigan 已提交
2110

2111
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2112 2113 2114 2115
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

2116
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2117
{
2118
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
2119

2120 2121 2122 2123 2124 2125
    return cJSON_DetachItemViaPointer(object, to_detach);
}

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

2127
    return cJSON_DetachItemViaPointer(object, to_detach);
2128 2129
}

2130
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2131 2132 2133
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
2134

2135 2136 2137 2138 2139
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
}

K
Kevin Branigan 已提交
2140
/* Replace array/object items with new ones. */
2141
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2142
{
M
Max Bruckner 已提交
2143 2144 2145
    cJSON *after_inserted = NULL;

    if (which < 0)
2146
    {
M
Max Bruckner 已提交
2147
        return;
2148
    }
M
Max Bruckner 已提交
2149 2150 2151

    after_inserted = get_array_item(array, (size_t)which);
    if (after_inserted == NULL)
2152
    {
2153
        add_item_to_array(array, newitem);
2154 2155
        return;
    }
M
Max Bruckner 已提交
2156 2157 2158 2159 2160

    newitem->next = after_inserted;
    newitem->prev = after_inserted->prev;
    after_inserted->prev = newitem;
    if (after_inserted == array->child)
2161 2162 2163 2164 2165 2166 2167 2168 2169
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
}

M
Max Bruckner 已提交
2170
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2171
{
2172
    if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2173
    {
M
Max Bruckner 已提交
2174
        return false;
2175
    }
M
Max Bruckner 已提交
2176

M
Max Bruckner 已提交
2177
    if (replacement == item)
2178
    {
M
Max Bruckner 已提交
2179
        return true;
2180
    }
M
Max Bruckner 已提交
2181

M
Max Bruckner 已提交
2182 2183 2184 2185
    replacement->next = item->next;
    replacement->prev = item->prev;

    if (replacement->next != NULL)
2186
    {
M
Max Bruckner 已提交
2187
        replacement->next->prev = replacement;
2188
    }
M
Max Bruckner 已提交
2189
    if (replacement->prev != NULL)
2190
    {
M
Max Bruckner 已提交
2191
        replacement->prev->next = replacement;
2192
    }
M
Max Bruckner 已提交
2193
    if (parent->child == item)
2194
    {
M
Max Bruckner 已提交
2195
        parent->child = replacement;
2196
    }
M
Max Bruckner 已提交
2197

M
Max Bruckner 已提交
2198 2199 2200
    item->next = NULL;
    item->prev = NULL;
    cJSON_Delete(item);
M
Max Bruckner 已提交
2201

M
Max Bruckner 已提交
2202
    return true;
2203
}
M
Max Bruckner 已提交
2204

2205
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
2206 2207 2208 2209 2210 2211
{
    if (which < 0)
    {
        return;
    }

M
Max Bruckner 已提交
2212
    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
M
Max Bruckner 已提交
2213
}
2214

2215 2216
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
{
2217
    if ((replacement == NULL) || (string == NULL))
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234
    {
        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;
}

2235
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2236
{
2237
    replace_item_in_object(object, string, newitem, false);
2238
}
2239

2240 2241
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
2242
    replace_item_in_object(object, string, newitem, true);
2243
}
K
Kevin Branigan 已提交
2244 2245

/* Create basic types: */
2246
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
2247
{
2248
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2249 2250 2251 2252 2253 2254 2255 2256
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

2257
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
2258
{
2259
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2260 2261 2262 2263 2264 2265 2266 2267
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

2268
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
2269
{
2270
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2271 2272 2273 2274 2275 2276 2277 2278
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

2279
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
2280
{
2281
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2282 2283 2284 2285 2286 2287 2288 2289
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

2290
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
2291
{
2292
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2293 2294 2295 2296
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310

        /* 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 已提交
2311 2312 2313 2314 2315
    }

    return item;
}

2316
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
2317
{
2318
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2319 2320 2321
    if(item)
    {
        item->type = cJSON_String;
2322
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
2323 2324 2325
        if(!item->valuestring)
        {
            cJSON_Delete(item);
2326
            return NULL;
M
Max Bruckner 已提交
2327 2328 2329 2330 2331 2332
        }
    }

    return item;
}

M
Max Bruckner 已提交
2333 2334 2335 2336 2337 2338
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL)
    {
        item->type = cJSON_String | cJSON_IsReference;
2339
        item->valuestring = (char*)cast_away_const(string);
M
Max Bruckner 已提交
2340 2341 2342 2343 2344
    }

    return item;
}

2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL) {
        item->type = cJSON_Object | cJSON_IsReference;
        item->child = (cJSON*)cast_away_const(child);
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL) {
        item->type = cJSON_Array | cJSON_IsReference;
        item->child = (cJSON*)cast_away_const(child);
    }

    return item;
}

2366
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
2367
{
2368
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2369 2370 2371
    if(item)
    {
        item->type = cJSON_Raw;
2372
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
2373 2374 2375 2376 2377 2378 2379 2380
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
2381 2382
}

2383
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
2384
{
2385
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2386 2387 2388 2389 2390 2391 2392 2393
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

2394
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
2395
{
2396
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2397 2398 2399 2400 2401 2402 2403
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
2404 2405

/* Create Arrays: */
2406
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
2407
{
2408
    size_t i = 0;
2409 2410
    cJSON *n = NULL;
    cJSON *p = NULL;
2411 2412
    cJSON *a = NULL;

2413
    if ((count < 0) || (numbers == NULL))
2414 2415 2416 2417 2418 2419
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2420 2421 2422 2423 2424
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
2425
            return NULL;
M
Max Bruckner 已提交
2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2441
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2442
{
2443
    size_t i = 0;
2444 2445
    cJSON *n = NULL;
    cJSON *p = NULL;
2446 2447
    cJSON *a = NULL;

2448
    if ((count < 0) || (numbers == NULL))
2449 2450 2451 2452 2453 2454 2455
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2456
    {
2457
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2458 2459 2460
        if(!n)
        {
            cJSON_Delete(a);
2461
            return NULL;
M
Max Bruckner 已提交
2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2477
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2478
{
2479
    size_t i = 0;
2480 2481
    cJSON *n = NULL;
    cJSON *p = NULL;
2482 2483
    cJSON *a = NULL;

2484
    if ((count < 0) || (numbers == NULL))
2485 2486 2487 2488 2489 2490 2491
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2492 2493 2494 2495 2496
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2497
            return NULL;
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2513
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2514
{
2515
    size_t i = 0;
2516 2517
    cJSON *n = NULL;
    cJSON *p = NULL;
2518 2519
    cJSON *a = NULL;

2520
    if ((count < 0) || (strings == NULL))
2521 2522 2523 2524 2525 2526 2527
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2528 2529 2530 2531 2532
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2533
            return NULL;
2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2548 2549

/* Duplication */
2550
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2551
{
M
Max Bruckner 已提交
2552
    cJSON *newitem = NULL;
2553 2554
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2555
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2556 2557 2558 2559

    /* Bail on bad ptr */
    if (!item)
    {
2560
        goto fail;
M
Max Bruckner 已提交
2561 2562
    }
    /* Create new item */
2563
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2564 2565
    if (!newitem)
    {
2566
        goto fail;
M
Max Bruckner 已提交
2567 2568 2569 2570 2571 2572 2573
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2574
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2575 2576
        if (!newitem->valuestring)
        {
2577
            goto fail;
M
Max Bruckner 已提交
2578 2579 2580 2581
        }
    }
    if (item->string)
    {
2582
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2583 2584
        if (!newitem->string)
        {
2585
            goto fail;
M
Max Bruckner 已提交
2586 2587 2588 2589 2590 2591 2592 2593
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2594 2595
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2596
    {
2597
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2598 2599
        if (!newchild)
        {
2600
            goto fail;
M
Max Bruckner 已提交
2601
        }
2602
        if (next != NULL)
M
Max Bruckner 已提交
2603 2604
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2605 2606 2607
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2608 2609 2610 2611
        }
        else
        {
            /* Set newitem->child and move to it */
2612 2613
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2614
        }
2615
        child = child->next;
M
Max Bruckner 已提交
2616 2617 2618
    }

    return newitem;
2619 2620 2621 2622 2623 2624 2625 2626

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

    return NULL;
2627
}
2628

2629
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2630
{
2631
    unsigned char *into = (unsigned char*)json;
2632 2633 2634 2635 2636 2637

    if (json == NULL)
    {
        return;
    }

M
Max Bruckner 已提交
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
    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 已提交
2677
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2678 2679 2680 2681
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2682
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2683
                }
M
Max Bruckner 已提交
2684
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2685
            }
M
Max Bruckner 已提交
2686
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2687 2688 2689 2690
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2691
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2692 2693 2694 2695 2696
        }
    }

    /* and null-terminate. */
    *into = '\0';
2697
}
2698

2699
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2700 2701 2702 2703 2704 2705 2706 2707 2708
{
    if (item == NULL)
    {
        return false;
    }

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

2709
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2710 2711 2712 2713 2714 2715 2716 2717 2718
{
    if (item == NULL)
    {
        return false;
    }

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

2719
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
{
    if (item == NULL)
    {
        return false;
    }

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


2730
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2731 2732 2733 2734 2735 2736 2737 2738
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2739
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2740 2741 2742 2743 2744 2745 2746 2747 2748
{
    if (item == NULL)
    {
        return false;
    }

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

2749
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2750 2751 2752 2753 2754 2755 2756 2757 2758
{
    if (item == NULL)
    {
        return false;
    }

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

2759
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2760 2761 2762 2763 2764 2765 2766 2767 2768
{
    if (item == NULL)
    {
        return false;
    }

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

2769
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2770 2771 2772 2773 2774 2775 2776 2777 2778
{
    if (item == NULL)
    {
        return false;
    }

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

2779
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2780 2781 2782 2783 2784 2785 2786 2787 2788
{
    if (item == NULL)
    {
        return false;
    }

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

2789
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2790 2791 2792 2793 2794 2795 2796 2797
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Raw;
}
2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858

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 已提交
2859 2860 2861 2862
            cJSON *a_element = a->child;
            cJSON *b_element = b->child;

            for (; (a_element != NULL) && (b_element != NULL);)
2863 2864 2865 2866 2867
            {
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }
M
Max Bruckner 已提交
2868 2869 2870

                a_element = a_element->next;
                b_element = b_element->next;
2871 2872
            }

2873 2874 2875 2876 2877
            /* one of the arrays is longer than the other */
            if (a_element != b_element) {
                return false;
            }

2878 2879 2880 2881 2882 2883
            return true;
        }

        case cJSON_Object:
        {
            cJSON *a_element = NULL;
2884
            cJSON *b_element = NULL;
2885 2886 2887
            cJSON_ArrayForEach(a_element, a)
            {
                /* TODO This has O(n^2) runtime, which is horrible! */
2888
                b_element = get_object_item(b, a_element->string, case_sensitive);
2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899
                if (b_element == NULL)
                {
                    return false;
                }

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

2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915
            /* 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;
                }
            }

2916 2917 2918 2919 2920 2921 2922
            return true;
        }

        default:
            return false;
    }
}
2923 2924 2925 2926 2927 2928 2929 2930 2931 2932

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

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