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

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

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

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

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

26
#ifdef __GNUC__
27
#pragma GCC visibility push(default)
28 29
#endif

K
Kevin Branigan 已提交
30 31 32 33 34 35 36
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
37
#include <locale.h>
38 39

#ifdef __GNUC__
40
#pragma GCC visibility pop
41
#endif
42

K
Kevin Branigan 已提交
43 44
#include "cJSON.h"

M
Max Bruckner 已提交
45
/* define our own boolean type */
46 47
#define true ((cJSON_bool)1)
#define false ((cJSON_bool)0)
M
Max Bruckner 已提交
48

49 50 51 52 53
typedef struct {
    const unsigned char *json;
    size_t position;
} error;
static error global_error = { NULL, 0 };
K
Kevin Branigan 已提交
54

55
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
M
Max Bruckner 已提交
56
{
57
    return (const char*) (global_error.json + global_error.position);
M
Max Bruckner 已提交
58
}
K
Kevin Branigan 已提交
59

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

65
CJSON_PUBLIC(const char*) cJSON_Version(void)
66 67 68 69 70 71 72
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

M
Max Bruckner 已提交
73
/* case insensitive strcmp */
74
static int cJSON_strcasecmp(const unsigned char *string1, const unsigned char *string2)
K
Kevin Branigan 已提交
75
{
76
    if (string1 == NULL)
M
Max Bruckner 已提交
77
    {
78 79 80 81 82 83 84
        if (string2 == NULL)
        {
            /* both NULL */
            return 0;
        }

        return 1;
M
Max Bruckner 已提交
85
    }
86 87

    if (string2 == NULL)
M
Max Bruckner 已提交
88 89 90
    {
        return 1;
    }
91 92

    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
M
Max Bruckner 已提交
93
    {
94
        if (*string1 == '\0')
M
Max Bruckner 已提交
95 96 97 98 99
        {
            return 0;
        }
    }

100
    return tolower(string1[0]) - tolower(string2[0]);
K
Kevin Branigan 已提交
101 102
}

103 104 105 106 107 108 109 110
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 已提交
111

M
Max Bruckner 已提交
112
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
113
{
M
Max Bruckner 已提交
114
    size_t length = 0;
115
    unsigned char *copy = NULL;
K
Kevin Branigan 已提交
116

M
Max Bruckner 已提交
117
    if (string == NULL)
118 119 120 121
    {
        return NULL;
    }

M
Max Bruckner 已提交
122 123
    length = strlen((const char*)string) + sizeof("");
    if (!(copy = (unsigned char*)hooks->allocate(length)))
M
Max Bruckner 已提交
124
    {
125
        return NULL;
M
Max Bruckner 已提交
126
    }
M
Max Bruckner 已提交
127
    memcpy(copy, string, length);
M
Max Bruckner 已提交
128 129

    return copy;
K
Kevin Branigan 已提交
130 131
}

132
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
K
Kevin Branigan 已提交
133
{
M
Max Bruckner 已提交
134
    if (hooks == NULL)
M
Max Bruckner 已提交
135 136
    {
        /* Reset hooks */
137 138 139
        global_hooks.allocate = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
K
Kevin Branigan 已提交
140 141 142
        return;
    }

143
    global_hooks.allocate = malloc;
M
Max Bruckner 已提交
144 145
    if (hooks->malloc_fn != NULL)
    {
146
        global_hooks.allocate = hooks->malloc_fn;
M
Max Bruckner 已提交
147 148
    }

149
    global_hooks.deallocate = free;
M
Max Bruckner 已提交
150 151
    if (hooks->free_fn != NULL)
    {
152
        global_hooks.deallocate = hooks->free_fn;
M
Max Bruckner 已提交
153 154 155
    }

    /* use realloc only if both free and malloc are used */
156 157
    global_hooks.reallocate = NULL;
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
M
Max Bruckner 已提交
158
    {
159
        global_hooks.reallocate = realloc;
M
Max Bruckner 已提交
160
    }
K
Kevin Branigan 已提交
161 162 163
}

/* Internal constructor. */
164
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
K
Kevin Branigan 已提交
165
{
166
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
M
Max Bruckner 已提交
167 168
    if (node)
    {
169
        memset(node, '\0', sizeof(cJSON));
M
Max Bruckner 已提交
170 171 172
    }

    return node;
K
Kevin Branigan 已提交
173 174 175
}

/* Delete a cJSON structure. */
M
Max Bruckner 已提交
176
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
K
Kevin Branigan 已提交
177
{
M
Max Bruckner 已提交
178
    cJSON *next = NULL;
M
Max Bruckner 已提交
179
    while (item != NULL)
M
Max Bruckner 已提交
180
    {
M
Max Bruckner 已提交
181 182
        next = item->next;
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
M
Max Bruckner 已提交
183
        {
M
Max Bruckner 已提交
184
            cJSON_Delete(item->child);
M
Max Bruckner 已提交
185
        }
M
Max Bruckner 已提交
186
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
M
Max Bruckner 已提交
187
        {
M
Max Bruckner 已提交
188
            global_hooks.deallocate(item->valuestring);
M
Max Bruckner 已提交
189
        }
M
Max Bruckner 已提交
190
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
M
Max Bruckner 已提交
191
        {
M
Max Bruckner 已提交
192
            global_hooks.deallocate(item->string);
M
Max Bruckner 已提交
193
        }
M
Max Bruckner 已提交
194 195
        global_hooks.deallocate(item);
        item = next;
M
Max Bruckner 已提交
196
    }
K
Kevin Branigan 已提交
197 198
}

199 200 201 202 203 204 205
/* 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 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
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 已提交
222
/* Parse the input text to generate a number, and populate the result into item. */
223
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
K
Kevin Branigan 已提交
224
{
225
    double number = 0;
226
    unsigned char *after_end = NULL;
227 228 229
    unsigned char number_c_string[64];
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
M
Max Bruckner 已提交
230

M
Max Bruckner 已提交
231
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
232
    {
233
        return false;
234 235
    }

236
    /* copy the number into a temporary buffer and replace '.' with the decimal point
M
Max Bruckner 已提交
237 238 239
     * 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++)
240
    {
M
Max Bruckner 已提交
241
        switch (buffer_at_offset(input_buffer)[i])
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
        {
            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 已提交
257
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
                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 已提交
273
    {
274
        return false; /* parse_error */
M
Max Bruckner 已提交
275 276
    }

277
    item->valuedouble = number;
M
Max Bruckner 已提交
278

279
    /* use saturation in case of overflow */
280
    if (number >= INT_MAX)
281 282 283
    {
        item->valueint = INT_MAX;
    }
284
    else if (number <= INT_MIN)
285 286 287 288 289
    {
        item->valueint = INT_MIN;
    }
    else
    {
290
        item->valueint = (int)number;
291
    }
292

M
Max Bruckner 已提交
293 294
    item->type = cJSON_Number;

M
Max Bruckner 已提交
295
    input_buffer->offset += (size_t)(after_end - number_c_string);
296
    return true;
K
Kevin Branigan 已提交
297 298
}

299
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
300
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
301 302 303 304 305 306 307 308 309 310 311
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
312
        object->valueint = (int)number;
313 314 315 316 317
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
318 319
typedef struct
{
320
    unsigned char *buffer;
321 322
    size_t length;
    size_t offset;
323
    cJSON_bool noalloc;
M
Max Bruckner 已提交
324
} printbuffer;
325

M
Max Bruckner 已提交
326
/* realloc printbuffer if necessary to have at least "needed" bytes more */
327
static unsigned char* ensure(printbuffer * const p, size_t needed, const internal_hooks * const hooks)
328
{
329
    unsigned char *newbuffer = NULL;
330 331
    size_t newsize = 0;

332
    if ((p == NULL) || (p->buffer == NULL))
333 334 335 336
    {
        return NULL;
    }

M
Max Bruckner 已提交
337 338 339 340 341 342
    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

343
    if (needed > INT_MAX)
M
Max Bruckner 已提交
344
    {
345
        /* sizes bigger than INT_MAX are currently not supported */
346
        return NULL;
M
Max Bruckner 已提交
347
    }
348

349
    needed += p->offset + 1;
M
Max Bruckner 已提交
350 351 352 353 354
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

355 356 357 358
    if (p->noalloc) {
        return NULL;
    }

359
    /* calculate new buffer size */
M
Max Bruckner 已提交
360
    if (needed > (INT_MAX / 2))
361 362 363 364 365 366 367 368 369 370 371
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
372 373 374 375
    else
    {
        newsize = needed * 2;
    }
376

377
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
378
    {
M
Max Bruckner 已提交
379
        /* reallocate with realloc if available */
380
        newbuffer = (unsigned char*)hooks->reallocate(p->buffer, newsize);
M
Max Bruckner 已提交
381
    }
M
Max Bruckner 已提交
382
    else
M
Max Bruckner 已提交
383
    {
M
Max Bruckner 已提交
384
        /* otherwise reallocate manually */
385
        newbuffer = (unsigned char*)hooks->allocate(newsize);
M
Max Bruckner 已提交
386 387
        if (!newbuffer)
        {
388
            hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
389 390 391 392 393 394 395
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
396
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
397
        }
398
        hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
399 400 401 402 403
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
404 405
}

406 407
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
408
{
409 410
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
411
    {
412
        return;
M
Max Bruckner 已提交
413
    }
414
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
415

416
    buffer->offset += strlen((const char*)buffer_pointer);
417 418
}

419
/* Removes trailing zeroes from the end of a printed number */
420
static int trim_trailing_zeroes(const unsigned char * const number, int length, const unsigned char decimal_point)
K
Kevin Branigan 已提交
421
{
422
    if ((number == NULL) || (length <= 0))
423
    {
424
        return -1;
425 426
    }

427
    while ((length > 0) && (number[length - 1] == '0'))
M
Max Bruckner 已提交
428
    {
429
        length--;
M
Max Bruckner 已提交
430
    }
431
    if ((length > 0) && (number[length - 1] == decimal_point))
432
    {
433 434
        /* remove trailing decimal_point */
        length--;
435 436
    }

437
    return length;
438 439 440
}

/* Render the number nicely from the given item into a string. */
441
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
442
{
M
Max Bruckner 已提交
443
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
444
    double d = item->valuedouble;
445
    int length = 0;
446
    size_t i = 0;
447
    cJSON_bool trim_zeroes = true; /* should zeroes at the end be removed? */
448 449
    unsigned char number_buffer[64]; /* temporary buffer to print the number into */
    unsigned char decimal_point = get_decimal_point();
M
Max Bruckner 已提交
450

M
Max Bruckner 已提交
451
    if (output_buffer == NULL)
M
Max Bruckner 已提交
452
    {
453
        return false;
M
Max Bruckner 已提交
454
    }
M
Max Bruckner 已提交
455

456 457 458
    /* This checks for NaN and Infinity */
    if ((d * 0) != 0)
    {
459
        length = sprintf((char*)number_buffer, "null");
460 461 462 463
    }
    else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
    {
        /* integer */
464
        length = sprintf((char*)number_buffer, "%.0f", d);
465 466 467 468
        trim_zeroes = false; /* don't remove zeroes for "big integers" */
    }
    else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
    {
469
        length = sprintf((char*)number_buffer, "%e", d);
470 471 472 473
        trim_zeroes = false; /* don't remove zeroes in engineering notation */
    }
    else
    {
474
        length = sprintf((char*)number_buffer, "%f", d);
M
Max Bruckner 已提交
475
    }
476

477 478
    /* sprintf failed or buffer overrun occured */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
479
    {
480
        return false;
481 482
    }

483 484
    if (trim_zeroes)
    {
485 486 487 488 489 490 491 492 493 494 495 496
        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;
497 498
    }

499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    /* 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;

515
    return true;
K
Kevin Branigan 已提交
516 517
}

M
Max Bruckner 已提交
518
/* parse 4 digit hexadecimal number */
519
static unsigned parse_hex4(const unsigned char * const input)
520
{
M
Max Bruckner 已提交
521
    unsigned int h = 0;
522
    size_t i = 0;
M
Max Bruckner 已提交
523

524
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
525
    {
526
        /* parse digit */
527
        if ((input[i] >= '0') && (input[i] <= '9'))
528
        {
529
            h += (unsigned int) input[i] - '0';
530
        }
531
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
532
        {
533
            h += (unsigned int) 10 + input[i] - 'A';
534
        }
535
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
536
        {
537
            h += (unsigned int) 10 + input[i] - 'a';
538 539 540 541 542
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
543

544 545 546 547 548
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
549 550 551
    }

    return h;
552 553
}

554 555
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
556
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
M
Max Bruckner 已提交
557
{
558 559 560
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
561
    unsigned char utf8_length = 0;
562
    unsigned char utf8_position = 0;
563
    unsigned char sequence_length = 0;
564
    unsigned char first_byte_mark = 0;
565 566 567 568 569 570

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

572 573 574
    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

575
    /* check that the code is valid */
576
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
M
Max Bruckner 已提交
577
    {
578
        goto fail;
M
Max Bruckner 已提交
579
    }
M
Max Bruckner 已提交
580

581 582
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
583
    {
584 585 586 587 588
        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 已提交
589
        {
590 591
            /* input ends unexpectedly */
            goto fail;
M
Max Bruckner 已提交
592
        }
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
        {
            /* missing second half of the surrogate pair */
            goto fail;
        }

        /* get the second utf16 sequence */
        second_code = parse_hex4(second_sequence + 2);
        /* check that the code is valid */
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
        {
            /* invalid second half of the surrogate pair */
            goto fail;
        }


        /* calculate the unicode codepoint from the surrogate pair */
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
    }
    else
    {
        sequence_length = 6; /* \uXXXX */
        codepoint = first_code;
M
Max Bruckner 已提交
617
    }
M
Max Bruckner 已提交
618

619 620 621 622 623 624 625 626 627 628 629 630
    /* 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;
631
        first_byte_mark = 0xC0; /* 11000000 */
632 633 634 635 636
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
637
        first_byte_mark = 0xE0; /* 11100000 */
638 639 640 641 642
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
643
        first_byte_mark = 0xF0; /* 11110000 */
644 645
    }
    else
M
Max Bruckner 已提交
646
    {
647
        /* invalid unicode codepoint */
648
        goto fail;
M
Max Bruckner 已提交
649 650
    }

651
    /* encode as utf8 */
652 653 654 655 656
    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;
657
    }
658 659 660 661 662 663 664 665
    /* 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);
666
    }
667

668 669 670 671 672 673 674 675 676
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
677
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
678
{
M
Max Bruckner 已提交
679 680
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
681 682 683 684
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
M
Max Bruckner 已提交
685
    if (buffer_at_offset(input_buffer)[0] != '\"')
686 687 688 689 690 691 692 693
    {
        goto fail;
    }

    {
        /* calculate approximate size of the output (overestimate) */
        size_t allocation_length = 0;
        size_t skipped_bytes = 0;
M
Max Bruckner 已提交
694
        while ((*input_end != '\"') && ((size_t)(input_end - input_buffer->content) < input_buffer->length))
695 696 697 698
        {
            /* is escape sequence */
            if (input_end[0] == '\\')
            {
M
Max Bruckner 已提交
699
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
700 701 702 703 704 705 706 707 708
                {
                    /* prevent buffer overflow when last input character is a backslash */
                    goto fail;
                }
                skipped_bytes++;
                input_end++;
            }
            input_end++;
        }
M
Max Bruckner 已提交
709
        if (*input_end != '\"')
710 711 712 713 714
        {
            goto fail; /* string ended unexpectedly */
        }

        /* This is at most how much we need for the output */
M
Max Bruckner 已提交
715
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
716
        output = (unsigned char*)hooks->allocate(allocation_length + sizeof(""));
717 718 719 720 721 722 723
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
724
    /* loop through the string literal */
725
    while (input_pointer < input_end)
M
Max Bruckner 已提交
726
    {
727
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
728
        {
729
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
730 731 732 733
        }
        /* escape sequence */
        else
        {
734
            unsigned char sequence_length = 2;
M
Max Bruckner 已提交
735 736 737 738 739
            if ((input_end - input_pointer) < 1)
            {
                goto fail;
            }

740
            switch (input_pointer[1])
M
Max Bruckner 已提交
741 742
            {
                case 'b':
743
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
744 745
                    break;
                case 'f':
746
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
747 748
                    break;
                case 'n':
749
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
750 751
                    break;
                case 'r':
752
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
753 754
                    break;
                case 't':
755
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
756
                    break;
757 758 759
                case '\"':
                case '\\':
                case '/':
760
                    *output_pointer++ = input_pointer[1];
761
                    break;
762 763

                /* UTF-16 literal */
M
Max Bruckner 已提交
764
                case 'u':
765
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
766
                    if (sequence_length == 0)
M
Max Bruckner 已提交
767
                    {
768
                        /* failed to convert UTF16-literal to UTF-8 */
769
                        goto fail;
M
Max Bruckner 已提交
770 771
                    }
                    break;
772

M
Max Bruckner 已提交
773
                default:
774
                    goto fail;
M
Max Bruckner 已提交
775
            }
776
            input_pointer += sequence_length;
M
Max Bruckner 已提交
777 778
        }
    }
779 780 781

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

783
    item->type = cJSON_String;
784
    item->valuestring = (char*)output;
785

M
Max Bruckner 已提交
786 787 788
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

789
    return true;
790 791

fail:
792
    if (output != NULL)
793
    {
794
        hooks->deallocate(output);
795 796
    }

797 798 799 800 801
    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

802
    return false;
K
Kevin Branigan 已提交
803 804 805
}

/* Render the cstring provided to an escaped version that can be printed. */
806
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
807
{
808 809 810
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
811 812 813
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
814

815
    if (output_buffer == NULL)
M
Max Bruckner 已提交
816
    {
817
        return false;
M
Max Bruckner 已提交
818 819 820
    }

    /* empty string */
821
    if (input == NULL)
M
Max Bruckner 已提交
822
    {
823
        output = ensure(output_buffer, sizeof("\"\""), hooks);
824
        if (output == NULL)
M
Max Bruckner 已提交
825
        {
826
            return false;
M
Max Bruckner 已提交
827
        }
828
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
829

830
        return true;
M
Max Bruckner 已提交
831 832 833
    }

    /* set "flag" to 1 if something needs to be escaped */
834
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
835
    {
M
Max Bruckner 已提交
836
        switch (*input_pointer)
M
Max Bruckner 已提交
837
        {
M
Max Bruckner 已提交
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
            case '\"':
            case '\\':
            case '\b':
            case '\f':
            case '\n':
            case '\r':
            case '\t':
                /* one character escape sequence */
                escape_characters++;
                break;
            default:
                if (*input_pointer < 32)
                {
                    /* UTF-16 escape sequence uXXXX */
                    escape_characters += 5;
                }
                break;
M
Max Bruckner 已提交
855 856
        }
    }
M
Max Bruckner 已提交
857
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
858

859
    output = ensure(output_buffer, output_length + sizeof("\"\""), hooks);
860
    if (output == NULL)
M
Max Bruckner 已提交
861
    {
862
        return false;
M
Max Bruckner 已提交
863 864
    }

M
Max Bruckner 已提交
865 866
    /* no characters have to be escaped */
    if (escape_characters == 0)
M
Max Bruckner 已提交
867
    {
M
Max Bruckner 已提交
868 869 870 871 872
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

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

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

924
    return true;
K
Kevin Branigan 已提交
925
}
M
Max Bruckner 已提交
926

M
Max Bruckner 已提交
927
/* Invoke print_string_ptr (which is useful) on an item. */
928
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks)
M
Max Bruckner 已提交
929
{
930
    return print_string_ptr((unsigned char*)item->valuestring, p, hooks);
M
Max Bruckner 已提交
931
}
K
Kevin Branigan 已提交
932 933

/* Predeclare these prototypes. */
934
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
935
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);
936
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
937
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);
938
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
939
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 已提交
940 941

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
942 943 944 945 946 947 948
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        return NULL;
    }

M
Max Bruckner 已提交
949 950 951 952 953 954 955 956 957
    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 已提交
958 959 960 961

    return buffer;
}

K
Kevin Branigan 已提交
962
/* Parse an object - create a new root, and populate. */
963
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
K
Kevin Branigan 已提交
964
{
965
    parse_buffer buffer = { 0 };
966
    cJSON *item = NULL;
967 968 969 970

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;
971 972 973 974

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

M
Max Bruckner 已提交
977 978 979 980
    buffer.content = (const unsigned char*)value;
    buffer.length = strlen((const char*)value) + sizeof("");
    buffer.offset = 0;

981 982 983 984 985 986 987
    item = cJSON_New_Item(&global_hooks);
    if (item == NULL) /* memory fail */
    {
        goto fail;
    }

    if (!parse_value(item, buffer_skip_whitespace(&buffer), &global_hooks))
M
Max Bruckner 已提交
988 989
    {
        /* parse failure. ep is set. */
990
        goto fail;
M
Max Bruckner 已提交
991 992 993 994 995
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
996 997
        buffer_skip_whitespace(&buffer);
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
M
Max Bruckner 已提交
998
        {
999
            goto fail;
M
Max Bruckner 已提交
1000 1001 1002 1003
        }
    }
    if (return_parse_end)
    {
1004
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
M
Max Bruckner 已提交
1005 1006
    }

1007
    return item;
1008 1009 1010 1011 1012 1013 1014

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

1015 1016
    if (value != NULL)
    {
1017 1018 1019 1020
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

1021 1022
        if (buffer.offset < buffer.length)
        {
1023
            local_error.position = buffer.offset;
1024 1025 1026
        }
        else if (buffer.length > 0)
        {
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
            local_error.position = buffer.length - 1;
        }

        if (return_parse_end != NULL)
        {
            *return_parse_end = (const char*)local_error.json + local_error.position;
        }
        else
        {
            global_error = local_error;
1037 1038 1039
        }
    }

1040
    return NULL;
K
Kevin Branigan 已提交
1041
}
M
Max Bruckner 已提交
1042

1043
/* Default options for cJSON_Parse */
1044
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
1045 1046 1047
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
1048

1049
#ifndef min
M
Max Bruckner 已提交
1050
#define min(a, b) ((a < b) ? a : b)
1051
#endif
M
Max Bruckner 已提交
1052

1053
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1054 1055 1056 1057 1058 1059 1060
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
1061
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
1062 1063 1064 1065 1066 1067
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
1068
    if (!print_value(item, 0, format, buffer, hooks))
M
Max Bruckner 已提交
1069 1070 1071
    {
        goto fail;
    }
1072
    update_offset(buffer);
M
Max Bruckner 已提交
1073

1074 1075
    /* check if reallocate is available */
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
1076
    {
1077 1078 1079 1080 1081
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length);
        buffer->buffer = NULL;
        if (printed == NULL) {
            goto fail;
        }
M
Max Bruckner 已提交
1082
    }
1083 1084 1085 1086 1087 1088 1089 1090 1091
    else /* otherwise copy the JSON over to a new buffer */
    {
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
        if (printed == NULL)
        {
            goto fail;
        }
        memcpy(printed, buffer->buffer, min(buffer->length, buffer->offset + 1));
        printed[buffer->offset] = '\0'; /* just to be sure */
M
Max Bruckner 已提交
1092

1093 1094 1095
        /* free the buffer */
        hooks->deallocate(buffer->buffer);
    }
M
Max Bruckner 已提交
1096 1097 1098 1099 1100 1101

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
1102
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
1103 1104 1105 1106
    }

    if (printed != NULL)
    {
1107
        hooks->deallocate(printed);
M
Max Bruckner 已提交
1108 1109 1110 1111 1112
    }

    return NULL;
}

K
Kevin Branigan 已提交
1113
/* Render a cJSON item/entity/structure to text. */
1114
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
1115
{
1116
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
1117 1118
}

1119
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1120
{
1121
    return (char*)print(item, false, &global_hooks);
1122
}
1123

1124
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1125
{
M
Max Bruckner 已提交
1126
    printbuffer p;
M
Max Bruckner 已提交
1127 1128 1129

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
1130
        return NULL;
M
Max Bruckner 已提交
1131 1132
    }

1133
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1134 1135
    if (!p.buffer)
    {
1136
        return NULL;
1137
    }
M
Max Bruckner 已提交
1138 1139

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
1140
    p.offset = 0;
1141
    p.noalloc = false;
M
Max Bruckner 已提交
1142

1143 1144 1145 1146 1147 1148
    if (!print_value(item, 0, fmt, &p, &global_hooks))
    {
        return NULL;
    }

    return (char*)p.buffer;
1149 1150
}

1151
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1152 1153
{
    printbuffer p;
M
Max Bruckner 已提交
1154 1155 1156 1157 1158 1159

    if (len < 0)
    {
        return false;
    }

1160
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
1161
    p.length = (size_t)len;
1162
    p.offset = 0;
1163
    p.noalloc = true;
1164
    return print_value(item, 0, fmt, &p, &global_hooks);
1165
}
K
Kevin Branigan 已提交
1166 1167

/* Parser core - when encountering text, process appropriately. */
1168
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1169
{
M
Max Bruckner 已提交
1170
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
M
Max Bruckner 已提交
1171
    {
1172
        return false; /* no input */
M
Max Bruckner 已提交
1173 1174 1175
    }

    /* parse the different types of values */
1176
    /* null */
M
Max Bruckner 已提交
1177
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
M
Max Bruckner 已提交
1178 1179
    {
        item->type = cJSON_NULL;
M
Max Bruckner 已提交
1180
        input_buffer->offset += 4;
1181
        return true;
M
Max Bruckner 已提交
1182
    }
1183
    /* false */
M
Max Bruckner 已提交
1184
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
M
Max Bruckner 已提交
1185 1186
    {
        item->type = cJSON_False;
M
Max Bruckner 已提交
1187
        input_buffer->offset += 5;
1188
        return true;
M
Max Bruckner 已提交
1189
    }
1190
    /* true */
M
Max Bruckner 已提交
1191
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
M
Max Bruckner 已提交
1192 1193 1194
    {
        item->type = cJSON_True;
        item->valueint = 1;
M
Max Bruckner 已提交
1195
        input_buffer->offset += 4;
1196
        return true;
M
Max Bruckner 已提交
1197
    }
1198
    /* string */
M
Max Bruckner 已提交
1199
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
M
Max Bruckner 已提交
1200
    {
1201
        return parse_string(item, input_buffer, hooks);
M
Max Bruckner 已提交
1202
    }
1203
    /* number */
M
Max Bruckner 已提交
1204
    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 已提交
1205
    {
M
Max Bruckner 已提交
1206
        return parse_number(item, input_buffer);
M
Max Bruckner 已提交
1207
    }
1208
    /* array */
M
Max Bruckner 已提交
1209
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
M
Max Bruckner 已提交
1210
    {
1211
        return parse_array(item, input_buffer, hooks);
M
Max Bruckner 已提交
1212
    }
1213
    /* object */
M
Max Bruckner 已提交
1214
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
M
Max Bruckner 已提交
1215
    {
1216
        return parse_object(item, input_buffer, hooks);
M
Max Bruckner 已提交
1217 1218
    }

M
Max Bruckner 已提交
1219

1220
    return false;
K
Kevin Branigan 已提交
1221 1222 1223
}

/* Render a value to text. */
1224
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 已提交
1225
{
M
Max Bruckner 已提交
1226
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1227

M
Max Bruckner 已提交
1228
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1229
    {
1230
        return false;
M
Max Bruckner 已提交
1231
    }
M
Max Bruckner 已提交
1232 1233

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1234
    {
M
Max Bruckner 已提交
1235
        case cJSON_NULL:
1236
            output = ensure(output_buffer, 5, hooks);
1237
            if (output == NULL)
M
Max Bruckner 已提交
1238
            {
1239
                return false;
M
Max Bruckner 已提交
1240
            }
1241 1242 1243
            strcpy((char*)output, "null");
            return true;

M
Max Bruckner 已提交
1244
        case cJSON_False:
1245
            output = ensure(output_buffer, 6, hooks);
1246
            if (output == NULL)
M
Max Bruckner 已提交
1247
            {
1248
                return false;
M
Max Bruckner 已提交
1249
            }
1250 1251 1252
            strcpy((char*)output, "false");
            return true;

M
Max Bruckner 已提交
1253
        case cJSON_True:
1254
            output = ensure(output_buffer, 5, hooks);
1255
            if (output == NULL)
M
Max Bruckner 已提交
1256
            {
1257
                return false;
M
Max Bruckner 已提交
1258
            }
1259 1260 1261
            strcpy((char*)output, "true");
            return true;

M
Max Bruckner 已提交
1262
        case cJSON_Number:
1263
            return print_number(item, output_buffer, hooks);
1264

M
Max Bruckner 已提交
1265
        case cJSON_Raw:
M
Max Bruckner 已提交
1266
        {
M
Max Bruckner 已提交
1267 1268
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1269
            {
M
Max Bruckner 已提交
1270
                if (!output_buffer->noalloc)
1271
                {
1272
                    hooks->deallocate(output_buffer->buffer);
1273
                }
1274
                return false;
M
Max Bruckner 已提交
1275
            }
1276

1277
            raw_length = strlen(item->valuestring) + sizeof("");
1278
            output = ensure(output_buffer, raw_length, hooks);
1279
            if (output == NULL)
M
Max Bruckner 已提交
1280
            {
1281
                return false;
1282
            }
1283 1284
            memcpy(output, item->valuestring, raw_length);
            return true;
M
Max Bruckner 已提交
1285
        }
1286

M
Max Bruckner 已提交
1287
        case cJSON_String:
1288
            return print_string(item, output_buffer, hooks);
1289

M
Max Bruckner 已提交
1290
        case cJSON_Array:
1291
            return print_array(item, depth, format, output_buffer, hooks);
1292

M
Max Bruckner 已提交
1293
        case cJSON_Object:
1294
            return print_object(item, depth, format, output_buffer, hooks);
1295

M
Max Bruckner 已提交
1296
        default:
1297
            return false;
M
Max Bruckner 已提交
1298
    }
K
Kevin Branigan 已提交
1299 1300 1301
}

/* Build an array from input text. */
1302
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1303
{
1304
    cJSON *head = NULL; /* head of the linked list */
1305 1306
    cJSON *current_item = NULL;

M
Max Bruckner 已提交
1307
    if (buffer_at_offset(input_buffer)[0] != '[')
M
Max Bruckner 已提交
1308
    {
1309
        /* not an array */
1310
        goto fail;
M
Max Bruckner 已提交
1311
    }
K
Kevin Branigan 已提交
1312

M
Max Bruckner 已提交
1313 1314 1315
    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 已提交
1316
    {
1317
        /* empty array */
1318
        goto success;
M
Max Bruckner 已提交
1319
    }
K
Kevin Branigan 已提交
1320

M
Max Bruckner 已提交
1321 1322 1323 1324 1325 1326 1327
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1328
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1329
    input_buffer->offset--;
M
Max Bruckner 已提交
1330
    /* loop through the comma separated array elements */
1331
    do
M
Max Bruckner 已提交
1332
    {
1333
        /* allocate next item */
1334
        cJSON *new_item = cJSON_New_Item(hooks);
1335
        if (new_item == NULL)
M
Max Bruckner 已提交
1336
        {
1337
            goto fail; /* allocation failure */
M
Max Bruckner 已提交
1338
        }
1339 1340 1341

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1342
        {
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
            /* 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 已提交
1355 1356
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1357
        if (!parse_value(current_item, input_buffer, hooks))
1358 1359
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1360
        }
M
Max Bruckner 已提交
1361
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1362
    }
M
Max Bruckner 已提交
1363
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
M
Max Bruckner 已提交
1364

M
Max Bruckner 已提交
1365
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
M
Max Bruckner 已提交
1366
    {
1367
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1368 1369
    }

1370 1371
success:
    item->type = cJSON_Array;
1372
    item->child = head;
1373

M
Max Bruckner 已提交
1374 1375
    input_buffer->offset++;

1376
    return true;
K
Kevin Branigan 已提交
1377

1378
fail:
1379
    if (head != NULL)
1380
    {
1381
        cJSON_Delete(head);
1382 1383
    }

1384
    return false;
K
Kevin Branigan 已提交
1385 1386 1387
}

/* Render an array to text */
1388
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 已提交
1389
{
M
Max Bruckner 已提交
1390
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1391
    size_t length = 0;
M
Max Bruckner 已提交
1392
    cJSON *current_element = item->child;
K
Kevin Branigan 已提交
1393

M
Max Bruckner 已提交
1394
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1395
    {
1396
        return false;
M
Max Bruckner 已提交
1397 1398
    }

M
Max Bruckner 已提交
1399 1400
    /* Compose the output array. */
    /* opening square bracket */
1401
    output_pointer = ensure(output_buffer, 1, hooks);
M
Max Bruckner 已提交
1402
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1403
    {
1404
        return false;
M
Max Bruckner 已提交
1405 1406
    }

M
Max Bruckner 已提交
1407 1408
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1409

M
Max Bruckner 已提交
1410
    while (current_element != NULL)
M
Max Bruckner 已提交
1411
    {
1412
        if (!print_value(current_element, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1413
        {
1414
            return false;
M
Max Bruckner 已提交
1415
        }
1416
        update_offset(output_buffer);
M
Max Bruckner 已提交
1417
        if (current_element->next)
M
Max Bruckner 已提交
1418
        {
1419
            length = (size_t) (format ? 2 : 1);
1420
            output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1421
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1422
            {
1423
                return false;
M
Max Bruckner 已提交
1424
            }
M
Max Bruckner 已提交
1425 1426
            *output_pointer++ = ',';
            if(format)
M
Max Bruckner 已提交
1427
            {
M
Max Bruckner 已提交
1428
                *output_pointer++ = ' ';
M
Max Bruckner 已提交
1429
            }
M
Max Bruckner 已提交
1430 1431
            *output_pointer = '\0';
            output_buffer->offset += length;
M
Max Bruckner 已提交
1432
        }
M
Max Bruckner 已提交
1433
        current_element = current_element->next;
M
Max Bruckner 已提交
1434 1435
    }

1436
    output_pointer = ensure(output_buffer, 2, hooks);
M
Max Bruckner 已提交
1437
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1438
    {
1439
        return false;
M
Max Bruckner 已提交
1440
    }
M
Max Bruckner 已提交
1441 1442
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1443

1444
    return true;
K
Kevin Branigan 已提交
1445 1446 1447
}

/* Build an object from the text. */
1448
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1449
{
1450
    cJSON *head = NULL; /* linked list head */
1451 1452
    cJSON *current_item = NULL;

M
Max Bruckner 已提交
1453
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
M
Max Bruckner 已提交
1454
    {
1455
        goto fail; /* not an object */
M
Max Bruckner 已提交
1456 1457
    }

M
Max Bruckner 已提交
1458 1459 1460
    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 已提交
1461
    {
1462
        goto success; /* empty object */
M
Max Bruckner 已提交
1463 1464
    }

M
Max Bruckner 已提交
1465 1466 1467 1468 1469 1470 1471
    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

1472
    /* step back to character in front of the first element */
M
Max Bruckner 已提交
1473
    input_buffer->offset--;
1474 1475
    /* loop through the comma separated array elements */
    do
M
Max Bruckner 已提交
1476
    {
1477
        /* allocate next item */
1478
        cJSON *new_item = cJSON_New_Item(hooks);
1479 1480 1481 1482
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }
M
Max Bruckner 已提交
1483

1484 1485
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1486
        {
1487 1488 1489 1490 1491 1492 1493 1494 1495
            /* 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 已提交
1496 1497
        }

1498
        /* parse the name of the child */
M
Max Bruckner 已提交
1499 1500
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1501
        if (!parse_string(current_item, input_buffer, hooks))
M
Max Bruckner 已提交
1502
        {
1503
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1504
        }
M
Max Bruckner 已提交
1505
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1506

1507 1508 1509
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1510

M
Max Bruckner 已提交
1511
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
M
Max Bruckner 已提交
1512
        {
1513
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1514
        }
1515 1516

        /* parse the value */
M
Max Bruckner 已提交
1517 1518
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
1519
        if (!parse_value(current_item, input_buffer, hooks))
M
Max Bruckner 已提交
1520
        {
1521
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1522
        }
M
Max Bruckner 已提交
1523
        buffer_skip_whitespace(input_buffer);
M
Max Bruckner 已提交
1524
    }
M
Max Bruckner 已提交
1525
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1526

M
Max Bruckner 已提交
1527
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
M
Max Bruckner 已提交
1528
    {
1529
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1530 1531
    }

1532 1533
success:
    item->type = cJSON_Object;
1534
    item->child = head;
1535

M
Max Bruckner 已提交
1536
    input_buffer->offset++;
1537
    return true;
1538 1539

fail:
1540
    if (head != NULL)
1541
    {
1542
        cJSON_Delete(head);
1543 1544
    }

1545
    return false;
K
Kevin Branigan 已提交
1546 1547 1548
}

/* Render an object to text. */
1549
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)
1550
{
M
Max Bruckner 已提交
1551
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1552
    size_t length = 0;
M
Max Bruckner 已提交
1553
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1554

M
Max Bruckner 已提交
1555
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1556
    {
1557
        return false;
M
Max Bruckner 已提交
1558 1559
    }

M
Max Bruckner 已提交
1560
    /* Compose the output: */
1561
    length = (size_t) (format ? 2 : 1); /* fmt: {\n */
1562
    output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1563
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1564
    {
1565
        return false;
M
Max Bruckner 已提交
1566 1567
    }

M
Max Bruckner 已提交
1568 1569
    *output_pointer++ = '{';
    if (format)
M
Max Bruckner 已提交
1570
    {
M
Max Bruckner 已提交
1571
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1572
    }
M
Max Bruckner 已提交
1573
    output_buffer->offset += length;
M
Max Bruckner 已提交
1574

M
Max Bruckner 已提交
1575
    while (current_item)
M
Max Bruckner 已提交
1576
    {
M
Max Bruckner 已提交
1577
        if (format)
M
Max Bruckner 已提交
1578
        {
M
Max Bruckner 已提交
1579
            size_t i;
1580
            output_pointer = ensure(output_buffer, depth + 1, hooks);
M
Max Bruckner 已提交
1581
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1582
            {
1583
                return false;
M
Max Bruckner 已提交
1584
            }
M
Max Bruckner 已提交
1585
            for (i = 0; i < depth + 1; i++)
M
Max Bruckner 已提交
1586
            {
M
Max Bruckner 已提交
1587
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1588
            }
M
Max Bruckner 已提交
1589
            output_buffer->offset += depth + 1;
M
Max Bruckner 已提交
1590 1591
        }

M
Max Bruckner 已提交
1592
        /* print key */
1593
        if (!print_string_ptr((unsigned char*)current_item->string, 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

1599
        length = (size_t) (format ? 2 : 1);
1600
        output_pointer = ensure(output_buffer, length, hooks);
M
Max Bruckner 已提交
1601
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1602
        {
1603
            return false;
M
Max Bruckner 已提交
1604
        }
M
Max Bruckner 已提交
1605 1606
        *output_pointer++ = ':';
        if (format)
M
Max Bruckner 已提交
1607
        {
M
Max Bruckner 已提交
1608
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1609
        }
M
Max Bruckner 已提交
1610
        output_buffer->offset += length;
M
Max Bruckner 已提交
1611

M
Max Bruckner 已提交
1612
        /* print value */
1613
        if (!print_value(current_item, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1614
        {
1615
            return false;
M
Max Bruckner 已提交
1616
        }
M
Max Bruckner 已提交
1617
        update_offset(output_buffer);
M
Max Bruckner 已提交
1618

M
Max Bruckner 已提交
1619
        /* print comma if not last */
1620
        length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
1621
        output_pointer = ensure(output_buffer, length + 1, 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 (current_item->next)
M
Max Bruckner 已提交
1627
        {
M
Max Bruckner 已提交
1628
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1629 1630
        }

M
Max Bruckner 已提交
1631
        if (format)
M
Max Bruckner 已提交
1632
        {
M
Max Bruckner 已提交
1633
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1634
        }
M
Max Bruckner 已提交
1635 1636
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1637

M
Max Bruckner 已提交
1638
        current_item = current_item->next;
M
Max Bruckner 已提交
1639
    }
M
Max Bruckner 已提交
1640

1641
    output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks);
M
Max Bruckner 已提交
1642
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1643
    {
1644
        return false;
M
Max Bruckner 已提交
1645
    }
M
Max Bruckner 已提交
1646
    if (format)
M
Max Bruckner 已提交
1647
    {
M
Max Bruckner 已提交
1648 1649
        size_t i;
        for (i = 0; i < (depth); i++)
M
Max Bruckner 已提交
1650
        {
M
Max Bruckner 已提交
1651
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1652 1653
        }
    }
M
Max Bruckner 已提交
1654 1655
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1656

1657
    return true;
K
Kevin Branigan 已提交
1658 1659 1660
}

/* Get Array size/item / object item. */
1661
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1662 1663
{
    cJSON *c = array->child;
1664
    size_t i = 0;
M
Max Bruckner 已提交
1665 1666 1667 1668 1669
    while(c)
    {
        i++;
        c = c->next;
    }
1670 1671 1672

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

M
Max Bruckner 已提交
1673
    return (int)i;
M
Max Bruckner 已提交
1674 1675
}

1676
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
M
Max Bruckner 已提交
1677
{
1678
    cJSON *c = array ? array->child : NULL;
M
Max Bruckner 已提交
1679 1680 1681 1682 1683 1684 1685 1686 1687
    while (c && item > 0)
    {
        item--;
        c = c->next;
    }

    return c;
}

1688
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1689
{
1690
    cJSON *c = object ? object->child : NULL;
1691
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
M
Max Bruckner 已提交
1692 1693 1694 1695 1696 1697
    {
        c = c->next;
    }
    return c;
}

1698
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * object, const char * string)
1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
{
    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;
}

1716
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1717 1718 1719
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1720 1721

/* Utility for array list handling. */
M
Max Bruckner 已提交
1722 1723 1724 1725 1726 1727
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1728
/* Utility for handling references. */
1729
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1730
{
1731
    cJSON *ref = cJSON_New_Item(hooks);
M
Max Bruckner 已提交
1732 1733
    if (!ref)
    {
1734
        return NULL;
M
Max Bruckner 已提交
1735 1736
    }
    memcpy(ref, item, sizeof(cJSON));
1737
    ref->string = NULL;
M
Max Bruckner 已提交
1738
    ref->type |= cJSON_IsReference;
1739
    ref->next = ref->prev = NULL;
M
Max Bruckner 已提交
1740 1741
    return ref;
}
K
Kevin Branigan 已提交
1742 1743

/* Add item to array/object. */
1744
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1745
{
1746 1747 1748
    cJSON *child = NULL;

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

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1756 1757 1758 1759 1760 1761 1762
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1763
        while (child->next)
M
Max Bruckner 已提交
1764
        {
1765
            child = child->next;
M
Max Bruckner 已提交
1766
        }
1767
        suffix_object(child, item);
M
Max Bruckner 已提交
1768 1769 1770
    }
}

1771
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1772
{
1773
    /* call cJSON_AddItemToObjectCS for code reuse */
1774
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1775 1776
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1777 1778
}

1779 1780 1781
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic push
#endif
1782
#ifdef __GNUC__
1783
#pragma GCC diagnostic ignored "-Wcast-qual"
1784 1785
#endif

1786
/* Add an item to an object with constant string as key */
1787
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1788 1789 1790 1791 1792 1793 1794
{
    if (!item)
    {
        return;
    }
    if (!(item->type & cJSON_StringIsConst) && item->string)
    {
1795
        global_hooks.deallocate(item->string);
1796 1797 1798 1799 1800
    }
    item->string = (char*)string;
    item->type |= cJSON_StringIsConst;
    cJSON_AddItemToArray(object, item);
}
1801 1802 1803
#if defined (__clang__) || ((__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic pop
#endif
1804

1805
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1806
{
1807
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1808 1809
}

1810
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1811
{
1812
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1813 1814
}

M
Max Bruckner 已提交
1815
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
1826
        return NULL;
1827
    }
1828
    if (c->prev)
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
    {
        /* 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 */
1842
    c->prev = c->next = NULL;
1843 1844 1845

    return c;
}
1846
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1847 1848 1849 1850 1851 1852 1853 1854
{
    if (which < 0)
    {
        return NULL;
    }

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

1856
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1857 1858 1859 1860
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1861
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1862
{
1863
    size_t i = 0;
1864
    cJSON *c = object->child;
1865
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1866 1867 1868 1869 1870 1871
    {
        i++;
        c = c->next;
    }
    if (c)
    {
M
Max Bruckner 已提交
1872
        return DetachItemFromArray(object, i);
1873 1874
    }

1875
    return NULL;
1876 1877
}

1878
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1879 1880 1881
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1882 1883

/* Replace array/object items with new ones. */
1884
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
{
    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 已提交
1910
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
{
    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;
    }
1936
    c->next = c->prev = NULL;
1937 1938
    cJSON_Delete(c);
}
1939
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
1940 1941 1942 1943 1944 1945 1946 1947
{
    if (which < 0)
    {
        return;
    }

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

1949
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1950
{
1951
    size_t i = 0;
1952
    cJSON *c = object->child;
1953
    while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1954 1955 1956 1957 1958 1959
    {
        i++;
        c = c->next;
    }
    if(c)
    {
1960 1961 1962
        /* free the old string if not const */
        if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
        {
1963
             global_hooks.deallocate(newitem->string);
1964 1965
        }

1966
        newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1967
        ReplaceItemInArray(object, i, newitem);
1968 1969
    }
}
K
Kevin Branigan 已提交
1970 1971

/* Create basic types: */
1972
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
1973
{
1974
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1975 1976 1977 1978 1979 1980 1981 1982
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

1983
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
1984
{
1985
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1986 1987 1988 1989 1990 1991 1992 1993
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

1994
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
1995
{
1996
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1997 1998 1999 2000 2001 2002 2003 2004
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

2005
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
M
Max Bruckner 已提交
2006
{
2007
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2008 2009 2010 2011 2012 2013 2014 2015
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

2016
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
2017
{
2018
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2019 2020 2021 2022
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036

        /* 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 已提交
2037 2038 2039 2040 2041
    }

    return item;
}

2042
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
2043
{
2044
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2045 2046 2047
    if(item)
    {
        item->type = cJSON_String;
2048
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
2049 2050 2051
        if(!item->valuestring)
        {
            cJSON_Delete(item);
2052
            return NULL;
M
Max Bruckner 已提交
2053 2054 2055 2056 2057 2058
        }
    }

    return item;
}

2059
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
2060
{
2061
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2062 2063 2064
    if(item)
    {
        item->type = cJSON_Raw;
2065
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
2066 2067 2068 2069 2070 2071 2072 2073
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
2074 2075
}

2076
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
2077
{
2078
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2079 2080 2081 2082 2083 2084 2085 2086
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

2087
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
2088
{
2089
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2090 2091 2092 2093 2094 2095 2096
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
2097 2098

/* Create Arrays: */
2099
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
2100
{
2101
    size_t i = 0;
2102 2103
    cJSON *n = NULL;
    cJSON *p = NULL;
2104 2105 2106 2107 2108 2109 2110 2111 2112
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2113 2114 2115 2116 2117
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
2118
            return NULL;
M
Max Bruckner 已提交
2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2134
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
2135
{
2136
    size_t i = 0;
2137 2138
    cJSON *n = NULL;
    cJSON *p = NULL;
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
2149
    {
2150
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
2151 2152 2153
        if(!n)
        {
            cJSON_Delete(a);
2154
            return NULL;
M
Max Bruckner 已提交
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2170
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2171
{
2172
    size_t i = 0;
2173 2174
    cJSON *n = NULL;
    cJSON *p = NULL;
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
2185 2186 2187 2188 2189
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
2190
            return NULL;
2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2206
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2207
{
2208
    size_t i = 0;
2209 2210
    cJSON *n = NULL;
    cJSON *p = NULL;
2211 2212 2213 2214 2215 2216 2217 2218 2219 2220
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2221 2222 2223 2224 2225
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2226
            return NULL;
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2241 2242

/* Duplication */
2243
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2244
{
M
Max Bruckner 已提交
2245
    cJSON *newitem = NULL;
2246 2247
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2248
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2249 2250 2251 2252

    /* Bail on bad ptr */
    if (!item)
    {
2253
        goto fail;
M
Max Bruckner 已提交
2254 2255
    }
    /* Create new item */
2256
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2257 2258
    if (!newitem)
    {
2259
        goto fail;
M
Max Bruckner 已提交
2260 2261 2262 2263 2264 2265 2266
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2267
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2268 2269
        if (!newitem->valuestring)
        {
2270
            goto fail;
M
Max Bruckner 已提交
2271 2272 2273 2274
        }
    }
    if (item->string)
    {
2275
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2276 2277
        if (!newitem->string)
        {
2278
            goto fail;
M
Max Bruckner 已提交
2279 2280 2281 2282 2283 2284 2285 2286
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2287 2288
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2289
    {
2290
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2291 2292
        if (!newchild)
        {
2293
            goto fail;
M
Max Bruckner 已提交
2294
        }
2295
        if (next != NULL)
M
Max Bruckner 已提交
2296 2297
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2298 2299 2300
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2301 2302 2303 2304
        }
        else
        {
            /* Set newitem->child and move to it */
2305 2306
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2307
        }
2308
        child = child->next;
M
Max Bruckner 已提交
2309 2310 2311
    }

    return newitem;
2312 2313 2314 2315 2316 2317 2318 2319

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

    return NULL;
2320
}
2321

2322
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2323
{
2324
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363
    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 已提交
2364
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2365 2366 2367 2368
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2369
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2370
                }
M
Max Bruckner 已提交
2371
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2372
            }
M
Max Bruckner 已提交
2373
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2374 2375 2376 2377
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2378
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2379 2380 2381 2382 2383
        }
    }

    /* and null-terminate. */
    *into = '\0';
2384
}
2385

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

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

2396
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2397 2398 2399 2400 2401 2402 2403 2404 2405
{
    if (item == NULL)
    {
        return false;
    }

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

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

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


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

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2426
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2427 2428 2429 2430 2431 2432 2433 2434 2435
{
    if (item == NULL)
    {
        return false;
    }

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

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

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

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

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

2456
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2457 2458 2459 2460 2461 2462 2463 2464 2465
{
    if (item == NULL)
    {
        return false;
    }

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

2466
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2467 2468 2469 2470 2471 2472 2473 2474 2475
{
    if (item == NULL)
    {
        return false;
    }

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

2476
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2477 2478 2479 2480 2481 2482 2483 2484
{
    if (item == NULL)
    {
        return false;
    }

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