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

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

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

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

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

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"

M
Max Bruckner 已提交
35
/* define our own boolean type */
M
Max Bruckner 已提交
36 37 38
typedef int cjbool;
#define true ((cjbool)1)
#define false ((cjbool)0)
M
Max Bruckner 已提交
39

40
static const unsigned char *global_ep = NULL;
K
Kevin Branigan 已提交
41

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

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

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

    return version;
}

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

79
    return tolower(*s1) - tolower(*s2);
K
Kevin Branigan 已提交
80 81
}

82 83 84 85 86 87 88 89
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 已提交
90

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

96 97 98 99 100
    if (str == NULL)
    {
        return NULL;
    }

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

    return copy;
K
Kevin Branigan 已提交
109 110
}

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

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

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

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

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

    return node;
K
Kevin Branigan 已提交
152 153 154
}

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

/* Parse the input text to generate a number, and populate the result into item. */
179
static const unsigned char *parse_number(cJSON * const item, const unsigned char * const input)
K
Kevin Branigan 已提交
180
{
181
    double number = 0;
182
    unsigned char *after_end = NULL;
M
Max Bruckner 已提交
183

184
    if (input == NULL)
185 186 187 188
    {
        return NULL;
    }

189 190
    number = strtod((const char*)input, (char**)&after_end);
    if (input == after_end)
M
Max Bruckner 已提交
191
    {
192
        return NULL; /* parse_error */
M
Max Bruckner 已提交
193 194
    }

195
    item->valuedouble = number;
M
Max Bruckner 已提交
196

197
    /* use saturation in case of overflow */
198
    if (number >= INT_MAX)
199 200 201
    {
        item->valueint = INT_MAX;
    }
202
    else if (number <= INT_MIN)
203 204 205 206 207
    {
        item->valueint = INT_MIN;
    }
    else
    {
208
        item->valueint = (int)number;
209
    }
210

M
Max Bruckner 已提交
211 212
    item->type = cJSON_Number;

213
    return after_end;
K
Kevin Branigan 已提交
214 215
}

216
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
217
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
{
    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
        object->valueint = cJSON_Number;
    }

    return object->valuedouble = number;
}

M
Max Bruckner 已提交
235 236
typedef struct
{
237
    unsigned char *buffer;
238 239
    size_t length;
    size_t offset;
240
    cjbool noalloc;
M
Max Bruckner 已提交
241
} printbuffer;
242

M
Max Bruckner 已提交
243
/* realloc printbuffer if necessary to have at least "needed" bytes more */
244
static unsigned char* ensure(printbuffer * const p, size_t needed, const internal_hooks * const hooks)
245
{
246
    unsigned char *newbuffer = NULL;
247 248
    size_t newsize = 0;

249
    if ((p == NULL) || (p->buffer == NULL))
250
    {
251
        return NULL;
252 253
    }

254 255 256 257 258 259
    if (needed > INT_MAX)
    {
        /* sizes bigger than INT_MAX are currently not supported */
        return NULL;
    }

M
Max Bruckner 已提交
260 261 262 263 264 265
    needed += p->offset;
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

266 267 268 269
    if (p->noalloc) {
        return NULL;
    }

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    /* calculate new buffer size */
    newsize = needed * 2;
    if (newsize > INT_MAX)
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }

285
    if (hooks->reallocate != NULL)
M
Max Bruckner 已提交
286
    {
M
Max Bruckner 已提交
287
        /* reallocate with realloc if available */
288
        newbuffer = (unsigned char*)hooks->reallocate(p->buffer, newsize);
M
Max Bruckner 已提交
289
    }
M
Max Bruckner 已提交
290
    else
M
Max Bruckner 已提交
291
    {
M
Max Bruckner 已提交
292
        /* otherwise reallocate manually */
293
        newbuffer = (unsigned char*)hooks->allocate(newsize);
M
Max Bruckner 已提交
294 295
        if (!newbuffer)
        {
296
            hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
297 298 299 300 301 302 303
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
        if (newbuffer)
        {
304
            memcpy(newbuffer, p->buffer, p->offset + 1);
M
Max Bruckner 已提交
305
        }
306
        hooks->deallocate(p->buffer);
M
Max Bruckner 已提交
307 308 309 310 311
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
312 313
}

314 315
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
K
Kevin Branigan 已提交
316
{
317 318
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
M
Max Bruckner 已提交
319
    {
320
        return;
M
Max Bruckner 已提交
321
    }
322
    buffer_pointer = buffer->buffer + buffer->offset;
M
Max Bruckner 已提交
323

324
    buffer->offset += strlen((const char*)buffer_pointer);
325 326
}

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
/* Removes trailing zeroes from the end of a printed number */
static unsigned char *trim_trailing_zeroes(printbuffer * const buffer)
{
    size_t offset = 0;
    unsigned char *content = NULL;

    if ((buffer == NULL) || (buffer->buffer == NULL) || (buffer->offset < 1))
    {
        return NULL;
    }

    offset = buffer->offset - 1;
    content = buffer->buffer;

    while ((offset > 0) && (content[offset] == '0'))
    {
        offset--;
    }
    if ((offset > 0) && (content[offset] == '.'))
    {
        offset--;
    }

    offset++;
    content[offset] = '\0';

    buffer->offset = offset;

    return content + offset;
}

358
/* Render the number nicely from the given item into a string. */
359
static unsigned char *print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks)
360
{
M
Max Bruckner 已提交
361
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
362
    double d = item->valuedouble;
363
    int length = 0;
364
    cjbool trim_zeroes = true; /* should at the end be removed? */
M
Max Bruckner 已提交
365

M
Max Bruckner 已提交
366
    if (output_buffer == NULL)
M
Max Bruckner 已提交
367 368 369 370
    {
        return NULL;
    }

371 372 373
    /* This is a nice tradeoff. */
    output_pointer = ensure(output_buffer, 64, hooks);
    if (output_pointer != NULL)
M
Max Bruckner 已提交
374
    {
375 376
        /* This checks for NaN and Infinity */
        if ((d * 0) != 0)
M
Max Bruckner 已提交
377
        {
378
            length = sprintf((char*)output_pointer, "null");
M
Max Bruckner 已提交
379
        }
380 381 382 383 384 385 386 387 388 389 390 391
        else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
        {
            /* integer */
            length = sprintf((char*)output_pointer, "%.0f", d);
            trim_zeroes = false; /* don't remove zeroes for "big integers" */
        }
        else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
        {
            length = sprintf((char*)output_pointer, "%e", d);
            trim_zeroes = false; /* don't remove zeroes in engineering notation */
        }
        else
M
Max Bruckner 已提交
392
        {
393
            length = sprintf((char*)output_pointer, "%f", d);
M
Max Bruckner 已提交
394 395
        }
    }
396

397 398 399 400 401 402 403 404
    /* sprintf failed */
    if (length < 0)
    {
        return NULL;
    }

    output_buffer->offset += (size_t)length;

405 406 407 408 409
    if (trim_zeroes)
    {
        return trim_trailing_zeroes(output_buffer);
    }

410
    return output_buffer->buffer + output_buffer->offset;
K
Kevin Branigan 已提交
411 412
}

M
Max Bruckner 已提交
413
/* parse 4 digit hexadecimal number */
414
static unsigned parse_hex4(const unsigned char * const input)
415
{
M
Max Bruckner 已提交
416
    unsigned int h = 0;
417
    size_t i = 0;
M
Max Bruckner 已提交
418

419
    for (i = 0; i < 4; i++)
M
Max Bruckner 已提交
420
    {
421
        /* parse digit */
422
        if ((input[i] >= '0') && (input[i] <= '9'))
423
        {
424
            h += (unsigned int) input[i] - '0';
425
        }
426
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
427
        {
428
            h += (unsigned int) 10 + input[i] - 'A';
429
        }
430
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
431
        {
432
            h += (unsigned int) 10 + input[i] - 'a';
433 434 435 436 437
        }
        else /* invalid */
        {
            return 0;
        }
M
Max Bruckner 已提交
438

439 440 441 442 443
        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
M
Max Bruckner 已提交
444 445 446
    }

    return h;
447 448
}

449 450
/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
451
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer, const unsigned char **error_pointer)
M
Max Bruckner 已提交
452
{
453 454 455 456 457 458 459 460 461 462 463 464 465
    /* first bytes of UTF8 encoding for a given length in bytes */
    static const unsigned char firstByteMark[5] =
    {
        0x00, /* should never happen */
        0x00, /* 0xxxxxxx */
        0xC0, /* 110xxxxx */
        0xE0, /* 1110xxxx */
        0xF0 /* 11110xxx */
    };

    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
466 467
    unsigned char utf8_length = 0;
    unsigned char sequence_length = 0;
468 469 470 471 472 473 474 475 476

    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);
    if ((input_end - first_sequence) < 6)
    {
        /* input ends unexpectedly */
        *error_pointer = first_sequence;
        goto fail;
    }
M
Max Bruckner 已提交
477

478 479
    /* check that the code is valid */
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)) || (first_code == 0))
M
Max Bruckner 已提交
480
    {
481
        *error_pointer = first_sequence;
482
        goto fail;
M
Max Bruckner 已提交
483
    }
M
Max Bruckner 已提交
484

485 486
    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
M
Max Bruckner 已提交
487
    {
488 489 490 491 492
        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 已提交
493
        {
494 495 496
            /* input ends unexpectedly */
            *error_pointer = first_sequence;
            goto fail;
M
Max Bruckner 已提交
497
        }
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523

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

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


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

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    /* 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;
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
    }
    else
M
Max Bruckner 已提交
550
    {
551 552
        /* invalid unicode codepoint */
        *error_pointer = first_sequence;
553
        goto fail;
M
Max Bruckner 已提交
554 555
    }

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
    /* encode as utf8 */
    switch (utf8_length)
    {
        case 4:
            /* 10xxxxxx */
            (*output_pointer)[3] = (unsigned char)((codepoint | 0x80) & 0xBF);
            codepoint >>= 6;
        case 3:
            /* 10xxxxxx */
            (*output_pointer)[2] = (unsigned char)((codepoint | 0x80) & 0xBF);
            codepoint >>= 6;
        case 2:
            (*output_pointer)[1] = (unsigned char)((codepoint | 0x80) & 0xBF);
            codepoint >>= 6;
        case 1:
            /* depending on the length in bytes this determines the
               encoding of the first UTF8 byte */
            (*output_pointer)[0] = (unsigned char)((codepoint | firstByteMark[utf8_length]) & 0xFF);
            break;
        default:
            *error_pointer = first_sequence;
            goto fail;
    }
    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
588
static const unsigned char *parse_string(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
589 590 591 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 617 618 619 620 621 622 623 624 625 626 627
{
    const unsigned char *input_pointer = input + 1;
    const unsigned char *input_end = input + 1;
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

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

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

        /* This is at most how much we need for the output */
        allocation_length = (size_t) (input_end - input) - skipped_bytes;
628
        output = (unsigned char*)hooks->allocate(allocation_length + sizeof('\0'));
629 630 631 632 633 634 635
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
M
Max Bruckner 已提交
636
    /* loop through the string literal */
637
    while (input_pointer < input_end)
M
Max Bruckner 已提交
638
    {
639
        if (*input_pointer != '\\')
M
Max Bruckner 已提交
640
        {
641
            *output_pointer++ = *input_pointer++;
M
Max Bruckner 已提交
642 643 644 645
        }
        /* escape sequence */
        else
        {
646
            unsigned char sequence_length = 2;
647
            switch (input_pointer[1])
M
Max Bruckner 已提交
648 649
            {
                case 'b':
650
                    *output_pointer++ = '\b';
M
Max Bruckner 已提交
651 652
                    break;
                case 'f':
653
                    *output_pointer++ = '\f';
M
Max Bruckner 已提交
654 655
                    break;
                case 'n':
656
                    *output_pointer++ = '\n';
M
Max Bruckner 已提交
657 658
                    break;
                case 'r':
659
                    *output_pointer++ = '\r';
M
Max Bruckner 已提交
660 661
                    break;
                case 't':
662
                    *output_pointer++ = '\t';
M
Max Bruckner 已提交
663
                    break;
664 665 666
                case '\"':
                case '\\':
                case '/':
667
                    *output_pointer++ = input_pointer[1];
668
                    break;
669 670

                /* UTF-16 literal */
M
Max Bruckner 已提交
671
                case 'u':
672 673
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer, error_pointer);
                    if (sequence_length == 0)
M
Max Bruckner 已提交
674
                    {
675
                        /* failed to convert UTF16-literal to UTF-8 */
676
                        goto fail;
M
Max Bruckner 已提交
677 678
                    }
                    break;
679

M
Max Bruckner 已提交
680
                default:
681
                    *error_pointer = input_pointer;
682
                    goto fail;
M
Max Bruckner 已提交
683
            }
684
            input_pointer += sequence_length;
M
Max Bruckner 已提交
685 686
        }
    }
687 688 689

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

691
    item->type = cJSON_String;
692
    item->valuestring = (char*)output;
693

694
    return input_end + 1;
695 696

fail:
697
    if (output != NULL)
698
    {
699
        hooks->deallocate(output);
700 701 702
    }

    return NULL;
K
Kevin Branigan 已提交
703 704 705
}

/* Render the cstring provided to an escaped version that can be printed. */
706
static unsigned char *print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
707
{
708 709 710
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
711 712 713
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;
M
Max Bruckner 已提交
714

715
    if (output_buffer == NULL)
M
Max Bruckner 已提交
716 717 718 719
    {
        return NULL;
    }

M
Max Bruckner 已提交
720
    /* empty string */
721
    if (input == NULL)
M
Max Bruckner 已提交
722
    {
723
        output = ensure(output_buffer, sizeof("\"\""), hooks);
724
        if (output == NULL)
M
Max Bruckner 已提交
725
        {
726
            return NULL;
M
Max Bruckner 已提交
727
        }
728
        strcpy((char*)output, "\"\"");
M
Max Bruckner 已提交
729

730
        return output;
M
Max Bruckner 已提交
731 732 733
    }

    /* set "flag" to 1 if something needs to be escaped */
734
    for (input_pointer = input; *input_pointer; input_pointer++)
M
Max Bruckner 已提交
735
    {
M
Max Bruckner 已提交
736
        if (strchr("\"\\\b\f\n\r\t", *input_pointer))
M
Max Bruckner 已提交
737
        {
M
Max Bruckner 已提交
738 739
            /* one character escape sequence */
            escape_characters++;
M
Max Bruckner 已提交
740
        }
M
Max Bruckner 已提交
741
        else if (*input_pointer < 32)
M
Max Bruckner 已提交
742
        {
M
Max Bruckner 已提交
743 744
            /* UTF-16 escape sequence uXXXX */
            escape_characters += 5;
M
Max Bruckner 已提交
745 746
        }
    }
M
Max Bruckner 已提交
747
    output_length = (size_t)(input_pointer - input) + escape_characters;
M
Max Bruckner 已提交
748

749
    output = ensure(output_buffer, output_length + sizeof("\"\""), hooks);
750
    if (output == NULL)
M
Max Bruckner 已提交
751
    {
752
        return NULL;
M
Max Bruckner 已提交
753 754
    }

M
Max Bruckner 已提交
755 756 757 758 759 760 761 762 763 764 765 766 767
    /* no characters have to be escaped */
    if (escape_characters == 0)
    {
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

        return output;
    }

    output[0] = '\"';
    output_pointer = output + 1;
M
Max Bruckner 已提交
768
    /* copy the string */
M
Max Bruckner 已提交
769
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
M
Max Bruckner 已提交
770
    {
771
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
M
Max Bruckner 已提交
772 773
        {
            /* normal character, copy */
M
Max Bruckner 已提交
774
            *output_pointer = *input_pointer;
M
Max Bruckner 已提交
775 776 777 778
        }
        else
        {
            /* character needs to be escaped */
779
            *output_pointer++ = '\\';
M
Max Bruckner 已提交
780
            switch (*input_pointer)
M
Max Bruckner 已提交
781 782
            {
                case '\\':
M
Max Bruckner 已提交
783
                    *output_pointer = '\\';
M
Max Bruckner 已提交
784 785
                    break;
                case '\"':
M
Max Bruckner 已提交
786
                    *output_pointer = '\"';
M
Max Bruckner 已提交
787 788
                    break;
                case '\b':
M
Max Bruckner 已提交
789
                    *output_pointer = 'b';
M
Max Bruckner 已提交
790 791
                    break;
                case '\f':
M
Max Bruckner 已提交
792
                    *output_pointer = 'f';
M
Max Bruckner 已提交
793 794
                    break;
                case '\n':
M
Max Bruckner 已提交
795
                    *output_pointer = 'n';
M
Max Bruckner 已提交
796 797
                    break;
                case '\r':
M
Max Bruckner 已提交
798
                    *output_pointer = 'r';
M
Max Bruckner 已提交
799 800
                    break;
                case '\t':
M
Max Bruckner 已提交
801
                    *output_pointer = 't';
M
Max Bruckner 已提交
802 803 804
                    break;
                default:
                    /* escape and print as unicode codepoint */
M
Max Bruckner 已提交
805 806
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
M
Max Bruckner 已提交
807 808 809 810
                    break;
            }
        }
    }
M
Max Bruckner 已提交
811 812
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';
M
Max Bruckner 已提交
813

814
    return output;
K
Kevin Branigan 已提交
815
}
M
Max Bruckner 已提交
816

M
Max Bruckner 已提交
817
/* Invoke print_string_ptr (which is useful) on an item. */
818
static unsigned char *print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks)
M
Max Bruckner 已提交
819
{
820
    return print_string_ptr((unsigned char*)item->valuestring, p, hooks);
M
Max Bruckner 已提交
821
}
K
Kevin Branigan 已提交
822 823

/* Predeclare these prototypes. */
824 825 826 827 828 829
static const unsigned char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const ep, const internal_hooks * const hooks);
static unsigned char *print_value(const cJSON * const item, const size_t depth, const cjbool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks);
static unsigned char *print_array(const cJSON * const item, const size_t depth, const cjbool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks);
static unsigned char *print_object(const cJSON * const item, const size_t depth, const cjbool format, printbuffer * const output_buffer, const internal_hooks * const hooks);
K
Kevin Branigan 已提交
830 831

/* Utility to jump whitespace and cr/lf */
M
Max Bruckner 已提交
832
static const unsigned char *skip_whitespace(const unsigned char *in)
M
Max Bruckner 已提交
833
{
834
    while (in && *in && (*in <= 32))
M
Max Bruckner 已提交
835 836 837 838 839 840
    {
        in++;
    }

    return in;
}
K
Kevin Branigan 已提交
841 842

/* Parse an object - create a new root, and populate. */
843
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated)
K
Kevin Branigan 已提交
844
{
845
    const unsigned char *end = NULL;
M
Max Bruckner 已提交
846
    /* use global error pointer if no specific one was given */
847
    const unsigned char **ep = return_parse_end ? (const unsigned char**)return_parse_end : &global_ep;
848
    cJSON *c = cJSON_New_Item(&global_hooks);
849
    *ep = NULL;
M
Max Bruckner 已提交
850 851
    if (!c) /* memory fail */
    {
852
        return NULL;
M
Max Bruckner 已提交
853 854
    }

855
    end = parse_value(c, skip_whitespace((const unsigned char*)value), ep, &global_hooks);
M
Max Bruckner 已提交
856 857 858 859
    if (!end)
    {
        /* parse failure. ep is set. */
        cJSON_Delete(c);
860
        return NULL;
M
Max Bruckner 已提交
861 862 863 864 865
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
M
Max Bruckner 已提交
866
        end = skip_whitespace(end);
M
Max Bruckner 已提交
867 868 869 870
        if (*end)
        {
            cJSON_Delete(c);
            *ep = end;
871
            return NULL;
M
Max Bruckner 已提交
872 873 874 875
        }
    }
    if (return_parse_end)
    {
876
        *return_parse_end = (const char*)end;
M
Max Bruckner 已提交
877 878 879
    }

    return c;
K
Kevin Branigan 已提交
880
}
M
Max Bruckner 已提交
881

882
/* Default options for cJSON_Parse */
883
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
M
Max Bruckner 已提交
884 885 886
{
    return cJSON_ParseWithOpts(value, 0, 0);
}
K
Kevin Branigan 已提交
887

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

890
static unsigned char *print(const cJSON * const item, cjbool format, const internal_hooks * const hooks)
M
Max Bruckner 已提交
891 892 893 894 895 896 897
{
    printbuffer buffer[1];
    unsigned char *printed = NULL;

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

    /* create buffer */
898
    buffer->buffer = (unsigned char*) hooks->allocate(256);
M
Max Bruckner 已提交
899 900 901 902 903 904
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
905
    if (print_value(item, 0, format, buffer, hooks) == NULL)
M
Max Bruckner 已提交
906 907 908
    {
        goto fail;
    }
909
    update_offset(buffer);
M
Max Bruckner 已提交
910 911

    /* copy the buffer over to a new one */
912
    printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
M
Max Bruckner 已提交
913 914 915 916 917 918 919 920
    if (printed == NULL)
    {
        goto fail;
    }
    strncpy((char*)printed, (char*)buffer->buffer, min(buffer->length, buffer->offset + 1));
    printed[buffer->offset] = '\0'; /* just to be sure */

    /* free the buffer */
921
    hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
922 923 924 925 926 927

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
928
        hooks->deallocate(buffer->buffer);
M
Max Bruckner 已提交
929 930 931 932
    }

    if (printed != NULL)
    {
933
        hooks->deallocate(printed);
M
Max Bruckner 已提交
934 935 936 937 938
    }

    return NULL;
}

K
Kevin Branigan 已提交
939
/* Render a cJSON item/entity/structure to text. */
940
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
M
Max Bruckner 已提交
941
{
942
    return (char*)print(item, true, &global_hooks);
M
Max Bruckner 已提交
943 944
}

945
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
946
{
947
    return (char*)print(item, false, &global_hooks);
948
}
949

950
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
951
{
M
Max Bruckner 已提交
952
    printbuffer p;
M
Max Bruckner 已提交
953 954 955

    if (prebuffer < 0)
    {
M
Max Bruckner 已提交
956
        return NULL;
M
Max Bruckner 已提交
957 958
    }

959
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
960 961
    if (!p.buffer)
    {
962
        return NULL;
963
    }
M
Max Bruckner 已提交
964 965

    p.length = (size_t)prebuffer;
M
Max Bruckner 已提交
966
    p.offset = 0;
967
    p.noalloc = false;
M
Max Bruckner 已提交
968

969
    return (char*)print_value(item, 0, fmt, &p, &global_hooks);
970 971
}

972
CJSON_PUBLIC(int) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cjbool fmt)
973 974
{
    printbuffer p;
M
Max Bruckner 已提交
975 976 977 978 979 980

    if (len < 0)
    {
        return false;
    }

981
    p.buffer = (unsigned char*)buf;
M
Max Bruckner 已提交
982
    p.length = (size_t)len;
983
    p.offset = 0;
984
    p.noalloc = true;
985
    return print_value(item, 0, fmt, &p, &global_hooks) != NULL;
986
}
K
Kevin Branigan 已提交
987 988

/* Parser core - when encountering text, process appropriately. */
989
static const unsigned  char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
990
{
991
    if (input == NULL)
M
Max Bruckner 已提交
992
    {
993
        return NULL; /* no input */
M
Max Bruckner 已提交
994 995 996
    }

    /* parse the different types of values */
997 998
    /* null */
    if (!strncmp((const char*)input, "null", 4))
M
Max Bruckner 已提交
999 1000
    {
        item->type = cJSON_NULL;
1001
        return input + 4;
M
Max Bruckner 已提交
1002
    }
1003 1004
    /* false */
    if (!strncmp((const char*)input, "false", 5))
M
Max Bruckner 已提交
1005 1006
    {
        item->type = cJSON_False;
1007
        return input + 5;
M
Max Bruckner 已提交
1008
    }
1009 1010
    /* true */
    if (!strncmp((const char*)input, "true", 4))
M
Max Bruckner 已提交
1011 1012 1013
    {
        item->type = cJSON_True;
        item->valueint = 1;
1014
        return input + 4;
M
Max Bruckner 已提交
1015
    }
1016 1017
    /* string */
    if (*input == '\"')
M
Max Bruckner 已提交
1018
    {
1019
        return parse_string(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1020
    }
1021 1022
    /* number */
    if ((*input == '-') || ((*input >= '0') && (*input <= '9')))
M
Max Bruckner 已提交
1023
    {
1024
        return parse_number(item, input);
M
Max Bruckner 已提交
1025
    }
1026 1027
    /* array */
    if (*input == '[')
M
Max Bruckner 已提交
1028
    {
1029
        return parse_array(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1030
    }
1031 1032
    /* object */
    if (*input == '{')
M
Max Bruckner 已提交
1033
    {
1034
        return parse_object(item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1035 1036
    }

M
Max Bruckner 已提交
1037
    /* failure. */
1038
    *error_pointer = input;
1039
    return NULL;
K
Kevin Branigan 已提交
1040 1041 1042
}

/* Render a value to text. */
1043
static unsigned char *print_value(const cJSON * const item, const size_t depth, const cjbool format,  printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1044
{
M
Max Bruckner 已提交
1045
    unsigned char *output = NULL;
M
Max Bruckner 已提交
1046

M
Max Bruckner 已提交
1047
    if ((item == NULL) || (output_buffer == NULL))
M
Max Bruckner 已提交
1048 1049 1050 1051 1052
    {
        return NULL;
    }

    switch ((item->type) & 0xFF)
M
Max Bruckner 已提交
1053
    {
M
Max Bruckner 已提交
1054
        case cJSON_NULL:
1055
            output = ensure(output_buffer, 5, hooks);
M
Max Bruckner 已提交
1056
            if (output != NULL)
M
Max Bruckner 已提交
1057
            {
M
Max Bruckner 已提交
1058
                strcpy((char*)output, "null");
M
Max Bruckner 已提交
1059 1060 1061
            }
            break;
        case cJSON_False:
1062
            output = ensure(output_buffer, 6, hooks);
M
Max Bruckner 已提交
1063
            if (output != NULL)
M
Max Bruckner 已提交
1064
            {
M
Max Bruckner 已提交
1065
                strcpy((char*)output, "false");
M
Max Bruckner 已提交
1066 1067 1068
            }
            break;
        case cJSON_True:
1069
            output = ensure(output_buffer, 5, hooks);
M
Max Bruckner 已提交
1070
            if (output != NULL)
M
Max Bruckner 已提交
1071
            {
M
Max Bruckner 已提交
1072
                strcpy((char*)output, "true");
M
Max Bruckner 已提交
1073 1074 1075
            }
            break;
        case cJSON_Number:
1076
            output = print_number(item, output_buffer, hooks);
M
Max Bruckner 已提交
1077 1078
            break;
        case cJSON_Raw:
M
Max Bruckner 已提交
1079
        {
M
Max Bruckner 已提交
1080 1081
            size_t raw_length = 0;
            if (item->valuestring == NULL)
1082
            {
M
Max Bruckner 已提交
1083
                if (!output_buffer->noalloc)
J
Jiri Zouhar 已提交
1084
                {
1085
                    hooks->deallocate(output_buffer->buffer);
J
Jiri Zouhar 已提交
1086
                }
M
Max Bruckner 已提交
1087
                output = NULL;
1088
                break;
M
Max Bruckner 已提交
1089 1090 1091
            }

            raw_length = strlen(item->valuestring) + sizeof('\0');
1092
            output = ensure(output_buffer, raw_length, hooks);
M
Max Bruckner 已提交
1093
            if (output != NULL)
M
Max Bruckner 已提交
1094
            {
M
Max Bruckner 已提交
1095
                memcpy(output, item->valuestring, raw_length);
M
Max Bruckner 已提交
1096 1097
            }
            break;
M
Max Bruckner 已提交
1098
        }
M
Max Bruckner 已提交
1099
        case cJSON_String:
1100
            output = print_string(item, output_buffer, hooks);
M
Max Bruckner 已提交
1101 1102
            break;
        case cJSON_Array:
1103
            output = print_array(item, depth, format, output_buffer, hooks);
M
Max Bruckner 已提交
1104 1105
            break;
        case cJSON_Object:
1106
            output = print_object(item, depth, format, output_buffer, hooks);
M
Max Bruckner 已提交
1107 1108
            break;
        default:
M
Max Bruckner 已提交
1109
            output = NULL;
M
Max Bruckner 已提交
1110
            break;
M
Max Bruckner 已提交
1111 1112
    }

M
Max Bruckner 已提交
1113
    return output;
K
Kevin Branigan 已提交
1114 1115 1116
}

/* Build an array from input text. */
1117
static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1118
{
1119
    cJSON *head = NULL; /* head of the linked list */
1120 1121
    cJSON *current_item = NULL;

1122
    if (*input != '[')
M
Max Bruckner 已提交
1123
    {
1124
        /* not an array */
1125
        *error_pointer = input;
1126
        goto fail;
M
Max Bruckner 已提交
1127
    }
K
Kevin Branigan 已提交
1128

M
Max Bruckner 已提交
1129
    input = skip_whitespace(input + 1);
1130
    if (*input == ']')
M
Max Bruckner 已提交
1131
    {
1132
        /* empty array */
1133
        goto success;
M
Max Bruckner 已提交
1134
    }
K
Kevin Branigan 已提交
1135

1136
    /* step back to character in front of the first element */
1137
    input--;
M
Max Bruckner 已提交
1138
    /* loop through the comma separated array elements */
1139
    do
M
Max Bruckner 已提交
1140
    {
1141
        /* allocate next item */
1142
        cJSON *new_item = cJSON_New_Item(hooks);
1143
        if (new_item == NULL)
M
Max Bruckner 已提交
1144
        {
1145
            goto fail; /* allocation failure */
M
Max Bruckner 已提交
1146
        }
1147 1148 1149

        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1150
        {
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
            /* 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 已提交
1163
        input = skip_whitespace(input + 1);
1164
        input = parse_value(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1165
        input = skip_whitespace(input);
1166
        if (input == NULL)
1167 1168
        {
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1169 1170
        }
    }
1171
    while (*input == ',');
M
Max Bruckner 已提交
1172

1173
    if (*input != ']')
M
Max Bruckner 已提交
1174
    {
1175 1176
        *error_pointer = input;
        goto fail; /* expected end of array */
M
Max Bruckner 已提交
1177 1178
    }

1179 1180
success:
    item->type = cJSON_Array;
1181
    item->child = head;
1182

1183
    return input + 1;
K
Kevin Branigan 已提交
1184

1185
fail:
1186
    if (head != NULL)
1187
    {
1188
        cJSON_Delete(head);
1189 1190
    }

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

/* Render an array to text */
1195
static unsigned char *print_array(const cJSON * const item, const size_t depth, const cjbool format, printbuffer * const output_buffer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1196
{
M
Max Bruckner 已提交
1197 1198
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1199
    size_t length = 0;
M
Max Bruckner 已提交
1200
    cJSON *current_element = item->child;
M
Max Bruckner 已提交
1201
    size_t output_offset = 0;
M
Max Bruckner 已提交
1202

M
Max Bruckner 已提交
1203
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1204 1205 1206
    {
        return NULL;
    }
K
Kevin Branigan 已提交
1207

M
Max Bruckner 已提交
1208 1209
    /* Compose the output array. */
    /* opening square bracket */
M
Max Bruckner 已提交
1210
    output_offset = output_buffer->offset;
1211
    output_pointer = ensure(output_buffer, 1, hooks);
M
Max Bruckner 已提交
1212
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1213
    {
M
Max Bruckner 已提交
1214 1215
        return NULL;
    }
M
Max Bruckner 已提交
1216

M
Max Bruckner 已提交
1217 1218
    *output_pointer = '[';
    output_buffer->offset++;
M
Max Bruckner 已提交
1219

M
Max Bruckner 已提交
1220
    while (current_element != NULL)
M
Max Bruckner 已提交
1221
    {
1222
        if (print_value(current_element, depth + 1, format, output_buffer, hooks) == NULL)
M
Max Bruckner 已提交
1223
        {
1224
            return NULL;
M
Max Bruckner 已提交
1225
        }
1226
        update_offset(output_buffer);
M
Max Bruckner 已提交
1227
        if (current_element->next)
M
Max Bruckner 已提交
1228
        {
M
Max Bruckner 已提交
1229
            length = format ? 2 : 1;
1230
            output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1231
            if (output_pointer == NULL)
1232 1233 1234
            {
                return NULL;
            }
M
Max Bruckner 已提交
1235 1236
            *output_pointer++ = ',';
            if(format)
M
Max Bruckner 已提交
1237
            {
M
Max Bruckner 已提交
1238
                *output_pointer++ = ' ';
M
Max Bruckner 已提交
1239
            }
M
Max Bruckner 已提交
1240 1241
            *output_pointer = '\0';
            output_buffer->offset += length;
M
Max Bruckner 已提交
1242
        }
M
Max Bruckner 已提交
1243
        current_element = current_element->next;
M
Max Bruckner 已提交
1244
    }
M
Max Bruckner 已提交
1245

1246
    output_pointer = ensure(output_buffer, 2, hooks);
M
Max Bruckner 已提交
1247
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1248
    {
M
Max Bruckner 已提交
1249
        return NULL;
M
Max Bruckner 已提交
1250
    }
M
Max Bruckner 已提交
1251 1252
    *output_pointer++ = ']';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1253
    output = output_buffer->buffer + output_offset;
M
Max Bruckner 已提交
1254

M
Max Bruckner 已提交
1255
    return output;
K
Kevin Branigan 已提交
1256 1257 1258
}

/* Build an object from the text. */
1259
static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
K
Kevin Branigan 已提交
1260
{
1261
    cJSON *head = NULL; /* linked list head */
1262 1263
    cJSON *current_item = NULL;

1264
    if (*input != '{')
M
Max Bruckner 已提交
1265
    {
1266 1267
        *error_pointer = input;
        goto fail; /* not an object */
M
Max Bruckner 已提交
1268 1269
    }

M
Max Bruckner 已提交
1270
    input = skip_whitespace(input + 1);
1271
    if (*input == '}')
M
Max Bruckner 已提交
1272
    {
1273
        goto success; /* empty object */
M
Max Bruckner 已提交
1274 1275
    }

1276
    /* step back to character in front of the first element */
1277
    input--;
1278 1279
    /* loop through the comma separated array elements */
    do
M
Max Bruckner 已提交
1280
    {
1281
        /* allocate next item */
1282
        cJSON *new_item = cJSON_New_Item(hooks);
1283 1284 1285 1286
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }
M
Max Bruckner 已提交
1287

1288 1289
        /* attach next item to list */
        if (head == NULL)
M
Max Bruckner 已提交
1290
        {
1291 1292 1293 1294 1295 1296 1297 1298 1299
            /* 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 已提交
1300 1301
        }

1302
        /* parse the name of the child */
M
Max Bruckner 已提交
1303
        input = skip_whitespace(input + 1);
1304
        input = parse_string(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1305
        input = skip_whitespace(input);
1306
        if (input == NULL)
M
Max Bruckner 已提交
1307
        {
1308
            goto fail; /* faile to parse name */
M
Max Bruckner 已提交
1309 1310
        }

1311 1312 1313
        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;
M
Max Bruckner 已提交
1314

1315
        if (*input != ':')
M
Max Bruckner 已提交
1316
        {
1317 1318
            *error_pointer = input;
            goto fail; /* invalid object */
M
Max Bruckner 已提交
1319
        }
1320 1321

        /* parse the value */
M
Max Bruckner 已提交
1322
        input = skip_whitespace(input + 1);
1323
        input = parse_value(current_item, input, error_pointer, hooks);
M
Max Bruckner 已提交
1324
        input = skip_whitespace(input);
1325
        if (input == NULL)
M
Max Bruckner 已提交
1326
        {
1327
            goto fail; /* failed to parse value */
M
Max Bruckner 已提交
1328 1329
        }
    }
1330
    while (*input == ',');
1331

1332
    if (*input != '}')
M
Max Bruckner 已提交
1333
    {
1334 1335
        *error_pointer = input;
        goto fail; /* expected end of object */
M
Max Bruckner 已提交
1336 1337
    }

1338 1339
success:
    item->type = cJSON_Object;
1340
    item->child = head;
1341

1342
    return input + 1;
1343 1344

fail:
1345
    if (head != NULL)
1346
    {
1347
        cJSON_Delete(head);
1348 1349
    }

1350
    return NULL;
K
Kevin Branigan 已提交
1351 1352 1353
}

/* Render an object to text. */
1354
static unsigned char *print_object(const cJSON * const item, const size_t depth, const cjbool format, printbuffer * const output_buffer, const internal_hooks * const hooks)
1355
{
M
Max Bruckner 已提交
1356 1357
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
M
Max Bruckner 已提交
1358 1359
    size_t length = 0;
    size_t output_offset = 0;
M
Max Bruckner 已提交
1360
    cJSON *current_item = item->child;
M
Max Bruckner 已提交
1361

M
Max Bruckner 已提交
1362
    if (output_buffer == NULL)
M
Max Bruckner 已提交
1363 1364 1365
    {
        return NULL;
    }
M
Max Bruckner 已提交
1366

M
Max Bruckner 已提交
1367
    /* Compose the output: */
M
Max Bruckner 已提交
1368
    output_offset = output_buffer->offset;
M
Max Bruckner 已提交
1369
    length = format ? 2 : 1; /* fmt: {\n */
1370
    output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1371
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1372
    {
M
Max Bruckner 已提交
1373 1374
        return NULL;
    }
M
Max Bruckner 已提交
1375

M
Max Bruckner 已提交
1376 1377
    *output_pointer++ = '{';
    if (format)
M
Max Bruckner 已提交
1378
    {
M
Max Bruckner 已提交
1379
        *output_pointer++ = '\n';
M
Max Bruckner 已提交
1380
    }
M
Max Bruckner 已提交
1381
    output_buffer->offset += length;
M
Max Bruckner 已提交
1382

M
Max Bruckner 已提交
1383
    while (current_item)
M
Max Bruckner 已提交
1384
    {
M
Max Bruckner 已提交
1385
        if (format)
M
Max Bruckner 已提交
1386
        {
M
Max Bruckner 已提交
1387
            size_t i;
1388
            output_pointer = ensure(output_buffer, depth + 1, hooks);
M
Max Bruckner 已提交
1389
            if (output_pointer == NULL)
M
Max Bruckner 已提交
1390
            {
1391
                return NULL;
M
Max Bruckner 已提交
1392
            }
M
Max Bruckner 已提交
1393
            for (i = 0; i < depth + 1; i++)
M
Max Bruckner 已提交
1394
            {
M
Max Bruckner 已提交
1395
                *output_pointer++ = '\t';
M
Max Bruckner 已提交
1396
            }
M
Max Bruckner 已提交
1397
            output_buffer->offset += depth + 1;
M
Max Bruckner 已提交
1398 1399
        }

M
Max Bruckner 已提交
1400
        /* print key */
1401
        if (print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks) == NULL)
M
Max Bruckner 已提交
1402
        {
1403
            return NULL;
M
Max Bruckner 已提交
1404
        }
M
Max Bruckner 已提交
1405
        update_offset(output_buffer);
M
Max Bruckner 已提交
1406

M
Max Bruckner 已提交
1407
        length = format ? 2 : 1;
1408
        output_pointer = ensure(output_buffer, length, hooks);
M
Max Bruckner 已提交
1409
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1410
        {
1411
            return NULL;
M
Max Bruckner 已提交
1412
        }
M
Max Bruckner 已提交
1413 1414
        *output_pointer++ = ':';
        if (format)
M
Max Bruckner 已提交
1415
        {
M
Max Bruckner 已提交
1416
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1417
        }
M
Max Bruckner 已提交
1418
        output_buffer->offset += length;
M
Max Bruckner 已提交
1419

M
Max Bruckner 已提交
1420
        /* print value */
1421
        if (!print_value(current_item, depth + 1, format, output_buffer, hooks))
M
Max Bruckner 已提交
1422
        {
M
Max Bruckner 已提交
1423
            return NULL;
M
Max Bruckner 已提交
1424
        }
M
Max Bruckner 已提交
1425
        update_offset(output_buffer);
M
Max Bruckner 已提交
1426

M
Max Bruckner 已提交
1427
        /* print comma if not last */
M
Max Bruckner 已提交
1428
        length = (size_t) (format ? 1 : 0) + (current_item->next ? 1 : 0);
1429
        output_pointer = ensure(output_buffer, length + 1, hooks);
M
Max Bruckner 已提交
1430
        if (output_pointer == NULL)
M
Max Bruckner 已提交
1431
        {
1432
            return NULL;
M
Max Bruckner 已提交
1433
        }
M
Max Bruckner 已提交
1434
        if (current_item->next)
M
Max Bruckner 已提交
1435
        {
M
Max Bruckner 已提交
1436
            *output_pointer++ = ',';
M
Max Bruckner 已提交
1437
        }
M
Max Bruckner 已提交
1438

M
Max Bruckner 已提交
1439
        if (format)
M
Max Bruckner 已提交
1440
        {
M
Max Bruckner 已提交
1441
            *output_pointer++ = '\n';
M
Max Bruckner 已提交
1442
        }
M
Max Bruckner 已提交
1443 1444
        *output_pointer = '\0';
        output_buffer->offset += length;
M
Max Bruckner 已提交
1445

M
Max Bruckner 已提交
1446
        current_item = current_item->next;
M
Max Bruckner 已提交
1447 1448
    }

1449
    output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks);
M
Max Bruckner 已提交
1450
    if (output_pointer == NULL)
M
Max Bruckner 已提交
1451 1452 1453
    {
        return NULL;
    }
M
Max Bruckner 已提交
1454
    if (format)
M
Max Bruckner 已提交
1455
    {
M
Max Bruckner 已提交
1456 1457
        size_t i;
        for (i = 0; i < (depth); i++)
M
Max Bruckner 已提交
1458
        {
M
Max Bruckner 已提交
1459
            *output_pointer++ = '\t';
M
Max Bruckner 已提交
1460 1461
        }
    }
M
Max Bruckner 已提交
1462 1463
    *output_pointer++ = '}';
    *output_pointer = '\0';
M
Max Bruckner 已提交
1464
    output = (output_buffer->buffer) + output_offset;
M
Max Bruckner 已提交
1465

M
Max Bruckner 已提交
1466
    return output;
K
Kevin Branigan 已提交
1467 1468 1469
}

/* Get Array size/item / object item. */
1470
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
M
Max Bruckner 已提交
1471 1472
{
    cJSON *c = array->child;
1473
    size_t i = 0;
M
Max Bruckner 已提交
1474 1475 1476 1477 1478
    while(c)
    {
        i++;
        c = c->next;
    }
1479 1480 1481

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

M
Max Bruckner 已提交
1482
    return (int)i;
M
Max Bruckner 已提交
1483 1484
}

1485
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
M
Max Bruckner 已提交
1486
{
1487
    cJSON *c = array ? array->child : NULL;
M
Max Bruckner 已提交
1488 1489 1490 1491 1492 1493 1494 1495 1496
    while (c && item > 0)
    {
        item--;
        c = c->next;
    }

    return c;
}

1497
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1498
{
1499
    cJSON *c = object ? object->child : NULL;
1500
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
M
Max Bruckner 已提交
1501 1502 1503 1504 1505 1506
    {
        c = c->next;
    }
    return c;
}

1507
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
{
    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;
}

1525
CJSON_PUBLIC(cjbool) cJSON_HasObjectItem(const cJSON *object, const char *string)
M
Max Bruckner 已提交
1526 1527 1528
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}
K
Kevin Branigan 已提交
1529 1530

/* Utility for array list handling. */
M
Max Bruckner 已提交
1531 1532 1533 1534 1535 1536
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

K
Kevin Branigan 已提交
1537
/* Utility for handling references. */
1538
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
M
Max Bruckner 已提交
1539
{
1540
    cJSON *ref = cJSON_New_Item(hooks);
M
Max Bruckner 已提交
1541 1542
    if (!ref)
    {
1543
        return NULL;
M
Max Bruckner 已提交
1544 1545
    }
    memcpy(ref, item, sizeof(cJSON));
1546
    ref->string = NULL;
M
Max Bruckner 已提交
1547
    ref->type |= cJSON_IsReference;
1548
    ref->next = ref->prev = NULL;
M
Max Bruckner 已提交
1549 1550
    return ref;
}
K
Kevin Branigan 已提交
1551 1552

/* Add item to array/object. */
1553
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
M
Max Bruckner 已提交
1554
{
1555 1556 1557
    cJSON *child = NULL;

    if ((item == NULL) || (array == NULL))
M
Max Bruckner 已提交
1558 1559 1560
    {
        return;
    }
1561 1562 1563 1564

    child = array->child;

    if (child == NULL)
M
Max Bruckner 已提交
1565 1566 1567 1568 1569 1570 1571
    {
        /* list is empty, start new one */
        array->child = item;
    }
    else
    {
        /* append to the end */
1572
        while (child->next)
M
Max Bruckner 已提交
1573
        {
1574
            child = child->next;
M
Max Bruckner 已提交
1575
        }
1576
        suffix_object(child, item);
M
Max Bruckner 已提交
1577 1578 1579
    }
}

1580
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
M
Max Bruckner 已提交
1581
{
1582
    /* call cJSON_AddItemToObjectCS for code reuse */
1583
    cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item);
1584 1585
    /* remove cJSON_StringIsConst flag */
    item->type &= ~cJSON_StringIsConst;
M
Max Bruckner 已提交
1586 1587
}

1588
/* Add an item to an object with constant string as key */
1589
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1590 1591 1592 1593 1594 1595 1596
{
    if (!item)
    {
        return;
    }
    if (!(item->type & cJSON_StringIsConst) && item->string)
    {
1597
        global_hooks.deallocate(item->string);
1598
    }
1599 1600
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
1601
    item->string = (char*)string;
1602
#pragma GCC diagnostic pop
1603 1604 1605 1606
    item->type |= cJSON_StringIsConst;
    cJSON_AddItemToArray(object, item);
}

1607
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1608
{
1609
    cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
1610 1611
}

1612
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1613
{
1614
    cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
1615 1616
}

M
Max Bruckner 已提交
1617
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
1628
        return NULL;
1629
    }
1630
    if (c->prev)
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
    {
        /* 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 */
1644
    c->prev = c->next = NULL;
1645 1646 1647

    return c;
}
1648
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
M
Max Bruckner 已提交
1649 1650 1651 1652 1653 1654 1655 1656
{
    if (which < 0)
    {
        return NULL;
    }

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

1658
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1659 1660 1661 1662
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

1663
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1664
{
1665
    size_t i = 0;
1666
    cJSON *c = object->child;
1667
    while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1668 1669 1670 1671 1672 1673
    {
        i++;
        c = c->next;
    }
    if (c)
    {
M
Max Bruckner 已提交
1674
        return DetachItemFromArray(object, i);
1675 1676
    }

1677
    return NULL;
1678 1679
}

1680
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1681 1682 1683
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}
K
Kevin Branigan 已提交
1684 1685

/* Replace array/object items with new ones. */
1686
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
{
    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 已提交
1712
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
{
    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;
    }
1738
    c->next = c->prev = NULL;
1739 1740
    cJSON_Delete(c);
}
1741
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
M
Max Bruckner 已提交
1742 1743 1744 1745 1746 1747 1748 1749
{
    if (which < 0)
    {
        return;
    }

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

1751
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1752
{
1753
    size_t i = 0;
1754
    cJSON *c = object->child;
1755
    while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string))
1756 1757 1758 1759 1760 1761
    {
        i++;
        c = c->next;
    }
    if(c)
    {
1762 1763 1764
        /* free the old string if not const */
        if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
        {
1765
             global_hooks.deallocate(newitem->string);
1766 1767
        }

1768
        newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1769
        ReplaceItemInArray(object, i, newitem);
1770 1771
    }
}
K
Kevin Branigan 已提交
1772 1773

/* Create basic types: */
1774
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
M
Max Bruckner 已提交
1775
{
1776
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1777 1778 1779 1780 1781 1782 1783 1784
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

1785
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
M
Max Bruckner 已提交
1786
{
1787
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1788 1789 1790 1791 1792 1793 1794 1795
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

1796
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
M
Max Bruckner 已提交
1797
{
1798
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1799 1800 1801 1802 1803 1804 1805 1806
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

1807
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cjbool b)
M
Max Bruckner 已提交
1808
{
1809
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1810 1811 1812 1813 1814 1815 1816 1817
    if(item)
    {
        item->type = b ? cJSON_True : cJSON_False;
    }

    return item;
}

1818
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
M
Max Bruckner 已提交
1819
{
1820
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1821 1822 1823 1824
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838

        /* 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 已提交
1839 1840 1841 1842 1843
    }

    return item;
}

1844
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
M
Max Bruckner 已提交
1845
{
1846
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1847 1848 1849
    if(item)
    {
        item->type = cJSON_String;
1850
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
M
Max Bruckner 已提交
1851 1852 1853
        if(!item->valuestring)
        {
            cJSON_Delete(item);
1854
            return NULL;
M
Max Bruckner 已提交
1855 1856 1857 1858 1859 1860
        }
    }

    return item;
}

1861
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
J
Jiri Zouhar 已提交
1862
{
1863
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1864 1865 1866
    if(item)
    {
        item->type = cJSON_Raw;
1867
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
M
Max Bruckner 已提交
1868 1869 1870 1871 1872 1873 1874 1875
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
J
Jiri Zouhar 已提交
1876 1877
}

1878
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
M
Max Bruckner 已提交
1879
{
1880
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1881 1882 1883 1884 1885 1886 1887 1888
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

1889
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
M
Max Bruckner 已提交
1890
{
1891
    cJSON *item = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
1892 1893 1894 1895 1896 1897 1898
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}
K
Kevin Branigan 已提交
1899 1900

/* Create Arrays: */
1901
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
M
Max Bruckner 已提交
1902
{
1903
    size_t i = 0;
1904 1905
    cJSON *n = NULL;
    cJSON *p = NULL;
1906 1907 1908 1909 1910 1911 1912 1913 1914
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();
    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
1915 1916 1917 1918 1919
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
1920
            return NULL;
M
Max Bruckner 已提交
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

1936
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
M
Max Bruckner 已提交
1937
{
1938
    size_t i = 0;
1939 1940
    cJSON *n = NULL;
    cJSON *p = NULL;
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
M
Max Bruckner 已提交
1951
    {
1952
        n = cJSON_CreateNumber((double)numbers[i]);
M
Max Bruckner 已提交
1953 1954 1955
        if(!n)
        {
            cJSON_Delete(a);
1956
            return NULL;
M
Max Bruckner 已提交
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

1972
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
1973
{
1974
    size_t i = 0;
1975 1976
    cJSON *n = NULL;
    cJSON *p = NULL;
1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0;a && (i < (size_t)count); i++)
1987 1988 1989 1990 1991
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
1992
            return NULL;
1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    return a;
}

2008
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2009
{
2010
    size_t i = 0;
2011 2012
    cJSON *n = NULL;
    cJSON *p = NULL;
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
    cJSON *a = NULL;

    if (count < 0)
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
2023 2024 2025 2026 2027
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
2028
            return NULL;
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    return a;
}
2043 2044

/* Duplication */
2045
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cjbool recurse)
2046
{
M
Max Bruckner 已提交
2047
    cJSON *newitem = NULL;
2048 2049
    cJSON *child = NULL;
    cJSON *next = NULL;
M
Max Bruckner 已提交
2050
    cJSON *newchild = NULL;
M
Max Bruckner 已提交
2051 2052 2053 2054

    /* Bail on bad ptr */
    if (!item)
    {
2055
        goto fail;
M
Max Bruckner 已提交
2056 2057
    }
    /* Create new item */
2058
    newitem = cJSON_New_Item(&global_hooks);
M
Max Bruckner 已提交
2059 2060
    if (!newitem)
    {
2061
        goto fail;
M
Max Bruckner 已提交
2062 2063 2064 2065 2066 2067 2068
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
2069
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
M
Max Bruckner 已提交
2070 2071
        if (!newitem->valuestring)
        {
2072
            goto fail;
M
Max Bruckner 已提交
2073 2074 2075 2076
        }
    }
    if (item->string)
    {
2077
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
M
Max Bruckner 已提交
2078 2079
        if (!newitem->string)
        {
2080
            goto fail;
M
Max Bruckner 已提交
2081 2082 2083 2084 2085 2086 2087 2088
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
2089 2090
    child = item->child;
    while (child != NULL)
M
Max Bruckner 已提交
2091
    {
2092
        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
M
Max Bruckner 已提交
2093 2094
        if (!newchild)
        {
2095
            goto fail;
M
Max Bruckner 已提交
2096
        }
2097
        if (next != NULL)
M
Max Bruckner 已提交
2098 2099
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2100 2101 2102
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
M
Max Bruckner 已提交
2103 2104 2105 2106
        }
        else
        {
            /* Set newitem->child and move to it */
2107 2108
            newitem->child = newchild;
            next = newchild;
M
Max Bruckner 已提交
2109
        }
2110
        child = child->next;
M
Max Bruckner 已提交
2111 2112 2113
    }

    return newitem;
2114 2115 2116 2117 2118 2119 2120 2121

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

    return NULL;
2122
}
2123

2124
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2125
{
2126
    unsigned char *into = (unsigned char*)json;
M
Max Bruckner 已提交
2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165
    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 已提交
2166
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2167 2168 2169 2170
            while (*json && (*json != '\"'))
            {
                if (*json == '\\')
                {
M
Max Bruckner 已提交
2171
                    *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2172
                }
M
Max Bruckner 已提交
2173
                *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2174
            }
M
Max Bruckner 已提交
2175
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2176 2177 2178 2179
        }
        else
        {
            /* All other characters. */
M
Max Bruckner 已提交
2180
            *into++ = (unsigned char)*json++;
M
Max Bruckner 已提交
2181 2182 2183 2184 2185
        }
    }

    /* and null-terminate. */
    *into = '\0';
2186
}
2187

2188
CJSON_PUBLIC(cjbool) cJSON_IsInvalid(const cJSON * const item)
2189 2190 2191 2192 2193 2194 2195 2196 2197
{
    if (item == NULL)
    {
        return false;
    }

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

2198
CJSON_PUBLIC(cjbool) cJSON_IsFalse(const cJSON * const item)
2199 2200 2201 2202 2203 2204 2205 2206 2207
{
    if (item == NULL)
    {
        return false;
    }

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

2208
CJSON_PUBLIC(cjbool) cJSON_IsTrue(const cJSON * const item)
2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
{
    if (item == NULL)
    {
        return false;
    }

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


2219
CJSON_PUBLIC(cjbool) cJSON_IsBool(const cJSON * const item)
2220 2221 2222 2223 2224 2225 2226 2227
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
2228
CJSON_PUBLIC(cjbool) cJSON_IsNull(const cJSON * const item)
2229 2230 2231 2232 2233 2234 2235 2236 2237
{
    if (item == NULL)
    {
        return false;
    }

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

2238
CJSON_PUBLIC(cjbool) cJSON_IsNumber(const cJSON * const item)
2239 2240 2241 2242 2243 2244 2245 2246 2247
{
    if (item == NULL)
    {
        return false;
    }

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

2248
CJSON_PUBLIC(cjbool) cJSON_IsString(const cJSON * const item)
2249 2250 2251 2252 2253 2254 2255 2256 2257
{
    if (item == NULL)
    {
        return false;
    }

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

2258
CJSON_PUBLIC(cjbool) cJSON_IsArray(const cJSON * const item)
2259 2260 2261 2262 2263 2264 2265 2266 2267
{
    if (item == NULL)
    {
        return false;
    }

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

2268
CJSON_PUBLIC(cjbool) cJSON_IsObject(const cJSON * const item)
2269 2270 2271 2272 2273 2274 2275 2276 2277
{
    if (item == NULL)
    {
        return false;
    }

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

2278
CJSON_PUBLIC(cjbool) cJSON_IsRaw(const cJSON * const item)
2279 2280 2281 2282 2283 2284 2285 2286
{
    if (item == NULL)
    {
        return false;
    }

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