cJSON.c 61.3 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];
}

M
Max Bruckner 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
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 已提交
204
/* Parse the input text to generate a number, and populate the result into item. */
M
Max Bruckner 已提交
205
static const unsigned char *parse_number(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
206
{
207
    double number = 0;
208
    unsigned char *after_end = NULL;
209 210 211
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
212

M
Max Bruckner 已提交
213
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
214 215 216 217
    {
        return NULL;
    }

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

259
    item->valuedouble = number;
M
Max Bruckner 已提交
260

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

M
Max Bruckner 已提交
275 276
    item->type = cJSON_Number;

M
Max Bruckner 已提交
277 278
    input_buffer->offset += (size_t)(after_end - number_c_string);
    return buffer_at_offset(input_buffer);
K
Kevin Branigan 已提交
279 280
}

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

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
300 301
typedef struct
{
302
    unsigned char *buffer;
303 304
    size_t length;
    size_t offset;
305
    cJSON_bool noalloc;
M
Max Bruckner 已提交
306
} printbuffer;
307

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

314
    if ((p == NULL) || (p->buffer == NULL))
315 316 317 318
    {
        return NULL;
    }

M
Max Bruckner 已提交
319 320 321 322 323 324
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

325
    if (needed > INT_MAX)
M
Max Bruckner 已提交
326
    {
327
        /* sizes bigger than INT_MAX are currently not supported */
328
        return NULL;
M
Max Bruckner 已提交
329
    }
330

331
    needed += p->offset + 1;
M
Max Bruckner 已提交
332 333 334 335 336
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

337 338 339 340
    if (p->noalloc) {
        return NULL;
    }

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

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

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

    return newbuffer + p->offset;
386 387
}

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

398
    buffer->offset += strlen((const char*)buffer_pointer);
399 400
}

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

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

419
    return length;
420 421 422
}

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

M
Max Bruckner 已提交
433
    if (output_buffer == NULL)
M
Max Bruckner 已提交
434
    {
435
        return false;
M
Max Bruckner 已提交
436
    }
M
Max Bruckner 已提交
437

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

459 460
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
461
    {
462
        return false;
463 464
    }

465 466
    if (trim_zeroes)
    {
467 468 469 470 471 472 473 474 475 476 477 478
        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;
479 480
    }

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
    /* 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;

497
    return true;
K
Kevin Branigan 已提交
498 499
}

M
Max Bruckner 已提交
500
/* parse 4 digit hexadecimal number */
501
static unsigned parse_hex4(const unsigned char * const input)
502
{
M
Max Bruckner 已提交
503
    unsigned int h = 0;
504
    size_t i = 0;
M
Max Bruckner 已提交
505

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

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

    return h;
534 535
}

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

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

555 556 557
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

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

565 566
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
567
    {
568 569 570 571 572
        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 已提交
573
        {
574 575 576
            /* input ends unexpectedly */
            *error_pointer = first_sequence;
            goto fail;
M
Max Bruckner 已提交
577
        }
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 603

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

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

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

656 657 658 659 660 661 662 663 664
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
665
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)
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
{
    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;
705
        output = (unsigned char*)hooks->allocate(allocation_length + sizeof(""));
706 707 708 709 710 711 712
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
713
    /* loop through the string literal */
714
    while (input_pointer < input_end)
M
Max Bruckner 已提交
715
    {
716
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
717
        {
718
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
719 720 721 722
        }
        /* escape sequence */
        else
        {
723
            unsigned char sequence_length = 2;
724
            switch (input_pointer[1])
M
Max Bruckner 已提交
725 726
            {
                case 'b':
727
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
728 729
                    break;
                case 'f':
730
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
731 732
                    break;
                case 'n':
733
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
734 735
                    break;
                case 'r':
736
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
737 738
                    break;
                case 't':
739
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
740
                    break;
741 742 743
                case '\"':
                case '\\':
                case '/':
744
                    *output_pointer++ = input_pointer[1];
745
                    break;
746 747

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

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

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

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

771
    return input_end + 1;
772 773

fail:
774
    if (output != NULL)
775
    {
776
        hooks->deallocate(output);
777 778 779
    }

    return NULL;
K
Kevin Branigan 已提交
780 781 782
}

/* Render the cstring provided to an escaped version that can be printed. */
783
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
784
{
785 786 787
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
788 789 790
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
791

792
    if (output_buffer == NULL)
M
Max Bruckner 已提交
793
    {
794
        return false;
M
Max Bruckner 已提交
795 796 797
    }

    /* empty string */
798
    if (input == NULL)
M
Max Bruckner 已提交
799
    {
800
        output = ensure(output_buffer, sizeof("\"\""), hooks);
801
        if (output == NULL)
M
Max Bruckner 已提交
802
        {
803
            return false;
M
Max Bruckner 已提交
804
        }
805
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
806

807
        return true;
M
Max Bruckner 已提交
808 809 810
    }

    /* set "flag" to 1 if something needs to be escaped */
811
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
812
    {
M
Max Bruckner 已提交
813
        if (strchr("\"\\\b\f\n\r\t", *input_pointer))
M
Max Bruckner 已提交
814
        {
M
Max Bruckner 已提交
815 816
            /* one character escape sequence */
            escape_characters++;
M
Max Bruckner 已提交
817
        }
M
Max Bruckner 已提交
818
        else if (*input_pointer < 32)
M
Max Bruckner 已提交
819
        {
M
Max Bruckner 已提交
820 821
            /* UTF-16 escape sequence uXXXX */
            escape_characters += 5;
M
Max Bruckner 已提交
822 823
        }
    }
M
Max Bruckner 已提交
824
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
825

826
    output = ensure(output_buffer, output_length + sizeof("\"\""), hooks);
827
    if (output == NULL)
M
Max Bruckner 已提交
828
    {
829
        return false;
M
Max Bruckner 已提交
830 831
    }

M
Max Bruckner 已提交
832 833
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
834
    {
M
Max Bruckner 已提交
835 836 837 838 839
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

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

M
Max Bruckner 已提交
843 844
    output[0] = '\"';
    output_pointer = output + 1;
M
Max Bruckner 已提交
845
    /* copy the string */
M
Max Bruckner 已提交
846
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
M
Max Bruckner 已提交
847
    {
848
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
M
Max Bruckner 已提交
849 850
        {
            /* normal character, copy */
M
Max Bruckner 已提交
851
            *output_pointer = *input_pointer;
M
Max Bruckner 已提交
852 853 854 855
        }
        else
        {
            /* character needs to be escaped */
856
            *output_pointer++ = '\\';
M
Max Bruckner 已提交
857
            switch (*input_pointer)
M
Max Bruckner 已提交
858 859
            {
                case '\\':
M
Max Bruckner 已提交
860
                    *output_pointer = '\\';
M
Max Bruckner 已提交
861 862
                    break;
                case '\"':
M
Max Bruckner 已提交
863
                    *output_pointer = '\"';
M
Max Bruckner 已提交
864 865
                    break;
                case '\b':
M
Max Bruckner 已提交
866
                    *output_pointer = 'b';
M
Max Bruckner 已提交
867 868
                    break;
                case '\f':
M
Max Bruckner 已提交
869
                    *output_pointer = 'f';
M
Max Bruckner 已提交
870 871
                    break;
                case '\n':
M
Max Bruckner 已提交
872
                    *output_pointer = 'n';
M
Max Bruckner 已提交
873 874
                    break;
                case '\r':
M
Max Bruckner 已提交
875
                    *output_pointer = 'r';
M
Max Bruckner 已提交
876 877
                    break;
                case '\t':
M
Max Bruckner 已提交
878
                    *output_pointer = 't';
M
Max Bruckner 已提交
879 880 881
                    break;
                default:
                    /* escape and print as unicode codepoint */
M
Max Bruckner 已提交
882 883
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
M
Max Bruckner 已提交
884 885 886 887
                    break;
            }
        }
    }
M
Max Bruckner 已提交
888 889
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';
M
Max Bruckner 已提交
890

891
    return true;
K
Kevin Branigan 已提交
892
}
M
Max Bruckner 已提交
893

M
Max Bruckner 已提交
894
/* Invoke print_string_ptr (which is useful) on an item. */
895
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks)
M
Max Bruckner 已提交
896
{
897
    return print_string_ptr((unsigned char*)item->valuestring, p, hooks);
M
Max Bruckner 已提交
898
}
K
Kevin Branigan 已提交
899 900

/* Predeclare these prototypes. */
M
Max Bruckner 已提交
901
static const unsigned char *parse_value(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
902
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);
M
Max Bruckner 已提交
903
static const unsigned char *parse_array(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
904
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);
M
Max Bruckner 已提交
905
static const unsigned char *parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
906
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 已提交
907 908

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
909
static const unsigned char *skip_whitespace(const unsigned char *in)
M
Max Bruckner 已提交
910
{
911
    while (in && *in && (*in <= 32))
M
Max Bruckner 已提交
912 913 914 915 916 917
    {
        in++;
    }

    return in;
}
K
Kevin Branigan 已提交
918

M
Max Bruckner 已提交
919 920 921 922 923 924 925
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        return NULL;
    }

M
Max Bruckner 已提交
926 927 928 929 930 931 932 933 934
    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 已提交
935 936 937 938

    return buffer;
}

K
Kevin Branigan 已提交
939
/* Parse an object - create a new root, and populate. */
940
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
941
{
M
Max Bruckner 已提交
942
    parse_buffer buffer;
943
    const unsigned char *end = NULL;
M
Max Bruckner 已提交
944
    /* use global error pointer if no specific one was given */
945
    const unsigned char **error_pointer = (return_parse_end != NULL) ? (const unsigned char**)return_parse_end : &global_ep;
946 947
    cJSON *item = NULL;

948
    *error_pointer = NULL;
949 950

    item = cJSON_New_Item(&global_hooks);
951
    if (item == NULL) /* memory fail */
M
Max Bruckner 已提交
952
    {
953 954 955 956 957 958
        goto fail;
    }

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

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

    end = parse_value(item, buffer_skip_whitespace(&buffer), error_pointer, &global_hooks);
966
    if (end == NULL)
M
Max Bruckner 已提交
967 968
    {
        /* parse failure. ep is set. */
969
        goto fail;
M
Max Bruckner 已提交
970 971 972 973 974
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
M
Max Bruckner 已提交
975
        end = skip_whitespace(end);
976
        if (*end != '\0')
M
Max Bruckner 已提交
977
        {
978
            *error_pointer = end;
979
            goto fail;
M
Max Bruckner 已提交
980 981 982 983
        }
    }
    if (return_parse_end)
    {
984
        *return_parse_end = (const char*)end;
M
Max Bruckner 已提交
985 986
    }

987
    return item;
988 989 990 991 992 993 994 995

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

    return NULL;
K
Kevin Branigan 已提交
996
}
M
Max Bruckner 已提交
997

998
/* Default options for cJSON_Parse */
999
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
1000 1001 1002
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
1003

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

1006
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1007 1008 1009 1010 1011 1012 1013
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
1014
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
1015 1016 1017 1018 1019 1020
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
1021
    if (!print_value(item, 0, format, buffer, hooks))
M
Max Bruckner 已提交
1022 1023 1024
    {
        goto fail;
    }
1025
    update_offset(buffer);
M
Max Bruckner 已提交
1026 1027

    /* copy the buffer over to a new one */
1028
    printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
M
Max Bruckner 已提交
1029 1030 1031 1032 1033 1034 1035 1036
    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 */
1037
    hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1038 1039 1040 1041 1042 1043

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1044
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1045 1046 1047 1048
    }

    if (printed != NULL)
    {
1049
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1050 1051 1052 1053 1054
    }

    return NULL;
}

K
Kevin Branigan 已提交
1055
/* Render a cJSON item/entity/structure to text. */
1056
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1057
{
1058
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1059 1060
}

1061
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1062
{
1063
    return (char*)print(item, false, &global_hooks);
1064
}
1065

1066
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1067
{
M
Max Bruckner 已提交
1068
    printbuffer p;
M
Max Bruckner 已提交
1069 1070 1071

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1072
        return NULL;
M
Max Bruckner 已提交
1073 1074
    }

1075
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1076 1077
    if (!p.buffer)
    {
1078
        return NULL;
1079
    }
M
Max Bruckner 已提交
1080 1081

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1082
    p.offset = 0;
1083
    p.noalloc = false;
M
Max Bruckner 已提交
1084

1085 1086 1087 1088 1089 1090
    if (!print_value(item, 0, fmt, &p, &global_hooks))
    {
        return NULL;
    }

    return (char*)p.buffer;
1091 1092
}

1093
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1094 1095
{
    printbuffer p;
M
Max Bruckner 已提交
1096 1097 1098 1099 1100 1101

    if (len < 0)
    {
        return false;
    }

1102
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1103
    p.length = (size_t)len;
1104
    p.offset = 0;
1105
    p.noalloc = true;
1106
    return print_value(item, 0, fmt, &p, &global_hooks);
1107
}
K
Kevin Branigan 已提交
1108 1109

/* Parser core - when encountering text, process appropriately. */
M
Max Bruckner 已提交
1110
static const unsigned  char *parse_value(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1111
{
M
Max Bruckner 已提交
1112
    const unsigned char *content_pointer = NULL;
M
Max Bruckner 已提交
1113
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
M
Max Bruckner 已提交
1114
    {
1115
        return NULL; /* no input */
M
Max Bruckner 已提交
1116 1117 1118
    }

    /* parse the different types of values */
1119
    /* null */
M
Max Bruckner 已提交
1120
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
M
Max Bruckner 已提交
1121 1122
    {
        item->type = cJSON_NULL;
M
Max Bruckner 已提交
1123 1124
        input_buffer->offset += 4;
        return buffer_at_offset(input_buffer);
M
Max Bruckner 已提交
1125
    }
1126
    /* false */
M
Max Bruckner 已提交
1127
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
M
Max Bruckner 已提交
1128 1129
    {
        item->type = cJSON_False;
M
Max Bruckner 已提交
1130 1131
        input_buffer->offset += 5;
        return buffer_at_offset(input_buffer);
M
Max Bruckner 已提交
1132
    }
1133
    /* true */
M
Max Bruckner 已提交
1134
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
M
Max Bruckner 已提交
1135 1136 1137
    {
        item->type = cJSON_True;
        item->valueint = 1;
M
Max Bruckner 已提交
1138 1139
        input_buffer->offset += 4;
        return buffer_at_offset(input_buffer);
M
Max Bruckner 已提交
1140
    }
1141
    /* string */
M
Max Bruckner 已提交
1142
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
M
Max Bruckner 已提交
1143
    {
M
Max Bruckner 已提交
1144 1145 1146 1147 1148 1149 1150 1151
        content_pointer = parse_string(item, buffer_at_offset(input_buffer), error_pointer, hooks);
        if (content_pointer == NULL)
        {
            return NULL;
        }

        input_buffer->offset = (size_t)(content_pointer - input_buffer->content);
        return buffer_at_offset(input_buffer);
M
Max Bruckner 已提交
1152
    }
1153
    /* number */
M
Max Bruckner 已提交
1154
    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 已提交
1155
    {
M
Max Bruckner 已提交
1156
        return parse_number(item, input_buffer);
M
Max Bruckner 已提交
1157
    }
1158
    /* array */
M
Max Bruckner 已提交
1159
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
M
Max Bruckner 已提交
1160
    {
M
Max Bruckner 已提交
1161
        return parse_array(item, input_buffer, error_pointer, hooks);
M
Max Bruckner 已提交
1162
    }
1163
    /* object */
M
Max Bruckner 已提交
1164
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
M
Max Bruckner 已提交
1165
    {
M
Max Bruckner 已提交
1166
        content_pointer = parse_object(item, input_buffer, error_pointer, hooks);
M
Max Bruckner 已提交
1167 1168 1169 1170 1171 1172 1173
        if (content_pointer == NULL)
        {
            return NULL;
        }

        input_buffer->offset = (size_t)(content_pointer - input_buffer->content);
        return buffer_at_offset(input_buffer);
M
Max Bruckner 已提交
1174 1175
    }

M
Max Bruckner 已提交
1176
    /* failure. */
M
Max Bruckner 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
    if (can_access_at_index(input_buffer, 0))
    {
        *error_pointer = buffer_at_offset(input_buffer);
    }
    else if (input_buffer->length > 0)
    {
        *error_pointer = input_buffer->content + input_buffer->length - 1;
    }
    else
    {
        *error_pointer = input_buffer->content;
    }

1190
    return NULL;
K
Kevin Branigan 已提交
1191 1192 1193
}

/* Render a value to text. */
1194
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 已提交
1195
{
M
Max Bruckner 已提交
1196
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1197

M
Max Bruckner 已提交
1198
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1199
    {
1200
        return false;
M
Max Bruckner 已提交
1201
    }
M
Max Bruckner 已提交
1202 1203

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

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

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

M
Max Bruckner 已提交
1232
        case cJSON_Number:
1233
            return print_number(item, output_buffer, hooks);
1234

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

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

M
Max Bruckner 已提交
1257
        case cJSON_String:
1258
            return print_string(item, output_buffer, hooks);
1259

M
Max Bruckner 已提交
1260
        case cJSON_Array:
1261
            return print_array(item, depth, format, output_buffer, hooks);
1262

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

M
Max Bruckner 已提交
1266
        default:
1267
            return false;
M
Max Bruckner 已提交
1268
    }
K
Kevin Branigan 已提交
1269 1270 1271
}

/* Build an array from input text. */
M
Max Bruckner 已提交
1272
static const unsigned char *parse_array(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1273
{
1274
    cJSON *head = NULL; /* head of the linked list */
1275 1276
    cJSON *current_item = NULL;

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

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

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

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

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

M
Max Bruckner 已提交
1337
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
M
Max Bruckner 已提交
1338
    {
M
Max Bruckner 已提交
1339
        *error_pointer = buffer_at_offset(input_buffer);
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 1349
    input_buffer->offset++;

    return buffer_at_offset(input_buffer);
K
Kevin Branigan 已提交
1350

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

1357
    return NULL;
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. */
M
Max Bruckner 已提交
1421
static const unsigned char *parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1422
{
1423
    cJSON *head = NULL; /* linked list head */
1424
    cJSON *current_item = NULL;
M
Max Bruckner 已提交
1425
    const unsigned char *content_pointer = NULL;
1426

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

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

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

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

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

1474
        /* parse the name of the child */
M
Max Bruckner 已提交
1475 1476 1477 1478
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
        content_pointer = parse_string(current_item, buffer_at_offset(input_buffer), error_pointer, hooks);
        if (content_pointer == NULL)
M
Max Bruckner 已提交
1479
        {
1480
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1481
        }
M
Max Bruckner 已提交
1482 1483
        input_buffer->offset = (size_t)(content_pointer - input_buffer->content);
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1484

1485 1486 1487
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1488

M
Max Bruckner 已提交
1489
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
M
Max Bruckner 已提交
1490
        {
M
Max Bruckner 已提交
1491
            *error_pointer = buffer_at_offset(input_buffer);
1492
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1493
        }
1494 1495

        /* parse the value */
M
Max Bruckner 已提交
1496 1497 1498
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
        if (parse_value(current_item, input_buffer, error_pointer, hooks) == NULL)
M
Max Bruckner 已提交
1499
        {
1500
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1501
        }
M
Max Bruckner 已提交
1502
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1503
    }
M
Max Bruckner 已提交
1504
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1505

M
Max Bruckner 已提交
1506
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
M
Max Bruckner 已提交
1507
    {
M
Max Bruckner 已提交
1508
        *error_pointer = buffer_at_offset(input_buffer);
1509
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1510 1511
    }

1512 1513
success:
    item->type = cJSON_Object;
1514
    item->child = head;
1515

M
Max Bruckner 已提交
1516 1517
    input_buffer->offset++;
    return buffer_at_offset(input_buffer);
1518 1519

fail:
1520
    if (head != NULL)
1521
    {
1522
        cJSON_Delete(head);
1523 1524
    }

1525
    return NULL;
K
Kevin Branigan 已提交
1526 1527 1528
}

/* Render an object to text. */
1529
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)
1530
{
M
Max Bruckner 已提交
1531
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1532
    size_t length = 0;
M
Max Bruckner 已提交
1533
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1534

M
Max Bruckner 已提交
1535
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1536
    {
1537
        return false;
M
Max Bruckner 已提交
1538 1539
    }

M
Max Bruckner 已提交
1540
    /* Compose the output: */
1541
    length = (size_t) (format ? 2 : 1); /* fmt: {\n */
1542
    output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1543
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1544
    {
1545
        return false;
M
Max Bruckner 已提交
1546 1547
    }

M
Max Bruckner 已提交
1548 1549
    *output_pointer++ = '{';
    if (format)
M
Max Bruckner 已提交
1550
    {
M
Max Bruckner 已提交
1551
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1552
    }
M
Max Bruckner 已提交
1553
    output_buffer->offset += length;
M
Max Bruckner 已提交
1554

M
Max Bruckner 已提交
1555
    while (current_item)
M
Max Bruckner 已提交
1556
    {
M
Max Bruckner 已提交
1557
        if (format)
M
Max Bruckner 已提交
1558
        {
M
Max Bruckner 已提交
1559
            size_t i;
1560
            output_pointer = ensure(output_buffer, depth + 1, hooks);
M
Max Bruckner 已提交
1561
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1562
            {
1563
                return false;
M
Max Bruckner 已提交
1564
            }
M
Max Bruckner 已提交
1565
            for (i = 0; i < depth + 1; i++)
M
Max Bruckner 已提交
1566
            {
M
Max Bruckner 已提交
1567
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1568
            }
M
Max Bruckner 已提交
1569
            output_buffer->offset += depth + 1;
M
Max Bruckner 已提交
1570 1571
        }

M
Max Bruckner 已提交
1572
        /* print key */
1573
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks))
M
Max Bruckner 已提交
1574
        {
1575
            return false;
M
Max Bruckner 已提交
1576
        }
M
Max Bruckner 已提交
1577
        update_offset(output_buffer);
M
Max Bruckner 已提交
1578

1579
        length = (size_t) (format ? 2 : 1);
1580
        output_pointer = ensure(output_buffer, length, hooks);
M
Max Bruckner 已提交
1581
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1582
        {
1583
            return false;
M
Max Bruckner 已提交
1584
        }
M
Max Bruckner 已提交
1585 1586
        *output_pointer++ = ':';
        if (format)
M
Max Bruckner 已提交
1587
        {
M
Max Bruckner 已提交
1588
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1589
        }
M
Max Bruckner 已提交
1590
        output_buffer->offset += length;
M
Max Bruckner 已提交
1591

M
Max Bruckner 已提交
1592
        /* print value */
1593
        if (!print_value(current_item, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1594
        {
1595
            return false;
M
Max Bruckner 已提交
1596
        }
M
Max Bruckner 已提交
1597
        update_offset(output_buffer);
M
Max Bruckner 已提交
1598

M
Max Bruckner 已提交
1599
        /* print comma if not last */
1600
        length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
1601
        output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1602
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1603
        {
1604
            return false;
M
Max Bruckner 已提交
1605
        }
M
Max Bruckner 已提交
1606
        if (current_item->next)
M
Max Bruckner 已提交
1607
        {
M
Max Bruckner 已提交
1608
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1609 1610
        }

M
Max Bruckner 已提交
1611
        if (format)
M
Max Bruckner 已提交
1612
        {
M
Max Bruckner 已提交
1613
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1614
        }
M
Max Bruckner 已提交
1615 1616
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1617

M
Max Bruckner 已提交
1618
        current_item = current_item->next;
M
Max Bruckner 已提交
1619
    }
M
Max Bruckner 已提交
1620

1621
    output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks);
M
Max Bruckner 已提交
1622
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1623
    {
1624
        return false;
M
Max Bruckner 已提交
1625
    }
M
Max Bruckner 已提交
1626
    if (format)
M
Max Bruckner 已提交
1627
    {
M
Max Bruckner 已提交
1628 1629
        size_t i;
        for (i = 0; i < (depth); i++)
M
Max Bruckner 已提交
1630
        {
M
Max Bruckner 已提交
1631
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1632 1633
        }
    }
M
Max Bruckner 已提交
1634 1635
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1636

1637
    return true;
K
Kevin Branigan 已提交
1638 1639 1640
}

/* Get Array size/item / object item. */
1641
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1642 1643
{
    cJSON *c = array->child;
1644
    size_t i = 0;
M
Max Bruckner 已提交
1645 1646 1647 1648 1649
    while(c)
    {
        i++;
        c = c->next;
    }
1650 1651 1652

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

M
Max Bruckner 已提交
1653
    return (int)i;
M
Max Bruckner 已提交
1654 1655
}

1656
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
M
Max Bruckner 已提交
1657
{
1658
    cJSON *c = array ? array->child : NULL;
M
Max Bruckner 已提交
1659 1660 1661 1662 1663 1664 1665 1666 1667
    while (c && item > 0)
    {
        item--;
        c = c->next;
    }

    return c;
}

1668
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1669
{
1670
    cJSON *c = object ? object->child : NULL;
1671
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
M
Max Bruckner 已提交
1672 1673 1674 1675 1676 1677
    {
        c = c->next;
    }
    return c;
}

1678
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
{
    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;
}

1696
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1697 1698 1699
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1700 1701

/* Utility for array list handling. */
M
Max Bruckner 已提交
1702 1703 1704 1705 1706 1707
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1708
/* Utility for handling references. */
1709
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1710
{
1711
    cJSON *ref = cJSON_New_Item(hooks);
M
Max Bruckner 已提交
1712 1713
    if (!ref)
    {
1714
        return NULL;
M
Max Bruckner 已提交
1715 1716
    }
    memcpy(ref, item, sizeof(cJSON));
1717
    ref->string = NULL;
M
Max Bruckner 已提交
1718
    ref->type |= cJSON_IsReference;
1719
    ref->next = ref->prev = NULL;
M
Max Bruckner 已提交
1720 1721
    return ref;
}
K
Kevin Branigan 已提交
1722 1723

/* Add item to array/object. */
1724
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1725
{
1726 1727 1728
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1729 1730 1731
    {
        return;
    }
1732 1733 1734 1735

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1736 1737 1738 1739 1740 1741 1742
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1743
        while (child->next)
M
Max Bruckner 已提交
1744
        {
1745
            child = child->next;
M
Max Bruckner 已提交
1746
        }
1747
        suffix_object(child, item);
M
Max Bruckner 已提交
1748 1749 1750
    }
}

1751
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1752
{
1753
    /* call cJSON_AddItemToObjectCS for code reuse */
1754
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1755 1756
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1757 1758
}

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

1782
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1783
{
1784
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1785 1786
}

1787
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1788
{
1789
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1790 1791
}

M
Max Bruckner 已提交
1792
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
1803
        return NULL;
1804
    }
1805
    if (c->prev)
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
    {
        /* 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 */
1819
    c->prev = c->next = NULL;
1820 1821 1822

    return c;
}
1823
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1824 1825 1826 1827 1828 1829 1830 1831
{
    if (which < 0)
    {
        return NULL;
    }

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

1833
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1834 1835 1836 1837
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1838
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1839
{
1840
    size_t i = 0;
1841
    cJSON *c = object->child;
1842
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1843 1844 1845 1846 1847 1848
    {
        i++;
        c = c->next;
    }
    if (c)
    {
M
Max Bruckner 已提交
1849
        return DetachItemFromArray(object, i);
1850 1851
    }

1852
    return NULL;
1853 1854
}

1855
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1856 1857 1858
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1859 1860

/* Replace array/object items with new ones. */
1861
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
{
    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 已提交
1887
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912
{
    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;
    }
1913
    c->next = c->prev = NULL;
1914 1915
    cJSON_Delete(c);
}
1916
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
1917 1918 1919 1920 1921 1922 1923 1924
{
    if (which < 0)
    {
        return;
    }

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

1926
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1927
{
1928
    size_t i = 0;
1929
    cJSON *c = object->child;
1930
    while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1931 1932 1933 1934 1935 1936
    {
        i++;
        c = c->next;
    }
    if(c)
    {
1937 1938 1939
        /* free the old string if not const */
        if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
        {
1940
             global_hooks.deallocate(newitem->string);
1941 1942
        }

1943
        newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1944
        ReplaceItemInArray(object, i, newitem);
1945 1946
    }
}
K
Kevin Branigan 已提交
1947 1948

/* Create basic types: */
1949
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
1950
{
1951
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1952 1953 1954 1955 1956 1957 1958 1959
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

1960
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
1961
{
1962
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1963 1964 1965 1966 1967 1968 1969 1970
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

1971
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
1972
{
1973
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1974 1975 1976 1977 1978 1979 1980 1981
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

1982
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
1983
{
1984
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1985 1986 1987 1988 1989 1990 1991 1992
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

1993
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
1994
{
1995
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1996 1997 1998 1999
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013

        /* 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 已提交
2014 2015 2016 2017 2018
    }

    return item;
}

2019
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
2020
{
2021
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2022 2023 2024
    if(item)
    {
        item->type = cJSON_String;
2025
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
2026 2027 2028
        if(!item->valuestring)
        {
            cJSON_Delete(item);
2029
            return NULL;
M
Max Bruckner 已提交
2030 2031 2032 2033 2034 2035
        }
    }

    return item;
}

2036
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
2037
{
2038
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2039 2040 2041
    if(item)
    {
        item->type = cJSON_Raw;
2042
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
2043 2044 2045 2046 2047 2048 2049 2050
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
2051 2052
}

2053
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
2054
{
2055
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2056 2057 2058 2059 2060 2061 2062 2063
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

2064
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
2065
{
2066
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2067 2068 2069 2070 2071 2072 2073
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
2074 2075

/* Create Arrays: */
2076
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
2077
{
2078
    size_t i = 0;
2079 2080
    cJSON *n = NULL;
    cJSON *p = NULL;
2081 2082 2083 2084 2085 2086 2087 2088 2089
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2090 2091 2092 2093 2094
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
2095
            return NULL;
M
Max Bruckner 已提交
2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2111
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2112
{
2113
    size_t i = 0;
2114 2115
    cJSON *n = NULL;
    cJSON *p = NULL;
2116 2117 2118 2119 2120 2121 2122 2123 2124 2125
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2126
    {
2127
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2128 2129 2130
        if(!n)
        {
            cJSON_Delete(a);
2131
            return NULL;
M
Max Bruckner 已提交
2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2147
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2148
{
2149
    size_t i = 0;
2150 2151
    cJSON *n = NULL;
    cJSON *p = NULL;
2152 2153 2154 2155 2156 2157 2158 2159 2160 2161
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2162 2163 2164 2165 2166
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2167
            return NULL;
2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2183
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2184
{
2185
    size_t i = 0;
2186 2187
    cJSON *n = NULL;
    cJSON *p = NULL;
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2198 2199 2200 2201 2202
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2203
            return NULL;
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2218 2219

/* Duplication */
2220
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2221
{
M
Max Bruckner 已提交
2222
    cJSON *newitem = NULL;
2223 2224
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2225
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2226 2227 2228 2229

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

    return newitem;
2289 2290 2291 2292 2293 2294 2295 2296

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

    return NULL;
2297
}
2298

2299
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2300
{
2301
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
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 2334 2335 2336 2337 2338 2339 2340
    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 已提交
2341
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2342 2343 2344 2345
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2346
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2347
                }
M
Max Bruckner 已提交
2348
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2349
            }
M
Max Bruckner 已提交
2350
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2351 2352 2353 2354
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2355
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2356 2357 2358 2359 2360
        }
    }

    /* and null-terminate. */
    *into = '\0';
2361
}
2362

2363
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2364 2365 2366 2367 2368 2369 2370 2371 2372
{
    if (item == NULL)
    {
        return false;
    }

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

2373
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2374 2375 2376 2377 2378 2379 2380 2381 2382
{
    if (item == NULL)
    {
        return false;
    }

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

2383
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
{
    if (item == NULL)
    {
        return false;
    }

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


2394
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2395 2396 2397 2398 2399 2400 2401 2402
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2403
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2404 2405 2406 2407 2408 2409 2410 2411 2412
{
    if (item == NULL)
    {
        return false;
    }

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

2413
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2414 2415 2416 2417 2418 2419 2420 2421 2422
{
    if (item == NULL)
    {
        return false;
    }

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

2423
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2424 2425 2426 2427 2428 2429 2430 2431 2432
{
    if (item == NULL)
    {
        return false;
    }

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

2433
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2434 2435 2436 2437 2438 2439 2440 2441 2442
{
    if (item == NULL)
    {
        return false;
    }

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

2443
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2444 2445 2446 2447 2448 2449 2450 2451 2452
{
    if (item == NULL)
    {
        return false;
    }

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

2453
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2454 2455 2456 2457 2458 2459 2460 2461
{
    if (item == NULL)
    {
        return false;
    }

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