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

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

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

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

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

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

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

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

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

K
Kevin Branigan 已提交
56 57
#include "cJSON.h"

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

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

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

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

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

    return version;
}

86 87
/* 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 已提交
88
{
89
    if ((string1 == NULL) || (string2 == NULL))
M
Max Bruckner 已提交
90
    {
91
        return 1;
M
Max Bruckner 已提交
92
    }
93

94
    if (string1 == string2)
M
Max Bruckner 已提交
95
    {
96
        return 0;
M
Max Bruckner 已提交
97
    }
98 99

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

107
    return tolower(*string1) - tolower(*string2);
K
Kevin Branigan 已提交
108 109
}

110 111 112 113 114 115 116
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 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#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 已提交
138

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

M
Max Bruckner 已提交
144
    if (string == NULL)
145 146 147 148
    {
        return NULL;
    }

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

    return copy;
K
Kevin Branigan 已提交
158 159
}

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

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

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

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

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

    return node;
K
Kevin Branigan 已提交
201 202 203
}

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

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

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

M
Max Bruckner 已提交
264
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
265
    {
266
        return false;
267 268
    }

269
    /* copy the number into a temporary buffer and replace '.' with the decimal point
M
Max Bruckner 已提交
270 271 272
     * 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++)
273
    {
M
Max Bruckner 已提交
274
        switch (buffer_at_offset(input_buffer)[i])
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
        {
            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 已提交
290
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
                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 已提交
306
    {
307
        return false; /* parse_error */
M
Max Bruckner 已提交
308 309
    }

310
    item->valuedouble = number;
M
Max Bruckner 已提交
311

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

M
Max Bruckner 已提交
326 327
    item->type = cJSON_Number;

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

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

    return object->valuedouble = number;
}

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

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

368
    if ((p == NULL) || (p->buffer == NULL))
369 370 371 372
    {
        return NULL;
    }

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

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

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

391 392 393 394
    if (p->noalloc) {
        return NULL;
    }

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

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

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

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

    return newbuffer + p->offset;
448 449
}

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

460
    buffer->offset += strlen((const char*)buffer_pointer);
461 462 463
}

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

M
Max Bruckner 已提交
474
    if (output_buffer == NULL)
M
Max Bruckner 已提交
475
    {
476
        return false;
M
Max Bruckner 已提交
477
    }
M
Max Bruckner 已提交
478

479 480 481
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
482
        length = sprintf((char*)number_buffer, "null");
483 484 485
    }
    else
    {
486 487 488 489 490 491 492 493 494
        /* 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 已提交
495
    }
496

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

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

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    /* 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;

526
    return true;
K
Kevin Branigan 已提交
527 528
}

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

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

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

    return h;
563 564
}

565 566
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
567
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 已提交
568
{
569 570 571
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
572
    unsigned char utf8_length = 0;
573
    unsigned char utf8_position = 0;
574
    unsigned char sequence_length = 0;
575
    unsigned char first_byte_mark = 0;
576 577 578 579 580 581

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

583 584 585
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

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

592 593
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
594
    {
595 596 597 598 599
        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 已提交
600
        {
601 602
            /* input ends unexpectedly */
            goto fail;
M
Max Bruckner 已提交
603
        }
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627

        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 已提交
628
    }
M
Max Bruckner 已提交
629

630 631 632 633 634 635 636 637 638 639 640 641
    /* 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;
642
        first_byte_mark = 0xC0; /* 11000000 */
643 644 645 646 647
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
648
        first_byte_mark = 0xE0; /* 11100000 */
649 650 651 652 653
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
654
        first_byte_mark = 0xF0; /* 11110000 */
655 656
    }
    else
M
Max Bruckner 已提交
657
    {
658
        /* invalid unicode codepoint */
659
        goto fail;
M
Max Bruckner 已提交
660 661
    }

662
    /* encode as utf8 */
663 664 665 666 667
    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;
668
    }
669 670 671 672 673 674 675 676
    /* 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);
677
    }
678

679 680 681 682 683 684 685 686 687
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

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

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

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

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

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

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

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

M
Max Bruckner 已提交
784
                default:
785
                    goto fail;
M
Max Bruckner 已提交
786
            }
787
            input_pointer += sequence_length;
M
Max Bruckner 已提交
788 789
        }
    }
790 791 792

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

794
    item->type = cJSON_String;
795
    item->valuestring = (char*)output;
796

M
Max Bruckner 已提交
797 798 799
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

800
    return true;
801 802

fail:
803
    if (output != NULL)
804
    {
805
        input_buffer->hooks.deallocate(output);
806 807
    }

808 809 810 811 812
    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

813
    return false;
K
Kevin Branigan 已提交
814 815 816
}

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

826
    if (output_buffer == NULL)
M
Max Bruckner 已提交
827
    {
828
        return false;
M
Max Bruckner 已提交
829 830 831
    }

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

841
        return true;
M
Max Bruckner 已提交
842 843 844
    }

    /* set "flag" to 1 if something needs to be escaped */
845
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
846
    {
M
Max Bruckner 已提交
847
        switch (*input_pointer)
M
Max Bruckner 已提交
848
        {
M
Max Bruckner 已提交
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
            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 已提交
866 867
        }
    }
M
Max Bruckner 已提交
868
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
869

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

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

884
        return true;
M
Max Bruckner 已提交
885 886
    }

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

935
    return true;
K
Kevin Branigan 已提交
936
}
M
Max Bruckner 已提交
937

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

/* Predeclare these prototypes. */
945 946 947 948 949 950
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 已提交
951 952

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

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

    if (buffer->offset == buffer->length)
M
Max Bruckner 已提交
966
    {
M
Max Bruckner 已提交
967
        buffer->offset--;
M
Max Bruckner 已提交
968 969
    }

M
Max Bruckner 已提交
970
    return buffer;
M
Max Bruckner 已提交
971
}
K
Kevin Branigan 已提交
972

973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
/* 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 已提交
989
/* Parse an object - create a new root, and populate. */
990
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
991
{
992
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
993
    cJSON *item = NULL;
994 995 996 997

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;
998 999

    if (value == NULL)
M
Max Bruckner 已提交
1000
    {
1001
        goto fail;
M
Max Bruckner 已提交
1002 1003
    }

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

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

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

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

1035
    return item;
1036 1037 1038 1039 1040 1041 1042

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

1043 1044
    if (value != NULL)
    {
1045 1046 1047 1048
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

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

        if (return_parse_end != NULL)
        {
            *return_parse_end = (const char*)local_error.json + local_error.position;
        }
1062 1063
 
        global_error = local_error;
M
Max Bruckner 已提交
1064 1065
    }

1066
    return NULL;
K
Kevin Branigan 已提交
1067
}
M
Max Bruckner 已提交
1068

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

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

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

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

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

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

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

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

    return printed;

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

    if (printed != NULL)
    {
1133
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1134 1135 1136 1137 1138
    }

    return NULL;
}

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

1145
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1146
{
1147
    return (char*)print(item, false, &global_hooks);
1148
}
1149

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

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1156
        return NULL;
M
Max Bruckner 已提交
1157 1158
    }

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

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

1171
    if (!print_value(item, &p))
1172
    {
1173
        global_hooks.deallocate(p.buffer);
1174 1175 1176 1177
        return NULL;
    }

    return (char*)p.buffer;
1178 1179
}

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

1184
    if ((len < 0) || (buf == NULL))
M
Max Bruckner 已提交
1185 1186 1187 1188
    {
        return false;
    }

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

1196
    return print_value(item, &p);
1197
}
K
Kevin Branigan 已提交
1198 1199

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

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

1251
    return false;
K
Kevin Branigan 已提交
1252 1253 1254
}

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

M
Max Bruckner 已提交
1259
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1260
    {
1261
        return false;
M
Max Bruckner 已提交
1262
    }
M
Max Bruckner 已提交
1263 1264

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

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

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

M
Max Bruckner 已提交
1293
        case cJSON_Number:
1294
            return print_number(item, output_buffer);
1295

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

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

M
Max Bruckner 已提交
1318
        case cJSON_String:
1319
            return print_string(item, output_buffer);
1320

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

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

M
Max Bruckner 已提交
1327
        default:
1328
            return false;
M
Max Bruckner 已提交
1329
    }
K
Kevin Branigan 已提交
1330 1331 1332
}

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

1338 1339 1340 1341 1342 1343
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

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

M
Max Bruckner 已提交
1350 1351 1352
    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 已提交
1353
    {
1354
        /* empty array */
1355
        goto success;
M
Max Bruckner 已提交
1356
    }
K
Kevin Branigan 已提交
1357

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

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

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

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

1407
success:
1408 1409
    input_buffer->depth--;

1410
    item->type = cJSON_Array;
1411
    item->child = head;
1412

M
Max Bruckner 已提交
1413 1414
    input_buffer->offset++;

1415
    return true;
K
Kevin Branigan 已提交
1416

1417
fail:
1418
    if (head != NULL)
1419
    {
1420
        cJSON_Delete(head);
1421 1422
    }

1423
    return false;
K
Kevin Branigan 已提交
1424 1425 1426
}

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

M
Max Bruckner 已提交
1433
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1434
    {
1435
        return false;
M
Max Bruckner 已提交
1436 1437
    }

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

M
Max Bruckner 已提交
1446 1447
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1448
    output_buffer->depth++;
M
Max Bruckner 已提交
1449

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

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

1485
    return true;
K
Kevin Branigan 已提交
1486 1487 1488
}

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

1494 1495 1496 1497 1498 1499
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

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

M
Max Bruckner 已提交
1505 1506 1507
    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 已提交
1508
    {
1509
        goto success; /* empty object */
M
Max Bruckner 已提交
1510 1511
    }

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

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

1531 1532
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1533
        {
1534 1535 1536 1537 1538 1539 1540 1541 1542
            /* 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 已提交
1543 1544
        }

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

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

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

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

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

1579
success:
1580 1581
    input_buffer->depth--;

1582
    item->type = cJSON_Object;
1583
    item->child = head;
1584

M
Max Bruckner 已提交
1585
    input_buffer->offset++;
1586
    return true;
1587 1588

fail:
1589
    if (head != NULL)
1590
    {
1591
        cJSON_Delete(head);
1592 1593
    }

1594
    return false;
K
Kevin Branigan 已提交
1595 1596 1597
}

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

M
Max Bruckner 已提交
1604
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1605
    {
1606
        return false;
M
Max Bruckner 已提交
1607 1608
    }

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

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

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

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

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

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

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

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

M
Max Bruckner 已提交
1688
        current_item = current_item->next;
M
Max Bruckner 已提交
1689
    }
M
Max Bruckner 已提交
1690

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

1708
    return true;
K
Kevin Branigan 已提交
1709 1710 1711
}

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

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

    child = array->child;

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

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

1732
    return (int)size;
M
Max Bruckner 已提交
1733 1734
}

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

    if (array == NULL)
M
Max Bruckner 已提交
1740
    {
M
Max Bruckner 已提交
1741
        return NULL;
M
Max Bruckner 已提交
1742 1743
    }

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

    return current_child;
M
Max Bruckner 已提交
1752 1753
}

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

M
Max Bruckner 已提交
1761
    return get_array_item(array, (size_t)index);
M
Max Bruckner 已提交
1762 1763
}

1764
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1765 1766 1767
{
    cJSON *current_element = NULL;

1768
    if ((object == NULL) || (name == NULL))
1769 1770 1771 1772 1773
    {
        return NULL;
    }

    current_element = object->child;
1774
    if (case_sensitive)
1775
    {
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
        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;
        }
1787 1788 1789 1790 1791
    }

    return current_element;
}

1792
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1793 1794 1795 1796 1797 1798 1799 1800 1801
{
    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);
}

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

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

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

    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 已提交
1834
}
K
Kevin Branigan 已提交
1835 1836

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

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1842 1843 1844
    {
        return;
    }
1845 1846 1847 1848

    child = array->child;

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

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

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

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

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

1903
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1904
{
1905 1906 1907 1908 1909
    if (array == NULL)
    {
        return;
    }

1910
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1911 1912
}

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

1920
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1921 1922
}

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

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

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

M
Max Bruckner 已提交
1950
    return item;
1951
}
M
Max Bruckner 已提交
1952

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

M
Max Bruckner 已提交
1960
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
M
Max Bruckner 已提交
1961
}
K
Kevin Branigan 已提交
1962

1963
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1964 1965 1966 1967
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1968
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1969
{
1970
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
1971

1972 1973 1974 1975 1976 1977
    return cJSON_DetachItemViaPointer(object, to_detach);
}

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

1979
    return cJSON_DetachItemViaPointer(object, to_detach);
1980 1981
}

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

1987 1988 1989 1990 1991
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
}

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

    if (which < 0)
1998
    {
M
Max Bruckner 已提交
1999
        return;
2000
    }
M
Max Bruckner 已提交
2001 2002 2003

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

    newitem->next = after_inserted;
    newitem->prev = after_inserted->prev;
    after_inserted->prev = newitem;
    if (after_inserted == array->child)
2013 2014 2015 2016 2017 2018 2019 2020 2021
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
}

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

M
Max Bruckner 已提交
2029
    if (replacement == item)
2030
    {
M
Max Bruckner 已提交
2031
        return true;
2032
    }
M
Max Bruckner 已提交
2033

M
Max Bruckner 已提交
2034 2035 2036 2037
    replacement->next = item->next;
    replacement->prev = item->prev;

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

M
Max Bruckner 已提交
2050 2051 2052
    item->next = NULL;
    item->prev = NULL;
    cJSON_Delete(item);
M
Max Bruckner 已提交
2053

M
Max Bruckner 已提交
2054
    return true;
2055
}
M
Max Bruckner 已提交
2056

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

M
Max Bruckner 已提交
2064
    cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
M
Max Bruckner 已提交
2065
}
2066

2067 2068
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
{
2069
    if ((replacement == NULL) || (string == NULL))
2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086
    {
        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;
}

2087
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2088
{
2089
    replace_item_in_object(object, string, newitem, false);
2090
}
2091

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

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

        /* 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 已提交
2163 2164 2165 2166 2167
    }

    return item;
}

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

    return item;
}

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

    return item;
J
Jiri Zouhar 已提交
2200 2201
}

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

    return item;
}

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

    return item;
}
K
Kevin Branigan 已提交
2223 2224

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

2232
    if ((count < 0) || (numbers == NULL))
2233 2234 2235 2236 2237 2238
    {
        return NULL;
    }

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

    return a;
}

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

2267
    if ((count < 0) || (numbers == NULL))
2268 2269 2270 2271 2272 2273 2274
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

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

2303
    if ((count < 0) || (numbers == NULL))
2304 2305 2306 2307 2308 2309 2310
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

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

2339
    if ((count < 0) || (strings == NULL))
2340 2341 2342 2343 2344 2345 2346
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}
2367 2368

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

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

    return newitem;
2438 2439 2440 2441 2442 2443 2444 2445

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

    return NULL;
2446
}
2447

2448
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2449
{
2450
    unsigned char *into = (unsigned char*)json;
2451 2452 2453 2454 2455 2456

    if (json == NULL)
    {
        return;
    }

M
Max Bruckner 已提交
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495
    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 已提交
2496
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2497 2498 2499 2500
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2501
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2502
                }
M
Max Bruckner 已提交
2503
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2504
            }
M
Max Bruckner 已提交
2505
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2506 2507 2508 2509
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2510
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2511 2512 2513 2514 2515
        }
    }

    /* and null-terminate. */
    *into = '\0';
2516
}
2517

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

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

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

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

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

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


2549
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2550 2551 2552 2553 2554 2555 2556 2557
{
    if (item == NULL)
    {
        return false;
    }

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

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

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

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

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

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

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

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

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

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

2608
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2609 2610 2611 2612 2613 2614 2615 2616
{
    if (item == NULL)
    {
        return false;
    }

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

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 已提交
2678 2679 2680 2681
            cJSON *a_element = a->child;
            cJSON *b_element = b->child;

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

                a_element = a_element->next;
                b_element = b_element->next;
2690 2691
            }

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

2697 2698 2699 2700 2701 2702
            return true;
        }

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

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

2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734
            /* 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;
                }
            }

2735 2736 2737 2738 2739 2740 2741
            return true;
        }

        default:
            return false;
    }
}
2742 2743 2744 2745 2746 2747 2748 2749 2750 2751

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

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