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

  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
#pragma GCC visibility push(default)
K
Kevin Branigan 已提交
27 28 29 30 31 32 33
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
34
#include <locale.h>
35 36
#pragma GCC visibility pop

K
Kevin Branigan 已提交
37 38
#include "cJSON.h"

M
Max Bruckner 已提交
39
/* define our own boolean type */
40 41
#define true ((cJSON_bool)1)
#define false ((cJSON_bool)0)
M
Max Bruckner 已提交
42

43 44 45 46 47
typedef struct {
    const unsigned char *json;
    size_t position;
} error;
static error global_error = { NULL, 0 };
K
Kevin Branigan 已提交
48

49
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
M
Max Bruckner 已提交
50
{
51
    return (const char*) (global_error.json + global_error.position);
M
Max Bruckner 已提交
52
}
K
Kevin Branigan 已提交
53

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

59
CJSON_PUBLIC(const char*) cJSON_Version(void)
60 61 62 63 64 65 66
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

M
Max Bruckner 已提交
67
/* case insensitive strcmp */
68
static int cJSON_strcasecmp(const unsigned char *s1, const unsigned char *s2)
K
Kevin Branigan 已提交
69
{
M
Max Bruckner 已提交
70 71 72 73 74 75 76 77
    if (!s1)
    {
        return (s1 == s2) ? 0 : 1; /* both NULL? */
    }
    if (!s2)
    {
        return 1;
    }
M
Max Bruckner 已提交
78
    for(; tolower(*s1) == tolower(*s2); (void)++s1, ++s2)
M
Max Bruckner 已提交
79
    {
80
        if (*s1 == '\0')
M
Max Bruckner 已提交
81 82 83 84 85
        {
            return 0;
        }
    }

86
    return tolower(*s1) - tolower(*s2);
K
Kevin Branigan 已提交
87 88
}

89 90 91 92 93 94 95 96
typedef struct internal_hooks
{
    void *(*allocate)(size_t size);
    void (*deallocate)(void *pointer);
    void *(*reallocate)(void *pointer, size_t size);
} internal_hooks;

static internal_hooks global_hooks = { malloc, free, realloc };
K
Kevin Branigan 已提交
97

98
static unsigned char* cJSON_strdup(const unsigned char* str, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
99
{
M
Max Bruckner 已提交
100
    size_t len = 0;
101
    unsigned char *copy = NULL;
K
Kevin Branigan 已提交
102

103 104 105 106 107
    if (str == NULL)
    {
        return NULL;
    }

108
    len = strlen((const char*)str) + sizeof("");
109
    if (!(copy = (unsigned char*)hooks->allocate(len)))
M
Max Bruckner 已提交
110
    {
111
        return NULL;
M
Max Bruckner 已提交
112 113 114 115
    }
    memcpy(copy, str, len);

    return copy;
K
Kevin Branigan 已提交
116 117
}

118
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
K
Kevin Branigan 已提交
119
{
M
Max Bruckner 已提交
120
    if (hooks == NULL)
M
Max Bruckner 已提交
121 122
    {
        /* Reset hooks */
123 124 125
        global_hooks.allocate = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
K
Kevin Branigan 已提交
126 127 128
        return;
    }

129
    global_hooks.allocate = malloc;
M
Max Bruckner 已提交
130 131
    if (hooks->malloc_fn != NULL)
    {
132
        global_hooks.allocate = hooks->malloc_fn;
M
Max Bruckner 已提交
133 134
    }

135
    global_hooks.deallocate = free;
M
Max Bruckner 已提交
136 137
    if (hooks->free_fn != NULL)
    {
138
        global_hooks.deallocate = hooks->free_fn;
M
Max Bruckner 已提交
139 140 141
    }

    /* use realloc only if both free and malloc are used */
142 143
    global_hooks.reallocate = NULL;
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
M
Max Bruckner 已提交
144
    {
145
        global_hooks.reallocate = realloc;
M
Max Bruckner 已提交
146
    }
K
Kevin Branigan 已提交
147 148 149
}

/* Internal constructor. */
150
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
K
Kevin Branigan 已提交
151
{
152
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
M
Max Bruckner 已提交
153 154
    if (node)
    {
155
        memset(node, '\0', sizeof(cJSON));
M
Max Bruckner 已提交
156 157 158
    }

    return node;
K
Kevin Branigan 已提交
159 160 161
}

/* Delete a cJSON structure. */
162
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c)
K
Kevin Branigan 已提交
163
{
M
Max Bruckner 已提交
164
    cJSON *next = NULL;
M
Max Bruckner 已提交
165 166 167 168 169 170 171 172 173
    while (c)
    {
        next = c->next;
        if (!(c->type & cJSON_IsReference) && c->child)
        {
            cJSON_Delete(c->child);
        }
        if (!(c->type & cJSON_IsReference) && c->valuestring)
        {
174
            global_hooks.deallocate(c->valuestring);
M
Max Bruckner 已提交
175 176 177
        }
        if (!(c->type & cJSON_StringIsConst) && c->string)
        {
178
            global_hooks.deallocate(c->string);
M
Max Bruckner 已提交
179
        }
180
        global_hooks.deallocate(c);
M
Max Bruckner 已提交
181 182
        c = next;
    }
K
Kevin Branigan 已提交
183 184
}

185 186 187 188 189 190 191
/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
    struct lconv *lconv = localeconv();
    return (unsigned char) lconv->decimal_point[0];
}

M
Max Bruckner 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
typedef struct
{
    const unsigned char *content;
    size_t length;
    size_t offset;
} 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))
#define cannot_read(buffer, size) (!can_read(buffer, size))
/* 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 已提交
208
/* Parse the input text to generate a number, and populate the result into item. */
209
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
210
{
211
    double number = 0;
212
    unsigned char *after_end = NULL;
213 214 215
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
216

M
Max Bruckner 已提交
217
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
218
    {
219
        return false;
220 221
    }

222
    /* copy the number into a temporary buffer and replace '.' with the decimal point
M
Max Bruckner 已提交
223 224 225
     * 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++)
226
    {
M
Max Bruckner 已提交
227
        switch (buffer_at_offset(input_buffer)[i])
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
        {
            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 已提交
243
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
                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 已提交
259
    {
260
        return false; /* parse_error */
M
Max Bruckner 已提交
261 262
    }

263
    item->valuedouble = number;
M
Max Bruckner 已提交
264

265
    /* use saturation in case of overflow */
266
    if (number >= INT_MAX)
267 268 269
    {
        item->valueint = INT_MAX;
    }
270
    else if (number <= INT_MIN)
271 272 273 274 275
    {
        item->valueint = INT_MIN;
    }
    else
    {
276
        item->valueint = (int)number;
277
    }
278

M
Max Bruckner 已提交
279 280
    item->type = cJSON_Number;

M
Max Bruckner 已提交
281
    input_buffer->offset += (size_t)(after_end - number_c_string);
282
    return true;
K
Kevin Branigan 已提交
283 284
}

285
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
286
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
287 288 289 290 291 292 293 294 295 296 297
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
298
        object->valueint = (int)number;
299 300 301 302 303
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
304 305
typedef struct
{
306
    unsigned char *buffer;
307 308
    size_t length;
    size_t offset;
309
    cJSON_bool noalloc;
M
Max Bruckner 已提交
310
} printbuffer;
311

M
Max Bruckner 已提交
312
/* realloc printbuffer if necessary to have at least "needed" bytes more */
313
static unsigned char* ensure(printbuffer * const p, size_t needed, const internal_hooks * const hooks)
314
{
315
    unsigned char *newbuffer = NULL;
316 317
    size_t newsize = 0;

318
    if ((p == NULL) || (p->buffer == NULL))
319 320 321 322
    {
        return NULL;
    }

M
Max Bruckner 已提交
323 324 325 326 327 328
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

329
    if (needed > INT_MAX)
M
Max Bruckner 已提交
330
    {
331
        /* sizes bigger than INT_MAX are currently not supported */
332
        return NULL;
M
Max Bruckner 已提交
333
    }
334

335
    needed += p->offset + 1;
M
Max Bruckner 已提交
336 337 338 339 340
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

341 342 343 344
    if (p->noalloc) {
        return NULL;
    }

345
    /* calculate new buffer size */
M
Max Bruckner 已提交
346
    if (needed > (INT_MAX / 2))
347 348 349 350 351 352 353 354 355 356 357
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
358 359 360 361
    else
    {
        newsize = needed * 2;
    }
362

363
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
364
    {
M
Max Bruckner 已提交
365
        /* reallocate with realloc if available */
366
        newbuffer = (unsigned char*)hooks->reallocate(p->buffer, newsize);
M
Max Bruckner 已提交
367
    }
M
Max Bruckner 已提交
368
    else
M
Max Bruckner 已提交
369
    {
M
Max Bruckner 已提交
370
        /* otherwise reallocate manually */
371
        newbuffer = (unsigned char*)hooks->allocate(newsize);
M
Max Bruckner 已提交
372 373
        if (!newbuffer)
        {
374
            hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
375 376 377 378 379 380 381
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
382
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
383
        }
384
        hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
385 386 387 388 389
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
390 391
}

392 393
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
394
{
395 396
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
397
    {
398
        return;
M
Max Bruckner 已提交
399
    }
400
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
401

402
    buffer->offset += strlen((const char*)buffer_pointer);
403 404
}

405
/* Removes trailing zeroes from the end of a printed number */
406
static int trim_trailing_zeroes(const unsigned char * const number, int length, const unsigned char decimal_point)
K
Kevin Branigan 已提交
407
{
408
    if ((number == NULL) || (length <= 0))
409
    {
410
        return -1;
411 412
    }

413
    while ((length > 0) && (number[length - 1] == '0'))
M
Max Bruckner 已提交
414
    {
415
        length--;
M
Max Bruckner 已提交
416
    }
417
    if ((length > 0) && (number[length - 1] == decimal_point))
418
    {
419 420
        /* remove trailing decimal_point */
        length--;
421 422
    }

423
    return length;
424 425 426
}

/* Render the number nicely from the given item into a string. */
427
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
428
{
M
Max Bruckner 已提交
429
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
430
    double d = item->valuedouble;
431
    int length = 0;
432
    size_t i = 0;
433
    cJSON_bool trim_zeroes = true; /* should zeroes at the end be removed? */
434 435
    unsigned char number_buffer[64]; /* temporary buffer to print the number into */
    unsigned char decimal_point = get_decimal_point();
M
Max Bruckner 已提交
436

M
Max Bruckner 已提交
437
    if (output_buffer == NULL)
M
Max Bruckner 已提交
438
    {
439
        return false;
M
Max Bruckner 已提交
440
    }
M
Max Bruckner 已提交
441

442 443 444
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
445
        length = sprintf((char*)number_buffer, "null");
446 447 448 449
    }
    else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
    {
        /* integer */
450
        length = sprintf((char*)number_buffer, "%.0f", d);
451 452 453 454
        trim_zeroes = false; /* don't remove zeroes for "big integers" */
    }
    else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
    {
455
        length = sprintf((char*)number_buffer, "%e", d);
456 457 458 459
        trim_zeroes = false; /* don't remove zeroes in engineering notation */
    }
    else
    {
460
        length = sprintf((char*)number_buffer, "%f", d);
M
Max Bruckner 已提交
461
    }
462

463 464
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
465
    {
466
        return false;
467 468
    }

469 470
    if (trim_zeroes)
    {
471 472 473 474 475 476 477 478 479 480 481 482
        length = trim_trailing_zeroes(number_buffer, length, decimal_point);
        if (length <= 0)
        {
            return false;
        }
    }

    /* reserve appropriate space in the output */
    output_pointer = ensure(output_buffer, (size_t)length, hooks);
    if (output_pointer == NULL)
    {
        return false;
483 484
    }

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
    /* 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;

501
    return true;
K
Kevin Branigan 已提交
502 503
}

M
Max Bruckner 已提交
504
/* parse 4 digit hexadecimal number */
505
static unsigned parse_hex4(const unsigned char * const input)
506
{
M
Max Bruckner 已提交
507
    unsigned int h = 0;
508
    size_t i = 0;
M
Max Bruckner 已提交
509

510
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
511
    {
512
        /* parse digit */
513
        if ((input[i] >= '0') && (input[i] <= '9'))
514
        {
515
            h += (unsigned int) input[i] - '0';
516
        }
517
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
518
        {
519
            h += (unsigned int) 10 + input[i] - 'A';
520
        }
521
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
522
        {
523
            h += (unsigned int) 10 + input[i] - 'a';
524 525 526 527 528
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
529

530 531 532 533 534
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
535 536 537
    }

    return h;
538 539
}

540 541
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
542
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 已提交
543
{
544 545 546
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
547
    unsigned char utf8_length = 0;
548
    unsigned char utf8_position = 0;
549
    unsigned char sequence_length = 0;
550
    unsigned char first_byte_mark = 0;
551 552 553 554 555 556

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

558 559 560
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

561
    /* check that the code is valid */
562
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
M
Max Bruckner 已提交
563
    {
564
        goto fail;
M
Max Bruckner 已提交
565
    }
M
Max Bruckner 已提交
566

567 568
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
569
    {
570 571 572 573 574
        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 已提交
575
        {
576 577
            /* input ends unexpectedly */
            goto fail;
M
Max Bruckner 已提交
578
        }
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

        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 已提交
603
    }
M
Max Bruckner 已提交
604

605 606 607 608 609 610 611 612 613 614 615 616
    /* 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;
617
        first_byte_mark = 0xC0; /* 11000000 */
618 619 620 621 622
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
623
        first_byte_mark = 0xE0; /* 11100000 */
624 625 626 627 628
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
629
        first_byte_mark = 0xF0; /* 11110000 */
630 631
    }
    else
M
Max Bruckner 已提交
632
    {
633
        /* invalid unicode codepoint */
634
        goto fail;
M
Max Bruckner 已提交
635 636
    }

637
    /* encode as utf8 */
638 639 640 641 642
    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;
643
    }
644 645 646 647 648 649 650 651
    /* 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);
652
    }
653

654 655 656 657 658 659 660 661 662
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
663
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
664
{
M
Max Bruckner 已提交
665 666
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
667 668 669 670
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
M
Max Bruckner 已提交
671
    if (buffer_at_offset(input_buffer)[0] != '\"')
672 673 674 675 676 677 678 679
    {
        goto fail;
    }

    {
        /* calculate approximate size of the output (overestimate) */
        size_t allocation_length = 0;
        size_t skipped_bytes = 0;
M
Max Bruckner 已提交
680
        while ((*input_end != '\"') && ((size_t)(input_end - input_buffer->content) < input_buffer->length))
681 682 683 684
        {
            /* is escape sequence */
            if (input_end[0] == '\\')
            {
M
Max Bruckner 已提交
685
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
686 687 688 689 690 691 692 693 694
                {
                    /* prevent buffer overflow when last input character is a backslash */
                    goto fail;
                }
                skipped_bytes++;
                input_end++;
            }
            input_end++;
        }
M
Max Bruckner 已提交
695
        if (*input_end != '\"')
696 697 698 699 700
        {
            goto fail; /* string ended unexpectedly */
        }

        /* This is at most how much we need for the output */
M
Max Bruckner 已提交
701
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
702
        output = (unsigned char*)hooks->allocate(allocation_length + sizeof(""));
703 704 705 706 707 708 709
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
710
    /* loop through the string literal */
711
    while (input_pointer < input_end)
M
Max Bruckner 已提交
712
    {
713
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
714
        {
715
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
716 717 718 719
        }
        /* escape sequence */
        else
        {
720
            unsigned char sequence_length = 2;
M
Max Bruckner 已提交
721 722 723 724 725
            if ((input_end - input_pointer) < 1)
            {
                goto fail;
            }

726
            switch (input_pointer[1])
M
Max Bruckner 已提交
727 728
            {
                case 'b':
729
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
730 731
                    break;
                case 'f':
732
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
733 734
                    break;
                case 'n':
735
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
736 737
                    break;
                case 'r':
738
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
739 740
                    break;
                case 't':
741
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
742
                    break;
743 744 745
                case '\"':
                case '\\':
                case '/':
746
                    *output_pointer++ = input_pointer[1];
747
                    break;
748 749

                /* UTF-16 literal */
M
Max Bruckner 已提交
750
                case 'u':
751
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
752
                    if (sequence_length == 0)
M
Max Bruckner 已提交
753
                    {
754
                        /* failed to convert UTF16-literal to UTF-8 */
755
                        goto fail;
M
Max Bruckner 已提交
756 757
                    }
                    break;
758

M
Max Bruckner 已提交
759
                default:
760
                    goto fail;
M
Max Bruckner 已提交
761
            }
762
            input_pointer += sequence_length;
M
Max Bruckner 已提交
763 764
        }
    }
765 766 767

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

769
    item->type = cJSON_String;
770
    item->valuestring = (char*)output;
771

M
Max Bruckner 已提交
772 773 774
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

775
    return true;
776 777

fail:
778
    if (output != NULL)
779
    {
780
        hooks->deallocate(output);
781 782
    }

783 784 785 786 787
    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

788
    return false;
K
Kevin Branigan 已提交
789 790 791
}

/* Render the cstring provided to an escaped version that can be printed. */
792
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
793
{
794 795 796
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
797 798 799
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
800

801
    if (output_buffer == NULL)
M
Max Bruckner 已提交
802
    {
803
        return false;
M
Max Bruckner 已提交
804 805 806
    }

    /* empty string */
807
    if (input == NULL)
M
Max Bruckner 已提交
808
    {
809
        output = ensure(output_buffer, sizeof("\"\""), hooks);
810
        if (output == NULL)
M
Max Bruckner 已提交
811
        {
812
            return false;
M
Max Bruckner 已提交
813
        }
814
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
815

816
        return true;
M
Max Bruckner 已提交
817 818 819
    }

    /* set "flag" to 1 if something needs to be escaped */
820
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
821
    {
M
Max Bruckner 已提交
822
        switch (*input_pointer)
M
Max Bruckner 已提交
823
        {
M
Max Bruckner 已提交
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
            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 已提交
841 842
        }
    }
M
Max Bruckner 已提交
843
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
844

845
    output = ensure(output_buffer, output_length + sizeof("\"\""), hooks);
846
    if (output == NULL)
M
Max Bruckner 已提交
847
    {
848
        return false;
M
Max Bruckner 已提交
849 850
    }

M
Max Bruckner 已提交
851 852
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
853
    {
M
Max Bruckner 已提交
854 855 856 857 858
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

859
        return true;
M
Max Bruckner 已提交
860 861
    }

M
Max Bruckner 已提交
862 863
    output[0] = '\"';
    output_pointer = output + 1;
M
Max Bruckner 已提交
864
    /* copy the string */
M
Max Bruckner 已提交
865
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
M
Max Bruckner 已提交
866
    {
867
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
M
Max Bruckner 已提交
868 869
        {
            /* normal character, copy */
M
Max Bruckner 已提交
870
            *output_pointer = *input_pointer;
M
Max Bruckner 已提交
871 872 873 874
        }
        else
        {
            /* character needs to be escaped */
875
            *output_pointer++ = '\\';
M
Max Bruckner 已提交
876
            switch (*input_pointer)
M
Max Bruckner 已提交
877 878
            {
                case '\\':
M
Max Bruckner 已提交
879
                    *output_pointer = '\\';
M
Max Bruckner 已提交
880 881
                    break;
                case '\"':
M
Max Bruckner 已提交
882
                    *output_pointer = '\"';
M
Max Bruckner 已提交
883 884
                    break;
                case '\b':
M
Max Bruckner 已提交
885
                    *output_pointer = 'b';
M
Max Bruckner 已提交
886 887
                    break;
                case '\f':
M
Max Bruckner 已提交
888
                    *output_pointer = 'f';
M
Max Bruckner 已提交
889 890
                    break;
                case '\n':
M
Max Bruckner 已提交
891
                    *output_pointer = 'n';
M
Max Bruckner 已提交
892 893
                    break;
                case '\r':
M
Max Bruckner 已提交
894
                    *output_pointer = 'r';
M
Max Bruckner 已提交
895 896
                    break;
                case '\t':
M
Max Bruckner 已提交
897
                    *output_pointer = 't';
M
Max Bruckner 已提交
898 899 900
                    break;
                default:
                    /* escape and print as unicode codepoint */
M
Max Bruckner 已提交
901 902
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
M
Max Bruckner 已提交
903 904 905 906
                    break;
            }
        }
    }
M
Max Bruckner 已提交
907 908
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';
M
Max Bruckner 已提交
909

910
    return true;
K
Kevin Branigan 已提交
911
}
M
Max Bruckner 已提交
912

M
Max Bruckner 已提交
913
/* Invoke print_string_ptr (which is useful) on an item. */
914
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks)
M
Max Bruckner 已提交
915
{
916
    return print_string_ptr((unsigned char*)item->valuestring, p, hooks);
M
Max Bruckner 已提交
917
}
K
Kevin Branigan 已提交
918 919

/* Predeclare these prototypes. */
920
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
921
static cJSON_bool print_value(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
922
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
923
static cJSON_bool print_array(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
924
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
925
static cJSON_bool print_object(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
K
Kevin Branigan 已提交
926 927

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
928 929 930 931 932 933 934
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        return NULL;
    }

M
Max Bruckner 已提交
935 936 937 938 939 940 941 942 943
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
    {
       buffer->offset++;
    }

    if (buffer->offset == buffer->length)
    {
        buffer->offset--;
    }
M
Max Bruckner 已提交
944 945 946 947

    return buffer;
}

K
Kevin Branigan 已提交
948
/* Parse an object - create a new root, and populate. */
949
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
950
{
M
Max Bruckner 已提交
951
    parse_buffer buffer;
952
    cJSON *item = NULL;
953 954 955 956

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;
957 958 959 960

    if (value == NULL)
    {
        goto fail;
M
Max Bruckner 已提交
961 962
    }

M
Max Bruckner 已提交
963 964 965 966
    buffer.content = (const unsigned char*)value;
    buffer.length = strlen((const char*)value) + sizeof("");
    buffer.offset = 0;

967 968 969 970 971 972 973
    item = cJSON_New_Item(&global_hooks);
    if (item == NULL) /* memory fail */
    {
        goto fail;
    }

    if (!parse_value(item, buffer_skip_whitespace(&buffer), &global_hooks))
M
Max Bruckner 已提交
974 975
    {
        /* parse failure. ep is set. */
976
        goto fail;
M
Max Bruckner 已提交
977 978 979 980 981
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
982 983
        buffer_skip_whitespace(&buffer);
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
M
Max Bruckner 已提交
984
        {
985
            goto fail;
M
Max Bruckner 已提交
986 987 988 989
        }
    }
    if (return_parse_end)
    {
990
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
M
Max Bruckner 已提交
991 992
    }

993
    return item;
994 995 996 997 998 999 1000

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

1001 1002
    if (value != NULL)
    {
1003 1004 1005 1006
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

1007 1008
        if (buffer.offset < buffer.length)
        {
1009
            local_error.position = buffer.offset;
1010 1011 1012
        }
        else if (buffer.length > 0)
        {
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
            local_error.position = buffer.length - 1;
        }

        if (return_parse_end != NULL)
        {
            *return_parse_end = (const char*)local_error.json + local_error.position;
        }
        else
        {
            global_error = local_error;
1023 1024 1025
        }
    }

1026
    return NULL;
K
Kevin Branigan 已提交
1027
}
M
Max Bruckner 已提交
1028

1029
/* Default options for cJSON_Parse */
1030
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
1031 1032 1033
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
1034

M
Max Bruckner 已提交
1035 1036
#define min(a, b) ((a < b) ? a : b)

1037
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1038 1039 1040 1041 1042 1043 1044
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
1045
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
1046 1047 1048 1049 1050 1051
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
1052
    if (!print_value(item, 0, format, buffer, hooks))
M
Max Bruckner 已提交
1053 1054 1055
    {
        goto fail;
    }
1056
    update_offset(buffer);
M
Max Bruckner 已提交
1057 1058

    /* copy the buffer over to a new one */
1059
    printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
M
Max Bruckner 已提交
1060 1061 1062 1063 1064 1065 1066 1067
    if (printed == NULL)
    {
        goto fail;
    }
    strncpy((char*)printed, (char*)buffer->buffer, min(buffer->length, buffer->offset + 1));
    printed[buffer->offset] = '\0'; /* just to be sure */

    /* free the buffer */
1068
    hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1069 1070 1071 1072 1073 1074

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1075
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1076 1077 1078 1079
    }

    if (printed != NULL)
    {
1080
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1081 1082 1083 1084 1085
    }

    return NULL;
}

K
Kevin Branigan 已提交
1086
/* Render a cJSON item/entity/structure to text. */
1087
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1088
{
1089
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1090 1091
}

1092
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1093
{
1094
    return (char*)print(item, false, &global_hooks);
1095
}
1096

1097
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1098
{
M
Max Bruckner 已提交
1099
    printbuffer p;
M
Max Bruckner 已提交
1100 1101 1102

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1103
        return NULL;
M
Max Bruckner 已提交
1104 1105
    }

1106
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1107 1108
    if (!p.buffer)
    {
1109
        return NULL;
1110
    }
M
Max Bruckner 已提交
1111 1112

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1113
    p.offset = 0;
1114
    p.noalloc = false;
M
Max Bruckner 已提交
1115

1116 1117 1118 1119 1120 1121
    if (!print_value(item, 0, fmt, &p, &global_hooks))
    {
        return NULL;
    }

    return (char*)p.buffer;
1122 1123
}

1124
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1125 1126
{
    printbuffer p;
M
Max Bruckner 已提交
1127 1128 1129 1130 1131 1132

    if (len < 0)
    {
        return false;
    }

1133
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1134
    p.length = (size_t)len;
1135
    p.offset = 0;
1136
    p.noalloc = true;
1137
    return print_value(item, 0, fmt, &p, &global_hooks);
1138
}
K
Kevin Branigan 已提交
1139 1140

/* Parser core - when encountering text, process appropriately. */
1141
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1142
{
M
Max Bruckner 已提交
1143
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
M
Max Bruckner 已提交
1144
    {
1145
        return false; /* no input */
M
Max Bruckner 已提交
1146 1147 1148
    }

    /* parse the different types of values */
1149
    /* null */
M
Max Bruckner 已提交
1150
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
M
Max Bruckner 已提交
1151 1152
    {
        item->type = cJSON_NULL;
M
Max Bruckner 已提交
1153
        input_buffer->offset += 4;
1154
        return true;
M
Max Bruckner 已提交
1155
    }
1156
    /* false */
M
Max Bruckner 已提交
1157
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
M
Max Bruckner 已提交
1158 1159
    {
        item->type = cJSON_False;
M
Max Bruckner 已提交
1160
        input_buffer->offset += 5;
1161
        return true;
M
Max Bruckner 已提交
1162
    }
1163
    /* true */
M
Max Bruckner 已提交
1164
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
M
Max Bruckner 已提交
1165 1166 1167
    {
        item->type = cJSON_True;
        item->valueint = 1;
M
Max Bruckner 已提交
1168
        input_buffer->offset += 4;
1169
        return true;
M
Max Bruckner 已提交
1170
    }
1171
    /* string */
M
Max Bruckner 已提交
1172
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
M
Max Bruckner 已提交
1173
    {
1174
        return parse_string(item, input_buffer, hooks);
M
Max Bruckner 已提交
1175
    }
1176
    /* number */
M
Max Bruckner 已提交
1177
    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 已提交
1178
    {
M
Max Bruckner 已提交
1179
        return parse_number(item, input_buffer);
M
Max Bruckner 已提交
1180
    }
1181
    /* array */
M
Max Bruckner 已提交
1182
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
M
Max Bruckner 已提交
1183
    {
1184
        return parse_array(item, input_buffer, hooks);
M
Max Bruckner 已提交
1185
    }
1186
    /* object */
M
Max Bruckner 已提交
1187
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
M
Max Bruckner 已提交
1188
    {
1189
        return parse_object(item, input_buffer, hooks);
M
Max Bruckner 已提交
1190 1191
    }

M
Max Bruckner 已提交
1192

1193
    return false;
K
Kevin Branigan 已提交
1194 1195 1196
}

/* Render a value to text. */
1197
static cJSON_bool print_value(const cJSON * const item, const size_t depth, const cJSON_bool format,  printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1198
{
M
Max Bruckner 已提交
1199
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1200

M
Max Bruckner 已提交
1201
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1202
    {
1203
        return false;
M
Max Bruckner 已提交
1204
    }
M
Max Bruckner 已提交
1205 1206

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1207
    {
M
Max Bruckner 已提交
1208
        case cJSON_NULL:
1209
            output = ensure(output_buffer, 5, hooks);
1210
            if (output == NULL)
M
Max Bruckner 已提交
1211
            {
1212
                return false;
M
Max Bruckner 已提交
1213
            }
1214 1215 1216
            strcpy((char*)output, "null");
            return true;

M
Max Bruckner 已提交
1217
        case cJSON_False:
1218
            output = ensure(output_buffer, 6, hooks);
1219
            if (output == NULL)
M
Max Bruckner 已提交
1220
            {
1221
                return false;
M
Max Bruckner 已提交
1222
            }
1223 1224 1225
            strcpy((char*)output, "false");
            return true;

M
Max Bruckner 已提交
1226
        case cJSON_True:
1227
            output = ensure(output_buffer, 5, hooks);
1228
            if (output == NULL)
M
Max Bruckner 已提交
1229
            {
1230
                return false;
M
Max Bruckner 已提交
1231
            }
1232 1233 1234
            strcpy((char*)output, "true");
            return true;

M
Max Bruckner 已提交
1235
        case cJSON_Number:
1236
            return print_number(item, output_buffer, hooks);
1237

M
Max Bruckner 已提交
1238
        case cJSON_Raw:
M
Max Bruckner 已提交
1239
        {
M
Max Bruckner 已提交
1240 1241
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1242
            {
M
Max Bruckner 已提交
1243
                if (!output_buffer->noalloc)
1244
                {
1245
                    hooks->deallocate(output_buffer->buffer);
1246
                }
1247
                return false;
M
Max Bruckner 已提交
1248
            }
1249

1250
            raw_length = strlen(item->valuestring) + sizeof("");
1251
            output = ensure(output_buffer, raw_length, hooks);
1252
            if (output == NULL)
M
Max Bruckner 已提交
1253
            {
1254
                return false;
1255
            }
1256 1257
            memcpy(output, item->valuestring, raw_length);
            return true;
M
Max Bruckner 已提交
1258
        }
1259

M
Max Bruckner 已提交
1260
        case cJSON_String:
1261
            return print_string(item, output_buffer, hooks);
1262

M
Max Bruckner 已提交
1263
        case cJSON_Array:
1264
            return print_array(item, depth, format, output_buffer, hooks);
1265

M
Max Bruckner 已提交
1266
        case cJSON_Object:
1267
            return print_object(item, depth, format, output_buffer, hooks);
1268

M
Max Bruckner 已提交
1269
        default:
1270
            return false;
M
Max Bruckner 已提交
1271
    }
K
Kevin Branigan 已提交
1272 1273 1274
}

/* Build an array from input text. */
1275
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1276
{
1277
    cJSON *head = NULL; /* head of the linked list */
1278 1279
    cJSON *current_item = NULL;

M
Max Bruckner 已提交
1280
    if (buffer_at_offset(input_buffer)[0] != '[')
M
Max Bruckner 已提交
1281
    {
1282
        /* not an array */
1283
        goto fail;
M
Max Bruckner 已提交
1284
    }
K
Kevin Branigan 已提交
1285

M
Max Bruckner 已提交
1286 1287 1288
    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 已提交
1289
    {
1290
        /* empty array */
1291
        goto success;
M
Max Bruckner 已提交
1292
    }
K
Kevin Branigan 已提交
1293

M
Max Bruckner 已提交
1294 1295 1296 1297 1298 1299 1300
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1301
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1302
    input_buffer->offset--;
M
Max Bruckner 已提交
1303
    /* loop through the comma separated array elements */
1304
    do
M
Max Bruckner 已提交
1305
    {
1306
        /* allocate next item */
1307
        cJSON *new_item = cJSON_New_Item(hooks);
1308
        if (new_item == NULL)
M
Max Bruckner 已提交
1309
        {
1310
            goto fail; /* allocation failure */
M
Max Bruckner 已提交
1311
        }
1312 1313 1314

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1315
        {
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
            /* 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 已提交
1328 1329
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1330
        if (!parse_value(current_item, input_buffer, hooks))
1331 1332
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1333
        }
M
Max Bruckner 已提交
1334
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1335
    }
M
Max Bruckner 已提交
1336
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
M
Max Bruckner 已提交
1337

M
Max Bruckner 已提交
1338
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
M
Max Bruckner 已提交
1339
    {
1340
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1341 1342
    }

1343 1344
success:
    item->type = cJSON_Array;
1345
    item->child = head;
1346

M
Max Bruckner 已提交
1347 1348
    input_buffer->offset++;

1349
    return true;
K
Kevin Branigan 已提交
1350

1351
fail:
1352
    if (head != NULL)
1353
    {
1354
        cJSON_Delete(head);
1355 1356
    }

1357
    return false;
K
Kevin Branigan 已提交
1358 1359 1360
}

/* Render an array to text */
1361
static cJSON_bool print_array(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1362
{
M
Max Bruckner 已提交
1363
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1364
    size_t length = 0;
M
Max Bruckner 已提交
1365
    cJSON *current_element = item->child;
K
Kevin Branigan 已提交
1366

M
Max Bruckner 已提交
1367
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1368
    {
1369
        return false;
M
Max Bruckner 已提交
1370 1371
    }

M
Max Bruckner 已提交
1372 1373
    /* Compose the output array. */
    /* opening square bracket */
1374
    output_pointer = ensure(output_buffer, 1, hooks);
M
Max Bruckner 已提交
1375
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1376
    {
1377
        return false;
M
Max Bruckner 已提交
1378 1379
    }

M
Max Bruckner 已提交
1380 1381
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1382

M
Max Bruckner 已提交
1383
    while (current_element != NULL)
M
Max Bruckner 已提交
1384
    {
1385
        if (!print_value(current_element, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1386
        {
1387
            return false;
M
Max Bruckner 已提交
1388
        }
1389
        update_offset(output_buffer);
M
Max Bruckner 已提交
1390
        if (current_element->next)
M
Max Bruckner 已提交
1391
        {
1392
            length = (size_t) (format ? 2 : 1);
1393
            output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1394
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1395
            {
1396
                return false;
M
Max Bruckner 已提交
1397
            }
M
Max Bruckner 已提交
1398 1399
            *output_pointer++ = ',';
            if(format)
M
Max Bruckner 已提交
1400
            {
M
Max Bruckner 已提交
1401
                *output_pointer++ = ' ';
M
Max Bruckner 已提交
1402
            }
M
Max Bruckner 已提交
1403 1404
            *output_pointer = '\0';
            output_buffer->offset += length;
M
Max Bruckner 已提交
1405
        }
M
Max Bruckner 已提交
1406
        current_element = current_element->next;
M
Max Bruckner 已提交
1407 1408
    }

1409
    output_pointer = ensure(output_buffer, 2, hooks);
M
Max Bruckner 已提交
1410
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1411
    {
1412
        return false;
M
Max Bruckner 已提交
1413
    }
M
Max Bruckner 已提交
1414 1415
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1416

1417
    return true;
K
Kevin Branigan 已提交
1418 1419 1420
}

/* Build an object from the text. */
1421
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1422
{
1423
    cJSON *head = NULL; /* linked list head */
1424 1425
    cJSON *current_item = NULL;

M
Max Bruckner 已提交
1426
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
M
Max Bruckner 已提交
1427
    {
1428
        goto fail; /* not an object */
M
Max Bruckner 已提交
1429 1430
    }

M
Max Bruckner 已提交
1431 1432 1433
    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 已提交
1434
    {
1435
        goto success; /* empty object */
M
Max Bruckner 已提交
1436 1437
    }

M
Max Bruckner 已提交
1438 1439 1440 1441 1442 1443 1444
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1445
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1446
    input_buffer->offset--;
1447 1448
    /* loop through the comma separated array elements */
    do
M
Max Bruckner 已提交
1449
    {
1450
        /* allocate next item */
1451
        cJSON *new_item = cJSON_New_Item(hooks);
1452 1453 1454 1455
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }
M
Max Bruckner 已提交
1456

1457 1458
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1459
        {
1460 1461 1462 1463 1464 1465 1466 1467 1468
            /* 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 已提交
1469 1470
        }

1471
        /* parse the name of the child */
M
Max Bruckner 已提交
1472 1473
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1474
        if (!parse_string(current_item, input_buffer, hooks))
M
Max Bruckner 已提交
1475
        {
1476
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1477
        }
M
Max Bruckner 已提交
1478
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1479

1480 1481 1482
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1483

M
Max Bruckner 已提交
1484
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
M
Max Bruckner 已提交
1485
        {
1486
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1487
        }
1488 1489

        /* parse the value */
M
Max Bruckner 已提交
1490 1491
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1492
        if (!parse_value(current_item, input_buffer, hooks))
M
Max Bruckner 已提交
1493
        {
1494
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1495
        }
M
Max Bruckner 已提交
1496
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1497
    }
M
Max Bruckner 已提交
1498
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1499

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; /* expected end of object */
M
Max Bruckner 已提交
1503 1504
    }

1505 1506
success:
    item->type = cJSON_Object;
1507
    item->child = head;
1508

M
Max Bruckner 已提交
1509
    input_buffer->offset++;
1510
    return true;
1511 1512

fail:
1513
    if (head != NULL)
1514
    {
1515
        cJSON_Delete(head);
1516 1517
    }

1518
    return false;
K
Kevin Branigan 已提交
1519 1520 1521
}

/* Render an object to text. */
1522
static cJSON_bool print_object(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks)
1523
{
M
Max Bruckner 已提交
1524
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1525
    size_t length = 0;
M
Max Bruckner 已提交
1526
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1527

M
Max Bruckner 已提交
1528
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1529
    {
1530
        return false;
M
Max Bruckner 已提交
1531 1532
    }

M
Max Bruckner 已提交
1533
    /* Compose the output: */
1534
    length = (size_t) (format ? 2 : 1); /* fmt: {\n */
1535
    output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1536
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1537
    {
1538
        return false;
M
Max Bruckner 已提交
1539 1540
    }

M
Max Bruckner 已提交
1541 1542
    *output_pointer++ = '{';
    if (format)
M
Max Bruckner 已提交
1543
    {
M
Max Bruckner 已提交
1544
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1545
    }
M
Max Bruckner 已提交
1546
    output_buffer->offset += length;
M
Max Bruckner 已提交
1547

M
Max Bruckner 已提交
1548
    while (current_item)
M
Max Bruckner 已提交
1549
    {
M
Max Bruckner 已提交
1550
        if (format)
M
Max Bruckner 已提交
1551
        {
M
Max Bruckner 已提交
1552
            size_t i;
1553
            output_pointer = ensure(output_buffer, depth + 1, hooks);
M
Max Bruckner 已提交
1554
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1555
            {
1556
                return false;
M
Max Bruckner 已提交
1557
            }
M
Max Bruckner 已提交
1558
            for (i = 0; i < depth + 1; i++)
M
Max Bruckner 已提交
1559
            {
M
Max Bruckner 已提交
1560
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1561
            }
M
Max Bruckner 已提交
1562
            output_buffer->offset += depth + 1;
M
Max Bruckner 已提交
1563 1564
        }

M
Max Bruckner 已提交
1565
        /* print key */
1566
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks))
M
Max Bruckner 已提交
1567
        {
1568
            return false;
M
Max Bruckner 已提交
1569
        }
M
Max Bruckner 已提交
1570
        update_offset(output_buffer);
M
Max Bruckner 已提交
1571

1572
        length = (size_t) (format ? 2 : 1);
1573
        output_pointer = ensure(output_buffer, length, hooks);
M
Max Bruckner 已提交
1574
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1575
        {
1576
            return false;
M
Max Bruckner 已提交
1577
        }
M
Max Bruckner 已提交
1578 1579
        *output_pointer++ = ':';
        if (format)
M
Max Bruckner 已提交
1580
        {
M
Max Bruckner 已提交
1581
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1582
        }
M
Max Bruckner 已提交
1583
        output_buffer->offset += length;
M
Max Bruckner 已提交
1584

M
Max Bruckner 已提交
1585
        /* print value */
1586
        if (!print_value(current_item, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1587
        {
1588
            return false;
M
Max Bruckner 已提交
1589
        }
M
Max Bruckner 已提交
1590
        update_offset(output_buffer);
M
Max Bruckner 已提交
1591

M
Max Bruckner 已提交
1592
        /* print comma if not last */
1593
        length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
1594
        output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1595
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1596
        {
1597
            return false;
M
Max Bruckner 已提交
1598
        }
M
Max Bruckner 已提交
1599
        if (current_item->next)
M
Max Bruckner 已提交
1600
        {
M
Max Bruckner 已提交
1601
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1602 1603
        }

M
Max Bruckner 已提交
1604
        if (format)
M
Max Bruckner 已提交
1605
        {
M
Max Bruckner 已提交
1606
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1607
        }
M
Max Bruckner 已提交
1608 1609
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1610

M
Max Bruckner 已提交
1611
        current_item = current_item->next;
M
Max Bruckner 已提交
1612
    }
M
Max Bruckner 已提交
1613

1614
    output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks);
M
Max Bruckner 已提交
1615
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1616
    {
1617
        return false;
M
Max Bruckner 已提交
1618
    }
M
Max Bruckner 已提交
1619
    if (format)
M
Max Bruckner 已提交
1620
    {
M
Max Bruckner 已提交
1621 1622
        size_t i;
        for (i = 0; i < (depth); i++)
M
Max Bruckner 已提交
1623
        {
M
Max Bruckner 已提交
1624
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1625 1626
        }
    }
M
Max Bruckner 已提交
1627 1628
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1629

1630
    return true;
K
Kevin Branigan 已提交
1631 1632 1633
}

/* Get Array size/item / object item. */
1634
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1635 1636
{
    cJSON *c = array->child;
1637
    size_t i = 0;
M
Max Bruckner 已提交
1638 1639 1640 1641 1642
    while(c)
    {
        i++;
        c = c->next;
    }
1643 1644 1645

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

M
Max Bruckner 已提交
1646
    return (int)i;
M
Max Bruckner 已提交
1647 1648
}

1649
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
M
Max Bruckner 已提交
1650
{
1651
    cJSON *c = array ? array->child : NULL;
M
Max Bruckner 已提交
1652 1653 1654 1655 1656 1657 1658 1659 1660
    while (c && item > 0)
    {
        item--;
        c = c->next;
    }

    return c;
}

1661
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1662
{
1663
    cJSON *c = object ? object->child : NULL;
1664
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
M
Max Bruckner 已提交
1665 1666 1667 1668 1669 1670
    {
        c = c->next;
    }
    return c;
}

1671
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
{
    cJSON *current_element = NULL;

    if ((object == NULL) || (string == NULL))
    {
        return NULL;
    }

    current_element = object->child;
    while ((current_element != NULL) && (strcmp(string, current_element->string) != 0))
    {
        current_element = current_element->next;
    }

    return current_element;
}

1689
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1690 1691 1692
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1693 1694

/* Utility for array list handling. */
M
Max Bruckner 已提交
1695 1696 1697 1698 1699 1700
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1701
/* Utility for handling references. */
1702
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1703
{
1704
    cJSON *ref = cJSON_New_Item(hooks);
M
Max Bruckner 已提交
1705 1706
    if (!ref)
    {
1707
        return NULL;
M
Max Bruckner 已提交
1708 1709
    }
    memcpy(ref, item, sizeof(cJSON));
1710
    ref->string = NULL;
M
Max Bruckner 已提交
1711
    ref->type |= cJSON_IsReference;
1712
    ref->next = ref->prev = NULL;
M
Max Bruckner 已提交
1713 1714
    return ref;
}
K
Kevin Branigan 已提交
1715 1716

/* Add item to array/object. */
1717
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1718
{
1719 1720 1721
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1722 1723 1724
    {
        return;
    }
1725 1726 1727 1728

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1729 1730 1731 1732 1733 1734 1735
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1736
        while (child->next)
M
Max Bruckner 已提交
1737
        {
1738
            child = child->next;
M
Max Bruckner 已提交
1739
        }
1740
        suffix_object(child, item);
M
Max Bruckner 已提交
1741 1742 1743
    }
}

1744
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1745
{
1746
    /* call cJSON_AddItemToObjectCS for code reuse */
1747
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1748 1749
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1750 1751
}

1752 1753 1754 1755
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wcast-qual"
1756
/* Add an item to an object with constant string as key */
1757
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1758 1759 1760 1761 1762 1763 1764
{
    if (!item)
    {
        return;
    }
    if (!(item->type & cJSON_StringIsConst) && item->string)
    {
1765
        global_hooks.deallocate(item->string);
1766 1767 1768 1769 1770
    }
    item->string = (char*)string;
    item->type |= cJSON_StringIsConst;
    cJSON_AddItemToArray(object, item);
}
1771 1772 1773
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic pop
#endif
1774

1775
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1776
{
1777
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1778 1779
}

1780
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1781
{
1782
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1783 1784
}

M
Max Bruckner 已提交
1785
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
1796
        return NULL;
1797
    }
1798
    if (c->prev)
1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811
    {
        /* not the first element */
        c->prev->next = c->next;
    }
    if (c->next)
    {
        c->next->prev = c->prev;
    }
    if (c==array->child)
    {
        array->child = c->next;
    }
    /* make sure the detached item doesn't point anywhere anymore */
1812
    c->prev = c->next = NULL;
1813 1814 1815

    return c;
}
1816
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1817 1818 1819 1820 1821 1822 1823 1824
{
    if (which < 0)
    {
        return NULL;
    }

    return DetachItemFromArray(array, (size_t)which);
}
K
Kevin Branigan 已提交
1825

1826
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1827 1828 1829 1830
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1831
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1832
{
1833
    size_t i = 0;
1834
    cJSON *c = object->child;
1835
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1836 1837 1838 1839 1840 1841
    {
        i++;
        c = c->next;
    }
    if (c)
    {
M
Max Bruckner 已提交
1842
        return DetachItemFromArray(object, i);
1843 1844
    }

1845
    return NULL;
1846 1847
}

1848
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1849 1850 1851
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1852 1853

/* Replace array/object items with new ones. */
1854
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        cJSON_AddItemToArray(array, newitem);
        return;
    }
    newitem->next = c;
    newitem->prev = c->prev;
    c->prev = newitem;
    if (c == array->child)
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
}

M
Max Bruckner 已提交
1880
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        return;
    }
    newitem->next = c->next;
    newitem->prev = c->prev;
    if (newitem->next)
    {
        newitem->next->prev = newitem;
    }
    if (c == array->child)
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
1906
    c->next = c->prev = NULL;
1907 1908
    cJSON_Delete(c);
}
1909
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
1910 1911 1912 1913 1914 1915 1916 1917
{
    if (which < 0)
    {
        return;
    }

    ReplaceItemInArray(array, (size_t)which, newitem);
}
1918

1919
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1920
{
1921
    size_t i = 0;
1922
    cJSON *c = object->child;
1923
    while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1924 1925 1926 1927 1928 1929
    {
        i++;
        c = c->next;
    }
    if(c)
    {
1930 1931 1932
        /* free the old string if not const */
        if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
        {
1933
             global_hooks.deallocate(newitem->string);
1934 1935
        }

1936
        newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1937
        ReplaceItemInArray(object, i, newitem);
1938 1939
    }
}
K
Kevin Branigan 已提交
1940 1941

/* Create basic types: */
1942
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
1943
{
1944
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1945 1946 1947 1948 1949 1950 1951 1952
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

1953
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
1954
{
1955
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1956 1957 1958 1959 1960 1961 1962 1963
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

1964
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
1965
{
1966
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1967 1968 1969 1970 1971 1972 1973 1974
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

1975
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
1976
{
1977
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1978 1979 1980 1981 1982 1983 1984 1985
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

1986
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
1987
{
1988
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1989 1990 1991 1992
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006

        /* 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 已提交
2007 2008 2009 2010 2011
    }

    return item;
}

2012
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
2013
{
2014
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2015 2016 2017
    if(item)
    {
        item->type = cJSON_String;
2018
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
2019 2020 2021
        if(!item->valuestring)
        {
            cJSON_Delete(item);
2022
            return NULL;
M
Max Bruckner 已提交
2023 2024 2025 2026 2027 2028
        }
    }

    return item;
}

2029
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
2030
{
2031
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2032 2033 2034
    if(item)
    {
        item->type = cJSON_Raw;
2035
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
2036 2037 2038 2039 2040 2041 2042 2043
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
2044 2045
}

2046
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
2047
{
2048
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2049 2050 2051 2052 2053 2054 2055 2056
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

2057
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
2058
{
2059
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2060 2061 2062 2063 2064 2065 2066
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
2067 2068

/* Create Arrays: */
2069
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
2070
{
2071
    size_t i = 0;
2072 2073
    cJSON *n = NULL;
    cJSON *p = NULL;
2074 2075 2076 2077 2078 2079 2080 2081 2082
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2083 2084 2085 2086 2087
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
2088
            return NULL;
M
Max Bruckner 已提交
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2104
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2105
{
2106
    size_t i = 0;
2107 2108
    cJSON *n = NULL;
    cJSON *p = NULL;
2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2119
    {
2120
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2121 2122 2123
        if(!n)
        {
            cJSON_Delete(a);
2124
            return NULL;
M
Max Bruckner 已提交
2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2140
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2141
{
2142
    size_t i = 0;
2143 2144
    cJSON *n = NULL;
    cJSON *p = NULL;
2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2155 2156 2157 2158 2159
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2160
            return NULL;
2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2176
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2177
{
2178
    size_t i = 0;
2179 2180
    cJSON *n = NULL;
    cJSON *p = NULL;
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2191 2192 2193 2194 2195
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2196
            return NULL;
2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2211 2212

/* Duplication */
2213
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2214
{
M
Max Bruckner 已提交
2215
    cJSON *newitem = NULL;
2216 2217
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2218
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2219 2220 2221 2222

    /* Bail on bad ptr */
    if (!item)
    {
2223
        goto fail;
M
Max Bruckner 已提交
2224 2225
    }
    /* Create new item */
2226
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2227 2228
    if (!newitem)
    {
2229
        goto fail;
M
Max Bruckner 已提交
2230 2231 2232 2233 2234 2235 2236
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2237
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2238 2239
        if (!newitem->valuestring)
        {
2240
            goto fail;
M
Max Bruckner 已提交
2241 2242 2243 2244
        }
    }
    if (item->string)
    {
2245
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2246 2247
        if (!newitem->string)
        {
2248
            goto fail;
M
Max Bruckner 已提交
2249 2250 2251 2252 2253 2254 2255 2256
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2257 2258
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2259
    {
2260
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2261 2262
        if (!newchild)
        {
2263
            goto fail;
M
Max Bruckner 已提交
2264
        }
2265
        if (next != NULL)
M
Max Bruckner 已提交
2266 2267
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2268 2269 2270
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2271 2272 2273 2274
        }
        else
        {
            /* Set newitem->child and move to it */
2275 2276
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2277
        }
2278
        child = child->next;
M
Max Bruckner 已提交
2279 2280 2281
    }

    return newitem;
2282 2283 2284 2285 2286 2287 2288 2289

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

    return NULL;
2290
}
2291

2292
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2293
{
2294
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
    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 已提交
2334
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2335 2336 2337 2338
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2339
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2340
                }
M
Max Bruckner 已提交
2341
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2342
            }
M
Max Bruckner 已提交
2343
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2344 2345 2346 2347
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2348
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2349 2350 2351 2352 2353
        }
    }

    /* and null-terminate. */
    *into = '\0';
2354
}
2355

2356
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2357 2358 2359 2360 2361 2362 2363 2364 2365
{
    if (item == NULL)
    {
        return false;
    }

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

2366
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2367 2368 2369 2370 2371 2372 2373 2374 2375
{
    if (item == NULL)
    {
        return false;
    }

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

2376
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
{
    if (item == NULL)
    {
        return false;
    }

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


2387
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2388 2389 2390 2391 2392 2393 2394 2395
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2396
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2397 2398 2399 2400 2401 2402 2403 2404 2405
{
    if (item == NULL)
    {
        return false;
    }

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

2406
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2407 2408 2409 2410 2411 2412 2413 2414 2415
{
    if (item == NULL)
    {
        return false;
    }

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

2416
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2417 2418 2419 2420 2421 2422 2423 2424 2425
{
    if (item == NULL)
    {
        return false;
    }

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

2426
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2427 2428 2429 2430 2431 2432 2433 2434 2435
{
    if (item == NULL)
    {
        return false;
    }

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

2436
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2437 2438 2439 2440 2441 2442 2443 2444 2445
{
    if (item == NULL)
    {
        return false;
    }

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

2446
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2447 2448 2449 2450 2451 2452 2453 2454
{
    if (item == NULL)
    {
        return false;
    }

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