Coverage Report

Created: 2026-08-31 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cjson/cJSON.c
Line
Count
Source
1
/*
2
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
  of this software and associated documentation files (the "Software"), to deal
6
  in the Software without restriction, including without limitation the rights
7
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
  copies of the Software, and to permit persons to whom the Software is
9
  furnished to do so, subject to the following conditions:
10
11
  The above copyright notice and this permission notice shall be included in
12
  all copies or substantial portions of the Software.
13
14
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
  THE SOFTWARE.
21
*/
22
23
/* cJSON */
24
/* JSON parser in C. */
25
26
/* disable warnings about old C89 functions in MSVC */
27
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
#define _CRT_SECURE_NO_DEPRECATE
29
#endif
30
31
#ifdef __GNUC__
32
#pragma GCC visibility push(default)
33
#endif
34
#if defined(_MSC_VER)
35
#pragma warning (push)
36
/* disable warning about single line comments in system headers */
37
#pragma warning (disable : 4001)
38
#endif
39
40
#include <string.h>
41
#include <stdio.h>
42
#include <math.h>
43
#include <stdlib.h>
44
#include <limits.h>
45
#include <ctype.h>
46
#include <float.h>
47
48
#ifdef ENABLE_LOCALES
49
#include <locale.h>
50
#endif
51
52
#if defined(_MSC_VER)
53
#pragma warning (pop)
54
#endif
55
#ifdef __GNUC__
56
#pragma GCC visibility pop
57
#endif
58
59
#include "cJSON.h"
60
61
/* define our own boolean type */
62
#ifdef true
63
#undef true
64
#endif
65
1.41M
#define true ((cJSON_bool)1)
66
67
#ifdef false
68
#undef false
69
#endif
70
86.2k
#define false ((cJSON_bool)0)
71
72
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73
#ifndef isinf
74
15.0k
#define isinf(d) (isnan((d - d)) && !isnan(d))
75
#endif
76
#ifndef isnan
77
60.3k
#define isnan(d) (d != d)
78
#endif
79
80
#ifndef NAN
81
#ifdef _WIN32
82
#define NAN sqrt(-1.0)
83
#else
84
0
#define NAN 0.0/0.0
85
#endif
86
#endif
87
88
typedef struct {
89
    const unsigned char *json;
90
    size_t position;
91
} error;
92
static error global_error = { NULL, 0 };
93
94
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
95
0
{
96
0
    return (const char*) (global_error.json + global_error.position);
97
0
}
98
99
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
100
0
{
101
0
    if (!cJSON_IsString(item))
102
0
    {
103
0
        return NULL;
104
0
    }
105
106
0
    return item->valuestring;
107
0
}
108
109
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
110
0
{
111
0
    if (!cJSON_IsNumber(item))
112
0
    {
113
0
        return (double) NAN;
114
0
    }
115
116
0
    return item->valuedouble;
117
0
}
118
119
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19)
121
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
#endif
123
124
CJSON_PUBLIC(const char*) cJSON_Version(void)
125
0
{
126
0
    static char version[15];
127
0
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
128
129
0
    return version;
130
0
}
131
132
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
134
0
{
135
0
    if ((string1 == NULL) || (string2 == NULL))
136
0
    {
137
0
        return 1;
138
0
    }
139
140
0
    if (string1 == string2)
141
0
    {
142
0
        return 0;
143
0
    }
144
145
0
    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
146
0
    {
147
0
        if (*string1 == '\0')
148
0
        {
149
0
            return 0;
150
0
        }
151
0
    }
152
153
0
    return tolower(*string1) - tolower(*string2);
154
0
}
155
156
typedef struct internal_hooks
157
{
158
    void *(CJSON_CDECL *allocate)(size_t size);
159
    void (CJSON_CDECL *deallocate)(void *pointer);
160
    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
161
} internal_hooks;
162
163
#if defined(_MSC_VER)
164
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165
static void * CJSON_CDECL internal_malloc(size_t size)
166
{
167
    return malloc(size);
168
}
169
static void CJSON_CDECL internal_free(void *pointer)
170
{
171
    free(pointer);
172
}
173
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
174
{
175
    return realloc(pointer, size);
176
}
177
#else
178
#define internal_malloc malloc
179
#define internal_free free
180
#define internal_realloc realloc
181
#endif
182
183
/* strlen of character literals resolved at compile time */
184
69.3k
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
185
186
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
187
188
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
189
0
{
190
0
    size_t length = 0;
191
0
    unsigned char *copy = NULL;
192
193
0
    if (string == NULL)
194
0
    {
195
0
        return NULL;
196
0
    }
197
198
0
    length = strlen((const char*)string) + sizeof("");
199
0
    copy = (unsigned char*)hooks->allocate(length);
200
0
    if (copy == NULL)
201
0
    {
202
0
        return NULL;
203
0
    }
204
0
    memcpy(copy, string, length);
205
206
0
    return copy;
207
0
}
208
209
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
210
0
{
211
0
    if (hooks == NULL)
212
0
    {
213
        /* Reset hooks */
214
0
        global_hooks.allocate = malloc;
215
0
        global_hooks.deallocate = free;
216
0
        global_hooks.reallocate = realloc;
217
0
        return;
218
0
    }
219
220
0
    global_hooks.allocate = malloc;
221
0
    if (hooks->malloc_fn != NULL)
222
0
    {
223
0
        global_hooks.allocate = hooks->malloc_fn;
224
0
    }
225
226
0
    global_hooks.deallocate = free;
227
0
    if (hooks->free_fn != NULL)
228
0
    {
229
0
        global_hooks.deallocate = hooks->free_fn;
230
0
    }
231
232
    /* use realloc only if both free and malloc are used */
233
0
    global_hooks.reallocate = NULL;
234
0
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
235
0
    {
236
0
        global_hooks.reallocate = realloc;
237
0
    }
238
0
}
239
240
/* Internal constructor. */
241
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
242
754k
{
243
754k
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
754k
    if (node)
245
754k
    {
246
754k
        memset(node, '\0', sizeof(cJSON));
247
754k
    }
248
249
754k
    return node;
250
754k
}
251
252
/* Delete a cJSON structure. */
253
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
309k
{
255
309k
    cJSON *next = NULL;
256
1.06M
    while (item != NULL)
257
754k
    {
258
754k
        next = item->next;
259
754k
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
254k
        {
261
254k
            cJSON_Delete(item->child);
262
254k
        }
263
754k
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
7.80k
        {
265
7.80k
            global_hooks.deallocate(item->valuestring);
266
7.80k
            item->valuestring = NULL;
267
7.80k
        }
268
754k
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
31.8k
        {
270
31.8k
            global_hooks.deallocate(item->string);
271
31.8k
            item->string = NULL;
272
31.8k
        }
273
754k
        global_hooks.deallocate(item);
274
754k
        item = next;
275
754k
    }
276
309k
}
277
278
/* get the decimal point character of the current locale */
279
static unsigned char get_decimal_point(void)
280
46.0k
{
281
46.0k
#ifdef ENABLE_LOCALES
282
46.0k
    struct lconv *lconv = localeconv();
283
46.0k
    return (unsigned char) lconv->decimal_point[0];
284
#else
285
    return '.';
286
#endif
287
46.0k
}
288
289
typedef struct
290
{
291
    const unsigned char *content;
292
    size_t length;
293
    size_t offset;
294
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
295
    internal_hooks hooks;
296
} parse_buffer;
297
298
/* check if the given size is left to read in a given parse buffer (starting with 1) */
299
4.52M
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300
/* check if the buffer can be accessed at the given index (starting with 0) */
301
18.5M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
3.96M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303
/* get a pointer to the buffer at the position */
304
12.9M
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
305
306
/* Parse the input text to generate a number, and populate the result into item. */
307
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308
31.0k
{
309
31.0k
    double number = 0;
310
31.0k
    unsigned char *after_end = NULL;
311
31.0k
    unsigned char *number_c_string;
312
31.0k
    unsigned char decimal_point = get_decimal_point();
313
31.0k
    size_t i = 0;
314
31.0k
    size_t number_string_length = 0;
315
31.0k
    cJSON_bool has_decimal_point = false;
316
317
31.0k
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
318
0
    {
319
0
        return false;
320
0
    }
321
322
    /* copy the number into a temporary buffer and replace '.' with the decimal point
323
     * of the current locale (for strtod)
324
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
325
628k
    for (i = 0; can_access_at_index(input_buffer, i); i++)
326
628k
    {
327
628k
        switch (buffer_at_offset(input_buffer)[i])
328
628k
        {
329
400k
            case '0':
330
433k
            case '1':
331
448k
            case '2':
332
453k
            case '3':
333
459k
            case '4':
334
470k
            case '5':
335
483k
            case '6':
336
495k
            case '7':
337
508k
            case '8':
338
533k
            case '9':
339
536k
            case '+':
340
585k
            case '-':
341
586k
            case 'e':
342
588k
            case 'E':
343
588k
                number_string_length++;
344
588k
                break;
345
346
8.82k
            case '.':
347
8.82k
                number_string_length++;
348
8.82k
                has_decimal_point = true;
349
8.82k
                break;
350
351
31.0k
            default:
352
31.0k
                goto loop_end;
353
628k
        }
354
628k
    }
355
31.0k
loop_end:
356
    /* malloc for temporary buffer, add 1 for '\0' */
357
31.0k
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
358
31.0k
    if (number_c_string == NULL)
359
0
    {
360
0
        return false; /* allocation failure */
361
0
    }
362
363
31.0k
    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
364
31.0k
    number_c_string[number_string_length] = '\0';
365
366
31.0k
    if (has_decimal_point)
367
835
    {
368
529k
        for (i = 0; i < number_string_length; i++)
369
528k
        {
370
528k
            if (number_c_string[i] == '.')
371
8.82k
            {
372
                /* replace '.' with the decimal point of the current locale (for strtod) */
373
8.82k
                number_c_string[i] = decimal_point;
374
8.82k
            }
375
528k
        }
376
835
    }
377
378
31.0k
    number = strtod((const char*)number_c_string, (char**)&after_end);
379
31.0k
    if (number_c_string == after_end)
380
20
    {
381
        /* free the temporary buffer */
382
20
        input_buffer->hooks.deallocate(number_c_string);
383
20
        return false; /* parse_error */
384
20
    }
385
386
31.0k
    item->valuedouble = number;
387
388
    /* use saturation in case of overflow */
389
31.0k
    if (number >= INT_MAX)
390
2.44k
    {
391
2.44k
        item->valueint = INT_MAX;
392
2.44k
    }
393
28.6k
    else if (number <= (double)INT_MIN)
394
259
    {
395
259
        item->valueint = INT_MIN;
396
259
    }
397
28.3k
    else
398
28.3k
    {
399
28.3k
        item->valueint = (int)number;
400
28.3k
    }
401
402
31.0k
    item->type = cJSON_Number;
403
404
31.0k
    input_buffer->offset += (size_t)(after_end - number_c_string);
405
    /* free the temporary buffer */
406
31.0k
    input_buffer->hooks.deallocate(number_c_string);
407
31.0k
    return true;
408
31.0k
}
409
410
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
411
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
412
0
{
413
0
    if (object == NULL)
414
0
    {
415
0
        return (double)NAN;
416
0
    }
417
418
0
    if (number >= INT_MAX)
419
0
    {
420
0
        object->valueint = INT_MAX;
421
0
    }
422
0
    else if (number <= (double)INT_MIN)
423
0
    {
424
0
        object->valueint = INT_MIN;
425
0
    }
426
0
    else
427
0
    {
428
0
        object->valueint = (int)number;
429
0
    }
430
431
0
    return object->valuedouble = number;
432
0
}
433
434
/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
435
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
436
0
{
437
0
    char *copy = NULL;
438
0
    size_t v1_len;
439
0
    size_t v2_len;
440
    /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
441
0
    if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
442
0
    {
443
0
        return NULL;
444
0
    }
445
    /* return NULL if the object is corrupted or valuestring is NULL */
446
0
    if (object->valuestring == NULL || valuestring == NULL)
447
0
    {
448
0
        return NULL;
449
0
    }
450
451
0
    v1_len = strlen(valuestring);
452
0
    v2_len = strlen(object->valuestring);
453
454
0
    if (v1_len <= v2_len)
455
0
    {
456
        /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
457
0
        if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
458
0
        {
459
0
            return NULL;
460
0
        }
461
0
        strcpy(object->valuestring, valuestring);
462
0
        return object->valuestring;
463
0
    }
464
0
    copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
465
0
    if (copy == NULL)
466
0
    {
467
0
        return NULL;
468
0
    }
469
0
    if (object->valuestring != NULL)
470
0
    {
471
0
        cJSON_free(object->valuestring);
472
0
    }
473
0
    object->valuestring = copy;
474
475
0
    return copy;
476
0
}
477
478
typedef struct
479
{
480
    unsigned char *buffer;
481
    size_t length;
482
    size_t offset;
483
    size_t depth; /* current nesting depth (for formatted printing) */
484
    cJSON_bool noalloc;
485
    cJSON_bool format; /* is this print a formatted print */
486
    internal_hooks hooks;
487
} printbuffer;
488
489
/* realloc printbuffer if necessary to have at least "needed" bytes more */
490
static unsigned char* ensure(printbuffer * const p, size_t needed)
491
1.77M
{
492
1.77M
    unsigned char *newbuffer = NULL;
493
1.77M
    size_t newsize = 0;
494
495
1.77M
    if ((p == NULL) || (p->buffer == NULL))
496
0
    {
497
0
        return NULL;
498
0
    }
499
500
1.77M
    if ((p->length > 0) && (p->offset >= p->length))
501
0
    {
502
        /* make sure that offset is valid */
503
0
        return NULL;
504
0
    }
505
506
1.77M
    if (needed > INT_MAX)
507
0
    {
508
        /* sizes bigger than INT_MAX are currently not supported */
509
0
        return NULL;
510
0
    }
511
512
1.77M
    needed += p->offset + 1;
513
1.77M
    if (needed <= p->length)
514
1.76M
    {
515
1.76M
        return p->buffer + p->offset;
516
1.76M
    }
517
518
1.91k
    if (p->noalloc) {
519
0
        return NULL;
520
0
    }
521
522
    /* calculate new buffer size */
523
1.91k
    if (needed > (INT_MAX / 2))
524
0
    {
525
        /* overflow of int, use INT_MAX if possible */
526
0
        if (needed <= INT_MAX)
527
0
        {
528
0
            newsize = INT_MAX;
529
0
        }
530
0
        else
531
0
        {
532
0
            return NULL;
533
0
        }
534
0
    }
535
1.91k
    else
536
1.91k
    {
537
1.91k
        newsize = needed * 2;
538
1.91k
    }
539
540
1.91k
    if (p->hooks.reallocate != NULL)
541
1.91k
    {
542
        /* reallocate with realloc if available */
543
1.91k
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
544
1.91k
        if (newbuffer == NULL)
545
0
        {
546
0
            p->hooks.deallocate(p->buffer);
547
0
            p->length = 0;
548
0
            p->buffer = NULL;
549
550
0
            return NULL;
551
0
        }
552
1.91k
    }
553
0
    else
554
0
    {
555
        /* otherwise reallocate manually */
556
0
        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
557
0
        if (!newbuffer)
558
0
        {
559
0
            p->hooks.deallocate(p->buffer);
560
0
            p->length = 0;
561
0
            p->buffer = NULL;
562
563
0
            return NULL;
564
0
        }
565
566
0
        memcpy(newbuffer, p->buffer, p->offset + 1);
567
0
        p->hooks.deallocate(p->buffer);
568
0
    }
569
1.91k
    p->length = newsize;
570
1.91k
    p->buffer = newbuffer;
571
572
1.91k
    return newbuffer + p->offset;
573
1.91k
}
574
575
/* calculate the new length of the string in a printbuffer and update the offset */
576
static void update_offset(printbuffer * const buffer)
577
676k
{
578
676k
    const unsigned char *buffer_pointer = NULL;
579
676k
    if ((buffer == NULL) || (buffer->buffer == NULL))
580
0
    {
581
0
        return;
582
0
    }
583
676k
    buffer_pointer = buffer->buffer + buffer->offset;
584
585
676k
    buffer->offset += strlen((const char*)buffer_pointer);
586
676k
}
587
588
/* securely comparison of floating-point variables */
589
static cJSON_bool compare_double(double a, double b)
590
1.12k
{
591
1.12k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
592
1.12k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
593
1.12k
}
594
595
/* Render the number nicely from the given item into a string. */
596
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
597
15.0k
{
598
15.0k
    unsigned char *output_pointer = NULL;
599
15.0k
    double d = item->valuedouble;
600
15.0k
    int length = 0;
601
15.0k
    size_t i = 0;
602
15.0k
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
603
15.0k
    unsigned char decimal_point = get_decimal_point();
604
15.0k
    double test = 0.0;
605
606
15.0k
    if (output_buffer == NULL)
607
0
    {
608
0
        return false;
609
0
    }
610
611
    /* This checks for NaN and Infinity */
612
15.0k
    if (isnan(d) || isinf(d))
613
289
    {
614
289
        length = sprintf((char*)number_buffer, "null");
615
289
    }
616
14.7k
    else if(d == (double)item->valueint)
617
13.5k
    {
618
13.5k
        length = sprintf((char*)number_buffer, "%d", item->valueint);
619
13.5k
    }
620
1.12k
    else
621
1.12k
    {
622
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
623
1.12k
        length = sprintf((char*)number_buffer, "%1.15g", d);
624
625
        /* Check whether the original double can be recovered */
626
1.12k
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
627
643
        {
628
            /* If not, print with 17 decimal places of precision */
629
643
            length = sprintf((char*)number_buffer, "%1.17g", d);
630
643
        }
631
1.12k
    }
632
633
    /* sprintf failed or buffer overrun occurred */
634
15.0k
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
635
0
    {
636
0
        return false;
637
0
    }
638
639
    /* reserve appropriate space in the output */
640
15.0k
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
641
15.0k
    if (output_pointer == NULL)
642
0
    {
643
0
        return false;
644
0
    }
645
646
    /* copy the printed number to the output and replace locale
647
     * dependent decimal point with '.' */
648
47.4k
    for (i = 0; i < ((size_t)length); i++)
649
32.4k
    {
650
32.4k
        if (number_buffer[i] == decimal_point)
651
467
        {
652
467
            output_pointer[i] = '.';
653
467
            continue;
654
467
        }
655
656
31.9k
        output_pointer[i] = number_buffer[i];
657
31.9k
    }
658
15.0k
    output_pointer[i] = '\0';
659
660
15.0k
    output_buffer->offset += (size_t)length;
661
662
15.0k
    return true;
663
15.0k
}
664
665
/* parse 4 digit hexadecimal number */
666
static unsigned parse_hex4(const unsigned char * const input)
667
67.9k
{
668
67.9k
    unsigned int h = 0;
669
67.9k
    size_t i = 0;
670
671
248k
    for (i = 0; i < 4; i++)
672
212k
    {
673
        /* parse digit */
674
212k
        if ((input[i] >= '0') && (input[i] <= '9'))
675
68.7k
        {
676
68.7k
            h += (unsigned int) input[i] - '0';
677
68.7k
        }
678
143k
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
679
25.8k
        {
680
25.8k
            h += (unsigned int) 10 + input[i] - 'A';
681
25.8k
        }
682
117k
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
683
86.1k
        {
684
86.1k
            h += (unsigned int) 10 + input[i] - 'a';
685
86.1k
        }
686
31.7k
        else /* invalid */
687
31.7k
        {
688
31.7k
            return 0;
689
31.7k
        }
690
691
180k
        if (i < 3)
692
144k
        {
693
            /* shift left to make place for the next nibble */
694
144k
            h = h << 4;
695
144k
        }
696
180k
    }
697
698
36.1k
    return h;
699
67.9k
}
700
701
/* converts a UTF-16 literal to UTF-8
702
 * A literal can be one or two sequences of the form \uXXXX */
703
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
704
64.8k
{
705
64.8k
    long unsigned int codepoint = 0;
706
64.8k
    unsigned int first_code = 0;
707
64.8k
    const unsigned char *first_sequence = input_pointer;
708
64.8k
    unsigned char utf8_length = 0;
709
64.8k
    unsigned char utf8_position = 0;
710
64.8k
    unsigned char sequence_length = 0;
711
64.8k
    unsigned char first_byte_mark = 0;
712
713
64.8k
    if ((input_end - first_sequence) < 6)
714
3
    {
715
        /* input ends unexpectedly */
716
3
        goto fail;
717
3
    }
718
719
    /* get the first utf16 sequence */
720
64.8k
    first_code = parse_hex4(first_sequence + 2);
721
722
    /* check that the code is valid */
723
64.8k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
724
13
    {
725
13
        goto fail;
726
13
    }
727
728
    /* UTF16 surrogate pair */
729
64.8k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
730
3.16k
    {
731
3.16k
        const unsigned char *second_sequence = first_sequence + 6;
732
3.16k
        unsigned int second_code = 0;
733
3.16k
        sequence_length = 12; /* \uXXXX\uXXXX */
734
735
3.16k
        if ((input_end - second_sequence) < 6)
736
18
        {
737
            /* input ends unexpectedly */
738
18
            goto fail;
739
18
        }
740
741
3.14k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
742
27
        {
743
            /* missing second half of the surrogate pair */
744
27
            goto fail;
745
27
        }
746
747
        /* get the second utf16 sequence */
748
3.11k
        second_code = parse_hex4(second_sequence + 2);
749
        /* check that the code is valid */
750
3.11k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
751
57
        {
752
            /* invalid second half of the surrogate pair */
753
57
            goto fail;
754
57
        }
755
756
757
        /* calculate the unicode codepoint from the surrogate pair */
758
3.05k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
759
3.05k
    }
760
61.6k
    else
761
61.6k
    {
762
61.6k
        sequence_length = 6; /* \uXXXX */
763
61.6k
        codepoint = first_code;
764
61.6k
    }
765
766
    /* encode as UTF-8
767
     * takes at maximum 4 bytes to encode:
768
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
769
64.7k
    if (codepoint < 0x80)
770
35.7k
    {
771
        /* normal ascii, encoding 0xxxxxxx */
772
35.7k
        utf8_length = 1;
773
35.7k
    }
774
29.0k
    else if (codepoint < 0x800)
775
4.22k
    {
776
        /* two bytes, encoding 110xxxxx 10xxxxxx */
777
4.22k
        utf8_length = 2;
778
4.22k
        first_byte_mark = 0xC0; /* 11000000 */
779
4.22k
    }
780
24.7k
    else if (codepoint < 0x10000)
781
21.7k
    {
782
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
783
21.7k
        utf8_length = 3;
784
21.7k
        first_byte_mark = 0xE0; /* 11100000 */
785
21.7k
    }
786
3.05k
    else if (codepoint <= 0x10FFFF)
787
3.05k
    {
788
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
789
3.05k
        utf8_length = 4;
790
3.05k
        first_byte_mark = 0xF0; /* 11110000 */
791
3.05k
    }
792
0
    else
793
0
    {
794
        /* invalid unicode codepoint */
795
0
        goto fail;
796
0
    }
797
798
    /* encode as utf8 */
799
121k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
800
56.8k
    {
801
        /* 10xxxxxx */
802
56.8k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
803
56.8k
        codepoint >>= 6;
804
56.8k
    }
805
    /* encode first byte */
806
64.7k
    if (utf8_length > 1)
807
29.0k
    {
808
29.0k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
809
29.0k
    }
810
35.7k
    else
811
35.7k
    {
812
35.7k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
813
35.7k
    }
814
815
64.7k
    *output_pointer += utf8_length;
816
817
64.7k
    return sequence_length;
818
819
118
fail:
820
118
    return 0;
821
64.7k
}
822
823
/* Parse the input text into an unescaped cinput, and populate item. */
824
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
825
40.0k
{
826
40.0k
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
827
40.0k
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
828
40.0k
    unsigned char *output_pointer = NULL;
829
40.0k
    unsigned char *output = NULL;
830
831
    /* not a string */
832
40.0k
    if (buffer_at_offset(input_buffer)[0] != '\"')
833
150
    {
834
150
        goto fail;
835
150
    }
836
837
39.9k
    {
838
        /* calculate approximate size of the output (overestimate) */
839
39.9k
        size_t allocation_length = 0;
840
39.9k
        size_t skipped_bytes = 0;
841
26.7M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
842
26.7M
        {
843
            /* is escape sequence */
844
26.7M
            if (input_end[0] == '\\')
845
214k
            {
846
214k
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
847
0
                {
848
                    /* prevent buffer overflow when last input character is a backslash */
849
0
                    goto fail;
850
0
                }
851
214k
                skipped_bytes++;
852
214k
                input_end++;
853
214k
            }
854
26.7M
            input_end++;
855
26.7M
        }
856
39.9k
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
857
70
        {
858
70
            goto fail; /* string ended unexpectedly */
859
70
        }
860
861
        /* This is at most how much we need for the output */
862
39.8k
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
863
39.8k
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
864
39.8k
        if (output == NULL)
865
0
        {
866
0
            goto fail; /* allocation failure */
867
0
        }
868
39.8k
    }
869
870
39.8k
    output_pointer = output;
871
    /* loop through the string literal */
872
25.4M
    while (input_pointer < input_end)
873
25.4M
    {
874
25.4M
        if (*input_pointer != '\\')
875
25.2M
        {
876
25.2M
            *output_pointer++ = *input_pointer++;
877
25.2M
        }
878
        /* escape sequence */
879
194k
        else
880
194k
        {
881
194k
            unsigned char sequence_length = 2;
882
194k
            if ((input_end - input_pointer) < 1)
883
0
            {
884
0
                goto fail;
885
0
            }
886
887
194k
            switch (input_pointer[1])
888
194k
            {
889
10.3k
                case 'b':
890
10.3k
                    *output_pointer++ = '\b';
891
10.3k
                    break;
892
13.6k
                case 'f':
893
13.6k
                    *output_pointer++ = '\f';
894
13.6k
                    break;
895
10.2k
                case 'n':
896
10.2k
                    *output_pointer++ = '\n';
897
10.2k
                    break;
898
7.39k
                case 'r':
899
7.39k
                    *output_pointer++ = '\r';
900
7.39k
                    break;
901
33.6k
                case 't':
902
33.6k
                    *output_pointer++ = '\t';
903
33.6k
                    break;
904
25.3k
                case '\"':
905
38.9k
                case '\\':
906
54.7k
                case '/':
907
54.7k
                    *output_pointer++ = input_pointer[1];
908
54.7k
                    break;
909
910
                /* UTF-16 literal */
911
64.8k
                case 'u':
912
64.8k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
913
64.8k
                    if (sequence_length == 0)
914
118
                    {
915
                        /* failed to convert UTF16-literal to UTF-8 */
916
118
                        goto fail;
917
118
                    }
918
64.7k
                    break;
919
920
64.7k
                default:
921
12
                    goto fail;
922
194k
            }
923
194k
            input_pointer += sequence_length;
924
194k
        }
925
25.4M
    }
926
927
    /* zero terminate the output */
928
39.7k
    *output_pointer = '\0';
929
930
39.7k
    item->type = cJSON_String;
931
39.7k
    item->valuestring = (char*)output;
932
933
39.7k
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
934
39.7k
    input_buffer->offset++;
935
936
39.7k
    return true;
937
938
350
fail:
939
350
    if (output != NULL)
940
130
    {
941
130
        input_buffer->hooks.deallocate(output);
942
130
        output = NULL;
943
130
    }
944
945
350
    if (input_pointer != NULL)
946
350
    {
947
350
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
948
350
    }
949
950
350
    return false;
951
39.8k
}
952
953
/* Render the cstring provided to an escaped version that can be printed. */
954
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
955
16.8k
{
956
16.8k
    const unsigned char *input_pointer = NULL;
957
16.8k
    unsigned char *output = NULL;
958
16.8k
    unsigned char *output_pointer = NULL;
959
16.8k
    size_t output_length = 0;
960
    /* numbers of additional characters needed for escaping */
961
16.8k
    size_t escape_characters = 0;
962
963
16.8k
    if (output_buffer == NULL)
964
0
    {
965
0
        return false;
966
0
    }
967
968
    /* empty string */
969
16.8k
    if (input == NULL)
970
0
    {
971
0
        output = ensure(output_buffer, sizeof("\"\""));
972
0
        if (output == NULL)
973
0
        {
974
0
            return false;
975
0
        }
976
0
        strcpy((char*)output, "\"\"");
977
978
0
        return true;
979
0
    }
980
981
    /* set "flag" to 1 if something needs to be escaped */
982
10.1M
    for (input_pointer = input; *input_pointer; input_pointer++)
983
10.0M
    {
984
10.0M
        switch (*input_pointer)
985
10.0M
        {
986
1.23k
            case '\"':
987
2.81k
            case '\\':
988
10.8k
            case '\b':
989
25.5k
            case '\f':
990
95.9k
            case '\n':
991
100k
            case '\r':
992
194k
            case '\t':
993
                /* one character escape sequence */
994
194k
                escape_characters++;
995
194k
                break;
996
9.90M
            default:
997
9.90M
                if (*input_pointer < 32)
998
7.71M
                {
999
                    /* UTF-16 escape sequence uXXXX */
1000
7.71M
                    escape_characters += 5;
1001
7.71M
                }
1002
9.90M
                break;
1003
10.0M
        }
1004
10.0M
    }
1005
16.8k
    output_length = (size_t)(input_pointer - input) + escape_characters;
1006
1007
16.8k
    output = ensure(output_buffer, output_length + sizeof("\"\""));
1008
16.8k
    if (output == NULL)
1009
0
    {
1010
0
        return false;
1011
0
    }
1012
1013
    /* no characters have to be escaped */
1014
16.8k
    if (escape_characters == 0)
1015
14.9k
    {
1016
14.9k
        output[0] = '\"';
1017
14.9k
        memcpy(output + 1, input, output_length);
1018
14.9k
        output[output_length + 1] = '\"';
1019
14.9k
        output[output_length + 2] = '\0';
1020
1021
14.9k
        return true;
1022
14.9k
    }
1023
1024
1.92k
    output[0] = '\"';
1025
1.92k
    output_pointer = output + 1;
1026
    /* copy the string */
1027
10.0M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1028
10.0M
    {
1029
10.0M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1030
2.16M
        {
1031
            /* normal character, copy */
1032
2.16M
            *output_pointer = *input_pointer;
1033
2.16M
        }
1034
7.91M
        else
1035
7.91M
        {
1036
            /* character needs to be escaped */
1037
7.91M
            *output_pointer++ = '\\';
1038
7.91M
            switch (*input_pointer)
1039
7.91M
            {
1040
1.57k
                case '\\':
1041
1.57k
                    *output_pointer = '\\';
1042
1.57k
                    break;
1043
1.23k
                case '\"':
1044
1.23k
                    *output_pointer = '\"';
1045
1.23k
                    break;
1046
8.00k
                case '\b':
1047
8.00k
                    *output_pointer = 'b';
1048
8.00k
                    break;
1049
14.7k
                case '\f':
1050
14.7k
                    *output_pointer = 'f';
1051
14.7k
                    break;
1052
70.3k
                case '\n':
1053
70.3k
                    *output_pointer = 'n';
1054
70.3k
                    break;
1055
4.94k
                case '\r':
1056
4.94k
                    *output_pointer = 'r';
1057
4.94k
                    break;
1058
94.1k
                case '\t':
1059
94.1k
                    *output_pointer = 't';
1060
94.1k
                    break;
1061
7.71M
                default:
1062
                    /* escape and print as unicode codepoint */
1063
7.71M
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
1064
7.71M
                    output_pointer += 4;
1065
7.71M
                    break;
1066
7.91M
            }
1067
7.91M
        }
1068
10.0M
    }
1069
1.92k
    output[output_length + 1] = '\"';
1070
1.92k
    output[output_length + 2] = '\0';
1071
1072
1.92k
    return true;
1073
1.92k
}
1074
1075
/* Invoke print_string_ptr (which is useful) on an item. */
1076
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1077
2.44k
{
1078
2.44k
    return print_string_ptr((unsigned char*)item->valuestring, p);
1079
2.44k
}
1080
1081
/* Predeclare these prototypes. */
1082
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1083
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1084
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1085
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1086
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1087
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1088
1089
/* Utility to jump whitespace and cr/lf */
1090
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1091
2.22M
{
1092
2.22M
    if ((buffer == NULL) || (buffer->content == NULL))
1093
0
    {
1094
0
        return NULL;
1095
0
    }
1096
1097
2.22M
    if (cannot_access_at_index(buffer, 0))
1098
0
    {
1099
0
        return buffer;
1100
0
    }
1101
1102
3.31M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1103
1.08M
    {
1104
1.08M
       buffer->offset++;
1105
1.08M
    }
1106
1107
2.22M
    if (buffer->offset == buffer->length)
1108
976
    {
1109
976
        buffer->offset--;
1110
976
    }
1111
1112
2.22M
    return buffer;
1113
2.22M
}
1114
1115
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1116
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1117
2.04k
{
1118
2.04k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1119
0
    {
1120
0
        return NULL;
1121
0
    }
1122
1123
2.04k
    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1124
92
    {
1125
92
        buffer->offset += 3;
1126
92
    }
1127
1128
2.04k
    return buffer;
1129
2.04k
}
1130
1131
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1132
2.04k
{
1133
2.04k
    size_t buffer_length;
1134
1135
2.04k
    if (NULL == value)
1136
0
    {
1137
0
        return NULL;
1138
0
    }
1139
1140
    /* Adding null character size due to require_null_terminated. */
1141
2.04k
    buffer_length = strlen(value) + sizeof("");
1142
1143
2.04k
    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1144
2.04k
}
1145
1146
/* Parse an object - create a new root, and populate. */
1147
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1148
2.04k
{
1149
2.04k
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1150
2.04k
    cJSON *item = NULL;
1151
1152
    /* reset error position */
1153
2.04k
    global_error.json = NULL;
1154
2.04k
    global_error.position = 0;
1155
1156
2.04k
    if (value == NULL || 0 == buffer_length)
1157
0
    {
1158
0
        goto fail;
1159
0
    }
1160
1161
2.04k
    buffer.content = (const unsigned char*)value;
1162
2.04k
    buffer.length = buffer_length;
1163
2.04k
    buffer.offset = 0;
1164
2.04k
    buffer.hooks = global_hooks;
1165
1166
2.04k
    item = cJSON_New_Item(&global_hooks);
1167
2.04k
    if (item == NULL) /* memory fail */
1168
0
    {
1169
0
        goto fail;
1170
0
    }
1171
1172
2.04k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1173
879
    {
1174
        /* parse failure. ep is set. */
1175
879
        goto fail;
1176
879
    }
1177
1178
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1179
1.16k
    if (require_null_terminated)
1180
427
    {
1181
427
        buffer_skip_whitespace(&buffer);
1182
427
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1183
50
        {
1184
50
            goto fail;
1185
50
        }
1186
427
    }
1187
1.11k
    if (return_parse_end)
1188
0
    {
1189
0
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
1190
0
    }
1191
1192
1.11k
    return item;
1193
1194
929
fail:
1195
929
    if (item != NULL)
1196
929
    {
1197
929
        cJSON_Delete(item);
1198
929
    }
1199
1200
929
    if (value != NULL)
1201
929
    {
1202
929
        error local_error;
1203
929
        local_error.json = (const unsigned char*)value;
1204
929
        local_error.position = 0;
1205
1206
929
        if (buffer.offset < buffer.length)
1207
804
        {
1208
804
            local_error.position = buffer.offset;
1209
804
        }
1210
125
        else if (buffer.length > 0)
1211
125
        {
1212
125
            local_error.position = buffer.length - 1;
1213
125
        }
1214
1215
929
        if (return_parse_end != NULL)
1216
0
        {
1217
0
            *return_parse_end = (const char*)local_error.json + local_error.position;
1218
0
        }
1219
1220
929
        global_error = local_error;
1221
929
    }
1222
1223
929
    return NULL;
1224
1.16k
}
1225
1226
/* Default options for cJSON_Parse */
1227
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1228
0
{
1229
0
    return cJSON_ParseWithOpts(value, 0, 0);
1230
0
}
1231
1232
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1233
0
{
1234
0
    return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1235
0
}
1236
1237
0
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1238
1239
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1240
507
{
1241
507
    static const size_t default_buffer_size = 256;
1242
507
    printbuffer buffer[1];
1243
507
    unsigned char *printed = NULL;
1244
1245
507
    memset(buffer, 0, sizeof(buffer));
1246
1247
    /* create buffer */
1248
507
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1249
507
    buffer->length = default_buffer_size;
1250
507
    buffer->format = format;
1251
507
    buffer->hooks = *hooks;
1252
507
    if (buffer->buffer == NULL)
1253
0
    {
1254
0
        goto fail;
1255
0
    }
1256
1257
    /* print the value */
1258
507
    if (!print_value(item, buffer))
1259
0
    {
1260
0
        goto fail;
1261
0
    }
1262
507
    update_offset(buffer);
1263
1264
    /* check if reallocate is available */
1265
507
    if (hooks->reallocate != NULL)
1266
507
    {
1267
507
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1268
507
        if (printed == NULL) {
1269
0
            goto fail;
1270
0
        }
1271
507
        buffer->buffer = NULL;
1272
507
    }
1273
0
    else /* otherwise copy the JSON over to a new buffer */
1274
0
    {
1275
0
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1276
0
        if (printed == NULL)
1277
0
        {
1278
0
            goto fail;
1279
0
        }
1280
0
        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1281
0
        printed[buffer->offset] = '\0'; /* just to be sure */
1282
1283
        /* free the buffer */
1284
0
        hooks->deallocate(buffer->buffer);
1285
0
        buffer->buffer = NULL;
1286
0
    }
1287
1288
507
    return printed;
1289
1290
0
fail:
1291
0
    if (buffer->buffer != NULL)
1292
0
    {
1293
0
        hooks->deallocate(buffer->buffer);
1294
0
        buffer->buffer = NULL;
1295
0
    }
1296
1297
0
    if (printed != NULL)
1298
0
    {
1299
0
        hooks->deallocate(printed);
1300
0
        printed = NULL;
1301
0
    }
1302
1303
0
    return NULL;
1304
507
}
1305
1306
/* Render a cJSON item/entity/structure to text. */
1307
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1308
282
{
1309
282
    return (char*)print(item, true, &global_hooks);
1310
282
}
1311
1312
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1313
225
{
1314
225
    return (char*)print(item, false, &global_hooks);
1315
225
}
1316
1317
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1318
604
{
1319
604
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1320
1321
604
    if (prebuffer < 0)
1322
0
    {
1323
0
        return NULL;
1324
0
    }
1325
1326
604
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1327
604
    if (!p.buffer)
1328
0
    {
1329
0
        return NULL;
1330
0
    }
1331
1332
604
    p.length = (size_t)prebuffer;
1333
604
    p.offset = 0;
1334
604
    p.noalloc = false;
1335
604
    p.format = fmt;
1336
604
    p.hooks = global_hooks;
1337
1338
604
    if (!print_value(item, &p))
1339
0
    {
1340
0
        global_hooks.deallocate(p.buffer);
1341
0
        p.buffer = NULL;
1342
0
        return NULL;
1343
0
    }
1344
1345
604
    return (char*)p.buffer;
1346
604
}
1347
1348
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1349
0
{
1350
0
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1351
1352
0
    if ((length < 0) || (buffer == NULL))
1353
0
    {
1354
0
        return false;
1355
0
    }
1356
1357
0
    p.buffer = (unsigned char*)buffer;
1358
0
    p.length = (size_t)length;
1359
0
    p.offset = 0;
1360
0
    p.noalloc = true;
1361
0
    p.format = format;
1362
0
    p.hooks = global_hooks;
1363
1364
0
    return print_value(item, &p);
1365
0
}
1366
1367
/* Parser core - when encountering text, process appropriately. */
1368
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1369
754k
{
1370
754k
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
1371
0
    {
1372
0
        return false; /* no input */
1373
0
    }
1374
1375
    /* parse the different types of values */
1376
    /* null */
1377
754k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1378
568
    {
1379
568
        item->type = cJSON_NULL;
1380
568
        input_buffer->offset += 4;
1381
568
        return true;
1382
568
    }
1383
    /* false */
1384
753k
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1385
900
    {
1386
900
        item->type = cJSON_False;
1387
900
        input_buffer->offset += 5;
1388
900
        return true;
1389
900
    }
1390
    /* true */
1391
753k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1392
2.12k
    {
1393
2.12k
        item->type = cJSON_True;
1394
2.12k
        item->valueint = 1;
1395
2.12k
        input_buffer->offset += 4;
1396
2.12k
        return true;
1397
2.12k
    }
1398
    /* string */
1399
750k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1400
7.99k
    {
1401
7.99k
        return parse_string(item, input_buffer);
1402
7.99k
    }
1403
    /* number */
1404
742k
    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'))))
1405
31.0k
    {
1406
31.0k
        return parse_number(item, input_buffer);
1407
31.0k
    }
1408
    /* array */
1409
711k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1410
297k
    {
1411
297k
        return parse_array(item, input_buffer);
1412
297k
    }
1413
    /* object */
1414
414k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1415
413k
    {
1416
413k
        return parse_object(item, input_buffer);
1417
413k
    }
1418
1419
306
    return false;
1420
414k
}
1421
1422
/* Render a value to text. */
1423
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1424
663k
{
1425
663k
    unsigned char *output = NULL;
1426
1427
663k
    if ((item == NULL) || (output_buffer == NULL))
1428
0
    {
1429
0
        return false;
1430
0
    }
1431
1432
663k
    switch ((item->type) & 0xFF)
1433
663k
    {
1434
353
        case cJSON_NULL:
1435
353
            output = ensure(output_buffer, 5);
1436
353
            if (output == NULL)
1437
0
            {
1438
0
                return false;
1439
0
            }
1440
353
            strcpy((char*)output, "null");
1441
353
            return true;
1442
1443
663
        case cJSON_False:
1444
663
            output = ensure(output_buffer, 6);
1445
663
            if (output == NULL)
1446
0
            {
1447
0
                return false;
1448
0
            }
1449
663
            strcpy((char*)output, "false");
1450
663
            return true;
1451
1452
1.70k
        case cJSON_True:
1453
1.70k
            output = ensure(output_buffer, 5);
1454
1.70k
            if (output == NULL)
1455
0
            {
1456
0
                return false;
1457
0
            }
1458
1.70k
            strcpy((char*)output, "true");
1459
1.70k
            return true;
1460
1461
15.0k
        case cJSON_Number:
1462
15.0k
            return print_number(item, output_buffer);
1463
1464
0
        case cJSON_Raw:
1465
0
        {
1466
0
            size_t raw_length = 0;
1467
0
            if (item->valuestring == NULL)
1468
0
            {
1469
0
                return false;
1470
0
            }
1471
1472
0
            raw_length = strlen(item->valuestring) + sizeof("");
1473
0
            output = ensure(output_buffer, raw_length);
1474
0
            if (output == NULL)
1475
0
            {
1476
0
                return false;
1477
0
            }
1478
0
            memcpy(output, item->valuestring, raw_length);
1479
0
            return true;
1480
0
        }
1481
1482
2.44k
        case cJSON_String:
1483
2.44k
            return print_string(item, output_buffer);
1484
1485
239k
        case cJSON_Array:
1486
239k
            return print_array(item, output_buffer);
1487
1488
403k
        case cJSON_Object:
1489
403k
            return print_object(item, output_buffer);
1490
1491
0
        default:
1492
0
            return false;
1493
663k
    }
1494
663k
}
1495
1496
/* Build an array from input text. */
1497
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1498
297k
{
1499
297k
    cJSON *head = NULL; /* head of the linked list */
1500
297k
    cJSON *current_item = NULL;
1501
1502
297k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1503
3
    {
1504
3
        return false; /* to deeply nested */
1505
3
    }
1506
297k
    input_buffer->depth++;
1507
1508
297k
    if (buffer_at_offset(input_buffer)[0] != '[')
1509
0
    {
1510
        /* not an array */
1511
0
        goto fail;
1512
0
    }
1513
1514
297k
    input_buffer->offset++;
1515
297k
    buffer_skip_whitespace(input_buffer);
1516
297k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1517
3.50k
    {
1518
        /* empty array */
1519
3.50k
        goto success;
1520
3.50k
    }
1521
1522
    /* check if we skipped to the end of the buffer */
1523
294k
    if (cannot_access_at_index(input_buffer, 0))
1524
0
    {
1525
0
        input_buffer->offset--;
1526
0
        goto fail;
1527
0
    }
1528
1529
    /* step back to character in front of the first element */
1530
294k
    input_buffer->offset--;
1531
    /* loop through the comma separated array elements */
1532
294k
    do
1533
720k
    {
1534
        /* allocate next item */
1535
720k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1536
720k
        if (new_item == NULL)
1537
0
        {
1538
0
            goto fail; /* allocation failure */
1539
0
        }
1540
1541
        /* attach next item to list */
1542
720k
        if (head == NULL)
1543
294k
        {
1544
            /* start the linked list */
1545
294k
            current_item = head = new_item;
1546
294k
        }
1547
426k
        else
1548
426k
        {
1549
            /* add to the end and advance */
1550
426k
            current_item->next = new_item;
1551
426k
            new_item->prev = current_item;
1552
426k
            current_item = new_item;
1553
426k
        }
1554
1555
        /* parse next value */
1556
720k
        input_buffer->offset++;
1557
720k
        buffer_skip_whitespace(input_buffer);
1558
720k
        if (!parse_value(current_item, input_buffer))
1559
50.7k
        {
1560
50.7k
            goto fail; /* failed to parse value */
1561
50.7k
        }
1562
669k
        buffer_skip_whitespace(input_buffer);
1563
669k
    }
1564
669k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1565
1566
243k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1567
119
    {
1568
119
        goto fail; /* expected end of array */
1569
119
    }
1570
1571
246k
success:
1572
246k
    input_buffer->depth--;
1573
1574
246k
    if (head != NULL) {
1575
243k
        head->prev = current_item;
1576
243k
    }
1577
1578
246k
    item->type = cJSON_Array;
1579
246k
    item->child = head;
1580
1581
246k
    input_buffer->offset++;
1582
1583
246k
    return true;
1584
1585
50.8k
fail:
1586
50.8k
    if (head != NULL)
1587
50.8k
    {
1588
50.8k
        cJSON_Delete(head);
1589
50.8k
    }
1590
1591
50.8k
    return false;
1592
243k
}
1593
1594
/* Render an array to text */
1595
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1596
239k
{
1597
239k
    unsigned char *output_pointer = NULL;
1598
239k
    size_t length = 0;
1599
239k
    cJSON *current_element = item->child;
1600
1601
239k
    if (output_buffer == NULL)
1602
0
    {
1603
0
        return false;
1604
0
    }
1605
1606
239k
    if (output_buffer->depth >= CJSON_NESTING_LIMIT)
1607
0
    {
1608
0
        return false; /* nesting is too deep */
1609
0
    }
1610
1611
    /* Compose the output array. */
1612
    /* opening square bracket */
1613
239k
    output_pointer = ensure(output_buffer, 1);
1614
239k
    if (output_pointer == NULL)
1615
0
    {
1616
0
        return false;
1617
0
    }
1618
1619
239k
    *output_pointer = '[';
1620
239k
    output_buffer->offset++;
1621
239k
    output_buffer->depth++;
1622
1623
886k
    while (current_element != NULL)
1624
647k
    {
1625
647k
        if (!print_value(current_element, output_buffer))
1626
0
        {
1627
0
            return false;
1628
0
        }
1629
647k
        update_offset(output_buffer);
1630
647k
        if (current_element->next)
1631
411k
        {
1632
411k
            length = (size_t) (output_buffer->format ? 2 : 1);
1633
411k
            output_pointer = ensure(output_buffer, length + 1);
1634
411k
            if (output_pointer == NULL)
1635
0
            {
1636
0
                return false;
1637
0
            }
1638
411k
            *output_pointer++ = ',';
1639
411k
            if(output_buffer->format)
1640
401k
            {
1641
401k
                *output_pointer++ = ' ';
1642
401k
            }
1643
411k
            *output_pointer = '\0';
1644
411k
            output_buffer->offset += length;
1645
411k
        }
1646
647k
        current_element = current_element->next;
1647
647k
    }
1648
1649
239k
    output_pointer = ensure(output_buffer, 2);
1650
239k
    if (output_pointer == NULL)
1651
0
    {
1652
0
        return false;
1653
0
    }
1654
239k
    *output_pointer++ = ']';
1655
239k
    *output_pointer = '\0';
1656
239k
    output_buffer->depth--;
1657
1658
239k
    return true;
1659
239k
}
1660
1661
/* Build an object from the text. */
1662
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1663
413k
{
1664
413k
    cJSON *head = NULL; /* linked list head */
1665
413k
    cJSON *current_item = NULL;
1666
1667
413k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1668
1
    {
1669
1
        return false; /* to deeply nested */
1670
1
    }
1671
413k
    input_buffer->depth++;
1672
1673
413k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1674
0
    {
1675
0
        goto fail; /* not an object */
1676
0
    }
1677
1678
413k
    input_buffer->offset++;
1679
413k
    buffer_skip_whitespace(input_buffer);
1680
413k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1681
400k
    {
1682
400k
        goto success; /* empty object */
1683
400k
    }
1684
1685
    /* check if we skipped to the end of the buffer */
1686
13.5k
    if (cannot_access_at_index(input_buffer, 0))
1687
0
    {
1688
0
        input_buffer->offset--;
1689
0
        goto fail;
1690
0
    }
1691
1692
    /* step back to character in front of the first element */
1693
13.5k
    input_buffer->offset--;
1694
    /* loop through the comma separated array elements */
1695
13.5k
    do
1696
32.0k
    {
1697
        /* allocate next item */
1698
32.0k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1699
32.0k
        if (new_item == NULL)
1700
0
        {
1701
0
            goto fail; /* allocation failure */
1702
0
        }
1703
1704
        /* attach next item to list */
1705
32.0k
        if (head == NULL)
1706
13.5k
        {
1707
            /* start the linked list */
1708
13.5k
            current_item = head = new_item;
1709
13.5k
        }
1710
18.4k
        else
1711
18.4k
        {
1712
            /* add to the end and advance */
1713
18.4k
            current_item->next = new_item;
1714
18.4k
            new_item->prev = current_item;
1715
18.4k
            current_item = new_item;
1716
18.4k
        }
1717
1718
32.0k
        if (cannot_access_at_index(input_buffer, 1))
1719
0
        {
1720
0
            goto fail; /* nothing comes after the comma */
1721
0
        }
1722
1723
        /* parse the name of the child */
1724
32.0k
        input_buffer->offset++;
1725
32.0k
        buffer_skip_whitespace(input_buffer);
1726
32.0k
        if (!parse_string(current_item, input_buffer))
1727
160
        {
1728
160
            goto fail; /* failed to parse name */
1729
160
        }
1730
31.8k
        buffer_skip_whitespace(input_buffer);
1731
1732
        /* swap valuestring and string, because we parsed the name */
1733
31.8k
        current_item->string = current_item->valuestring;
1734
31.8k
        current_item->valuestring = NULL;
1735
1736
31.8k
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1737
38
        {
1738
38
            goto fail; /* invalid object */
1739
38
        }
1740
1741
        /* parse the value */
1742
31.8k
        input_buffer->offset++;
1743
31.8k
        buffer_skip_whitespace(input_buffer);
1744
31.8k
        if (!parse_value(current_item, input_buffer))
1745
2.59k
        {
1746
2.59k
            goto fail; /* failed to parse value */
1747
2.59k
        }
1748
29.2k
        buffer_skip_whitespace(input_buffer);
1749
29.2k
    }
1750
29.2k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1751
1752
10.8k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1753
42
    {
1754
42
        goto fail; /* expected end of object */
1755
42
    }
1756
1757
410k
success:
1758
410k
    input_buffer->depth--;
1759
1760
410k
    if (head != NULL) {
1761
10.7k
        head->prev = current_item;
1762
10.7k
    }
1763
1764
410k
    item->type = cJSON_Object;
1765
410k
    item->child = head;
1766
1767
410k
    input_buffer->offset++;
1768
410k
    return true;
1769
1770
2.83k
fail:
1771
2.83k
    if (head != NULL)
1772
2.83k
    {
1773
2.83k
        cJSON_Delete(head);
1774
2.83k
    }
1775
1776
2.83k
    return false;
1777
10.8k
}
1778
1779
/* Render an object to text. */
1780
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1781
403k
{
1782
403k
    unsigned char *output_pointer = NULL;
1783
403k
    size_t length = 0;
1784
403k
    cJSON *current_item = item->child;
1785
1786
403k
    if (output_buffer == NULL)
1787
0
    {
1788
0
        return false;
1789
0
    }
1790
1791
403k
    if (output_buffer->depth >= CJSON_NESTING_LIMIT)
1792
0
    {
1793
0
        return false; /* nesting is too deep */
1794
0
    }
1795
1796
    /* Compose the output: */
1797
403k
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1798
403k
    output_pointer = ensure(output_buffer, length + 1);
1799
403k
    if (output_pointer == NULL)
1800
0
    {
1801
0
        return false;
1802
0
    }
1803
1804
403k
    *output_pointer++ = '{';
1805
403k
    output_buffer->depth++;
1806
403k
    if (output_buffer->format)
1807
402k
    {
1808
402k
        *output_pointer++ = '\n';
1809
402k
    }
1810
403k
    output_buffer->offset += length;
1811
1812
418k
    while (current_item)
1813
14.4k
    {
1814
14.4k
        if (output_buffer->format)
1815
10.7k
        {
1816
10.7k
            size_t i;
1817
10.7k
            output_pointer = ensure(output_buffer, output_buffer->depth);
1818
10.7k
            if (output_pointer == NULL)
1819
0
            {
1820
0
                return false;
1821
0
            }
1822
4.18M
            for (i = 0; i < output_buffer->depth; i++)
1823
4.17M
            {
1824
4.17M
                *output_pointer++ = '\t';
1825
4.17M
            }
1826
10.7k
            output_buffer->offset += output_buffer->depth;
1827
10.7k
        }
1828
1829
        /* print key */
1830
14.4k
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1831
0
        {
1832
0
            return false;
1833
0
        }
1834
14.4k
        update_offset(output_buffer);
1835
1836
14.4k
        length = (size_t) (output_buffer->format ? 2 : 1);
1837
14.4k
        output_pointer = ensure(output_buffer, length);
1838
14.4k
        if (output_pointer == NULL)
1839
0
        {
1840
0
            return false;
1841
0
        }
1842
14.4k
        *output_pointer++ = ':';
1843
14.4k
        if (output_buffer->format)
1844
10.7k
        {
1845
10.7k
            *output_pointer++ = '\t';
1846
10.7k
        }
1847
14.4k
        output_buffer->offset += length;
1848
1849
        /* print value */
1850
14.4k
        if (!print_value(current_item, output_buffer))
1851
0
        {
1852
0
            return false;
1853
0
        }
1854
14.4k
        update_offset(output_buffer);
1855
1856
        /* print comma if not last */
1857
14.4k
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1858
14.4k
        output_pointer = ensure(output_buffer, length + 1);
1859
14.4k
        if (output_pointer == NULL)
1860
0
        {
1861
0
            return false;
1862
0
        }
1863
14.4k
        if (current_item->next)
1864
5.65k
        {
1865
5.65k
            *output_pointer++ = ',';
1866
5.65k
        }
1867
1868
14.4k
        if (output_buffer->format)
1869
10.7k
        {
1870
10.7k
            *output_pointer++ = '\n';
1871
10.7k
        }
1872
14.4k
        *output_pointer = '\0';
1873
14.4k
        output_buffer->offset += length;
1874
1875
14.4k
        current_item = current_item->next;
1876
14.4k
    }
1877
1878
403k
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1879
403k
    if (output_pointer == NULL)
1880
0
    {
1881
0
        return false;
1882
0
    }
1883
403k
    if (output_buffer->format)
1884
402k
    {
1885
402k
        size_t i;
1886
219M
        for (i = 0; i < (output_buffer->depth - 1); i++)
1887
219M
        {
1888
219M
            *output_pointer++ = '\t';
1889
219M
        }
1890
402k
    }
1891
403k
    *output_pointer++ = '}';
1892
403k
    *output_pointer = '\0';
1893
403k
    output_buffer->depth--;
1894
1895
403k
    return true;
1896
403k
}
1897
1898
/* Get Array size/item / object item. */
1899
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1900
0
{
1901
0
    cJSON *child = NULL;
1902
0
    size_t size = 0;
1903
1904
0
    if (array == NULL)
1905
0
    {
1906
0
        return 0;
1907
0
    }
1908
1909
0
    child = array->child;
1910
1911
0
    while(child != NULL)
1912
0
    {
1913
0
        size++;
1914
0
        child = child->next;
1915
0
    }
1916
1917
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1918
1919
0
    return (int)size;
1920
0
}
1921
1922
static cJSON* get_array_item(const cJSON *array, size_t index)
1923
0
{
1924
0
    cJSON *current_child = NULL;
1925
1926
0
    if (array == NULL)
1927
0
    {
1928
0
        return NULL;
1929
0
    }
1930
1931
0
    current_child = array->child;
1932
0
    while ((current_child != NULL) && (index > 0))
1933
0
    {
1934
0
        index--;
1935
0
        current_child = current_child->next;
1936
0
    }
1937
1938
0
    return current_child;
1939
0
}
1940
1941
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1942
0
{
1943
0
    if (index < 0)
1944
0
    {
1945
0
        return NULL;
1946
0
    }
1947
1948
0
    return get_array_item(array, (size_t)index);
1949
0
}
1950
1951
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1952
0
{
1953
0
    cJSON *current_element = NULL;
1954
1955
0
    if ((object == NULL) || (name == NULL))
1956
0
    {
1957
0
        return NULL;
1958
0
    }
1959
1960
0
    current_element = object->child;
1961
0
    if (case_sensitive)
1962
0
    {
1963
0
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1964
0
        {
1965
0
            current_element = current_element->next;
1966
0
        }
1967
0
    }
1968
0
    else
1969
0
    {
1970
0
        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1971
0
        {
1972
0
            current_element = current_element->next;
1973
0
        }
1974
0
    }
1975
1976
0
    if ((current_element == NULL) || (current_element->string == NULL)) {
1977
0
        return NULL;
1978
0
    }
1979
1980
0
    return current_element;
1981
0
}
1982
1983
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1984
0
{
1985
0
    return get_object_item(object, string, false);
1986
0
}
1987
1988
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1989
0
{
1990
0
    return get_object_item(object, string, true);
1991
0
}
1992
1993
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1994
0
{
1995
0
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
1996
0
}
1997
1998
/* Utility for array list handling. */
1999
static void suffix_object(cJSON *prev, cJSON *item)
2000
0
{
2001
0
    prev->next = item;
2002
0
    item->prev = prev;
2003
0
}
2004
2005
/* Utility for handling references. */
2006
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
2007
0
{
2008
0
    cJSON *reference = NULL;
2009
0
    if (item == NULL)
2010
0
    {
2011
0
        return NULL;
2012
0
    }
2013
2014
0
    reference = cJSON_New_Item(hooks);
2015
0
    if (reference == NULL)
2016
0
    {
2017
0
        return NULL;
2018
0
    }
2019
2020
0
    memcpy(reference, item, sizeof(cJSON));
2021
0
    reference->string = NULL;
2022
0
    reference->type |= cJSON_IsReference;
2023
0
    reference->next = reference->prev = NULL;
2024
0
    return reference;
2025
0
}
2026
2027
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2028
0
{
2029
0
    cJSON *child = NULL;
2030
2031
0
    if ((item == NULL) || (array == NULL) || (array == item))
2032
0
    {
2033
0
        return false;
2034
0
    }
2035
2036
0
    child = array->child;
2037
    /*
2038
     * To find the last item in array quickly, we use prev in array
2039
     */
2040
0
    if (child == NULL)
2041
0
    {
2042
        /* list is empty, start new one */
2043
0
        array->child = item;
2044
0
        item->prev = item;
2045
0
        item->next = NULL;
2046
0
    }
2047
0
    else
2048
0
    {
2049
        /* append to the end */
2050
0
        if (child->prev)
2051
0
        {
2052
0
            suffix_object(child->prev, item);
2053
0
            array->child->prev = item;
2054
0
        }
2055
0
    }
2056
2057
0
    return true;
2058
0
}
2059
2060
/* Add item to array/object. */
2061
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2062
0
{
2063
0
    return add_item_to_array(array, item);
2064
0
}
2065
2066
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2067
    #pragma GCC diagnostic push
2068
#endif
2069
#ifdef __GNUC__
2070
#pragma GCC diagnostic ignored "-Wcast-qual"
2071
#endif
2072
/* helper function to cast away const */
2073
static void* cast_away_const(const void* string)
2074
0
{
2075
0
    return (void*)string;
2076
0
}
2077
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2078
    #pragma GCC diagnostic pop
2079
#endif
2080
2081
2082
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2083
0
{
2084
0
    char *new_key = NULL;
2085
0
    int new_type = cJSON_Invalid;
2086
2087
0
    if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2088
0
    {
2089
0
        return false;
2090
0
    }
2091
2092
0
    if (constant_key)
2093
0
    {
2094
0
        new_key = (char*)cast_away_const(string);
2095
0
        new_type = item->type | cJSON_StringIsConst;
2096
0
    }
2097
0
    else
2098
0
    {
2099
0
        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2100
0
        if (new_key == NULL)
2101
0
        {
2102
0
            return false;
2103
0
        }
2104
2105
0
        new_type = item->type & ~cJSON_StringIsConst;
2106
0
    }
2107
2108
0
    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2109
0
    {
2110
0
        hooks->deallocate(item->string);
2111
0
    }
2112
2113
0
    item->string = new_key;
2114
0
    item->type = new_type;
2115
2116
0
    return add_item_to_array(object, item);
2117
0
}
2118
2119
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2120
0
{
2121
0
    return add_item_to_object(object, string, item, &global_hooks, false);
2122
0
}
2123
2124
/* Add an item to an object with constant string as key */
2125
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2126
0
{
2127
0
    return add_item_to_object(object, string, item, &global_hooks, true);
2128
0
}
2129
2130
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2131
0
{
2132
0
    if (array == NULL)
2133
0
    {
2134
0
        return false;
2135
0
    }
2136
2137
0
    return add_item_to_array(array, create_reference(item, &global_hooks));
2138
0
}
2139
2140
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2141
0
{
2142
0
    if ((object == NULL) || (string == NULL))
2143
0
    {
2144
0
        return false;
2145
0
    }
2146
2147
0
    return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2148
0
}
2149
2150
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2151
0
{
2152
0
    cJSON *null = cJSON_CreateNull();
2153
0
    if (add_item_to_object(object, name, null, &global_hooks, false))
2154
0
    {
2155
0
        return null;
2156
0
    }
2157
2158
0
    cJSON_Delete(null);
2159
0
    return NULL;
2160
0
}
2161
2162
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2163
0
{
2164
0
    cJSON *true_item = cJSON_CreateTrue();
2165
0
    if (add_item_to_object(object, name, true_item, &global_hooks, false))
2166
0
    {
2167
0
        return true_item;
2168
0
    }
2169
2170
0
    cJSON_Delete(true_item);
2171
0
    return NULL;
2172
0
}
2173
2174
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2175
0
{
2176
0
    cJSON *false_item = cJSON_CreateFalse();
2177
0
    if (add_item_to_object(object, name, false_item, &global_hooks, false))
2178
0
    {
2179
0
        return false_item;
2180
0
    }
2181
2182
0
    cJSON_Delete(false_item);
2183
0
    return NULL;
2184
0
}
2185
2186
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2187
0
{
2188
0
    cJSON *bool_item = cJSON_CreateBool(boolean);
2189
0
    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2190
0
    {
2191
0
        return bool_item;
2192
0
    }
2193
2194
0
    cJSON_Delete(bool_item);
2195
0
    return NULL;
2196
0
}
2197
2198
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2199
0
{
2200
0
    cJSON *number_item = cJSON_CreateNumber(number);
2201
0
    if (add_item_to_object(object, name, number_item, &global_hooks, false))
2202
0
    {
2203
0
        return number_item;
2204
0
    }
2205
2206
0
    cJSON_Delete(number_item);
2207
0
    return NULL;
2208
0
}
2209
2210
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2211
0
{
2212
0
    cJSON *string_item = cJSON_CreateString(string);
2213
0
    if (add_item_to_object(object, name, string_item, &global_hooks, false))
2214
0
    {
2215
0
        return string_item;
2216
0
    }
2217
2218
0
    cJSON_Delete(string_item);
2219
0
    return NULL;
2220
0
}
2221
2222
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2223
0
{
2224
0
    cJSON *raw_item = cJSON_CreateRaw(raw);
2225
0
    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2226
0
    {
2227
0
        return raw_item;
2228
0
    }
2229
2230
0
    cJSON_Delete(raw_item);
2231
0
    return NULL;
2232
0
}
2233
2234
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2235
0
{
2236
0
    cJSON *object_item = cJSON_CreateObject();
2237
0
    if (add_item_to_object(object, name, object_item, &global_hooks, false))
2238
0
    {
2239
0
        return object_item;
2240
0
    }
2241
2242
0
    cJSON_Delete(object_item);
2243
0
    return NULL;
2244
0
}
2245
2246
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2247
0
{
2248
0
    cJSON *array = cJSON_CreateArray();
2249
0
    if (add_item_to_object(object, name, array, &global_hooks, false))
2250
0
    {
2251
0
        return array;
2252
0
    }
2253
2254
0
    cJSON_Delete(array);
2255
0
    return NULL;
2256
0
}
2257
2258
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2259
0
{
2260
0
    if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
2261
0
    {
2262
0
        return NULL;
2263
0
    }
2264
2265
0
    if (item != parent->child)
2266
0
    {
2267
        /* not the first element */
2268
0
        item->prev->next = item->next;
2269
0
    }
2270
0
    if (item->next != NULL)
2271
0
    {
2272
        /* not the last element */
2273
0
        item->next->prev = item->prev;
2274
0
    }
2275
2276
0
    if (item == parent->child)
2277
0
    {
2278
        /* first element */
2279
0
        parent->child = item->next;
2280
0
    }
2281
0
    else if (item->next == NULL)
2282
0
    {
2283
        /* last element */
2284
0
        parent->child->prev = item->prev;
2285
0
    }
2286
2287
    /* make sure the detached item doesn't point anywhere anymore */
2288
0
    item->prev = NULL;
2289
0
    item->next = NULL;
2290
2291
0
    return item;
2292
0
}
2293
2294
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2295
0
{
2296
0
    if (which < 0)
2297
0
    {
2298
0
        return NULL;
2299
0
    }
2300
2301
0
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2302
0
}
2303
2304
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2305
0
{
2306
0
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2307
0
}
2308
2309
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2310
0
{
2311
0
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
2312
2313
0
    return cJSON_DetachItemViaPointer(object, to_detach);
2314
0
}
2315
2316
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2317
0
{
2318
0
    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2319
2320
0
    return cJSON_DetachItemViaPointer(object, to_detach);
2321
0
}
2322
2323
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2324
0
{
2325
0
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2326
0
}
2327
2328
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2329
0
{
2330
0
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2331
0
}
2332
2333
/* Replace array/object items with new ones. */
2334
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2335
0
{
2336
0
    cJSON *after_inserted = NULL;
2337
2338
0
    if (which < 0 || newitem == NULL)
2339
0
    {
2340
0
        return false;
2341
0
    }
2342
2343
0
    after_inserted = get_array_item(array, (size_t)which);
2344
0
    if (after_inserted == NULL)
2345
0
    {
2346
0
        return add_item_to_array(array, newitem);
2347
0
    }
2348
2349
0
    if (after_inserted != array->child && after_inserted->prev == NULL) {
2350
        /* return false if after_inserted is a corrupted array item */
2351
0
        return false;
2352
0
    }
2353
2354
0
    newitem->next = after_inserted;
2355
0
    newitem->prev = after_inserted->prev;
2356
0
    after_inserted->prev = newitem;
2357
0
    if (after_inserted == array->child)
2358
0
    {
2359
0
        array->child = newitem;
2360
0
    }
2361
0
    else
2362
0
    {
2363
0
        newitem->prev->next = newitem;
2364
0
    }
2365
0
    return true;
2366
0
}
2367
2368
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2369
0
{
2370
0
    if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2371
0
    {
2372
0
        return false;
2373
0
    }
2374
2375
0
    if (replacement == item)
2376
0
    {
2377
0
        return true;
2378
0
    }
2379
2380
0
    replacement->next = item->next;
2381
0
    replacement->prev = item->prev;
2382
2383
0
    if (replacement->next != NULL)
2384
0
    {
2385
0
        replacement->next->prev = replacement;
2386
0
    }
2387
0
    if (parent->child == item)
2388
0
    {
2389
0
        if (parent->child->prev == parent->child)
2390
0
        {
2391
0
            replacement->prev = replacement;
2392
0
        }
2393
0
        parent->child = replacement;
2394
0
    }
2395
0
    else
2396
0
    {   /*
2397
         * To find the last item in array quickly, we use prev in array.
2398
         * We can't modify the last item's next pointer where this item was the parent's child
2399
         */
2400
0
        if (replacement->prev != NULL)
2401
0
        {
2402
0
            replacement->prev->next = replacement;
2403
0
        }
2404
0
        if (replacement->next == NULL)
2405
0
        {
2406
0
            parent->child->prev = replacement;
2407
0
        }
2408
0
    }
2409
2410
0
    item->next = NULL;
2411
0
    item->prev = NULL;
2412
0
    cJSON_Delete(item);
2413
2414
0
    return true;
2415
0
}
2416
2417
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2418
0
{
2419
0
    if (which < 0)
2420
0
    {
2421
0
        return false;
2422
0
    }
2423
2424
0
    return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2425
0
}
2426
2427
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2428
0
{
2429
0
    if ((replacement == NULL) || (string == NULL))
2430
0
    {
2431
0
        return false;
2432
0
    }
2433
2434
    /* replace the name in the replacement */
2435
0
    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2436
0
    {
2437
0
        cJSON_free(replacement->string);
2438
0
    }
2439
0
    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2440
0
    if (replacement->string == NULL)
2441
0
    {
2442
0
        return false;
2443
0
    }
2444
2445
0
    replacement->type &= ~cJSON_StringIsConst;
2446
2447
0
    return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2448
0
}
2449
2450
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2451
0
{
2452
0
    return replace_item_in_object(object, string, newitem, false);
2453
0
}
2454
2455
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2456
0
{
2457
0
    return replace_item_in_object(object, string, newitem, true);
2458
0
}
2459
2460
/* Create basic types: */
2461
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2462
0
{
2463
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2464
0
    if(item)
2465
0
    {
2466
0
        item->type = cJSON_NULL;
2467
0
    }
2468
2469
0
    return item;
2470
0
}
2471
2472
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2473
0
{
2474
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2475
0
    if(item)
2476
0
    {
2477
0
        item->type = cJSON_True;
2478
0
    }
2479
2480
0
    return item;
2481
0
}
2482
2483
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2484
0
{
2485
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2486
0
    if(item)
2487
0
    {
2488
0
        item->type = cJSON_False;
2489
0
    }
2490
2491
0
    return item;
2492
0
}
2493
2494
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2495
0
{
2496
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2497
0
    if(item)
2498
0
    {
2499
0
        item->type = boolean ? cJSON_True : cJSON_False;
2500
0
    }
2501
2502
0
    return item;
2503
0
}
2504
2505
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2506
0
{
2507
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2508
0
    if(item)
2509
0
    {
2510
0
        item->type = cJSON_Number;
2511
0
        item->valuedouble = num;
2512
2513
        /* use saturation in case of overflow */
2514
0
        if (num >= INT_MAX)
2515
0
        {
2516
0
            item->valueint = INT_MAX;
2517
0
        }
2518
0
        else if (num <= (double)INT_MIN)
2519
0
        {
2520
0
            item->valueint = INT_MIN;
2521
0
        }
2522
0
        else
2523
0
        {
2524
0
            item->valueint = (int)num;
2525
0
        }
2526
0
    }
2527
2528
0
    return item;
2529
0
}
2530
2531
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2532
0
{
2533
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2534
0
    if(item)
2535
0
    {
2536
0
        item->type = cJSON_String;
2537
0
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2538
0
        if(!item->valuestring)
2539
0
        {
2540
0
            cJSON_Delete(item);
2541
0
            return NULL;
2542
0
        }
2543
0
    }
2544
2545
0
    return item;
2546
0
}
2547
2548
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2549
0
{
2550
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2551
0
    if (item != NULL)
2552
0
    {
2553
0
        item->type = cJSON_String | cJSON_IsReference;
2554
0
        item->valuestring = (char*)cast_away_const(string);
2555
0
    }
2556
2557
0
    return item;
2558
0
}
2559
2560
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2561
0
{
2562
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2563
0
    if (item != NULL) {
2564
0
        item->type = cJSON_Object | cJSON_IsReference;
2565
0
        item->child = (cJSON*)cast_away_const(child);
2566
0
    }
2567
2568
0
    return item;
2569
0
}
2570
2571
0
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2572
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2573
0
    if (item != NULL) {
2574
0
        item->type = cJSON_Array | cJSON_IsReference;
2575
0
        item->child = (cJSON*)cast_away_const(child);
2576
0
    }
2577
2578
0
    return item;
2579
0
}
2580
2581
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2582
0
{
2583
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2584
0
    if(item)
2585
0
    {
2586
0
        item->type = cJSON_Raw;
2587
0
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2588
0
        if(!item->valuestring)
2589
0
        {
2590
0
            cJSON_Delete(item);
2591
0
            return NULL;
2592
0
        }
2593
0
    }
2594
2595
0
    return item;
2596
0
}
2597
2598
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2599
0
{
2600
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2601
0
    if(item)
2602
0
    {
2603
0
        item->type=cJSON_Array;
2604
0
    }
2605
2606
0
    return item;
2607
0
}
2608
2609
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2610
0
{
2611
0
    cJSON *item = cJSON_New_Item(&global_hooks);
2612
0
    if (item)
2613
0
    {
2614
0
        item->type = cJSON_Object;
2615
0
    }
2616
2617
0
    return item;
2618
0
}
2619
2620
/* Create Arrays: */
2621
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2622
0
{
2623
0
    size_t i = 0;
2624
0
    cJSON *n = NULL;
2625
0
    cJSON *p = NULL;
2626
0
    cJSON *a = NULL;
2627
2628
0
    if ((count < 0) || (numbers == NULL))
2629
0
    {
2630
0
        return NULL;
2631
0
    }
2632
2633
0
    a = cJSON_CreateArray();
2634
2635
0
    for(i = 0; a && (i < (size_t)count); i++)
2636
0
    {
2637
0
        n = cJSON_CreateNumber(numbers[i]);
2638
0
        if (!n)
2639
0
        {
2640
0
            cJSON_Delete(a);
2641
0
            return NULL;
2642
0
        }
2643
0
        if(!i)
2644
0
        {
2645
0
            a->child = n;
2646
0
        }
2647
0
        else
2648
0
        {
2649
0
            suffix_object(p, n);
2650
0
        }
2651
0
        p = n;
2652
0
    }
2653
2654
0
    if (a && a->child) {
2655
0
        a->child->prev = n;
2656
0
    }
2657
2658
0
    return a;
2659
0
}
2660
2661
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2662
0
{
2663
0
    size_t i = 0;
2664
0
    cJSON *n = NULL;
2665
0
    cJSON *p = NULL;
2666
0
    cJSON *a = NULL;
2667
2668
0
    if ((count < 0) || (numbers == NULL))
2669
0
    {
2670
0
        return NULL;
2671
0
    }
2672
2673
0
    a = cJSON_CreateArray();
2674
2675
0
    for(i = 0; a && (i < (size_t)count); i++)
2676
0
    {
2677
0
        n = cJSON_CreateNumber((double)numbers[i]);
2678
0
        if(!n)
2679
0
        {
2680
0
            cJSON_Delete(a);
2681
0
            return NULL;
2682
0
        }
2683
0
        if(!i)
2684
0
        {
2685
0
            a->child = n;
2686
0
        }
2687
0
        else
2688
0
        {
2689
0
            suffix_object(p, n);
2690
0
        }
2691
0
        p = n;
2692
0
    }
2693
2694
0
    if (a && a->child) {
2695
0
        a->child->prev = n;
2696
0
    }
2697
2698
0
    return a;
2699
0
}
2700
2701
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2702
0
{
2703
0
    size_t i = 0;
2704
0
    cJSON *n = NULL;
2705
0
    cJSON *p = NULL;
2706
0
    cJSON *a = NULL;
2707
2708
0
    if ((count < 0) || (numbers == NULL))
2709
0
    {
2710
0
        return NULL;
2711
0
    }
2712
2713
0
    a = cJSON_CreateArray();
2714
2715
0
    for(i = 0; a && (i < (size_t)count); i++)
2716
0
    {
2717
0
        n = cJSON_CreateNumber(numbers[i]);
2718
0
        if(!n)
2719
0
        {
2720
0
            cJSON_Delete(a);
2721
0
            return NULL;
2722
0
        }
2723
0
        if(!i)
2724
0
        {
2725
0
            a->child = n;
2726
0
        }
2727
0
        else
2728
0
        {
2729
0
            suffix_object(p, n);
2730
0
        }
2731
0
        p = n;
2732
0
    }
2733
2734
0
    if (a && a->child) {
2735
0
        a->child->prev = n;
2736
0
    }
2737
2738
0
    return a;
2739
0
}
2740
2741
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2742
0
{
2743
0
    size_t i = 0;
2744
0
    cJSON *n = NULL;
2745
0
    cJSON *p = NULL;
2746
0
    cJSON *a = NULL;
2747
2748
0
    if ((count < 0) || (strings == NULL))
2749
0
    {
2750
0
        return NULL;
2751
0
    }
2752
2753
0
    a = cJSON_CreateArray();
2754
2755
0
    for (i = 0; a && (i < (size_t)count); i++)
2756
0
    {
2757
0
        n = cJSON_CreateString(strings[i]);
2758
0
        if(!n)
2759
0
        {
2760
0
            cJSON_Delete(a);
2761
0
            return NULL;
2762
0
        }
2763
0
        if(!i)
2764
0
        {
2765
0
            a->child = n;
2766
0
        }
2767
0
        else
2768
0
        {
2769
0
            suffix_object(p,n);
2770
0
        }
2771
0
        p = n;
2772
0
    }
2773
2774
0
    if (a && a->child) {
2775
0
        a->child->prev = n;
2776
0
    }
2777
2778
0
    return a;
2779
0
}
2780
2781
/* Duplication */
2782
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
2783
2784
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2785
0
{
2786
0
    return cJSON_Duplicate_rec(item, 0, recurse );
2787
0
}
2788
2789
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
2790
0
{
2791
0
    cJSON *newitem = NULL;
2792
0
    cJSON *child = NULL;
2793
0
    cJSON *next = NULL;
2794
0
    cJSON *newchild = NULL;
2795
2796
    /* Bail on bad ptr */
2797
0
    if (!item)
2798
0
    {
2799
0
        goto fail;
2800
0
    }
2801
    /* Create new item */
2802
0
    newitem = cJSON_New_Item(&global_hooks);
2803
0
    if (!newitem)
2804
0
    {
2805
0
        goto fail;
2806
0
    }
2807
    /* Copy over all vars */
2808
0
    newitem->type = item->type & (~cJSON_IsReference);
2809
0
    newitem->valueint = item->valueint;
2810
0
    newitem->valuedouble = item->valuedouble;
2811
0
    if (item->valuestring)
2812
0
    {
2813
0
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2814
0
        if (!newitem->valuestring)
2815
0
        {
2816
0
            goto fail;
2817
0
        }
2818
0
    }
2819
0
    if (item->string)
2820
0
    {
2821
0
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2822
0
        if (!newitem->string)
2823
0
        {
2824
0
            goto fail;
2825
0
        }
2826
0
    }
2827
    /* If non-recursive, then we're done! */
2828
0
    if (!recurse)
2829
0
    {
2830
0
        return newitem;
2831
0
    }
2832
    /* Walk the ->next chain for the child. */
2833
0
    child = item->child;
2834
0
    while (child != NULL)
2835
0
    {
2836
0
        if(depth >= CJSON_CIRCULAR_LIMIT) {
2837
0
            goto fail;
2838
0
        }
2839
0
        newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
2840
0
        if (!newchild)
2841
0
        {
2842
0
            goto fail;
2843
0
        }
2844
0
        if (next != NULL)
2845
0
        {
2846
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2847
0
            next->next = newchild;
2848
0
            newchild->prev = next;
2849
0
            next = newchild;
2850
0
        }
2851
0
        else
2852
0
        {
2853
            /* Set newitem->child and move to it */
2854
0
            newitem->child = newchild;
2855
0
            next = newchild;
2856
0
        }
2857
0
        child = child->next;
2858
0
    }
2859
0
    if (newitem && newitem->child)
2860
0
    {
2861
0
        newitem->child->prev = newchild;
2862
0
    }
2863
2864
0
    return newitem;
2865
2866
0
fail:
2867
0
    if (newitem != NULL)
2868
0
    {
2869
0
        cJSON_Delete(newitem);
2870
0
    }
2871
2872
0
    return NULL;
2873
0
}
2874
2875
static void skip_oneline_comment(char **input)
2876
228
{
2877
228
    *input += static_strlen("//");
2878
2879
445
    for (; (*input)[0] != '\0'; ++(*input))
2880
425
    {
2881
425
        if ((*input)[0] == '\n') {
2882
208
            *input += static_strlen("\n");
2883
208
            return;
2884
208
        }
2885
425
    }
2886
228
}
2887
2888
static void skip_multiline_comment(char **input)
2889
238
{
2890
238
    *input += static_strlen("/*");
2891
2892
850
    for (; (*input)[0] != '\0'; ++(*input))
2893
806
    {
2894
806
        if (((*input)[0] == '*') && ((*input)[1] == '/'))
2895
194
        {
2896
194
            *input += static_strlen("*/");
2897
194
            return;
2898
194
        }
2899
806
    }
2900
238
}
2901
2902
16.4k
static void minify_string(char **input, char **output) {
2903
16.4k
    (*output)[0] = (*input)[0];
2904
16.4k
    *input += static_strlen("\"");
2905
16.4k
    *output += static_strlen("\"");
2906
2907
2908
10.4M
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2909
10.4M
        (*output)[0] = (*input)[0];
2910
2911
10.4M
        if ((*input)[0] == '\"') {
2912
16.3k
            (*output)[0] = '\"';
2913
16.3k
            *input += static_strlen("\"");
2914
16.3k
            *output += static_strlen("\"");
2915
16.3k
            return;
2916
10.4M
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2917
1.46k
            (*output)[1] = (*input)[1];
2918
1.46k
            *input += static_strlen("\"");
2919
1.46k
            *output += static_strlen("\"");
2920
1.46k
        }
2921
10.4M
    }
2922
16.4k
}
2923
2924
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2925
875
{
2926
875
    char *into = json;
2927
2928
875
    if (json == NULL)
2929
0
    {
2930
0
        return;
2931
0
    }
2932
2933
2.34M
    while (json[0] != '\0')
2934
2.34M
    {
2935
2.34M
        switch (json[0])
2936
2.34M
        {
2937
223
            case ' ':
2938
423
            case '\t':
2939
633
            case '\r':
2940
1.65k
            case '\n':
2941
1.65k
                json++;
2942
1.65k
                break;
2943
2944
684
            case '/':
2945
684
                if (json[1] == '/')
2946
228
                {
2947
228
                    skip_oneline_comment(&json);
2948
228
                }
2949
456
                else if (json[1] == '*')
2950
238
                {
2951
238
                    skip_multiline_comment(&json);
2952
238
                } else {
2953
218
                    json++;
2954
218
                }
2955
684
                break;
2956
2957
16.4k
            case '\"':
2958
16.4k
                minify_string(&json, (char**)&into);
2959
16.4k
                break;
2960
2961
2.32M
            default:
2962
2.32M
                into[0] = json[0];
2963
2.32M
                json++;
2964
2.32M
                into++;
2965
2.34M
        }
2966
2.34M
    }
2967
2968
    /* and null-terminate. */
2969
875
    *into = '\0';
2970
875
}
2971
2972
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2973
0
{
2974
0
    if (item == NULL)
2975
0
    {
2976
0
        return false;
2977
0
    }
2978
2979
0
    return (item->type & 0xFF) == cJSON_Invalid;
2980
0
}
2981
2982
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2983
0
{
2984
0
    if (item == NULL)
2985
0
    {
2986
0
        return false;
2987
0
    }
2988
2989
0
    return (item->type & 0xFF) == cJSON_False;
2990
0
}
2991
2992
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2993
0
{
2994
0
    if (item == NULL)
2995
0
    {
2996
0
        return false;
2997
0
    }
2998
2999
0
    return (item->type & 0xff) == cJSON_True;
3000
0
}
3001
3002
3003
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
3004
0
{
3005
0
    if (item == NULL)
3006
0
    {
3007
0
        return false;
3008
0
    }
3009
3010
0
    return (item->type & (cJSON_True | cJSON_False)) != 0;
3011
0
}
3012
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
3013
0
{
3014
0
    if (item == NULL)
3015
0
    {
3016
0
        return false;
3017
0
    }
3018
3019
0
    return (item->type & 0xFF) == cJSON_NULL;
3020
0
}
3021
3022
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
3023
0
{
3024
0
    if (item == NULL)
3025
0
    {
3026
0
        return false;
3027
0
    }
3028
3029
0
    return (item->type & 0xFF) == cJSON_Number;
3030
0
}
3031
3032
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
3033
0
{
3034
0
    if (item == NULL)
3035
0
    {
3036
0
        return false;
3037
0
    }
3038
3039
0
    return (item->type & 0xFF) == cJSON_String;
3040
0
}
3041
3042
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3043
0
{
3044
0
    if (item == NULL)
3045
0
    {
3046
0
        return false;
3047
0
    }
3048
3049
0
    return (item->type & 0xFF) == cJSON_Array;
3050
0
}
3051
3052
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3053
0
{
3054
0
    if (item == NULL)
3055
0
    {
3056
0
        return false;
3057
0
    }
3058
3059
0
    return (item->type & 0xFF) == cJSON_Object;
3060
0
}
3061
3062
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3063
0
{
3064
0
    if (item == NULL)
3065
0
    {
3066
0
        return false;
3067
0
    }
3068
3069
0
    return (item->type & 0xFF) == cJSON_Raw;
3070
0
}
3071
3072
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3073
0
{
3074
0
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3075
0
    {
3076
0
        return false;
3077
0
    }
3078
3079
    /* check if type is valid */
3080
0
    switch (a->type & 0xFF)
3081
0
    {
3082
0
        case cJSON_False:
3083
0
        case cJSON_True:
3084
0
        case cJSON_NULL:
3085
0
        case cJSON_Number:
3086
0
        case cJSON_String:
3087
0
        case cJSON_Raw:
3088
0
        case cJSON_Array:
3089
0
        case cJSON_Object:
3090
0
            break;
3091
3092
0
        default:
3093
0
            return false;
3094
0
    }
3095
3096
    /* identical objects are equal */
3097
0
    if (a == b)
3098
0
    {
3099
0
        return true;
3100
0
    }
3101
3102
0
    switch (a->type & 0xFF)
3103
0
    {
3104
        /* in these cases and equal type is enough */
3105
0
        case cJSON_False:
3106
0
        case cJSON_True:
3107
0
        case cJSON_NULL:
3108
0
            return true;
3109
3110
0
        case cJSON_Number:
3111
0
            if (compare_double(a->valuedouble, b->valuedouble))
3112
0
            {
3113
0
                return true;
3114
0
            }
3115
0
            return false;
3116
3117
0
        case cJSON_String:
3118
0
        case cJSON_Raw:
3119
0
            if ((a->valuestring == NULL) || (b->valuestring == NULL))
3120
0
            {
3121
0
                return false;
3122
0
            }
3123
0
            if (strcmp(a->valuestring, b->valuestring) == 0)
3124
0
            {
3125
0
                return true;
3126
0
            }
3127
3128
0
            return false;
3129
3130
0
        case cJSON_Array:
3131
0
        {
3132
0
            cJSON *a_element = a->child;
3133
0
            cJSON *b_element = b->child;
3134
3135
0
            for (; (a_element != NULL) && (b_element != NULL);)
3136
0
            {
3137
0
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
3138
0
                {
3139
0
                    return false;
3140
0
                }
3141
3142
0
                a_element = a_element->next;
3143
0
                b_element = b_element->next;
3144
0
            }
3145
3146
            /* one of the arrays is longer than the other */
3147
0
            if (a_element != b_element) {
3148
0
                return false;
3149
0
            }
3150
3151
0
            return true;
3152
0
        }
3153
3154
0
        case cJSON_Object:
3155
0
        {
3156
0
            cJSON *a_element = NULL;
3157
0
            cJSON *b_element = NULL;
3158
0
            cJSON_ArrayForEach(a_element, a)
3159
0
            {
3160
                /* TODO This has O(n^2) runtime, which is horrible! */
3161
0
                b_element = get_object_item(b, a_element->string, case_sensitive);
3162
0
                if (b_element == NULL)
3163
0
                {
3164
0
                    return false;
3165
0
                }
3166
3167
0
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
3168
0
                {
3169
0
                    return false;
3170
0
                }
3171
0
            }
3172
3173
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
3174
             * TODO: Do this the proper way, this is just a fix for now */
3175
0
            cJSON_ArrayForEach(b_element, b)
3176
0
            {
3177
0
                a_element = get_object_item(a, b_element->string, case_sensitive);
3178
0
                if (a_element == NULL)
3179
0
                {
3180
0
                    return false;
3181
0
                }
3182
3183
0
                if (!cJSON_Compare(b_element, a_element, case_sensitive))
3184
0
                {
3185
0
                    return false;
3186
0
                }
3187
0
            }
3188
3189
0
            return true;
3190
0
        }
3191
3192
0
        default:
3193
0
            return false;
3194
0
    }
3195
0
}
3196
3197
CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3198
0
{
3199
0
    return global_hooks.allocate(size);
3200
0
}
3201
3202
CJSON_PUBLIC(void) cJSON_free(void *object)
3203
0
{
3204
0
    global_hooks.deallocate(object);
3205
    object = NULL;
3206
0
}