Coverage Report

Created: 2026-04-12 06:55

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.42M
#define true ((cJSON_bool)1)
66
67
#ifdef false
68
#undef false
69
#endif
70
82.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
23.6k
#define isinf(d) (isnan((d - d)) && !isnan(d))
75
#endif
76
#ifndef isnan
77
94.9k
#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
56.6k
#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
751k
{
243
751k
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
751k
    if (node)
245
751k
    {
246
751k
        memset(node, '\0', sizeof(cJSON));
247
751k
    }
248
249
751k
    return node;
250
751k
}
251
252
/* Delete a cJSON structure. */
253
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
303k
{
255
303k
    cJSON *next = NULL;
256
1.05M
    while (item != NULL)
257
751k
    {
258
751k
        next = item->next;
259
751k
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
253k
        {
261
253k
            cJSON_Delete(item->child);
262
253k
        }
263
751k
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
3.32k
        {
265
3.32k
            global_hooks.deallocate(item->valuestring);
266
3.32k
            item->valuestring = NULL;
267
3.32k
        }
268
751k
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
21.6k
        {
270
21.6k
            global_hooks.deallocate(item->string);
271
21.6k
            item->string = NULL;
272
21.6k
        }
273
751k
        global_hooks.deallocate(item);
274
751k
        item = next;
275
751k
    }
276
303k
}
277
278
/* get the decimal point character of the current locale */
279
static unsigned char get_decimal_point(void)
280
55.8k
{
281
55.8k
#ifdef ENABLE_LOCALES
282
55.8k
    struct lconv *lconv = localeconv();
283
55.8k
    return (unsigned char) lconv->decimal_point[0];
284
#else
285
    return '.';
286
#endif
287
55.8k
}
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.50M
#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.0M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
3.92M
#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.6M
#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
32.1k
{
309
32.1k
    double number = 0;
310
32.1k
    unsigned char *after_end = NULL;
311
32.1k
    unsigned char *number_c_string;
312
32.1k
    unsigned char decimal_point = get_decimal_point();
313
32.1k
    size_t i = 0;
314
32.1k
    size_t number_string_length = 0;
315
32.1k
    cJSON_bool has_decimal_point = false;
316
317
32.1k
    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
730k
    for (i = 0; can_access_at_index(input_buffer, i); i++)
326
730k
    {
327
730k
        switch (buffer_at_offset(input_buffer)[i])
328
730k
        {
329
403k
            case '0':
330
444k
            case '1':
331
462k
            case '2':
332
473k
            case '3':
333
481k
            case '4':
334
502k
            case '5':
335
576k
            case '6':
336
590k
            case '7':
337
613k
            case '8':
338
636k
            case '9':
339
637k
            case '+':
340
685k
            case '-':
341
687k
            case 'e':
342
689k
            case 'E':
343
689k
                number_string_length++;
344
689k
                break;
345
346
8.18k
            case '.':
347
8.18k
                number_string_length++;
348
8.18k
                has_decimal_point = true;
349
8.18k
                break;
350
351
32.1k
            default:
352
32.1k
                goto loop_end;
353
730k
        }
354
730k
    }
355
32.1k
loop_end:
356
    /* malloc for temporary buffer, add 1 for '\0' */
357
32.1k
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
358
32.1k
    if (number_c_string == NULL)
359
0
    {
360
0
        return false; /* allocation failure */
361
0
    }
362
363
32.1k
    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
364
32.1k
    number_c_string[number_string_length] = '\0';
365
366
32.1k
    if (has_decimal_point)
367
617
    {
368
528k
        for (i = 0; i < number_string_length; i++)
369
527k
        {
370
527k
            if (number_c_string[i] == '.')
371
8.18k
            {
372
                /* replace '.' with the decimal point of the current locale (for strtod) */
373
8.18k
                number_c_string[i] = decimal_point;
374
8.18k
            }
375
527k
        }
376
617
    }
377
378
32.1k
    number = strtod((const char*)number_c_string, (char**)&after_end);
379
32.1k
    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
32.1k
    item->valuedouble = number;
387
388
    /* use saturation in case of overflow */
389
32.1k
    if (number >= INT_MAX)
390
9.25k
    {
391
9.25k
        item->valueint = INT_MAX;
392
9.25k
    }
393
22.9k
    else if (number <= (double)INT_MIN)
394
251
    {
395
251
        item->valueint = INT_MIN;
396
251
    }
397
22.6k
    else
398
22.6k
    {
399
22.6k
        item->valueint = (int)number;
400
22.6k
    }
401
402
32.1k
    item->type = cJSON_Number;
403
404
32.1k
    input_buffer->offset += (size_t)(after_end - number_c_string);
405
    /* free the temporary buffer */
406
32.1k
    input_buffer->hooks.deallocate(number_c_string);
407
32.1k
    return true;
408
32.1k
}
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.82M
{
492
1.82M
    unsigned char *newbuffer = NULL;
493
1.82M
    size_t newsize = 0;
494
495
1.82M
    if ((p == NULL) || (p->buffer == NULL))
496
0
    {
497
0
        return NULL;
498
0
    }
499
500
1.82M
    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.82M
    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.82M
    needed += p->offset + 1;
513
1.82M
    if (needed <= p->length)
514
1.81M
    {
515
1.81M
        return p->buffer + p->offset;
516
1.81M
    }
517
518
1.93k
    if (p->noalloc) {
519
0
        return NULL;
520
0
    }
521
522
    /* calculate new buffer size */
523
1.93k
    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.93k
    else
536
1.93k
    {
537
1.93k
        newsize = needed * 2;
538
1.93k
    }
539
540
1.93k
    if (p->hooks.reallocate != NULL)
541
1.93k
    {
542
        /* reallocate with realloc if available */
543
1.93k
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
544
1.93k
        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.93k
    }
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.93k
    p->length = newsize;
570
1.93k
    p->buffer = newbuffer;
571
572
1.93k
    return newbuffer + p->offset;
573
1.93k
}
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
696k
{
578
696k
    const unsigned char *buffer_pointer = NULL;
579
696k
    if ((buffer == NULL) || (buffer->buffer == NULL))
580
0
    {
581
0
        return;
582
0
    }
583
696k
    buffer_pointer = buffer->buffer + buffer->offset;
584
585
696k
    buffer->offset += strlen((const char*)buffer_pointer);
586
696k
}
587
588
/* securely comparison of floating-point variables */
589
static cJSON_bool compare_double(double a, double b)
590
8.30k
{
591
8.30k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
592
8.30k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
593
8.30k
}
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
23.6k
{
598
23.6k
    unsigned char *output_pointer = NULL;
599
23.6k
    double d = item->valuedouble;
600
23.6k
    int length = 0;
601
23.6k
    size_t i = 0;
602
23.6k
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
603
23.6k
    unsigned char decimal_point = get_decimal_point();
604
23.6k
    double test = 0.0;
605
606
23.6k
    if (output_buffer == NULL)
607
0
    {
608
0
        return false;
609
0
    }
610
611
    /* This checks for NaN and Infinity */
612
23.6k
    if (isnan(d) || isinf(d))
613
367
    {
614
367
        length = sprintf((char*)number_buffer, "null");
615
367
    }
616
23.2k
    else if(d == (double)item->valueint)
617
14.9k
    {
618
14.9k
        length = sprintf((char*)number_buffer, "%d", item->valueint);
619
14.9k
    }
620
8.30k
    else
621
8.30k
    {
622
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
623
8.30k
        length = sprintf((char*)number_buffer, "%1.15g", d);
624
625
        /* Check whether the original double can be recovered */
626
8.30k
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
627
7.92k
        {
628
            /* If not, print with 17 decimal places of precision */
629
7.92k
            length = sprintf((char*)number_buffer, "%1.17g", d);
630
7.92k
        }
631
8.30k
    }
632
633
    /* sprintf failed or buffer overrun occurred */
634
23.6k
    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
23.6k
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
641
23.6k
    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
173k
    for (i = 0; i < ((size_t)length); i++)
649
149k
    {
650
149k
        if (number_buffer[i] == decimal_point)
651
609
        {
652
609
            output_pointer[i] = '.';
653
609
            continue;
654
609
        }
655
656
149k
        output_pointer[i] = number_buffer[i];
657
149k
    }
658
23.6k
    output_pointer[i] = '\0';
659
660
23.6k
    output_buffer->offset += (size_t)length;
661
662
23.6k
    return true;
663
23.6k
}
664
665
/* parse 4 digit hexadecimal number */
666
static unsigned parse_hex4(const unsigned char * const input)
667
65.4k
{
668
65.4k
    unsigned int h = 0;
669
65.4k
    size_t i = 0;
670
671
249k
    for (i = 0; i < 4; i++)
672
211k
    {
673
        /* parse digit */
674
211k
        if ((input[i] >= '0') && (input[i] <= '9'))
675
73.2k
        {
676
73.2k
            h += (unsigned int) input[i] - '0';
677
73.2k
        }
678
138k
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
679
25.0k
        {
680
25.0k
            h += (unsigned int) 10 + input[i] - 'A';
681
25.0k
        }
682
113k
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
683
85.6k
        {
684
85.6k
            h += (unsigned int) 10 + input[i] - 'a';
685
85.6k
        }
686
27.5k
        else /* invalid */
687
27.5k
        {
688
27.5k
            return 0;
689
27.5k
        }
690
691
184k
        if (i < 3)
692
146k
        {
693
            /* shift left to make place for the next nibble */
694
146k
            h = h << 4;
695
146k
        }
696
184k
    }
697
698
37.8k
    return h;
699
65.4k
}
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
60.9k
{
705
60.9k
    long unsigned int codepoint = 0;
706
60.9k
    unsigned int first_code = 0;
707
60.9k
    const unsigned char *first_sequence = input_pointer;
708
60.9k
    unsigned char utf8_length = 0;
709
60.9k
    unsigned char utf8_position = 0;
710
60.9k
    unsigned char sequence_length = 0;
711
60.9k
    unsigned char first_byte_mark = 0;
712
713
60.9k
    if ((input_end - first_sequence) < 6)
714
7
    {
715
        /* input ends unexpectedly */
716
7
        goto fail;
717
7
    }
718
719
    /* get the first utf16 sequence */
720
60.9k
    first_code = parse_hex4(first_sequence + 2);
721
722
    /* check that the code is valid */
723
60.9k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
724
13
    {
725
13
        goto fail;
726
13
    }
727
728
    /* UTF16 surrogate pair */
729
60.8k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
730
4.54k
    {
731
4.54k
        const unsigned char *second_sequence = first_sequence + 6;
732
4.54k
        unsigned int second_code = 0;
733
4.54k
        sequence_length = 12; /* \uXXXX\uXXXX */
734
735
4.54k
        if ((input_end - second_sequence) < 6)
736
17
        {
737
            /* input ends unexpectedly */
738
17
            goto fail;
739
17
        }
740
741
4.53k
        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
4.50k
        second_code = parse_hex4(second_sequence + 2);
749
        /* check that the code is valid */
750
4.50k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
751
59
        {
752
            /* invalid second half of the surrogate pair */
753
59
            goto fail;
754
59
        }
755
756
757
        /* calculate the unicode codepoint from the surrogate pair */
758
4.44k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
759
4.44k
    }
760
56.3k
    else
761
56.3k
    {
762
56.3k
        sequence_length = 6; /* \uXXXX */
763
56.3k
        codepoint = first_code;
764
56.3k
    }
765
766
    /* encode as UTF-8
767
     * takes at maximum 4 bytes to encode:
768
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
769
60.7k
    if (codepoint < 0x80)
770
30.0k
    {
771
        /* normal ascii, encoding 0xxxxxxx */
772
30.0k
        utf8_length = 1;
773
30.0k
    }
774
30.7k
    else if (codepoint < 0x800)
775
8.00k
    {
776
        /* two bytes, encoding 110xxxxx 10xxxxxx */
777
8.00k
        utf8_length = 2;
778
8.00k
        first_byte_mark = 0xC0; /* 11000000 */
779
8.00k
    }
780
22.7k
    else if (codepoint < 0x10000)
781
18.3k
    {
782
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
783
18.3k
        utf8_length = 3;
784
18.3k
        first_byte_mark = 0xE0; /* 11100000 */
785
18.3k
    }
786
4.44k
    else if (codepoint <= 0x10FFFF)
787
4.44k
    {
788
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
789
4.44k
        utf8_length = 4;
790
4.44k
        first_byte_mark = 0xF0; /* 11110000 */
791
4.44k
    }
792
0
    else
793
0
    {
794
        /* invalid unicode codepoint */
795
0
        goto fail;
796
0
    }
797
798
    /* encode as utf8 */
799
118k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
800
57.9k
    {
801
        /* 10xxxxxx */
802
57.9k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
803
57.9k
        codepoint >>= 6;
804
57.9k
    }
805
    /* encode first byte */
806
60.7k
    if (utf8_length > 1)
807
30.7k
    {
808
30.7k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
809
30.7k
    }
810
30.0k
    else
811
30.0k
    {
812
30.0k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
813
30.0k
    }
814
815
60.7k
    *output_pointer += utf8_length;
816
817
60.7k
    return sequence_length;
818
819
123
fail:
820
123
    return 0;
821
60.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
25.2k
{
826
25.2k
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
827
25.2k
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
828
25.2k
    unsigned char *output_pointer = NULL;
829
25.2k
    unsigned char *output = NULL;
830
831
    /* not a string */
832
25.2k
    if (buffer_at_offset(input_buffer)[0] != '\"')
833
134
    {
834
134
        goto fail;
835
134
    }
836
837
25.1k
    {
838
        /* calculate approximate size of the output (overestimate) */
839
25.1k
        size_t allocation_length = 0;
840
25.1k
        size_t skipped_bytes = 0;
841
24.5M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
842
24.5M
        {
843
            /* is escape sequence */
844
24.5M
            if (input_end[0] == '\\')
845
192k
            {
846
192k
                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
192k
                skipped_bytes++;
852
192k
                input_end++;
853
192k
            }
854
24.5M
            input_end++;
855
24.5M
        }
856
25.1k
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
857
75
        {
858
75
            goto fail; /* string ended unexpectedly */
859
75
        }
860
861
        /* This is at most how much we need for the output */
862
25.0k
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
863
25.0k
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
864
25.0k
        if (output == NULL)
865
0
        {
866
0
            goto fail; /* allocation failure */
867
0
        }
868
25.0k
    }
869
870
25.0k
    output_pointer = output;
871
    /* loop through the string literal */
872
22.4M
    while (input_pointer < input_end)
873
22.4M
    {
874
22.4M
        if (*input_pointer != '\\')
875
22.3M
        {
876
22.3M
            *output_pointer++ = *input_pointer++;
877
22.3M
        }
878
        /* escape sequence */
879
162k
        else
880
162k
        {
881
162k
            unsigned char sequence_length = 2;
882
162k
            if ((input_end - input_pointer) < 1)
883
0
            {
884
0
                goto fail;
885
0
            }
886
887
162k
            switch (input_pointer[1])
888
162k
            {
889
11.8k
                case 'b':
890
11.8k
                    *output_pointer++ = '\b';
891
11.8k
                    break;
892
5.45k
                case 'f':
893
5.45k
                    *output_pointer++ = '\f';
894
5.45k
                    break;
895
13.8k
                case 'n':
896
13.8k
                    *output_pointer++ = '\n';
897
13.8k
                    break;
898
12.6k
                case 'r':
899
12.6k
                    *output_pointer++ = '\r';
900
12.6k
                    break;
901
10.0k
                case 't':
902
10.0k
                    *output_pointer++ = '\t';
903
10.0k
                    break;
904
17.3k
                case '\"':
905
30.0k
                case '\\':
906
47.4k
                case '/':
907
47.4k
                    *output_pointer++ = input_pointer[1];
908
47.4k
                    break;
909
910
                /* UTF-16 literal */
911
60.9k
                case 'u':
912
60.9k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
913
60.9k
                    if (sequence_length == 0)
914
123
                    {
915
                        /* failed to convert UTF16-literal to UTF-8 */
916
123
                        goto fail;
917
123
                    }
918
60.7k
                    break;
919
920
60.7k
                default:
921
15
                    goto fail;
922
162k
            }
923
162k
            input_pointer += sequence_length;
924
162k
        }
925
22.4M
    }
926
927
    /* zero terminate the output */
928
24.9k
    *output_pointer = '\0';
929
930
24.9k
    item->type = cJSON_String;
931
24.9k
    item->valuestring = (char*)output;
932
933
24.9k
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
934
24.9k
    input_buffer->offset++;
935
936
24.9k
    return true;
937
938
347
fail:
939
347
    if (output != NULL)
940
138
    {
941
138
        input_buffer->hooks.deallocate(output);
942
138
        output = NULL;
943
138
    }
944
945
347
    if (input_pointer != NULL)
946
347
    {
947
347
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
948
347
    }
949
950
347
    return false;
951
25.0k
}
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
13.8k
{
956
13.8k
    const unsigned char *input_pointer = NULL;
957
13.8k
    unsigned char *output = NULL;
958
13.8k
    unsigned char *output_pointer = NULL;
959
13.8k
    size_t output_length = 0;
960
    /* numbers of additional characters needed for escaping */
961
13.8k
    size_t escape_characters = 0;
962
963
13.8k
    if (output_buffer == NULL)
964
0
    {
965
0
        return false;
966
0
    }
967
968
    /* empty string */
969
13.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.6M
    for (input_pointer = input; *input_pointer; input_pointer++)
983
10.6M
    {
984
10.6M
        switch (*input_pointer)
985
10.6M
        {
986
1.34k
            case '\"':
987
2.82k
            case '\\':
988
17.5k
            case '\b':
989
70.0k
            case '\f':
990
171k
            case '\n':
991
178k
            case '\r':
992
186k
            case '\t':
993
                /* one character escape sequence */
994
186k
                escape_characters++;
995
186k
                break;
996
10.4M
            default:
997
10.4M
                if (*input_pointer < 32)
998
7.81M
                {
999
                    /* UTF-16 escape sequence uXXXX */
1000
7.81M
                    escape_characters += 5;
1001
7.81M
                }
1002
10.4M
                break;
1003
10.6M
        }
1004
10.6M
    }
1005
13.8k
    output_length = (size_t)(input_pointer - input) + escape_characters;
1006
1007
13.8k
    output = ensure(output_buffer, output_length + sizeof("\"\""));
1008
13.8k
    if (output == NULL)
1009
0
    {
1010
0
        return false;
1011
0
    }
1012
1013
    /* no characters have to be escaped */
1014
13.8k
    if (escape_characters == 0)
1015
12.4k
    {
1016
12.4k
        output[0] = '\"';
1017
12.4k
        memcpy(output + 1, input, output_length);
1018
12.4k
        output[output_length + 1] = '\"';
1019
12.4k
        output[output_length + 2] = '\0';
1020
1021
12.4k
        return true;
1022
12.4k
    }
1023
1024
1.42k
    output[0] = '\"';
1025
1.42k
    output_pointer = output + 1;
1026
    /* copy the string */
1027
10.6M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1028
10.6M
    {
1029
10.6M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1030
2.65M
        {
1031
            /* normal character, copy */
1032
2.65M
            *output_pointer = *input_pointer;
1033
2.65M
        }
1034
7.99M
        else
1035
7.99M
        {
1036
            /* character needs to be escaped */
1037
7.99M
            *output_pointer++ = '\\';
1038
7.99M
            switch (*input_pointer)
1039
7.99M
            {
1040
1.48k
                case '\\':
1041
1.48k
                    *output_pointer = '\\';
1042
1.48k
                    break;
1043
1.34k
                case '\"':
1044
1.34k
                    *output_pointer = '\"';
1045
1.34k
                    break;
1046
14.6k
                case '\b':
1047
14.6k
                    *output_pointer = 'b';
1048
14.6k
                    break;
1049
52.5k
                case '\f':
1050
52.5k
                    *output_pointer = 'f';
1051
52.5k
                    break;
1052
101k
                case '\n':
1053
101k
                    *output_pointer = 'n';
1054
101k
                    break;
1055
6.82k
                case '\r':
1056
6.82k
                    *output_pointer = 'r';
1057
6.82k
                    break;
1058
7.80k
                case '\t':
1059
7.80k
                    *output_pointer = 't';
1060
7.80k
                    break;
1061
7.81M
                default:
1062
                    /* escape and print as unicode codepoint */
1063
7.81M
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
1064
7.81M
                    output_pointer += 4;
1065
7.81M
                    break;
1066
7.99M
            }
1067
7.99M
        }
1068
10.6M
    }
1069
1.42k
    output[output_length + 1] = '\"';
1070
1.42k
    output[output_length + 2] = '\0';
1071
1072
1.42k
    return true;
1073
1.42k
}
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
1.07k
{
1078
1.07k
    return print_string_ptr((unsigned char*)item->valuestring, p);
1079
1.07k
}
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.20M
{
1092
2.20M
    if ((buffer == NULL) || (buffer->content == NULL))
1093
0
    {
1094
0
        return NULL;
1095
0
    }
1096
1097
2.20M
    if (cannot_access_at_index(buffer, 0))
1098
0
    {
1099
0
        return buffer;
1100
0
    }
1101
1102
3.01M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1103
810k
    {
1104
810k
       buffer->offset++;
1105
810k
    }
1106
1107
2.20M
    if (buffer->offset == buffer->length)
1108
974
    {
1109
974
        buffer->offset--;
1110
974
    }
1111
1112
2.20M
    return buffer;
1113
2.20M
}
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.01k
{
1118
2.01k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1119
0
    {
1120
0
        return NULL;
1121
0
    }
1122
1123
2.01k
    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1124
93
    {
1125
93
        buffer->offset += 3;
1126
93
    }
1127
1128
2.01k
    return buffer;
1129
2.01k
}
1130
1131
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1132
2.01k
{
1133
2.01k
    size_t buffer_length;
1134
1135
2.01k
    if (NULL == value)
1136
0
    {
1137
0
        return NULL;
1138
0
    }
1139
1140
    /* Adding null character size due to require_null_terminated. */
1141
2.01k
    buffer_length = strlen(value) + sizeof("");
1142
1143
2.01k
    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1144
2.01k
}
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.01k
{
1149
2.01k
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1150
2.01k
    cJSON *item = NULL;
1151
1152
    /* reset error position */
1153
2.01k
    global_error.json = NULL;
1154
2.01k
    global_error.position = 0;
1155
1156
2.01k
    if (value == NULL || 0 == buffer_length)
1157
0
    {
1158
0
        goto fail;
1159
0
    }
1160
1161
2.01k
    buffer.content = (const unsigned char*)value;
1162
2.01k
    buffer.length = buffer_length;
1163
2.01k
    buffer.offset = 0;
1164
2.01k
    buffer.hooks = global_hooks;
1165
1166
2.01k
    item = cJSON_New_Item(&global_hooks);
1167
2.01k
    if (item == NULL) /* memory fail */
1168
0
    {
1169
0
        goto fail;
1170
0
    }
1171
1172
2.01k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1173
861
    {
1174
        /* parse failure. ep is set. */
1175
861
        goto fail;
1176
861
    }
1177
1178
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1179
1.15k
    if (require_null_terminated)
1180
454
    {
1181
454
        buffer_skip_whitespace(&buffer);
1182
454
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1183
56
        {
1184
56
            goto fail;
1185
56
        }
1186
454
    }
1187
1.09k
    if (return_parse_end)
1188
0
    {
1189
0
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
1190
0
    }
1191
1192
1.09k
    return item;
1193
1194
917
fail:
1195
917
    if (item != NULL)
1196
917
    {
1197
917
        cJSON_Delete(item);
1198
917
    }
1199
1200
917
    if (value != NULL)
1201
917
    {
1202
917
        error local_error;
1203
917
        local_error.json = (const unsigned char*)value;
1204
917
        local_error.position = 0;
1205
1206
917
        if (buffer.offset < buffer.length)
1207
809
        {
1208
809
            local_error.position = buffer.offset;
1209
809
        }
1210
108
        else if (buffer.length > 0)
1211
108
        {
1212
108
            local_error.position = buffer.length - 1;
1213
108
        }
1214
1215
917
        if (return_parse_end != NULL)
1216
0
        {
1217
0
            *return_parse_end = (const char*)local_error.json + local_error.position;
1218
0
        }
1219
1220
917
        global_error = local_error;
1221
917
    }
1222
1223
917
    return NULL;
1224
1.15k
}
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
532
{
1241
532
    static const size_t default_buffer_size = 256;
1242
532
    printbuffer buffer[1];
1243
532
    unsigned char *printed = NULL;
1244
1245
532
    memset(buffer, 0, sizeof(buffer));
1246
1247
    /* create buffer */
1248
532
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1249
532
    buffer->length = default_buffer_size;
1250
532
    buffer->format = format;
1251
532
    buffer->hooks = *hooks;
1252
532
    if (buffer->buffer == NULL)
1253
0
    {
1254
0
        goto fail;
1255
0
    }
1256
1257
    /* print the value */
1258
532
    if (!print_value(item, buffer))
1259
0
    {
1260
0
        goto fail;
1261
0
    }
1262
532
    update_offset(buffer);
1263
1264
    /* check if reallocate is available */
1265
532
    if (hooks->reallocate != NULL)
1266
532
    {
1267
532
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1268
532
        if (printed == NULL) {
1269
0
            goto fail;
1270
0
        }
1271
532
        buffer->buffer = NULL;
1272
532
    }
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
532
    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
532
}
1305
1306
/* Render a cJSON item/entity/structure to text. */
1307
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1308
251
{
1309
251
    return (char*)print(item, true, &global_hooks);
1310
251
}
1311
1312
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1313
281
{
1314
281
    return (char*)print(item, false, &global_hooks);
1315
281
}
1316
1317
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1318
563
{
1319
563
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1320
1321
563
    if (prebuffer < 0)
1322
0
    {
1323
0
        return NULL;
1324
0
    }
1325
1326
563
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1327
563
    if (!p.buffer)
1328
0
    {
1329
0
        return NULL;
1330
0
    }
1331
1332
563
    p.length = (size_t)prebuffer;
1333
563
    p.offset = 0;
1334
563
    p.noalloc = false;
1335
563
    p.format = fmt;
1336
563
    p.hooks = global_hooks;
1337
1338
563
    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
563
    return (char*)p.buffer;
1346
563
}
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
751k
{
1370
751k
    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
751k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1378
651
    {
1379
651
        item->type = cJSON_NULL;
1380
651
        input_buffer->offset += 4;
1381
651
        return true;
1382
651
    }
1383
    /* false */
1384
750k
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1385
867
    {
1386
867
        item->type = cJSON_False;
1387
867
        input_buffer->offset += 5;
1388
867
        return true;
1389
867
    }
1390
    /* true */
1391
749k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1392
550
    {
1393
550
        item->type = cJSON_True;
1394
550
        item->valueint = 1;
1395
550
        input_buffer->offset += 4;
1396
550
        return true;
1397
550
    }
1398
    /* string */
1399
749k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1400
3.52k
    {
1401
3.52k
        return parse_string(item, input_buffer);
1402
3.52k
    }
1403
    /* number */
1404
745k
    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
32.1k
    {
1406
32.1k
        return parse_number(item, input_buffer);
1407
32.1k
    }
1408
    /* array */
1409
713k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1410
291k
    {
1411
291k
        return parse_array(item, input_buffer);
1412
291k
    }
1413
    /* object */
1414
422k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1415
421k
    {
1416
421k
        return parse_object(item, input_buffer);
1417
421k
    }
1418
1419
310
    return false;
1420
422k
}
1421
1422
/* Render a value to text. */
1423
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1424
683k
{
1425
683k
    unsigned char *output = NULL;
1426
1427
683k
    if ((item == NULL) || (output_buffer == NULL))
1428
0
    {
1429
0
        return false;
1430
0
    }
1431
1432
683k
    switch ((item->type) & 0xFF)
1433
683k
    {
1434
388
        case cJSON_NULL:
1435
388
            output = ensure(output_buffer, 5);
1436
388
            if (output == NULL)
1437
0
            {
1438
0
                return false;
1439
0
            }
1440
388
            strcpy((char*)output, "null");
1441
388
            return true;
1442
1443
667
        case cJSON_False:
1444
667
            output = ensure(output_buffer, 6);
1445
667
            if (output == NULL)
1446
0
            {
1447
0
                return false;
1448
0
            }
1449
667
            strcpy((char*)output, "false");
1450
667
            return true;
1451
1452
209
        case cJSON_True:
1453
209
            output = ensure(output_buffer, 5);
1454
209
            if (output == NULL)
1455
0
            {
1456
0
                return false;
1457
0
            }
1458
209
            strcpy((char*)output, "true");
1459
209
            return true;
1460
1461
23.6k
        case cJSON_Number:
1462
23.6k
            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
1.07k
        case cJSON_String:
1483
1.07k
            return print_string(item, output_buffer);
1484
1485
242k
        case cJSON_Array:
1486
242k
            return print_array(item, output_buffer);
1487
1488
415k
        case cJSON_Object:
1489
415k
            return print_object(item, output_buffer);
1490
1491
0
        default:
1492
0
            return false;
1493
683k
    }
1494
683k
}
1495
1496
/* Build an array from input text. */
1497
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1498
291k
{
1499
291k
    cJSON *head = NULL; /* head of the linked list */
1500
291k
    cJSON *current_item = NULL;
1501
1502
291k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1503
1
    {
1504
1
        return false; /* to deeply nested */
1505
1
    }
1506
291k
    input_buffer->depth++;
1507
1508
291k
    if (buffer_at_offset(input_buffer)[0] != '[')
1509
0
    {
1510
        /* not an array */
1511
0
        goto fail;
1512
0
    }
1513
1514
291k
    input_buffer->offset++;
1515
291k
    buffer_skip_whitespace(input_buffer);
1516
291k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1517
3.10k
    {
1518
        /* empty array */
1519
3.10k
        goto success;
1520
3.10k
    }
1521
1522
    /* check if we skipped to the end of the buffer */
1523
288k
    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
288k
    input_buffer->offset--;
1531
    /* loop through the comma separated array elements */
1532
288k
    do
1533
727k
    {
1534
        /* allocate next item */
1535
727k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1536
727k
        if (new_item == NULL)
1537
0
        {
1538
0
            goto fail; /* allocation failure */
1539
0
        }
1540
1541
        /* attach next item to list */
1542
727k
        if (head == NULL)
1543
288k
        {
1544
            /* start the linked list */
1545
288k
            current_item = head = new_item;
1546
288k
        }
1547
439k
        else
1548
439k
        {
1549
            /* add to the end and advance */
1550
439k
            current_item->next = new_item;
1551
439k
            new_item->prev = current_item;
1552
439k
            current_item = new_item;
1553
439k
        }
1554
1555
        /* parse next value */
1556
727k
        input_buffer->offset++;
1557
727k
        buffer_skip_whitespace(input_buffer);
1558
727k
        if (!parse_value(current_item, input_buffer))
1559
44.2k
        {
1560
44.2k
            goto fail; /* failed to parse value */
1561
44.2k
        }
1562
683k
        buffer_skip_whitespace(input_buffer);
1563
683k
    }
1564
683k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1565
1566
244k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1567
108
    {
1568
108
        goto fail; /* expected end of array */
1569
108
    }
1570
1571
247k
success:
1572
247k
    input_buffer->depth--;
1573
1574
247k
    if (head != NULL) {
1575
244k
        head->prev = current_item;
1576
244k
    }
1577
1578
247k
    item->type = cJSON_Array;
1579
247k
    item->child = head;
1580
1581
247k
    input_buffer->offset++;
1582
1583
247k
    return true;
1584
1585
44.3k
fail:
1586
44.3k
    if (head != NULL)
1587
44.3k
    {
1588
44.3k
        cJSON_Delete(head);
1589
44.3k
    }
1590
1591
44.3k
    return false;
1592
244k
}
1593
1594
/* Render an array to text */
1595
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1596
242k
{
1597
242k
    unsigned char *output_pointer = NULL;
1598
242k
    size_t length = 0;
1599
242k
    cJSON *current_element = item->child;
1600
1601
242k
    if (output_buffer == NULL)
1602
0
    {
1603
0
        return false;
1604
0
    }
1605
1606
242k
    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
242k
    output_pointer = ensure(output_buffer, 1);
1614
242k
    if (output_pointer == NULL)
1615
0
    {
1616
0
        return false;
1617
0
    }
1618
1619
242k
    *output_pointer = '[';
1620
242k
    output_buffer->offset++;
1621
242k
    output_buffer->depth++;
1622
1623
912k
    while (current_element != NULL)
1624
670k
    {
1625
670k
        if (!print_value(current_element, output_buffer))
1626
0
        {
1627
0
            return false;
1628
0
        }
1629
670k
        update_offset(output_buffer);
1630
670k
        if (current_element->next)
1631
430k
        {
1632
430k
            length = (size_t) (output_buffer->format ? 2 : 1);
1633
430k
            output_pointer = ensure(output_buffer, length + 1);
1634
430k
            if (output_pointer == NULL)
1635
0
            {
1636
0
                return false;
1637
0
            }
1638
430k
            *output_pointer++ = ',';
1639
430k
            if(output_buffer->format)
1640
421k
            {
1641
421k
                *output_pointer++ = ' ';
1642
421k
            }
1643
430k
            *output_pointer = '\0';
1644
430k
            output_buffer->offset += length;
1645
430k
        }
1646
670k
        current_element = current_element->next;
1647
670k
    }
1648
1649
242k
    output_pointer = ensure(output_buffer, 2);
1650
242k
    if (output_pointer == NULL)
1651
0
    {
1652
0
        return false;
1653
0
    }
1654
242k
    *output_pointer++ = ']';
1655
242k
    *output_pointer = '\0';
1656
242k
    output_buffer->depth--;
1657
1658
242k
    return true;
1659
242k
}
1660
1661
/* Build an object from the text. */
1662
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1663
421k
{
1664
421k
    cJSON *head = NULL; /* linked list head */
1665
421k
    cJSON *current_item = NULL;
1666
1667
421k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1668
2
    {
1669
2
        return false; /* to deeply nested */
1670
2
    }
1671
421k
    input_buffer->depth++;
1672
1673
421k
    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
421k
    input_buffer->offset++;
1679
421k
    buffer_skip_whitespace(input_buffer);
1680
421k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1681
408k
    {
1682
408k
        goto success; /* empty object */
1683
408k
    }
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
21.7k
    {
1697
        /* allocate next item */
1698
21.7k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1699
21.7k
        if (new_item == NULL)
1700
0
        {
1701
0
            goto fail; /* allocation failure */
1702
0
        }
1703
1704
        /* attach next item to list */
1705
21.7k
        if (head == NULL)
1706
13.5k
        {
1707
            /* start the linked list */
1708
13.5k
            current_item = head = new_item;
1709
13.5k
        }
1710
8.21k
        else
1711
8.21k
        {
1712
            /* add to the end and advance */
1713
8.21k
            current_item->next = new_item;
1714
8.21k
            new_item->prev = current_item;
1715
8.21k
            current_item = new_item;
1716
8.21k
        }
1717
1718
21.7k
        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
21.7k
        input_buffer->offset++;
1725
21.7k
        buffer_skip_whitespace(input_buffer);
1726
21.7k
        if (!parse_string(current_item, input_buffer))
1727
146
        {
1728
146
            goto fail; /* failed to parse name */
1729
146
        }
1730
21.6k
        buffer_skip_whitespace(input_buffer);
1731
1732
        /* swap valuestring and string, because we parsed the name */
1733
21.6k
        current_item->string = current_item->valuestring;
1734
21.6k
        current_item->valuestring = NULL;
1735
1736
21.6k
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1737
30
        {
1738
30
            goto fail; /* invalid object */
1739
30
        }
1740
1741
        /* parse the value */
1742
21.5k
        input_buffer->offset++;
1743
21.5k
        buffer_skip_whitespace(input_buffer);
1744
21.5k
        if (!parse_value(current_item, input_buffer))
1745
4.00k
        {
1746
4.00k
            goto fail; /* failed to parse value */
1747
4.00k
        }
1748
17.5k
        buffer_skip_whitespace(input_buffer);
1749
17.5k
    }
1750
17.5k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1751
1752
9.35k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1753
43
    {
1754
43
        goto fail; /* expected end of object */
1755
43
    }
1756
1757
417k
success:
1758
417k
    input_buffer->depth--;
1759
1760
417k
    if (head != NULL) {
1761
9.31k
        head->prev = current_item;
1762
9.31k
    }
1763
1764
417k
    item->type = cJSON_Object;
1765
417k
    item->child = head;
1766
1767
417k
    input_buffer->offset++;
1768
417k
    return true;
1769
1770
4.22k
fail:
1771
4.22k
    if (head != NULL)
1772
4.22k
    {
1773
4.22k
        cJSON_Delete(head);
1774
4.22k
    }
1775
1776
4.22k
    return false;
1777
9.35k
}
1778
1779
/* Render an object to text. */
1780
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1781
415k
{
1782
415k
    unsigned char *output_pointer = NULL;
1783
415k
    size_t length = 0;
1784
415k
    cJSON *current_item = item->child;
1785
1786
415k
    if (output_buffer == NULL)
1787
0
    {
1788
0
        return false;
1789
0
    }
1790
1791
415k
    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
415k
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1798
415k
    output_pointer = ensure(output_buffer, length + 1);
1799
415k
    if (output_pointer == NULL)
1800
0
    {
1801
0
        return false;
1802
0
    }
1803
1804
415k
    *output_pointer++ = '{';
1805
415k
    output_buffer->depth++;
1806
415k
    if (output_buffer->format)
1807
414k
    {
1808
414k
        *output_pointer++ = '\n';
1809
414k
    }
1810
415k
    output_buffer->offset += length;
1811
1812
427k
    while (current_item)
1813
12.7k
    {
1814
12.7k
        if (output_buffer->format)
1815
11.1k
        {
1816
11.1k
            size_t i;
1817
11.1k
            output_pointer = ensure(output_buffer, output_buffer->depth);
1818
11.1k
            if (output_pointer == NULL)
1819
0
            {
1820
0
                return false;
1821
0
            }
1822
4.27M
            for (i = 0; i < output_buffer->depth; i++)
1823
4.26M
            {
1824
4.26M
                *output_pointer++ = '\t';
1825
4.26M
            }
1826
11.1k
            output_buffer->offset += output_buffer->depth;
1827
11.1k
        }
1828
1829
        /* print key */
1830
12.7k
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1831
0
        {
1832
0
            return false;
1833
0
        }
1834
12.7k
        update_offset(output_buffer);
1835
1836
12.7k
        length = (size_t) (output_buffer->format ? 2 : 1);
1837
12.7k
        output_pointer = ensure(output_buffer, length);
1838
12.7k
        if (output_pointer == NULL)
1839
0
        {
1840
0
            return false;
1841
0
        }
1842
12.7k
        *output_pointer++ = ':';
1843
12.7k
        if (output_buffer->format)
1844
11.1k
        {
1845
11.1k
            *output_pointer++ = '\t';
1846
11.1k
        }
1847
12.7k
        output_buffer->offset += length;
1848
1849
        /* print value */
1850
12.7k
        if (!print_value(current_item, output_buffer))
1851
0
        {
1852
0
            return false;
1853
0
        }
1854
12.7k
        update_offset(output_buffer);
1855
1856
        /* print comma if not last */
1857
12.7k
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1858
12.7k
        output_pointer = ensure(output_buffer, length + 1);
1859
12.7k
        if (output_pointer == NULL)
1860
0
        {
1861
0
            return false;
1862
0
        }
1863
12.7k
        if (current_item->next)
1864
4.02k
        {
1865
4.02k
            *output_pointer++ = ',';
1866
4.02k
        }
1867
1868
12.7k
        if (output_buffer->format)
1869
11.1k
        {
1870
11.1k
            *output_pointer++ = '\n';
1871
11.1k
        }
1872
12.7k
        *output_pointer = '\0';
1873
12.7k
        output_buffer->offset += length;
1874
1875
12.7k
        current_item = current_item->next;
1876
12.7k
    }
1877
1878
415k
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1879
415k
    if (output_pointer == NULL)
1880
0
    {
1881
0
        return false;
1882
0
    }
1883
415k
    if (output_buffer->format)
1884
414k
    {
1885
414k
        size_t i;
1886
225M
        for (i = 0; i < (output_buffer->depth - 1); i++)
1887
224M
        {
1888
224M
            *output_pointer++ = '\t';
1889
224M
        }
1890
414k
    }
1891
415k
    *output_pointer++ = '}';
1892
415k
    *output_pointer = '\0';
1893
415k
    output_buffer->depth--;
1894
1895
415k
    return true;
1896
415k
}
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
289
{
2877
289
    *input += static_strlen("//");
2878
2879
505
    for (; (*input)[0] != '\0'; ++(*input))
2880
485
    {
2881
485
        if ((*input)[0] == '\n') {
2882
269
            *input += static_strlen("\n");
2883
269
            return;
2884
269
        }
2885
485
    }
2886
289
}
2887
2888
static void skip_multiline_comment(char **input)
2889
289
{
2890
289
    *input += static_strlen("/*");
2891
2892
1.35k
    for (; (*input)[0] != '\0'; ++(*input))
2893
1.31k
    {
2894
1.31k
        if (((*input)[0] == '*') && ((*input)[1] == '/'))
2895
246
        {
2896
246
            *input += static_strlen("*/");
2897
246
            return;
2898
246
        }
2899
1.31k
    }
2900
289
}
2901
2902
13.0k
static void minify_string(char **input, char **output) {
2903
13.0k
    (*output)[0] = (*input)[0];
2904
13.0k
    *input += static_strlen("\"");
2905
13.0k
    *output += static_strlen("\"");
2906
2907
2908
11.8M
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2909
11.8M
        (*output)[0] = (*input)[0];
2910
2911
11.8M
        if ((*input)[0] == '\"') {
2912
12.9k
            (*output)[0] = '\"';
2913
12.9k
            *input += static_strlen("\"");
2914
12.9k
            *output += static_strlen("\"");
2915
12.9k
            return;
2916
11.8M
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2917
1.76k
            (*output)[1] = (*input)[1];
2918
1.76k
            *input += static_strlen("\"");
2919
1.76k
            *output += static_strlen("\"");
2920
1.76k
        }
2921
11.8M
    }
2922
13.0k
}
2923
2924
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2925
914
{
2926
914
    char *into = json;
2927
2928
914
    if (json == NULL)
2929
0
    {
2930
0
        return;
2931
0
    }
2932
2933
2.69M
    while (json[0] != '\0')
2934
2.69M
    {
2935
2.69M
        switch (json[0])
2936
2.69M
        {
2937
1.55k
            case ' ':
2938
1.81k
            case '\t':
2939
2.15k
            case '\r':
2940
3.29k
            case '\n':
2941
3.29k
                json++;
2942
3.29k
                break;
2943
2944
805
            case '/':
2945
805
                if (json[1] == '/')
2946
289
                {
2947
289
                    skip_oneline_comment(&json);
2948
289
                }
2949
516
                else if (json[1] == '*')
2950
289
                {
2951
289
                    skip_multiline_comment(&json);
2952
289
                } else {
2953
227
                    json++;
2954
227
                }
2955
805
                break;
2956
2957
13.0k
            case '\"':
2958
13.0k
                minify_string(&json, (char**)&into);
2959
13.0k
                break;
2960
2961
2.68M
            default:
2962
2.68M
                into[0] = json[0];
2963
2.68M
                json++;
2964
2.68M
                into++;
2965
2.69M
        }
2966
2.69M
    }
2967
2968
    /* and null-terminate. */
2969
914
    *into = '\0';
2970
914
}
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
}