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