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
#define cjson_min(a, b) ((a < b) ? a : b)
M
Max Bruckner 已提交
1050

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

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

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

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

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

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

    return printed;

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

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

    return NULL;
}

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

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

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

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

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

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

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

    return (char*)p.buffer;
1147 1148
}

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

    if (len < 0)
    {
        return false;
    }

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

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

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

M
Max Bruckner 已提交
1217

1218
    return false;
K
Kevin Branigan 已提交
1219 1220 1221
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1368 1369
success:
    item->type = cJSON_Array;
1370
    item->child = head;
1371

M
Max Bruckner 已提交
1372 1373
    input_buffer->offset++;

1374
    return true;
K
Kevin Branigan 已提交
1375

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

1382
    return false;
K
Kevin Branigan 已提交
1383 1384 1385
}

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

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

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

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

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

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

1442
    return true;
K
Kevin Branigan 已提交
1443 1444 1445
}

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

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

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

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

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

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

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

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

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

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

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

1530 1531
success:
    item->type = cJSON_Object;
1532
    item->child = head;
1533

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

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

1543
    return false;
K
Kevin Branigan 已提交
1544 1545 1546
}

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

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

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

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

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

M
Max Bruckner 已提交
1590
        /* print key */
1591
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks))
M
Max Bruckner 已提交
1592
        {
1593
            return false;
M
Max Bruckner 已提交
1594
        }
M
Max Bruckner 已提交
1595
        update_offset(output_buffer);
M
Max Bruckner 已提交
1596

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

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

M
Max Bruckner 已提交
1617
        /* print comma if not last */
1618
        length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
1619
        output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1620
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1621
        {
1622
            return false;
M
Max Bruckner 已提交
1623
        }
M
Max Bruckner 已提交
1624
        if (current_item->next)
M
Max Bruckner 已提交
1625
        {
M
Max Bruckner 已提交
1626
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1627 1628
        }

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

M
Max Bruckner 已提交
1636
        current_item = current_item->next;
M
Max Bruckner 已提交
1637
    }
M
Max Bruckner 已提交
1638

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

1655
    return true;
K
Kevin Branigan 已提交
1656 1657 1658
}

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

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

M
Max Bruckner 已提交
1671
    return (int)i;
M
Max Bruckner 已提交
1672 1673
}

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

    return c;
}

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

P
Pawel Winogrodzki 已提交
1696
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
{
    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;
}

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

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

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

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

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

    child = array->child;

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

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

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

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

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

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

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

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

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

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

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

1873
    return NULL;
1874 1875
}

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

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

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

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

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

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

    return item;
}

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

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

    return item;
}

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

    return item;
}

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

    return item;
J
Jiri Zouhar 已提交
2072 2073
}

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

    return item;
}

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

    return item;
}
K
Kevin Branigan 已提交
2095 2096

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

    if (count < 0)
    {
        return NULL;
    }

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

    return a;
}

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

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

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

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}

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

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

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

    return a;
}
2239 2240

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

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

    return newitem;
2310 2311 2312 2313 2314 2315 2316 2317

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

    return NULL;
2318
}
2319

2320
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2321
{
2322
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
2323 2324 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
    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 已提交
2362
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2363 2364 2365 2366
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2367
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2368
                }
M
Max Bruckner 已提交
2369
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2370
            }
M
Max Bruckner 已提交
2371
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2372 2373 2374 2375
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2376
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2377 2378 2379 2380 2381
        }
    }

    /* and null-terminate. */
    *into = '\0';
2382
}
2383

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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