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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return item->valuestring;
}

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

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

    return version;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return object->valuedouble = number;
}

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

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

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

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

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

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

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

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

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

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

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

    return newbuffer + p->offset;
459 460
}

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

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

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

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

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

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

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

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

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

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

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

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

    return h;
574 575
}

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

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

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

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

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

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

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

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

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

    return sequence_length;

fail:
    return 0;
}

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

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

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

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

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

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

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

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

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

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

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

811
    return true;
812 813

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1046
    return item;
1047 1048 1049 1050 1051 1052 1053

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return printed;

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

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

    return NULL;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1424
    return true;
K
Kevin Branigan 已提交
1425

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    child = array->child;

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

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

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

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

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

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

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

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

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

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

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

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

    return current_element;
}

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

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

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

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

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

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

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

    child = array->child;

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

    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 已提交
1878 1879
}

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

1895 1896

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)
1897
{
1898
    if ((object == NULL) || (string == NULL) || (item == NULL))
1899
    {
1900
        return false;
1901
    }
1902 1903 1904 1905 1906 1907 1908

    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
    {
        hooks->deallocate(item->string);
    }

    if (constant_key)
1909
    {
1910 1911
        item->string = (char*)cast_away_const(string);
        item->type |= cJSON_StringIsConst;
1912
    }
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936
    else
    {
        char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
        if (key == NULL)
        {
            return false;
        }

        item->string = key;
        item->type &= ~cJSON_StringIsConst;
    }

    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);
1937 1938
}

1939
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1940
{
1941 1942 1943 1944 1945
    if (array == NULL)
    {
        return;
    }

1946
    add_item_to_array(array, create_reference(item, &global_hooks));
1947 1948
}

1949
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1950
{
1951 1952 1953 1954 1955
    if ((object == NULL) || (string == NULL))
    {
        return;
    }

1956
    add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1957 1958
}

1959 1960 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
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 已提交
2067
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2068
{
M
Max Bruckner 已提交
2069
    if ((parent == NULL) || (item == NULL))
2070
    {
2071
        return NULL;
2072
    }
M
Max Bruckner 已提交
2073 2074

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

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

M
Max Bruckner 已提交
2094
    return item;
2095
}
M
Max Bruckner 已提交
2096

2097
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
2098 2099 2100 2101 2102 2103
{
    if (which < 0)
    {
        return NULL;
    }

M
Max Bruckner 已提交
2104
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
M
Max Bruckner 已提交
2105
}
K
Kevin Branigan 已提交
2106

2107
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2108 2109 2110 2111
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

2112
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2113
{
2114
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
2115

2116 2117 2118 2119 2120 2121
    return cJSON_DetachItemViaPointer(object, to_detach);
}

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

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

2126
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2127 2128 2129
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
2130

2131 2132 2133 2134 2135
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
}

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

    if (which < 0)
2142
    {
M
Max Bruckner 已提交
2143
        return;
2144
    }
M
Max Bruckner 已提交
2145 2146 2147

    after_inserted = get_array_item(array, (size_t)which);
    if (after_inserted == NULL)
2148
    {
2149
        add_item_to_array(array, newitem);
2150 2151
        return;
    }
M
Max Bruckner 已提交
2152 2153 2154 2155 2156

    newitem->next = after_inserted;
    newitem->prev = after_inserted->prev;
    after_inserted->prev = newitem;
    if (after_inserted == array->child)
2157 2158 2159 2160 2161 2162 2163 2164 2165
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
}

M
Max Bruckner 已提交
2166
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2167
{
2168
    if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2169
    {
M
Max Bruckner 已提交
2170
        return false;
2171
    }
M
Max Bruckner 已提交
2172

M
Max Bruckner 已提交
2173
    if (replacement == item)
2174
    {
M
Max Bruckner 已提交
2175
        return true;
2176
    }
M
Max Bruckner 已提交
2177

M
Max Bruckner 已提交
2178 2179 2180 2181
    replacement->next = item->next;
    replacement->prev = item->prev;

    if (replacement->next != NULL)
2182
    {
M
Max Bruckner 已提交
2183
        replacement->next->prev = replacement;
2184
    }
M
Max Bruckner 已提交
2185
    if (replacement->prev != NULL)
2186
    {
M
Max Bruckner 已提交
2187
        replacement->prev->next = replacement;
2188
    }
M
Max Bruckner 已提交
2189
    if (parent->child == item)
2190
    {
M
Max Bruckner 已提交
2191
        parent->child = replacement;
2192
    }
M
Max Bruckner 已提交
2193

M
Max Bruckner 已提交
2194 2195 2196
    item->next = NULL;
    item->prev = NULL;
    cJSON_Delete(item);
M
Max Bruckner 已提交
2197

M
Max Bruckner 已提交
2198
    return true;
2199
}
M
Max Bruckner 已提交
2200

2201
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
2202 2203 2204 2205 2206 2207
{
    if (which < 0)
    {
        return;
    }

M
Max Bruckner 已提交
2208
    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
M
Max Bruckner 已提交
2209
}
2210

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

2231
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2232
{
2233
    replace_item_in_object(object, string, newitem, false);
2234
}
2235

2236 2237
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
2238
    replace_item_in_object(object, string, newitem, true);
2239
}
K
Kevin Branigan 已提交
2240 2241

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

        /* 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 已提交
2307 2308 2309 2310 2311
    }

    return item;
}

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

    return item;
}

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

    return item;
}

2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361
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;
}

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

    return item;
J
Jiri Zouhar 已提交
2377 2378
}

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

    return item;
}

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

    return item;
}
K
Kevin Branigan 已提交
2400 2401

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

2409
    if ((count < 0) || (numbers == NULL))
2410 2411 2412 2413 2414 2415
    {
        return NULL;
    }

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

    return a;
}

2437
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2438
{
2439
    size_t i = 0;
2440 2441
    cJSON *n = NULL;
    cJSON *p = NULL;
2442 2443
    cJSON *a = NULL;

2444
    if ((count < 0) || (numbers == NULL))
2445 2446 2447 2448 2449 2450 2451
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

2473
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2474
{
2475
    size_t i = 0;
2476 2477
    cJSON *n = NULL;
    cJSON *p = NULL;
2478 2479
    cJSON *a = NULL;

2480
    if ((count < 0) || (numbers == NULL))
2481 2482 2483 2484 2485 2486 2487
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

2509
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2510
{
2511
    size_t i = 0;
2512 2513
    cJSON *n = NULL;
    cJSON *p = NULL;
2514 2515
    cJSON *a = NULL;

2516
    if ((count < 0) || (strings == NULL))
2517 2518 2519 2520 2521 2522 2523
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}
2544 2545

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

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

    return newitem;
2615 2616 2617 2618 2619 2620 2621 2622

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

    return NULL;
2623
}
2624

2625
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2626
{
2627
    unsigned char *into = (unsigned char*)json;
2628 2629 2630 2631 2632 2633

    if (json == NULL)
    {
        return;
    }

M
Max Bruckner 已提交
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
    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 已提交
2673
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2674 2675 2676 2677
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2678
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2679
                }
M
Max Bruckner 已提交
2680
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2681
            }
M
Max Bruckner 已提交
2682
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2683 2684 2685 2686
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2687
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2688 2689 2690 2691 2692
        }
    }

    /* and null-terminate. */
    *into = '\0';
2693
}
2694

2695
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2696 2697 2698 2699 2700 2701 2702 2703 2704
{
    if (item == NULL)
    {
        return false;
    }

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

2705
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2706 2707 2708 2709 2710 2711 2712 2713 2714
{
    if (item == NULL)
    {
        return false;
    }

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

2715
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2716 2717 2718 2719 2720 2721 2722 2723 2724 2725
{
    if (item == NULL)
    {
        return false;
    }

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


2726
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2727 2728 2729 2730 2731 2732 2733 2734
{
    if (item == NULL)
    {
        return false;
    }

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

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

2745
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2746 2747 2748 2749 2750 2751 2752 2753 2754
{
    if (item == NULL)
    {
        return false;
    }

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

2755
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2756 2757 2758 2759 2760 2761 2762 2763 2764
{
    if (item == NULL)
    {
        return false;
    }

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

2765
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2766 2767 2768 2769 2770 2771 2772 2773 2774
{
    if (item == NULL)
    {
        return false;
    }

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

2775
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2776 2777 2778 2779 2780 2781 2782 2783 2784
{
    if (item == NULL)
    {
        return false;
    }

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

2785
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2786 2787 2788 2789 2790 2791 2792 2793
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Raw;
}
2794 2795 2796 2797 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

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 已提交
2855 2856 2857 2858
            cJSON *a_element = a->child;
            cJSON *b_element = b->child;

            for (; (a_element != NULL) && (b_element != NULL);)
2859 2860 2861 2862 2863
            {
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }
M
Max Bruckner 已提交
2864 2865 2866

                a_element = a_element->next;
                b_element = b_element->next;
2867 2868
            }

2869 2870 2871 2872 2873
            /* one of the arrays is longer than the other */
            if (a_element != b_element) {
                return false;
            }

2874 2875 2876 2877 2878 2879
            return true;
        }

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

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

2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
            /* 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;
                }
            }

2912 2913 2914 2915 2916 2917 2918
            return true;
        }

        default:
            return false;
    }
}
2919 2920 2921 2922 2923 2924 2925 2926 2927 2928

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

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