cJSON.c 56.6 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
static const unsigned char *global_ep = NULL;
K
Kevin Branigan 已提交
44

45
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
M
Max Bruckner 已提交
46
{
47
    return (const char*) global_ep;
M
Max Bruckner 已提交
48
}
K
Kevin Branigan 已提交
49

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

55
CJSON_PUBLIC(const char*) cJSON_Version(void)
56 57 58 59 60 61 62
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

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

82
    return tolower(*s1) - tolower(*s2);
K
Kevin Branigan 已提交
83 84
}

85 86 87 88 89 90 91 92
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 已提交
93

94
static unsigned char* cJSON_strdup(const unsigned char* str, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
95
{
M
Max Bruckner 已提交
96
    size_t len = 0;
97
    unsigned char *copy = NULL;
K
Kevin Branigan 已提交
98

99 100 101 102 103
    if (str == NULL)
    {
        return NULL;
    }

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

    return copy;
K
Kevin Branigan 已提交
112 113
}

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

125
    global_hooks.allocate = malloc;
M
Max Bruckner 已提交
126 127
    if (hooks->malloc_fn != NULL)
    {
128
        global_hooks.allocate = hooks->malloc_fn;
M
Max Bruckner 已提交
129 130
    }

131
    global_hooks.deallocate = free;
M
Max Bruckner 已提交
132 133
    if (hooks->free_fn != NULL)
    {
134
        global_hooks.deallocate = hooks->free_fn;
M
Max Bruckner 已提交
135 136 137
    }

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

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

    return node;
K
Kevin Branigan 已提交
155 156 157
}

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

181 182 183 184 185 186 187
/* 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];
}

K
Kevin Branigan 已提交
188
/* Parse the input text to generate a number, and populate the result into item. */
189
static const unsigned char *parse_number(cJSON * const item, const unsigned char * const input)
K
Kevin Branigan 已提交
190
{
191
    double number = 0;
192
    unsigned char *after_end = NULL;
193 194 195
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
196

197
    if (input == NULL)
198 199 200 201
    {
        return NULL;
    }

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    /* copy the number into a temporary buffer and replace '.' with the decimal point
     * of the current locale (for strtod) */
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && (input[i] != '\0'); i++)
    {
        switch (input[i])
        {
            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':
                number_c_string[i] = input[i];
                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 已提交
238
    {
239
        return NULL; /* parse_error */
M
Max Bruckner 已提交
240 241
    }

242
    item->valuedouble = number;
M
Max Bruckner 已提交
243

244
    /* use saturation in case of overflow */
245
    if (number >= INT_MAX)
246 247 248
    {
        item->valueint = INT_MAX;
    }
249
    else if (number <= INT_MIN)
250 251 252 253 254
    {
        item->valueint = INT_MIN;
    }
    else
    {
255
        item->valueint = (int)number;
256
    }
257

M
Max Bruckner 已提交
258 259
    item->type = cJSON_Number;

260
    return input + (after_end - number_c_string);
K
Kevin Branigan 已提交
261 262
}

263
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
264
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
265 266 267 268 269 270 271 272 273 274 275
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
276
        object->valueint = (int)number;
277 278 279 280 281
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
282 283
typedef struct
{
284
    unsigned char *buffer;
285 286
    size_t length;
    size_t offset;
287
    cJSON_bool noalloc;
M
Max Bruckner 已提交
288
} printbuffer;
289

M
Max Bruckner 已提交
290
/* realloc printbuffer if necessary to have at least "needed" bytes more */
291
static unsigned char* ensure(printbuffer * const p, size_t needed, const internal_hooks * const hooks)
292
{
293
    unsigned char *newbuffer = NULL;
294 295
    size_t newsize = 0;

296
    if ((p == NULL) || (p->buffer == NULL))
297 298 299 300
    {
        return NULL;
    }

M
Max Bruckner 已提交
301 302 303 304 305 306
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

307
    if (needed > INT_MAX)
M
Max Bruckner 已提交
308
    {
309
        /* sizes bigger than INT_MAX are currently not supported */
310
        return NULL;
M
Max Bruckner 已提交
311
    }
312

313
    needed += p->offset + 1;
M
Max Bruckner 已提交
314 315 316 317 318
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

319 320 321 322
    if (p->noalloc) {
        return NULL;
    }

323
    /* calculate new buffer size */
M
Max Bruckner 已提交
324
    if (needed > (INT_MAX / 2))
325 326 327 328 329 330 331 332 333 334 335
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
336 337 338 339
    else
    {
        newsize = needed * 2;
    }
340

341
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
342
    {
M
Max Bruckner 已提交
343
        /* reallocate with realloc if available */
344
        newbuffer = (unsigned char*)hooks->reallocate(p->buffer, newsize);
M
Max Bruckner 已提交
345
    }
M
Max Bruckner 已提交
346
    else
M
Max Bruckner 已提交
347
    {
M
Max Bruckner 已提交
348
        /* otherwise reallocate manually */
349
        newbuffer = (unsigned char*)hooks->allocate(newsize);
M
Max Bruckner 已提交
350 351
        if (!newbuffer)
        {
352
            hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
353 354 355 356 357 358 359
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
360
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
361
        }
362
        hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
363 364 365 366 367
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
368 369
}

370 371
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
372
{
373 374
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
375
    {
376
        return;
M
Max Bruckner 已提交
377
    }
378
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
379

380
    buffer->offset += strlen((const char*)buffer_pointer);
381 382
}

383
/* Removes trailing zeroes from the end of a printed number */
384
static int trim_trailing_zeroes(const unsigned char * const number, int length, const unsigned char decimal_point)
K
Kevin Branigan 已提交
385
{
386
    if ((number == NULL) || (length <= 0))
387
    {
388
        return -1;
389 390
    }

391
    while ((length > 0) && (number[length - 1] == '0'))
M
Max Bruckner 已提交
392
    {
393
        length--;
M
Max Bruckner 已提交
394
    }
395
    if ((length > 0) && (number[length - 1] == decimal_point))
396
    {
397 398
        /* remove trailing decimal_point */
        length--;
399 400
    }

401
    return length;
402 403 404
}

/* Render the number nicely from the given item into a string. */
405
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
406
{
M
Max Bruckner 已提交
407
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
408
    double d = item->valuedouble;
409
    int length = 0;
410
    size_t i = 0;
411
    cJSON_bool trim_zeroes = true; /* should zeroes at the end be removed? */
412 413
    unsigned char number_buffer[64]; /* temporary buffer to print the number into */
    unsigned char decimal_point = get_decimal_point();
M
Max Bruckner 已提交
414

M
Max Bruckner 已提交
415
    if (output_buffer == NULL)
M
Max Bruckner 已提交
416
    {
417
        return false;
M
Max Bruckner 已提交
418
    }
M
Max Bruckner 已提交
419

420 421 422
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
423
        length = sprintf((char*)number_buffer, "null");
424 425 426 427
    }
    else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
    {
        /* integer */
428
        length = sprintf((char*)number_buffer, "%.0f", d);
429 430 431 432
        trim_zeroes = false; /* don't remove zeroes for "big integers" */
    }
    else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
    {
433
        length = sprintf((char*)number_buffer, "%e", d);
434 435 436 437
        trim_zeroes = false; /* don't remove zeroes in engineering notation */
    }
    else
    {
438
        length = sprintf((char*)number_buffer, "%f", d);
M
Max Bruckner 已提交
439
    }
440

441 442
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
443
    {
444
        return false;
445 446
    }

447 448
    if (trim_zeroes)
    {
449 450 451 452 453 454 455 456 457 458 459 460
        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;
461 462
    }

463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
    /* 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;

479
    return true;
K
Kevin Branigan 已提交
480 481
}

M
Max Bruckner 已提交
482
/* parse 4 digit hexadecimal number */
483
static unsigned parse_hex4(const unsigned char * const input)
484
{
M
Max Bruckner 已提交
485
    unsigned int h = 0;
486
    size_t i = 0;
M
Max Bruckner 已提交
487

488
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
489
    {
490
        /* parse digit */
491
        if ((input[i] >= '0') && (input[i] <= '9'))
492
        {
493
            h += (unsigned int) input[i] - '0';
494
        }
495
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
496
        {
497
            h += (unsigned int) 10 + input[i] - 'A';
498
        }
499
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
500
        {
501
            h += (unsigned int) 10 + input[i] - 'a';
502 503 504 505 506
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
507

508 509 510 511 512
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
513 514 515
    }

    return h;
516 517
}

518 519
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
520
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer, const unsigned char **error_pointer)
M
Max Bruckner 已提交
521
{
522 523 524
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
525
    unsigned char utf8_length = 0;
526
    unsigned char utf8_position = 0;
527
    unsigned char sequence_length = 0;
528
    unsigned char first_byte_mark = 0;
529 530 531 532 533 534 535

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

537 538 539
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

540 541
    /* check that the code is valid */
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)) || (first_code == 0))
M
Max Bruckner 已提交
542
    {
543
        *error_pointer = first_sequence;
544
        goto fail;
M
Max Bruckner 已提交
545
    }
M
Max Bruckner 已提交
546

547 548
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
549
    {
550 551 552 553 554
        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 已提交
555
        {
556 557 558
            /* input ends unexpectedly */
            *error_pointer = first_sequence;
            goto fail;
M
Max Bruckner 已提交
559
        }
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585

        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
        {
            /* missing second half of the surrogate pair */
            *error_pointer = first_sequence;
            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 */
            *error_pointer = first_sequence;
            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 已提交
586
    }
M
Max Bruckner 已提交
587

588 589 590 591 592 593 594 595 596 597 598 599
    /* 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;
600
        first_byte_mark = 0xC0; /* 11000000 */
601 602 603 604 605
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
606
        first_byte_mark = 0xE0; /* 11100000 */
607 608 609 610 611
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
612
        first_byte_mark = 0xF0; /* 11110000 */
613 614
    }
    else
M
Max Bruckner 已提交
615
    {
616 617
        /* invalid unicode codepoint */
        *error_pointer = first_sequence;
618
        goto fail;
M
Max Bruckner 已提交
619 620
    }

621
    /* encode as utf8 */
622 623 624 625 626
    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;
627
    }
628 629 630 631 632 633 634 635
    /* 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);
636
    }
637

638 639 640 641 642 643 644 645 646
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
647
static const unsigned char *parse_string(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
{
    const unsigned char *input_pointer = input + 1;
    const unsigned char *input_end = input + 1;
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
    if (*input != '\"')
    {
        *error_pointer = input;
        goto fail;
    }

    {
        /* calculate approximate size of the output (overestimate) */
        size_t allocation_length = 0;
        size_t skipped_bytes = 0;
        while ((*input_end != '\"') && (*input_end != '\0'))
        {
            /* is escape sequence */
            if (input_end[0] == '\\')
            {
                if (input_end[1] == '\0')
                {
                    /* prevent buffer overflow when last input character is a backslash */
                    goto fail;
                }
                skipped_bytes++;
                input_end++;
            }
            input_end++;
        }
        if (*input_end == '\0')
        {
            goto fail; /* string ended unexpectedly */
        }

        /* This is at most how much we need for the output */
        allocation_length = (size_t) (input_end - input) - skipped_bytes;
687
        output = (unsigned char*)hooks->allocate(allocation_length + sizeof(""));
688 689 690 691 692 693 694
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
695
    /* loop through the string literal */
696
    while (input_pointer < input_end)
M
Max Bruckner 已提交
697
    {
698
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
699
        {
700
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
701 702 703 704
        }
        /* escape sequence */
        else
        {
705
            unsigned char sequence_length = 2;
706
            switch (input_pointer[1])
M
Max Bruckner 已提交
707 708
            {
                case 'b':
709
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
710 711
                    break;
                case 'f':
712
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
713 714
                    break;
                case 'n':
715
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
716 717
                    break;
                case 'r':
718
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
719 720
                    break;
                case 't':
721
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
722
                    break;
723 724 725
                case '\"':
                case '\\':
                case '/':
726
                    *output_pointer++ = input_pointer[1];
727
                    break;
728 729

                /* UTF-16 literal */
M
Max Bruckner 已提交
730
                case 'u':
731 732
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer, error_pointer);
                    if (sequence_length == 0)
M
Max Bruckner 已提交
733
                    {
734
                        /* failed to convert UTF16-literal to UTF-8 */
735
                        goto fail;
M
Max Bruckner 已提交
736 737
                    }
                    break;
738

M
Max Bruckner 已提交
739
                default:
740
                    *error_pointer = input_pointer;
741
                    goto fail;
M
Max Bruckner 已提交
742
            }
743
            input_pointer += sequence_length;
M
Max Bruckner 已提交
744 745
        }
    }
746 747 748

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

750
    item->type = cJSON_String;
751
    item->valuestring = (char*)output;
752

753
    return input_end + 1;
754 755

fail:
756
    if (output != NULL)
757
    {
758
        hooks->deallocate(output);
759 760 761
    }

    return NULL;
K
Kevin Branigan 已提交
762 763 764
}

/* Render the cstring provided to an escaped version that can be printed. */
765
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
766
{
767 768 769
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
770 771 772
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
773

774
    if (output_buffer == NULL)
M
Max Bruckner 已提交
775
    {
776
        return false;
M
Max Bruckner 已提交
777 778 779
    }

    /* empty string */
780
    if (input == NULL)
M
Max Bruckner 已提交
781
    {
782
        output = ensure(output_buffer, sizeof("\"\""), hooks);
783
        if (output == NULL)
M
Max Bruckner 已提交
784
        {
785
            return false;
M
Max Bruckner 已提交
786
        }
787
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
788

789
        return true;
M
Max Bruckner 已提交
790 791 792
    }

    /* set "flag" to 1 if something needs to be escaped */
793
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
794
    {
M
Max Bruckner 已提交
795
        if (strchr("\"\\\b\f\n\r\t", *input_pointer))
M
Max Bruckner 已提交
796
        {
M
Max Bruckner 已提交
797 798
            /* one character escape sequence */
            escape_characters++;
M
Max Bruckner 已提交
799
        }
M
Max Bruckner 已提交
800
        else if (*input_pointer < 32)
M
Max Bruckner 已提交
801
        {
M
Max Bruckner 已提交
802 803
            /* UTF-16 escape sequence uXXXX */
            escape_characters += 5;
M
Max Bruckner 已提交
804 805
        }
    }
M
Max Bruckner 已提交
806
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
807

808
    output = ensure(output_buffer, output_length + sizeof("\"\""), hooks);
809
    if (output == NULL)
M
Max Bruckner 已提交
810
    {
811
        return false;
M
Max Bruckner 已提交
812 813
    }

M
Max Bruckner 已提交
814 815
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
816
    {
M
Max Bruckner 已提交
817 818 819 820 821
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

822
        return true;
M
Max Bruckner 已提交
823 824
    }

M
Max Bruckner 已提交
825 826
    output[0] = '\"';
    output_pointer = output + 1;
M
Max Bruckner 已提交
827
    /* copy the string */
M
Max Bruckner 已提交
828
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
M
Max Bruckner 已提交
829
    {
830
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
M
Max Bruckner 已提交
831 832
        {
            /* normal character, copy */
M
Max Bruckner 已提交
833
            *output_pointer = *input_pointer;
M
Max Bruckner 已提交
834 835 836 837
        }
        else
        {
            /* character needs to be escaped */
838
            *output_pointer++ = '\\';
M
Max Bruckner 已提交
839
            switch (*input_pointer)
M
Max Bruckner 已提交
840 841
            {
                case '\\':
M
Max Bruckner 已提交
842
                    *output_pointer = '\\';
M
Max Bruckner 已提交
843 844
                    break;
                case '\"':
M
Max Bruckner 已提交
845
                    *output_pointer = '\"';
M
Max Bruckner 已提交
846 847
                    break;
                case '\b':
M
Max Bruckner 已提交
848
                    *output_pointer = 'b';
M
Max Bruckner 已提交
849 850
                    break;
                case '\f':
M
Max Bruckner 已提交
851
                    *output_pointer = 'f';
M
Max Bruckner 已提交
852 853
                    break;
                case '\n':
M
Max Bruckner 已提交
854
                    *output_pointer = 'n';
M
Max Bruckner 已提交
855 856
                    break;
                case '\r':
M
Max Bruckner 已提交
857
                    *output_pointer = 'r';
M
Max Bruckner 已提交
858 859
                    break;
                case '\t':
M
Max Bruckner 已提交
860
                    *output_pointer = 't';
M
Max Bruckner 已提交
861 862 863
                    break;
                default:
                    /* escape and print as unicode codepoint */
M
Max Bruckner 已提交
864 865
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
M
Max Bruckner 已提交
866 867 868 869
                    break;
            }
        }
    }
M
Max Bruckner 已提交
870 871
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';
M
Max Bruckner 已提交
872

873
    return true;
K
Kevin Branigan 已提交
874
}
M
Max Bruckner 已提交
875

M
Max Bruckner 已提交
876
/* Invoke print_string_ptr (which is useful) on an item. */
877
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks)
M
Max Bruckner 已提交
878
{
879
    return print_string_ptr((unsigned char*)item->valuestring, p, hooks);
M
Max Bruckner 已提交
880
}
K
Kevin Branigan 已提交
881 882

/* Predeclare these prototypes. */
883
static const unsigned char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const ep, const internal_hooks * const hooks);
884
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);
885
static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks);
886
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);
887
static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks);
888
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 已提交
889 890

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
891
static const unsigned char *skip_whitespace(const unsigned char *in)
M
Max Bruckner 已提交
892
{
893
    while (in && *in && (*in <= 32))
M
Max Bruckner 已提交
894 895 896 897 898 899
    {
        in++;
    }

    return in;
}
K
Kevin Branigan 已提交
900 901

/* Parse an object - create a new root, and populate. */
902
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
903
{
904
    const unsigned char *end = NULL;
M
Max Bruckner 已提交
905
    /* use global error pointer if no specific one was given */
906
    const unsigned char **error_pointer = (return_parse_end != NULL) ? (const unsigned char**)return_parse_end : &global_ep;
907 908
    cJSON *item = NULL;

909
    *error_pointer = NULL;
910 911

    item = cJSON_New_Item(&global_hooks);
912
    if (item == NULL) /* memory fail */
M
Max Bruckner 已提交
913
    {
914 915 916 917 918 919
        goto fail;
    }

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

922 923
    end = parse_value(item, skip_whitespace((const unsigned char*)value), error_pointer, &global_hooks);
    if (end == NULL)
M
Max Bruckner 已提交
924 925
    {
        /* parse failure. ep is set. */
926
        goto fail;
M
Max Bruckner 已提交
927 928 929 930 931
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
M
Max Bruckner 已提交
932
        end = skip_whitespace(end);
933
        if (*end != '\0')
M
Max Bruckner 已提交
934
        {
935
            *error_pointer = end;
936
            goto fail;
M
Max Bruckner 已提交
937 938 939 940
        }
    }
    if (return_parse_end)
    {
941
        *return_parse_end = (const char*)end;
M
Max Bruckner 已提交
942 943
    }

944
    return item;
945 946 947 948 949 950 951 952

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

    return NULL;
K
Kevin Branigan 已提交
953
}
M
Max Bruckner 已提交
954

955
/* Default options for cJSON_Parse */
956
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
957 958 959
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
960

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

963
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
964 965 966 967 968 969 970
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
971
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
972 973 974 975 976 977
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
978
    if (!print_value(item, 0, format, buffer, hooks))
M
Max Bruckner 已提交
979 980 981
    {
        goto fail;
    }
982
    update_offset(buffer);
M
Max Bruckner 已提交
983 984

    /* copy the buffer over to a new one */
985
    printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
M
Max Bruckner 已提交
986 987 988 989 990 991 992 993
    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 */
994
    hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
995 996 997 998 999 1000

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1001
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1002 1003 1004 1005
    }

    if (printed != NULL)
    {
1006
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1007 1008 1009 1010 1011
    }

    return NULL;
}

K
Kevin Branigan 已提交
1012
/* Render a cJSON item/entity/structure to text. */
1013
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1014
{
1015
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1016 1017
}

1018
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1019
{
1020
    return (char*)print(item, false, &global_hooks);
1021
}
1022

1023
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1024
{
M
Max Bruckner 已提交
1025
    printbuffer p;
M
Max Bruckner 已提交
1026 1027 1028

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1029
        return NULL;
M
Max Bruckner 已提交
1030 1031
    }

1032
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1033 1034
    if (!p.buffer)
    {
1035
        return NULL;
1036
    }
M
Max Bruckner 已提交
1037 1038

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1039
    p.offset = 0;
1040
    p.noalloc = false;
M
Max Bruckner 已提交
1041

1042 1043 1044 1045 1046 1047
    if (!print_value(item, 0, fmt, &p, &global_hooks))
    {
        return NULL;
    }

    return (char*)p.buffer;
1048 1049
}

1050
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1051 1052
{
    printbuffer p;
M
Max Bruckner 已提交
1053 1054 1055 1056 1057 1058

    if (len < 0)
    {
        return false;
    }

1059
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1060
    p.length = (size_t)len;
1061
    p.offset = 0;
1062
    p.noalloc = true;
1063
    return print_value(item, 0, fmt, &p, &global_hooks);
1064
}
K
Kevin Branigan 已提交
1065 1066

/* Parser core - when encountering text, process appropriately. */
1067
static const unsigned  char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1068
{
1069
    if (input == NULL)
M
Max Bruckner 已提交
1070
    {
1071
        return NULL; /* no input */
M
Max Bruckner 已提交
1072 1073 1074
    }

    /* parse the different types of values */
1075 1076
    /* null */
    if (!strncmp((const char*)input, "null", 4))
M
Max Bruckner 已提交
1077 1078
    {
        item->type = cJSON_NULL;
1079
        return input + 4;
M
Max Bruckner 已提交
1080
    }
1081 1082
    /* false */
    if (!strncmp((const char*)input, "false", 5))
M
Max Bruckner 已提交
1083 1084
    {
        item->type = cJSON_False;
1085
        return input + 5;
M
Max Bruckner 已提交
1086
    }
1087 1088
    /* true */
    if (!strncmp((const char*)input, "true", 4))
M
Max Bruckner 已提交
1089 1090 1091
    {
        item->type = cJSON_True;
        item->valueint = 1;
1092
        return input + 4;
M
Max Bruckner 已提交
1093
    }
1094 1095
    /* string */
    if (*input == '\"')
M
Max Bruckner 已提交
1096
    {
1097
        return parse_string(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1098
    }
1099 1100
    /* number */
    if ((*input == '-') || ((*input >= '0') && (*input <= '9')))
M
Max Bruckner 已提交
1101
    {
1102
        return parse_number(item, input);
M
Max Bruckner 已提交
1103
    }
1104 1105
    /* array */
    if (*input == '[')
M
Max Bruckner 已提交
1106
    {
1107
        return parse_array(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1108
    }
1109 1110
    /* object */
    if (*input == '{')
M
Max Bruckner 已提交
1111
    {
1112
        return parse_object(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1113 1114
    }

M
Max Bruckner 已提交
1115
    /* failure. */
1116
    *error_pointer = input;
1117
    return NULL;
K
Kevin Branigan 已提交
1118 1119 1120
}

/* Render a value to text. */
1121
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 已提交
1122
{
M
Max Bruckner 已提交
1123
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1124

M
Max Bruckner 已提交
1125
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1126
    {
1127
        return false;
M
Max Bruckner 已提交
1128
    }
M
Max Bruckner 已提交
1129 1130

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1131
    {
M
Max Bruckner 已提交
1132
        case cJSON_NULL:
1133
            output = ensure(output_buffer, 5, hooks);
1134
            if (output == NULL)
M
Max Bruckner 已提交
1135
            {
1136
                return false;
M
Max Bruckner 已提交
1137
            }
1138 1139 1140
            strcpy((char*)output, "null");
            return true;

M
Max Bruckner 已提交
1141
        case cJSON_False:
1142
            output = ensure(output_buffer, 6, hooks);
1143
            if (output == NULL)
M
Max Bruckner 已提交
1144
            {
1145
                return false;
M
Max Bruckner 已提交
1146
            }
1147 1148 1149
            strcpy((char*)output, "false");
            return true;

M
Max Bruckner 已提交
1150
        case cJSON_True:
1151
            output = ensure(output_buffer, 5, hooks);
1152
            if (output == NULL)
M
Max Bruckner 已提交
1153
            {
1154
                return false;
M
Max Bruckner 已提交
1155
            }
1156 1157 1158
            strcpy((char*)output, "true");
            return true;

M
Max Bruckner 已提交
1159
        case cJSON_Number:
1160
            return print_number(item, output_buffer, hooks);
1161

M
Max Bruckner 已提交
1162
        case cJSON_Raw:
M
Max Bruckner 已提交
1163
        {
M
Max Bruckner 已提交
1164 1165
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1166
            {
M
Max Bruckner 已提交
1167
                if (!output_buffer->noalloc)
1168
                {
1169
                    hooks->deallocate(output_buffer->buffer);
1170
                }
1171
                return false;
M
Max Bruckner 已提交
1172
            }
1173

1174
            raw_length = strlen(item->valuestring) + sizeof("");
1175
            output = ensure(output_buffer, raw_length, hooks);
1176
            if (output == NULL)
M
Max Bruckner 已提交
1177
            {
1178
                return false;
1179
            }
1180 1181
            memcpy(output, item->valuestring, raw_length);
            return true;
M
Max Bruckner 已提交
1182
        }
1183

M
Max Bruckner 已提交
1184
        case cJSON_String:
1185
            return print_string(item, output_buffer, hooks);
1186

M
Max Bruckner 已提交
1187
        case cJSON_Array:
1188
            return print_array(item, depth, format, output_buffer, hooks);
1189

M
Max Bruckner 已提交
1190
        case cJSON_Object:
1191
            return print_object(item, depth, format, output_buffer, hooks);
1192

M
Max Bruckner 已提交
1193
        default:
1194
            return false;
M
Max Bruckner 已提交
1195
    }
K
Kevin Branigan 已提交
1196 1197 1198
}

/* Build an array from input text. */
1199
static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1200
{
1201
    cJSON *head = NULL; /* head of the linked list */
1202 1203
    cJSON *current_item = NULL;

1204
    if (*input != '[')
M
Max Bruckner 已提交
1205
    {
1206
        /* not an array */
1207
        *error_pointer = input;
1208
        goto fail;
M
Max Bruckner 已提交
1209
    }
K
Kevin Branigan 已提交
1210

M
Max Bruckner 已提交
1211
    input = skip_whitespace(input + 1);
1212
    if (*input == ']')
M
Max Bruckner 已提交
1213
    {
1214
        /* empty array */
1215
        goto success;
M
Max Bruckner 已提交
1216
    }
K
Kevin Branigan 已提交
1217

1218
    /* step back to character in front of the first element */
1219
    input--;
M
Max Bruckner 已提交
1220
    /* loop through the comma separated array elements */
1221
    do
M
Max Bruckner 已提交
1222
    {
1223
        /* allocate next item */
1224
        cJSON *new_item = cJSON_New_Item(hooks);
1225
        if (new_item == NULL)
M
Max Bruckner 已提交
1226
        {
1227
            goto fail; /* allocation failure */
M
Max Bruckner 已提交
1228
        }
1229 1230 1231

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1232
        {
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
            /* 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 已提交
1245
        input = skip_whitespace(input + 1);
1246
        input = parse_value(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1247
        input = skip_whitespace(input);
1248
        if (input == NULL)
1249 1250
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1251 1252
        }
    }
1253
    while (*input == ',');
M
Max Bruckner 已提交
1254

1255
    if (*input != ']')
M
Max Bruckner 已提交
1256
    {
1257 1258
        *error_pointer = input;
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1259 1260
    }

1261 1262
success:
    item->type = cJSON_Array;
1263
    item->child = head;
1264

1265
    return input + 1;
K
Kevin Branigan 已提交
1266

1267
fail:
1268
    if (head != NULL)
1269
    {
1270
        cJSON_Delete(head);
1271 1272
    }

1273
    return NULL;
K
Kevin Branigan 已提交
1274 1275 1276
}

/* Render an array to text */
1277
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 已提交
1278
{
M
Max Bruckner 已提交
1279
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1280
    size_t length = 0;
M
Max Bruckner 已提交
1281
    cJSON *current_element = item->child;
K
Kevin Branigan 已提交
1282

M
Max Bruckner 已提交
1283
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1284
    {
1285
        return false;
M
Max Bruckner 已提交
1286 1287
    }

M
Max Bruckner 已提交
1288 1289
    /* Compose the output array. */
    /* opening square bracket */
1290
    output_pointer = ensure(output_buffer, 1, hooks);
M
Max Bruckner 已提交
1291
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1292
    {
1293
        return false;
M
Max Bruckner 已提交
1294 1295
    }

M
Max Bruckner 已提交
1296 1297
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1298

M
Max Bruckner 已提交
1299
    while (current_element != NULL)
M
Max Bruckner 已提交
1300
    {
1301
        if (!print_value(current_element, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1302
        {
1303
            return false;
M
Max Bruckner 已提交
1304
        }
1305
        update_offset(output_buffer);
M
Max Bruckner 已提交
1306
        if (current_element->next)
M
Max Bruckner 已提交
1307
        {
1308
            length = (size_t) (format ? 2 : 1);
1309
            output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1310
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1311
            {
1312
                return false;
M
Max Bruckner 已提交
1313
            }
M
Max Bruckner 已提交
1314 1315
            *output_pointer++ = ',';
            if(format)
M
Max Bruckner 已提交
1316
            {
M
Max Bruckner 已提交
1317
                *output_pointer++ = ' ';
M
Max Bruckner 已提交
1318
            }
M
Max Bruckner 已提交
1319 1320
            *output_pointer = '\0';
            output_buffer->offset += length;
M
Max Bruckner 已提交
1321
        }
M
Max Bruckner 已提交
1322
        current_element = current_element->next;
M
Max Bruckner 已提交
1323 1324
    }

1325
    output_pointer = ensure(output_buffer, 2, hooks);
M
Max Bruckner 已提交
1326
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1327
    {
1328
        return false;
M
Max Bruckner 已提交
1329
    }
M
Max Bruckner 已提交
1330 1331
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1332

1333
    return true;
K
Kevin Branigan 已提交
1334 1335 1336
}

/* Build an object from the text. */
1337
static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1338
{
1339
    cJSON *head = NULL; /* linked list head */
1340 1341
    cJSON *current_item = NULL;

1342
    if (*input != '{')
M
Max Bruckner 已提交
1343
    {
1344 1345
        *error_pointer = input;
        goto fail; /* not an object */
M
Max Bruckner 已提交
1346 1347
    }

M
Max Bruckner 已提交
1348
    input = skip_whitespace(input + 1);
1349
    if (*input == '}')
M
Max Bruckner 已提交
1350
    {
1351
        goto success; /* empty object */
M
Max Bruckner 已提交
1352 1353
    }

1354
    /* step back to character in front of the first element */
1355
    input--;
1356 1357
    /* loop through the comma separated array elements */
    do
M
Max Bruckner 已提交
1358
    {
1359
        /* allocate next item */
1360
        cJSON *new_item = cJSON_New_Item(hooks);
1361 1362 1363 1364
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }
M
Max Bruckner 已提交
1365

1366 1367
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1368
        {
1369 1370 1371 1372 1373 1374 1375 1376 1377
            /* 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 已提交
1378 1379
        }

1380
        /* parse the name of the child */
M
Max Bruckner 已提交
1381
        input = skip_whitespace(input + 1);
1382
        input = parse_string(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1383
        input = skip_whitespace(input);
1384
        if (input == NULL)
M
Max Bruckner 已提交
1385
        {
1386
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1387 1388
        }

1389 1390 1391
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1392

1393
        if (*input != ':')
M
Max Bruckner 已提交
1394
        {
1395 1396
            *error_pointer = input;
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1397
        }
1398 1399

        /* parse the value */
M
Max Bruckner 已提交
1400
        input = skip_whitespace(input + 1);
1401
        input = parse_value(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1402
        input = skip_whitespace(input);
1403
        if (input == NULL)
M
Max Bruckner 已提交
1404
        {
1405
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1406 1407
        }
    }
1408
    while (*input == ',');
1409

1410
    if (*input != '}')
M
Max Bruckner 已提交
1411
    {
1412 1413
        *error_pointer = input;
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1414 1415
    }

1416 1417
success:
    item->type = cJSON_Object;
1418
    item->child = head;
1419

1420
    return input + 1;
1421 1422

fail:
1423
    if (head != NULL)
1424
    {
1425
        cJSON_Delete(head);
1426 1427
    }

1428
    return NULL;
K
Kevin Branigan 已提交
1429 1430 1431
}

/* Render an object to text. */
1432
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)
1433
{
M
Max Bruckner 已提交
1434
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1435
    size_t length = 0;
M
Max Bruckner 已提交
1436
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1437

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

M
Max Bruckner 已提交
1443
    /* Compose the output: */
1444
    length = (size_t) (format ? 2 : 1); /* fmt: {\n */
1445
    output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1446
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1447
    {
1448
        return false;
M
Max Bruckner 已提交
1449 1450
    }

M
Max Bruckner 已提交
1451 1452
    *output_pointer++ = '{';
    if (format)
M
Max Bruckner 已提交
1453
    {
M
Max Bruckner 已提交
1454
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1455
    }
M
Max Bruckner 已提交
1456
    output_buffer->offset += length;
M
Max Bruckner 已提交
1457

M
Max Bruckner 已提交
1458
    while (current_item)
M
Max Bruckner 已提交
1459
    {
M
Max Bruckner 已提交
1460
        if (format)
M
Max Bruckner 已提交
1461
        {
M
Max Bruckner 已提交
1462
            size_t i;
1463
            output_pointer = ensure(output_buffer, depth + 1, hooks);
M
Max Bruckner 已提交
1464
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1465
            {
1466
                return false;
M
Max Bruckner 已提交
1467
            }
M
Max Bruckner 已提交
1468
            for (i = 0; i < depth + 1; i++)
M
Max Bruckner 已提交
1469
            {
M
Max Bruckner 已提交
1470
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1471
            }
M
Max Bruckner 已提交
1472
            output_buffer->offset += depth + 1;
M
Max Bruckner 已提交
1473 1474
        }

M
Max Bruckner 已提交
1475
        /* print key */
1476
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks))
M
Max Bruckner 已提交
1477
        {
1478
            return false;
M
Max Bruckner 已提交
1479
        }
M
Max Bruckner 已提交
1480
        update_offset(output_buffer);
M
Max Bruckner 已提交
1481

1482
        length = (size_t) (format ? 2 : 1);
1483
        output_pointer = ensure(output_buffer, length, hooks);
M
Max Bruckner 已提交
1484
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1485
        {
1486
            return false;
M
Max Bruckner 已提交
1487
        }
M
Max Bruckner 已提交
1488 1489
        *output_pointer++ = ':';
        if (format)
M
Max Bruckner 已提交
1490
        {
M
Max Bruckner 已提交
1491
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1492
        }
M
Max Bruckner 已提交
1493
        output_buffer->offset += length;
M
Max Bruckner 已提交
1494

M
Max Bruckner 已提交
1495
        /* print value */
1496
        if (!print_value(current_item, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1497
        {
1498
            return false;
M
Max Bruckner 已提交
1499
        }
M
Max Bruckner 已提交
1500
        update_offset(output_buffer);
M
Max Bruckner 已提交
1501

M
Max Bruckner 已提交
1502
        /* print comma if not last */
1503
        length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
1504
        output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1505
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1506
        {
1507
            return false;
M
Max Bruckner 已提交
1508
        }
M
Max Bruckner 已提交
1509
        if (current_item->next)
M
Max Bruckner 已提交
1510
        {
M
Max Bruckner 已提交
1511
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1512 1513
        }

M
Max Bruckner 已提交
1514
        if (format)
M
Max Bruckner 已提交
1515
        {
M
Max Bruckner 已提交
1516
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1517
        }
M
Max Bruckner 已提交
1518 1519
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1520

M
Max Bruckner 已提交
1521
        current_item = current_item->next;
M
Max Bruckner 已提交
1522
    }
M
Max Bruckner 已提交
1523

1524
    output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks);
M
Max Bruckner 已提交
1525
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1526
    {
1527
        return false;
M
Max Bruckner 已提交
1528
    }
M
Max Bruckner 已提交
1529
    if (format)
M
Max Bruckner 已提交
1530
    {
M
Max Bruckner 已提交
1531 1532
        size_t i;
        for (i = 0; i < (depth); i++)
M
Max Bruckner 已提交
1533
        {
M
Max Bruckner 已提交
1534
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1535 1536
        }
    }
M
Max Bruckner 已提交
1537 1538
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1539

1540
    return true;
K
Kevin Branigan 已提交
1541 1542 1543
}

/* Get Array size/item / object item. */
1544
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1545 1546
{
    cJSON *c = array->child;
1547
    size_t i = 0;
M
Max Bruckner 已提交
1548 1549 1550 1551 1552
    while(c)
    {
        i++;
        c = c->next;
    }
1553 1554 1555

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

M
Max Bruckner 已提交
1556
    return (int)i;
M
Max Bruckner 已提交
1557 1558
}

1559
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
M
Max Bruckner 已提交
1560
{
1561
    cJSON *c = array ? array->child : NULL;
M
Max Bruckner 已提交
1562 1563 1564 1565 1566 1567 1568 1569 1570
    while (c && item > 0)
    {
        item--;
        c = c->next;
    }

    return c;
}

1571
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1572
{
1573
    cJSON *c = object ? object->child : NULL;
1574
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
M
Max Bruckner 已提交
1575 1576 1577 1578 1579 1580
    {
        c = c->next;
    }
    return c;
}

1581
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
{
    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;
}

1599
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1600 1601 1602
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1603 1604

/* Utility for array list handling. */
M
Max Bruckner 已提交
1605 1606 1607 1608 1609 1610
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1611
/* Utility for handling references. */
1612
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1613
{
1614
    cJSON *ref = cJSON_New_Item(hooks);
M
Max Bruckner 已提交
1615 1616
    if (!ref)
    {
1617
        return NULL;
M
Max Bruckner 已提交
1618 1619
    }
    memcpy(ref, item, sizeof(cJSON));
1620
    ref->string = NULL;
M
Max Bruckner 已提交
1621
    ref->type |= cJSON_IsReference;
1622
    ref->next = ref->prev = NULL;
M
Max Bruckner 已提交
1623 1624
    return ref;
}
K
Kevin Branigan 已提交
1625 1626

/* Add item to array/object. */
1627
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1628
{
1629 1630 1631
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1632 1633 1634
    {
        return;
    }
1635 1636 1637 1638

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1639 1640 1641 1642 1643 1644 1645
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1646
        while (child->next)
M
Max Bruckner 已提交
1647
        {
1648
            child = child->next;
M
Max Bruckner 已提交
1649
        }
1650
        suffix_object(child, item);
M
Max Bruckner 已提交
1651 1652 1653
    }
}

1654
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1655
{
1656
    /* call cJSON_AddItemToObjectCS for code reuse */
1657
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1658 1659
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1660 1661
}

1662 1663 1664 1665
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wcast-qual"
1666
/* Add an item to an object with constant string as key */
1667
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1668 1669 1670 1671 1672 1673 1674
{
    if (!item)
    {
        return;
    }
    if (!(item->type & cJSON_StringIsConst) && item->string)
    {
1675
        global_hooks.deallocate(item->string);
1676 1677 1678 1679 1680
    }
    item->string = (char*)string;
    item->type |= cJSON_StringIsConst;
    cJSON_AddItemToArray(object, item);
}
1681 1682 1683
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic pop
#endif
1684

1685
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1686
{
1687
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1688 1689
}

1690
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1691
{
1692
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1693 1694
}

M
Max Bruckner 已提交
1695
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
1706
        return NULL;
1707
    }
1708
    if (c->prev)
1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721
    {
        /* 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 */
1722
    c->prev = c->next = NULL;
1723 1724 1725

    return c;
}
1726
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1727 1728 1729 1730 1731 1732 1733 1734
{
    if (which < 0)
    {
        return NULL;
    }

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

1736
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1737 1738 1739 1740
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1741
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1742
{
1743
    size_t i = 0;
1744
    cJSON *c = object->child;
1745
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1746 1747 1748 1749 1750 1751
    {
        i++;
        c = c->next;
    }
    if (c)
    {
M
Max Bruckner 已提交
1752
        return DetachItemFromArray(object, i);
1753 1754
    }

1755
    return NULL;
1756 1757
}

1758
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1759 1760 1761
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1762 1763

/* Replace array/object items with new ones. */
1764
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789
{
    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 已提交
1790
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
{
    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;
    }
1816
    c->next = c->prev = NULL;
1817 1818
    cJSON_Delete(c);
}
1819
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
1820 1821 1822 1823 1824 1825 1826 1827
{
    if (which < 0)
    {
        return;
    }

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

1829
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1830
{
1831
    size_t i = 0;
1832
    cJSON *c = object->child;
1833
    while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1834 1835 1836 1837 1838 1839
    {
        i++;
        c = c->next;
    }
    if(c)
    {
1840 1841 1842
        /* free the old string if not const */
        if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
        {
1843
             global_hooks.deallocate(newitem->string);
1844 1845
        }

1846
        newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1847
        ReplaceItemInArray(object, i, newitem);
1848 1849
    }
}
K
Kevin Branigan 已提交
1850 1851

/* Create basic types: */
1852
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
1853
{
1854
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1855 1856 1857 1858 1859 1860 1861 1862
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

1863
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
1864
{
1865
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1866 1867 1868 1869 1870 1871 1872 1873
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

1874
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
1875
{
1876
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1877 1878 1879 1880 1881 1882 1883 1884
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

1885
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
1886
{
1887
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1888 1889 1890 1891 1892 1893 1894 1895
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

1896
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
1897
{
1898
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1899 1900 1901 1902
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916

        /* 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 已提交
1917 1918 1919 1920 1921
    }

    return item;
}

1922
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
1923
{
1924
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1925 1926 1927
    if(item)
    {
        item->type = cJSON_String;
1928
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1929 1930 1931
        if(!item->valuestring)
        {
            cJSON_Delete(item);
1932
            return NULL;
M
Max Bruckner 已提交
1933 1934 1935 1936 1937 1938
        }
    }

    return item;
}

1939
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
1940
{
1941
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1942 1943 1944
    if(item)
    {
        item->type = cJSON_Raw;
1945
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
1946 1947 1948 1949 1950 1951 1952 1953
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
1954 1955
}

1956
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
1957
{
1958
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1959 1960 1961 1962 1963 1964 1965 1966
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

1967
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
1968
{
1969
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1970 1971 1972 1973 1974 1975 1976
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
1977 1978

/* Create Arrays: */
1979
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
1980
{
1981
    size_t i = 0;
1982 1983
    cJSON *n = NULL;
    cJSON *p = NULL;
1984 1985 1986 1987 1988 1989 1990 1991 1992
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
1993 1994 1995 1996 1997
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
1998
            return NULL;
M
Max Bruckner 已提交
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2014
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2015
{
2016
    size_t i = 0;
2017 2018
    cJSON *n = NULL;
    cJSON *p = NULL;
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2029
    {
2030
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2031 2032 2033
        if(!n)
        {
            cJSON_Delete(a);
2034
            return NULL;
M
Max Bruckner 已提交
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2050
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2051
{
2052
    size_t i = 0;
2053 2054
    cJSON *n = NULL;
    cJSON *p = NULL;
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2065 2066 2067 2068 2069
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2070
            return NULL;
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2086
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2087
{
2088
    size_t i = 0;
2089 2090
    cJSON *n = NULL;
    cJSON *p = NULL;
2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2101 2102 2103 2104 2105
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2106
            return NULL;
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2121 2122

/* Duplication */
2123
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2124
{
M
Max Bruckner 已提交
2125
    cJSON *newitem = NULL;
2126 2127
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2128
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2129 2130 2131 2132

    /* Bail on bad ptr */
    if (!item)
    {
2133
        goto fail;
M
Max Bruckner 已提交
2134 2135
    }
    /* Create new item */
2136
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2137 2138
    if (!newitem)
    {
2139
        goto fail;
M
Max Bruckner 已提交
2140 2141 2142 2143 2144 2145 2146
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2147
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2148 2149
        if (!newitem->valuestring)
        {
2150
            goto fail;
M
Max Bruckner 已提交
2151 2152 2153 2154
        }
    }
    if (item->string)
    {
2155
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2156 2157
        if (!newitem->string)
        {
2158
            goto fail;
M
Max Bruckner 已提交
2159 2160 2161 2162 2163 2164 2165 2166
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2167 2168
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2169
    {
2170
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2171 2172
        if (!newchild)
        {
2173
            goto fail;
M
Max Bruckner 已提交
2174
        }
2175
        if (next != NULL)
M
Max Bruckner 已提交
2176 2177
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2178 2179 2180
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2181 2182 2183 2184
        }
        else
        {
            /* Set newitem->child and move to it */
2185 2186
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2187
        }
2188
        child = child->next;
M
Max Bruckner 已提交
2189 2190 2191
    }

    return newitem;
2192 2193 2194 2195 2196 2197 2198 2199

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

    return NULL;
2200
}
2201

2202
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2203
{
2204
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
    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 已提交
2244
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2245 2246 2247 2248
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2249
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2250
                }
M
Max Bruckner 已提交
2251
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2252
            }
M
Max Bruckner 已提交
2253
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2254 2255 2256 2257
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2258
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2259 2260 2261 2262 2263
        }
    }

    /* and null-terminate. */
    *into = '\0';
2264
}
2265

2266
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2267 2268 2269 2270 2271 2272 2273 2274 2275
{
    if (item == NULL)
    {
        return false;
    }

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

2276
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2277 2278 2279 2280 2281 2282 2283 2284 2285
{
    if (item == NULL)
    {
        return false;
    }

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

2286
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296
{
    if (item == NULL)
    {
        return false;
    }

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


2297
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2298 2299 2300 2301 2302 2303 2304 2305
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2306
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2307 2308 2309 2310 2311 2312 2313 2314 2315
{
    if (item == NULL)
    {
        return false;
    }

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

2316
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2317 2318 2319 2320 2321 2322 2323 2324 2325
{
    if (item == NULL)
    {
        return false;
    }

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

2326
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2327 2328 2329 2330 2331 2332 2333 2334 2335
{
    if (item == NULL)
    {
        return false;
    }

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

2336
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2337 2338 2339 2340 2341 2342 2343 2344 2345
{
    if (item == NULL)
    {
        return false;
    }

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

2346
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2347 2348 2349 2350 2351 2352 2353 2354 2355
{
    if (item == NULL)
    {
        return false;
    }

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

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

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