xref: /aosp_15_r20/external/mesa3d/src/util/parson.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker 
4*61046927SAndroid Build Coastguard Worker  Parson 1.5.3 (https://github.com/kgabis/parson)
5*61046927SAndroid Build Coastguard Worker  Copyright (c) 2012 - 2023 Krzysztof Gabis
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker  Permission is hereby granted, free of charge, to any person obtaining a copy
8*61046927SAndroid Build Coastguard Worker  of this software and associated documentation files (the "Software"), to deal
9*61046927SAndroid Build Coastguard Worker  in the Software without restriction, including without limitation the rights
10*61046927SAndroid Build Coastguard Worker  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*61046927SAndroid Build Coastguard Worker  copies of the Software, and to permit persons to whom the Software is
12*61046927SAndroid Build Coastguard Worker  furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker  The above copyright notice and this permission notice shall be included in
15*61046927SAndroid Build Coastguard Worker  all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*61046927SAndroid Build Coastguard Worker  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*61046927SAndroid Build Coastguard Worker  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*61046927SAndroid Build Coastguard Worker  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*61046927SAndroid Build Coastguard Worker  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23*61046927SAndroid Build Coastguard Worker  THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker */
25*61046927SAndroid Build Coastguard Worker #ifdef _MSC_VER
26*61046927SAndroid Build Coastguard Worker #ifndef _CRT_SECURE_NO_WARNINGS
27*61046927SAndroid Build Coastguard Worker #define _CRT_SECURE_NO_WARNINGS
28*61046927SAndroid Build Coastguard Worker #endif /* _CRT_SECURE_NO_WARNINGS */
29*61046927SAndroid Build Coastguard Worker #endif /* _MSC_VER */
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #include "parson.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #define PARSON_IMPL_VERSION_MAJOR 1
34*61046927SAndroid Build Coastguard Worker #define PARSON_IMPL_VERSION_MINOR 5
35*61046927SAndroid Build Coastguard Worker #define PARSON_IMPL_VERSION_PATCH 3
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker #if (PARSON_VERSION_MAJOR != PARSON_IMPL_VERSION_MAJOR)\
38*61046927SAndroid Build Coastguard Worker || (PARSON_VERSION_MINOR != PARSON_IMPL_VERSION_MINOR)\
39*61046927SAndroid Build Coastguard Worker || (PARSON_VERSION_PATCH != PARSON_IMPL_VERSION_PATCH)
40*61046927SAndroid Build Coastguard Worker #error "parson version mismatch between parson.c and parson.h"
41*61046927SAndroid Build Coastguard Worker #endif
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
44*61046927SAndroid Build Coastguard Worker #include <stdio.h>
45*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
46*61046927SAndroid Build Coastguard Worker #include <string.h>
47*61046927SAndroid Build Coastguard Worker #include <ctype.h>
48*61046927SAndroid Build Coastguard Worker #include <math.h>
49*61046927SAndroid Build Coastguard Worker #include <errno.h>
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker /* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you
52*61046927SAndroid Build Coastguard Worker  * don't have to. */
53*61046927SAndroid Build Coastguard Worker #ifdef sscanf
54*61046927SAndroid Build Coastguard Worker #undef sscanf
55*61046927SAndroid Build Coastguard Worker #define sscanf THINK_TWICE_ABOUT_USING_SSCANF
56*61046927SAndroid Build Coastguard Worker #endif
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker /* strcpy is unsafe */
59*61046927SAndroid Build Coastguard Worker #ifdef strcpy
60*61046927SAndroid Build Coastguard Worker #undef strcpy
61*61046927SAndroid Build Coastguard Worker #endif
62*61046927SAndroid Build Coastguard Worker #define strcpy USE_MEMCPY_INSTEAD_OF_STRCPY
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker #define STARTING_CAPACITY 16
65*61046927SAndroid Build Coastguard Worker #define MAX_NESTING       2048
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker #ifndef PARSON_DEFAULT_FLOAT_FORMAT
68*61046927SAndroid Build Coastguard Worker #define PARSON_DEFAULT_FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */
69*61046927SAndroid Build Coastguard Worker #endif
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker #ifndef PARSON_NUM_BUF_SIZE
72*61046927SAndroid Build Coastguard Worker #define PARSON_NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */
73*61046927SAndroid Build Coastguard Worker #endif
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker #ifndef PARSON_INDENT_STR
76*61046927SAndroid Build Coastguard Worker #define PARSON_INDENT_STR "    "
77*61046927SAndroid Build Coastguard Worker #endif
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker #define SIZEOF_TOKEN(a)       (sizeof(a) - 1)
80*61046927SAndroid Build Coastguard Worker #define SKIP_CHAR(str)        ((*str)++)
81*61046927SAndroid Build Coastguard Worker #define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); }
82*61046927SAndroid Build Coastguard Worker #define MAX(a, b)             ((a) > (b) ? (a) : (b))
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker #undef malloc
85*61046927SAndroid Build Coastguard Worker #undef free
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker #if defined(isnan) && defined(isinf)
88*61046927SAndroid Build Coastguard Worker #define IS_NUMBER_INVALID(x) (isnan((x)) || isinf((x)))
89*61046927SAndroid Build Coastguard Worker #else
90*61046927SAndroid Build Coastguard Worker #define IS_NUMBER_INVALID(x) (((x) * 0.0) != 0.0)
91*61046927SAndroid Build Coastguard Worker #endif
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker #define OBJECT_INVALID_IX ((size_t)-1)
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker static JSON_Malloc_Function parson_malloc = malloc;
96*61046927SAndroid Build Coastguard Worker static JSON_Free_Function parson_free = free;
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker static int parson_escape_slashes = 1;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker static char *parson_float_format = NULL;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker static JSON_Number_Serialization_Function parson_number_serialization_function = NULL;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker typedef int parson_bool_t;
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker #define PARSON_TRUE 1
109*61046927SAndroid Build Coastguard Worker #define PARSON_FALSE 0
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker typedef struct json_string {
112*61046927SAndroid Build Coastguard Worker     char *chars;
113*61046927SAndroid Build Coastguard Worker     size_t length;
114*61046927SAndroid Build Coastguard Worker } JSON_String;
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker /* Type definitions */
117*61046927SAndroid Build Coastguard Worker typedef union json_value_value {
118*61046927SAndroid Build Coastguard Worker     JSON_String  string;
119*61046927SAndroid Build Coastguard Worker     double       number;
120*61046927SAndroid Build Coastguard Worker     JSON_Object *object;
121*61046927SAndroid Build Coastguard Worker     JSON_Array  *array;
122*61046927SAndroid Build Coastguard Worker     int          boolean;
123*61046927SAndroid Build Coastguard Worker     int          null;
124*61046927SAndroid Build Coastguard Worker } JSON_Value_Value;
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker struct json_value_t {
127*61046927SAndroid Build Coastguard Worker     JSON_Value      *parent;
128*61046927SAndroid Build Coastguard Worker     JSON_Value_Type  type;
129*61046927SAndroid Build Coastguard Worker     JSON_Value_Value value;
130*61046927SAndroid Build Coastguard Worker };
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker struct json_object_t {
133*61046927SAndroid Build Coastguard Worker     JSON_Value    *wrapping_value;
134*61046927SAndroid Build Coastguard Worker     size_t        *cells;
135*61046927SAndroid Build Coastguard Worker     unsigned long *hashes;
136*61046927SAndroid Build Coastguard Worker     char         **names;
137*61046927SAndroid Build Coastguard Worker     JSON_Value   **values;
138*61046927SAndroid Build Coastguard Worker     size_t        *cell_ixs;
139*61046927SAndroid Build Coastguard Worker     size_t         count;
140*61046927SAndroid Build Coastguard Worker     size_t         item_capacity;
141*61046927SAndroid Build Coastguard Worker     size_t         cell_capacity;
142*61046927SAndroid Build Coastguard Worker };
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker struct json_array_t {
145*61046927SAndroid Build Coastguard Worker     JSON_Value  *wrapping_value;
146*61046927SAndroid Build Coastguard Worker     JSON_Value **items;
147*61046927SAndroid Build Coastguard Worker     size_t       count;
148*61046927SAndroid Build Coastguard Worker     size_t       capacity;
149*61046927SAndroid Build Coastguard Worker };
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker /* Various */
152*61046927SAndroid Build Coastguard Worker static char * read_file(const char *filename);
153*61046927SAndroid Build Coastguard Worker static void   remove_comments(char *string, const char *start_token, const char *end_token);
154*61046927SAndroid Build Coastguard Worker static char * parson_strndup(const char *string, size_t n);
155*61046927SAndroid Build Coastguard Worker static char * parson_strdup(const char *string);
156*61046927SAndroid Build Coastguard Worker static int    parson_sprintf(char * s, const char * format, ...);
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker static int    hex_char_to_int(char c);
159*61046927SAndroid Build Coastguard Worker static JSON_Status parse_utf16_hex(const char *string, unsigned int *result);
160*61046927SAndroid Build Coastguard Worker static int         num_bytes_in_utf8_sequence(unsigned char c);
161*61046927SAndroid Build Coastguard Worker static JSON_Status   verify_utf8_sequence(const unsigned char *string, int *len);
162*61046927SAndroid Build Coastguard Worker static parson_bool_t is_valid_utf8(const char *string, size_t string_len);
163*61046927SAndroid Build Coastguard Worker static parson_bool_t is_decimal(const char *string, size_t length);
164*61046927SAndroid Build Coastguard Worker static unsigned long hash_string(const char *string, size_t n);
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker /* JSON Object */
167*61046927SAndroid Build Coastguard Worker static JSON_Object * json_object_make(JSON_Value *wrapping_value);
168*61046927SAndroid Build Coastguard Worker static JSON_Status   json_object_init(JSON_Object *object, size_t capacity);
169*61046927SAndroid Build Coastguard Worker static void          json_object_deinit(JSON_Object *object, parson_bool_t free_keys, parson_bool_t free_values);
170*61046927SAndroid Build Coastguard Worker static JSON_Status   json_object_grow_and_rehash(JSON_Object *object);
171*61046927SAndroid Build Coastguard Worker static size_t        json_object_get_cell_ix(const JSON_Object *object, const char *key, size_t key_len, unsigned long hash, parson_bool_t *out_found);
172*61046927SAndroid Build Coastguard Worker static JSON_Status   json_object_add(JSON_Object *object, char *name, JSON_Value *value);
173*61046927SAndroid Build Coastguard Worker static JSON_Value  * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len);
174*61046927SAndroid Build Coastguard Worker static JSON_Status   json_object_remove_internal(JSON_Object *object, const char *name, parson_bool_t free_value);
175*61046927SAndroid Build Coastguard Worker static JSON_Status   json_object_dotremove_internal(JSON_Object *object, const char *name, parson_bool_t free_value);
176*61046927SAndroid Build Coastguard Worker static void          json_object_free(JSON_Object *object);
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker /* JSON Array */
179*61046927SAndroid Build Coastguard Worker static JSON_Array * json_array_make(JSON_Value *wrapping_value);
180*61046927SAndroid Build Coastguard Worker static JSON_Status  json_array_add(JSON_Array *array, JSON_Value *value);
181*61046927SAndroid Build Coastguard Worker static JSON_Status  json_array_resize(JSON_Array *array, size_t new_capacity);
182*61046927SAndroid Build Coastguard Worker static void         json_array_free(JSON_Array *array);
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker /* JSON Value */
185*61046927SAndroid Build Coastguard Worker static JSON_Value * json_value_init_string_no_copy(char *string, size_t length);
186*61046927SAndroid Build Coastguard Worker static const JSON_String * json_value_get_string_desc(const JSON_Value *value);
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker /* Parser */
189*61046927SAndroid Build Coastguard Worker static JSON_Status   skip_quotes(const char **string);
190*61046927SAndroid Build Coastguard Worker static JSON_Status   parse_utf16(const char **unprocessed, char **processed);
191*61046927SAndroid Build Coastguard Worker static char *        process_string(const char *input, size_t input_len, size_t *output_len);
192*61046927SAndroid Build Coastguard Worker static char *        get_quoted_string(const char **string, size_t *output_string_len);
193*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_object_value(const char **string, size_t nesting);
194*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_array_value(const char **string, size_t nesting);
195*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_string_value(const char **string);
196*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_boolean_value(const char **string);
197*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_number_value(const char **string);
198*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_null_value(const char **string);
199*61046927SAndroid Build Coastguard Worker static JSON_Value *  parse_value(const char **string, size_t nesting);
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker /* Serialization */
202*61046927SAndroid Build Coastguard Worker static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf);
203*61046927SAndroid Build Coastguard Worker static int json_serialize_string(const char *string, size_t len, char *buf);
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker /* Various */
read_file(const char * filename)206*61046927SAndroid Build Coastguard Worker static char * read_file(const char * filename) {
207*61046927SAndroid Build Coastguard Worker     FILE *fp = fopen(filename, "r");
208*61046927SAndroid Build Coastguard Worker     size_t size_to_read = 0;
209*61046927SAndroid Build Coastguard Worker     size_t size_read = 0;
210*61046927SAndroid Build Coastguard Worker     long pos;
211*61046927SAndroid Build Coastguard Worker     char *file_contents;
212*61046927SAndroid Build Coastguard Worker     if (!fp) {
213*61046927SAndroid Build Coastguard Worker         return NULL;
214*61046927SAndroid Build Coastguard Worker     }
215*61046927SAndroid Build Coastguard Worker     fseek(fp, 0L, SEEK_END);
216*61046927SAndroid Build Coastguard Worker     pos = ftell(fp);
217*61046927SAndroid Build Coastguard Worker     if (pos < 0) {
218*61046927SAndroid Build Coastguard Worker         fclose(fp);
219*61046927SAndroid Build Coastguard Worker         return NULL;
220*61046927SAndroid Build Coastguard Worker     }
221*61046927SAndroid Build Coastguard Worker     size_to_read = pos;
222*61046927SAndroid Build Coastguard Worker     rewind(fp);
223*61046927SAndroid Build Coastguard Worker     file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1));
224*61046927SAndroid Build Coastguard Worker     if (!file_contents) {
225*61046927SAndroid Build Coastguard Worker         fclose(fp);
226*61046927SAndroid Build Coastguard Worker         return NULL;
227*61046927SAndroid Build Coastguard Worker     }
228*61046927SAndroid Build Coastguard Worker     size_read = fread(file_contents, 1, size_to_read, fp);
229*61046927SAndroid Build Coastguard Worker     if (size_read == 0 || ferror(fp)) {
230*61046927SAndroid Build Coastguard Worker         fclose(fp);
231*61046927SAndroid Build Coastguard Worker         parson_free(file_contents);
232*61046927SAndroid Build Coastguard Worker         return NULL;
233*61046927SAndroid Build Coastguard Worker     }
234*61046927SAndroid Build Coastguard Worker     fclose(fp);
235*61046927SAndroid Build Coastguard Worker     file_contents[size_read] = '\0';
236*61046927SAndroid Build Coastguard Worker     return file_contents;
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker 
remove_comments(char * string,const char * start_token,const char * end_token)239*61046927SAndroid Build Coastguard Worker static void remove_comments(char *string, const char *start_token, const char *end_token) {
240*61046927SAndroid Build Coastguard Worker     parson_bool_t in_string = PARSON_FALSE, escaped = PARSON_FALSE;
241*61046927SAndroid Build Coastguard Worker     size_t i;
242*61046927SAndroid Build Coastguard Worker     char *ptr = NULL, current_char;
243*61046927SAndroid Build Coastguard Worker     size_t start_token_len = strlen(start_token);
244*61046927SAndroid Build Coastguard Worker     size_t end_token_len = strlen(end_token);
245*61046927SAndroid Build Coastguard Worker     if (start_token_len == 0 || end_token_len == 0) {
246*61046927SAndroid Build Coastguard Worker         return;
247*61046927SAndroid Build Coastguard Worker     }
248*61046927SAndroid Build Coastguard Worker     while ((current_char = *string) != '\0') {
249*61046927SAndroid Build Coastguard Worker         if (current_char == '\\' && !escaped) {
250*61046927SAndroid Build Coastguard Worker             escaped = PARSON_TRUE;
251*61046927SAndroid Build Coastguard Worker             string++;
252*61046927SAndroid Build Coastguard Worker             continue;
253*61046927SAndroid Build Coastguard Worker         } else if (current_char == '\"' && !escaped) {
254*61046927SAndroid Build Coastguard Worker             in_string = !in_string;
255*61046927SAndroid Build Coastguard Worker         } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
256*61046927SAndroid Build Coastguard Worker             for(i = 0; i < start_token_len; i++) {
257*61046927SAndroid Build Coastguard Worker                 string[i] = ' ';
258*61046927SAndroid Build Coastguard Worker             }
259*61046927SAndroid Build Coastguard Worker             string = string + start_token_len;
260*61046927SAndroid Build Coastguard Worker             ptr = strstr(string, end_token);
261*61046927SAndroid Build Coastguard Worker             if (!ptr) {
262*61046927SAndroid Build Coastguard Worker                 return;
263*61046927SAndroid Build Coastguard Worker             }
264*61046927SAndroid Build Coastguard Worker             for (i = 0; i < (ptr - string) + end_token_len; i++) {
265*61046927SAndroid Build Coastguard Worker                 string[i] = ' ';
266*61046927SAndroid Build Coastguard Worker             }
267*61046927SAndroid Build Coastguard Worker             string = ptr + end_token_len - 1;
268*61046927SAndroid Build Coastguard Worker         }
269*61046927SAndroid Build Coastguard Worker         escaped = PARSON_FALSE;
270*61046927SAndroid Build Coastguard Worker         string++;
271*61046927SAndroid Build Coastguard Worker     }
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker 
parson_strndup(const char * string,size_t n)274*61046927SAndroid Build Coastguard Worker static char * parson_strndup(const char *string, size_t n) {
275*61046927SAndroid Build Coastguard Worker     /* We expect the caller has validated that 'n' fits within the input buffer. */
276*61046927SAndroid Build Coastguard Worker     char *output_string = (char*)parson_malloc(n + 1);
277*61046927SAndroid Build Coastguard Worker     if (!output_string) {
278*61046927SAndroid Build Coastguard Worker         return NULL;
279*61046927SAndroid Build Coastguard Worker     }
280*61046927SAndroid Build Coastguard Worker     output_string[n] = '\0';
281*61046927SAndroid Build Coastguard Worker     memcpy(output_string, string, n);
282*61046927SAndroid Build Coastguard Worker     return output_string;
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
parson_strdup(const char * string)285*61046927SAndroid Build Coastguard Worker static char * parson_strdup(const char *string) {
286*61046927SAndroid Build Coastguard Worker     return parson_strndup(string, strlen(string));
287*61046927SAndroid Build Coastguard Worker }
288*61046927SAndroid Build Coastguard Worker 
parson_sprintf(char * s,const char * format,...)289*61046927SAndroid Build Coastguard Worker static int parson_sprintf(char * s, const char * format, ...) {
290*61046927SAndroid Build Coastguard Worker     int result;
291*61046927SAndroid Build Coastguard Worker     va_list args;
292*61046927SAndroid Build Coastguard Worker     va_start(args, format);
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker     #if defined(__APPLE__) && defined(__clang__)
295*61046927SAndroid Build Coastguard Worker         #pragma clang diagnostic push
296*61046927SAndroid Build Coastguard Worker         #pragma clang diagnostic ignored "-Wdeprecated-declarations"
297*61046927SAndroid Build Coastguard Worker     #endif
298*61046927SAndroid Build Coastguard Worker         result = vsprintf(s, format, args);
299*61046927SAndroid Build Coastguard Worker     #if defined(__APPLE__) && defined(__clang__)
300*61046927SAndroid Build Coastguard Worker         #pragma clang diagnostic pop
301*61046927SAndroid Build Coastguard Worker     #endif
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker     va_end(args);
304*61046927SAndroid Build Coastguard Worker     return result;
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker 
hex_char_to_int(char c)308*61046927SAndroid Build Coastguard Worker static int hex_char_to_int(char c) {
309*61046927SAndroid Build Coastguard Worker     if (c >= '0' && c <= '9') {
310*61046927SAndroid Build Coastguard Worker         return c - '0';
311*61046927SAndroid Build Coastguard Worker     } else if (c >= 'a' && c <= 'f') {
312*61046927SAndroid Build Coastguard Worker         return c - 'a' + 10;
313*61046927SAndroid Build Coastguard Worker     } else if (c >= 'A' && c <= 'F') {
314*61046927SAndroid Build Coastguard Worker         return c - 'A' + 10;
315*61046927SAndroid Build Coastguard Worker     }
316*61046927SAndroid Build Coastguard Worker     return -1;
317*61046927SAndroid Build Coastguard Worker }
318*61046927SAndroid Build Coastguard Worker 
parse_utf16_hex(const char * s,unsigned int * result)319*61046927SAndroid Build Coastguard Worker static JSON_Status parse_utf16_hex(const char *s, unsigned int *result) {
320*61046927SAndroid Build Coastguard Worker     int x1, x2, x3, x4;
321*61046927SAndroid Build Coastguard Worker     if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') {
322*61046927SAndroid Build Coastguard Worker         return JSONFailure;
323*61046927SAndroid Build Coastguard Worker     }
324*61046927SAndroid Build Coastguard Worker     x1 = hex_char_to_int(s[0]);
325*61046927SAndroid Build Coastguard Worker     x2 = hex_char_to_int(s[1]);
326*61046927SAndroid Build Coastguard Worker     x3 = hex_char_to_int(s[2]);
327*61046927SAndroid Build Coastguard Worker     x4 = hex_char_to_int(s[3]);
328*61046927SAndroid Build Coastguard Worker     if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) {
329*61046927SAndroid Build Coastguard Worker         return JSONFailure;
330*61046927SAndroid Build Coastguard Worker     }
331*61046927SAndroid Build Coastguard Worker     *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4);
332*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
num_bytes_in_utf8_sequence(unsigned char c)335*61046927SAndroid Build Coastguard Worker static int num_bytes_in_utf8_sequence(unsigned char c) {
336*61046927SAndroid Build Coastguard Worker     if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
337*61046927SAndroid Build Coastguard Worker         return 0;
338*61046927SAndroid Build Coastguard Worker     } else if ((c & 0x80) == 0) {    /* 0xxxxxxx */
339*61046927SAndroid Build Coastguard Worker         return 1;
340*61046927SAndroid Build Coastguard Worker     } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
341*61046927SAndroid Build Coastguard Worker         return 2;
342*61046927SAndroid Build Coastguard Worker     } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
343*61046927SAndroid Build Coastguard Worker         return 3;
344*61046927SAndroid Build Coastguard Worker     } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
345*61046927SAndroid Build Coastguard Worker         return 4;
346*61046927SAndroid Build Coastguard Worker     }
347*61046927SAndroid Build Coastguard Worker     return 0; /* won't happen */
348*61046927SAndroid Build Coastguard Worker }
349*61046927SAndroid Build Coastguard Worker 
verify_utf8_sequence(const unsigned char * string,int * len)350*61046927SAndroid Build Coastguard Worker static JSON_Status verify_utf8_sequence(const unsigned char *string, int *len) {
351*61046927SAndroid Build Coastguard Worker     unsigned int cp = 0;
352*61046927SAndroid Build Coastguard Worker     *len = num_bytes_in_utf8_sequence(string[0]);
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker     if (*len == 1) {
355*61046927SAndroid Build Coastguard Worker         cp = string[0];
356*61046927SAndroid Build Coastguard Worker     } else if (*len == 2 && IS_CONT(string[1])) {
357*61046927SAndroid Build Coastguard Worker         cp = string[0] & 0x1F;
358*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[1] & 0x3F);
359*61046927SAndroid Build Coastguard Worker     } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
360*61046927SAndroid Build Coastguard Worker         cp = ((unsigned char)string[0]) & 0xF;
361*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[1] & 0x3F);
362*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[2] & 0x3F);
363*61046927SAndroid Build Coastguard Worker     } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
364*61046927SAndroid Build Coastguard Worker         cp = string[0] & 0x7;
365*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[1] & 0x3F);
366*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[2] & 0x3F);
367*61046927SAndroid Build Coastguard Worker         cp = (cp << 6) | (string[3] & 0x3F);
368*61046927SAndroid Build Coastguard Worker     } else {
369*61046927SAndroid Build Coastguard Worker         return JSONFailure;
370*61046927SAndroid Build Coastguard Worker     }
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker     /* overlong encodings */
373*61046927SAndroid Build Coastguard Worker     if ((cp < 0x80    && *len > 1) ||
374*61046927SAndroid Build Coastguard Worker         (cp < 0x800   && *len > 2) ||
375*61046927SAndroid Build Coastguard Worker         (cp < 0x10000 && *len > 3)) {
376*61046927SAndroid Build Coastguard Worker         return JSONFailure;
377*61046927SAndroid Build Coastguard Worker     }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker     /* invalid unicode */
380*61046927SAndroid Build Coastguard Worker     if (cp > 0x10FFFF) {
381*61046927SAndroid Build Coastguard Worker         return JSONFailure;
382*61046927SAndroid Build Coastguard Worker     }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker     /* surrogate halves */
385*61046927SAndroid Build Coastguard Worker     if (cp >= 0xD800 && cp <= 0xDFFF) {
386*61046927SAndroid Build Coastguard Worker         return JSONFailure;
387*61046927SAndroid Build Coastguard Worker     }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker 
is_valid_utf8(const char * string,size_t string_len)392*61046927SAndroid Build Coastguard Worker static int is_valid_utf8(const char *string, size_t string_len) {
393*61046927SAndroid Build Coastguard Worker     int len = 0;
394*61046927SAndroid Build Coastguard Worker     const char *string_end =  string + string_len;
395*61046927SAndroid Build Coastguard Worker     while (string < string_end) {
396*61046927SAndroid Build Coastguard Worker         if (verify_utf8_sequence((const unsigned char*)string, &len) != JSONSuccess) {
397*61046927SAndroid Build Coastguard Worker             return PARSON_FALSE;
398*61046927SAndroid Build Coastguard Worker         }
399*61046927SAndroid Build Coastguard Worker         string += len;
400*61046927SAndroid Build Coastguard Worker     }
401*61046927SAndroid Build Coastguard Worker     return PARSON_TRUE;
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
is_decimal(const char * string,size_t length)404*61046927SAndroid Build Coastguard Worker static parson_bool_t is_decimal(const char *string, size_t length) {
405*61046927SAndroid Build Coastguard Worker     if (length > 1 && string[0] == '0' && string[1] != '.') {
406*61046927SAndroid Build Coastguard Worker         return PARSON_FALSE;
407*61046927SAndroid Build Coastguard Worker     }
408*61046927SAndroid Build Coastguard Worker     if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
409*61046927SAndroid Build Coastguard Worker         return PARSON_FALSE;
410*61046927SAndroid Build Coastguard Worker     }
411*61046927SAndroid Build Coastguard Worker     while (length--) {
412*61046927SAndroid Build Coastguard Worker         if (strchr("xX", string[length])) {
413*61046927SAndroid Build Coastguard Worker             return PARSON_FALSE;
414*61046927SAndroid Build Coastguard Worker         }
415*61046927SAndroid Build Coastguard Worker     }
416*61046927SAndroid Build Coastguard Worker     return PARSON_TRUE;
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker 
hash_string(const char * string,size_t n)419*61046927SAndroid Build Coastguard Worker static unsigned long hash_string(const char *string, size_t n) {
420*61046927SAndroid Build Coastguard Worker #ifdef PARSON_FORCE_HASH_COLLISIONS
421*61046927SAndroid Build Coastguard Worker     (void)string;
422*61046927SAndroid Build Coastguard Worker     (void)n;
423*61046927SAndroid Build Coastguard Worker     return 0;
424*61046927SAndroid Build Coastguard Worker #else
425*61046927SAndroid Build Coastguard Worker     unsigned long hash = 5381;
426*61046927SAndroid Build Coastguard Worker     unsigned char c;
427*61046927SAndroid Build Coastguard Worker     size_t i = 0;
428*61046927SAndroid Build Coastguard Worker     for (i = 0; i < n; i++) {
429*61046927SAndroid Build Coastguard Worker         c = string[i];
430*61046927SAndroid Build Coastguard Worker         if (c == '\0') {
431*61046927SAndroid Build Coastguard Worker             break;
432*61046927SAndroid Build Coastguard Worker         }
433*61046927SAndroid Build Coastguard Worker         hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
434*61046927SAndroid Build Coastguard Worker     }
435*61046927SAndroid Build Coastguard Worker     return hash;
436*61046927SAndroid Build Coastguard Worker #endif
437*61046927SAndroid Build Coastguard Worker }
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker /* JSON Object */
json_object_make(JSON_Value * wrapping_value)440*61046927SAndroid Build Coastguard Worker static JSON_Object * json_object_make(JSON_Value *wrapping_value) {
441*61046927SAndroid Build Coastguard Worker     JSON_Status res = JSONFailure;
442*61046927SAndroid Build Coastguard Worker     JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
443*61046927SAndroid Build Coastguard Worker     if (new_obj == NULL) {
444*61046927SAndroid Build Coastguard Worker         return NULL;
445*61046927SAndroid Build Coastguard Worker     }
446*61046927SAndroid Build Coastguard Worker     new_obj->wrapping_value = wrapping_value;
447*61046927SAndroid Build Coastguard Worker     res = json_object_init(new_obj, 0);
448*61046927SAndroid Build Coastguard Worker     if (res != JSONSuccess) {
449*61046927SAndroid Build Coastguard Worker         parson_free(new_obj);
450*61046927SAndroid Build Coastguard Worker         return NULL;
451*61046927SAndroid Build Coastguard Worker     }
452*61046927SAndroid Build Coastguard Worker     return new_obj;
453*61046927SAndroid Build Coastguard Worker }
454*61046927SAndroid Build Coastguard Worker 
json_object_init(JSON_Object * object,size_t capacity)455*61046927SAndroid Build Coastguard Worker static JSON_Status json_object_init(JSON_Object *object, size_t capacity) {
456*61046927SAndroid Build Coastguard Worker     unsigned int i = 0;
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker     object->cells = NULL;
459*61046927SAndroid Build Coastguard Worker     object->names = NULL;
460*61046927SAndroid Build Coastguard Worker     object->values = NULL;
461*61046927SAndroid Build Coastguard Worker     object->cell_ixs = NULL;
462*61046927SAndroid Build Coastguard Worker     object->hashes = NULL;
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker     object->count = 0;
465*61046927SAndroid Build Coastguard Worker     object->cell_capacity = capacity;
466*61046927SAndroid Build Coastguard Worker     object->item_capacity = (unsigned int)(capacity * 7/10);
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker     if (capacity == 0) {
469*61046927SAndroid Build Coastguard Worker         return JSONSuccess;
470*61046927SAndroid Build Coastguard Worker     }
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker     object->cells = (size_t*)parson_malloc(object->cell_capacity * sizeof(*object->cells));
473*61046927SAndroid Build Coastguard Worker     object->names = (char**)parson_malloc(object->item_capacity * sizeof(*object->names));
474*61046927SAndroid Build Coastguard Worker     object->values = (JSON_Value**)parson_malloc(object->item_capacity * sizeof(*object->values));
475*61046927SAndroid Build Coastguard Worker     object->cell_ixs = (size_t*)parson_malloc(object->item_capacity * sizeof(*object->cell_ixs));
476*61046927SAndroid Build Coastguard Worker     object->hashes = (unsigned long*)parson_malloc(object->item_capacity * sizeof(*object->hashes));
477*61046927SAndroid Build Coastguard Worker     if (object->cells == NULL
478*61046927SAndroid Build Coastguard Worker         || object->names == NULL
479*61046927SAndroid Build Coastguard Worker         || object->values == NULL
480*61046927SAndroid Build Coastguard Worker         || object->cell_ixs == NULL
481*61046927SAndroid Build Coastguard Worker         || object->hashes == NULL) {
482*61046927SAndroid Build Coastguard Worker         goto error;
483*61046927SAndroid Build Coastguard Worker     }
484*61046927SAndroid Build Coastguard Worker     for (i = 0; i < object->cell_capacity; i++) {
485*61046927SAndroid Build Coastguard Worker         object->cells[i] = OBJECT_INVALID_IX;
486*61046927SAndroid Build Coastguard Worker     }
487*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
488*61046927SAndroid Build Coastguard Worker error:
489*61046927SAndroid Build Coastguard Worker     parson_free(object->cells);
490*61046927SAndroid Build Coastguard Worker     parson_free(object->names);
491*61046927SAndroid Build Coastguard Worker     parson_free(object->values);
492*61046927SAndroid Build Coastguard Worker     parson_free(object->cell_ixs);
493*61046927SAndroid Build Coastguard Worker     parson_free(object->hashes);
494*61046927SAndroid Build Coastguard Worker     return JSONFailure;
495*61046927SAndroid Build Coastguard Worker }
496*61046927SAndroid Build Coastguard Worker 
json_object_deinit(JSON_Object * object,parson_bool_t free_keys,parson_bool_t free_values)497*61046927SAndroid Build Coastguard Worker static void json_object_deinit(JSON_Object *object, parson_bool_t free_keys, parson_bool_t free_values) {
498*61046927SAndroid Build Coastguard Worker     unsigned int i = 0;
499*61046927SAndroid Build Coastguard Worker     for (i = 0; i < object->count; i++) {
500*61046927SAndroid Build Coastguard Worker         if (free_keys) {
501*61046927SAndroid Build Coastguard Worker             parson_free(object->names[i]);
502*61046927SAndroid Build Coastguard Worker         }
503*61046927SAndroid Build Coastguard Worker         if (free_values) {
504*61046927SAndroid Build Coastguard Worker             json_value_free(object->values[i]);
505*61046927SAndroid Build Coastguard Worker         }
506*61046927SAndroid Build Coastguard Worker     }
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker     object->count = 0;
509*61046927SAndroid Build Coastguard Worker     object->item_capacity = 0;
510*61046927SAndroid Build Coastguard Worker     object->cell_capacity = 0;
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker     parson_free(object->cells);
513*61046927SAndroid Build Coastguard Worker     parson_free(object->names);
514*61046927SAndroid Build Coastguard Worker     parson_free(object->values);
515*61046927SAndroid Build Coastguard Worker     parson_free(object->cell_ixs);
516*61046927SAndroid Build Coastguard Worker     parson_free(object->hashes);
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker     object->cells = NULL;
519*61046927SAndroid Build Coastguard Worker     object->names = NULL;
520*61046927SAndroid Build Coastguard Worker     object->values = NULL;
521*61046927SAndroid Build Coastguard Worker     object->cell_ixs = NULL;
522*61046927SAndroid Build Coastguard Worker     object->hashes = NULL;
523*61046927SAndroid Build Coastguard Worker }
524*61046927SAndroid Build Coastguard Worker 
json_object_grow_and_rehash(JSON_Object * object)525*61046927SAndroid Build Coastguard Worker static JSON_Status json_object_grow_and_rehash(JSON_Object *object) {
526*61046927SAndroid Build Coastguard Worker     JSON_Value *wrapping_value = NULL;
527*61046927SAndroid Build Coastguard Worker     JSON_Object new_object;
528*61046927SAndroid Build Coastguard Worker     char *key = NULL;
529*61046927SAndroid Build Coastguard Worker     JSON_Value *value = NULL;
530*61046927SAndroid Build Coastguard Worker     unsigned int i = 0;
531*61046927SAndroid Build Coastguard Worker     size_t new_capacity = MAX(object->cell_capacity * 2, STARTING_CAPACITY);
532*61046927SAndroid Build Coastguard Worker     JSON_Status res = json_object_init(&new_object, new_capacity);
533*61046927SAndroid Build Coastguard Worker     if (res != JSONSuccess) {
534*61046927SAndroid Build Coastguard Worker         return JSONFailure;
535*61046927SAndroid Build Coastguard Worker     }
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker     wrapping_value = json_object_get_wrapping_value(object);
538*61046927SAndroid Build Coastguard Worker     new_object.wrapping_value = wrapping_value;
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker     for (i = 0; i < object->count; i++) {
541*61046927SAndroid Build Coastguard Worker         key = object->names[i];
542*61046927SAndroid Build Coastguard Worker         value = object->values[i];
543*61046927SAndroid Build Coastguard Worker         res = json_object_add(&new_object, key, value);
544*61046927SAndroid Build Coastguard Worker         if (res != JSONSuccess) {
545*61046927SAndroid Build Coastguard Worker             json_object_deinit(&new_object, PARSON_FALSE, PARSON_FALSE);
546*61046927SAndroid Build Coastguard Worker             return JSONFailure;
547*61046927SAndroid Build Coastguard Worker         }
548*61046927SAndroid Build Coastguard Worker         value->parent = wrapping_value;
549*61046927SAndroid Build Coastguard Worker     }
550*61046927SAndroid Build Coastguard Worker     json_object_deinit(object, PARSON_FALSE, PARSON_FALSE);
551*61046927SAndroid Build Coastguard Worker     *object = new_object;
552*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
553*61046927SAndroid Build Coastguard Worker }
554*61046927SAndroid Build Coastguard Worker 
json_object_get_cell_ix(const JSON_Object * object,const char * key,size_t key_len,unsigned long hash,parson_bool_t * out_found)555*61046927SAndroid Build Coastguard Worker static size_t json_object_get_cell_ix(const JSON_Object *object, const char *key, size_t key_len, unsigned long hash, parson_bool_t *out_found) {
556*61046927SAndroid Build Coastguard Worker     size_t cell_ix = hash & (object->cell_capacity - 1);
557*61046927SAndroid Build Coastguard Worker     size_t cell = 0;
558*61046927SAndroid Build Coastguard Worker     size_t ix = 0;
559*61046927SAndroid Build Coastguard Worker     unsigned int i = 0;
560*61046927SAndroid Build Coastguard Worker     unsigned long hash_to_check = 0;
561*61046927SAndroid Build Coastguard Worker     const char *key_to_check = NULL;
562*61046927SAndroid Build Coastguard Worker     size_t key_to_check_len = 0;
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker     *out_found = PARSON_FALSE;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker     for (i = 0; i < object->cell_capacity; i++) {
567*61046927SAndroid Build Coastguard Worker         ix = (cell_ix + i) & (object->cell_capacity - 1);
568*61046927SAndroid Build Coastguard Worker         cell = object->cells[ix];
569*61046927SAndroid Build Coastguard Worker         if (cell == OBJECT_INVALID_IX) {
570*61046927SAndroid Build Coastguard Worker             return ix;
571*61046927SAndroid Build Coastguard Worker         }
572*61046927SAndroid Build Coastguard Worker         hash_to_check = object->hashes[cell];
573*61046927SAndroid Build Coastguard Worker         if (hash != hash_to_check) {
574*61046927SAndroid Build Coastguard Worker             continue;
575*61046927SAndroid Build Coastguard Worker         }
576*61046927SAndroid Build Coastguard Worker         key_to_check = object->names[cell];
577*61046927SAndroid Build Coastguard Worker         key_to_check_len = strlen(key_to_check);
578*61046927SAndroid Build Coastguard Worker         if (key_to_check_len == key_len && strncmp(key, key_to_check, key_len) == 0) {
579*61046927SAndroid Build Coastguard Worker             *out_found = PARSON_TRUE;
580*61046927SAndroid Build Coastguard Worker             return ix;
581*61046927SAndroid Build Coastguard Worker         }
582*61046927SAndroid Build Coastguard Worker     }
583*61046927SAndroid Build Coastguard Worker     return OBJECT_INVALID_IX;
584*61046927SAndroid Build Coastguard Worker }
585*61046927SAndroid Build Coastguard Worker 
json_object_add(JSON_Object * object,char * name,JSON_Value * value)586*61046927SAndroid Build Coastguard Worker static JSON_Status json_object_add(JSON_Object *object, char *name, JSON_Value *value) {
587*61046927SAndroid Build Coastguard Worker     unsigned long hash = 0;
588*61046927SAndroid Build Coastguard Worker     parson_bool_t found = PARSON_FALSE;
589*61046927SAndroid Build Coastguard Worker     size_t cell_ix = 0;
590*61046927SAndroid Build Coastguard Worker     JSON_Status res = JSONFailure;
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker     if (!object || !name || !value) {
593*61046927SAndroid Build Coastguard Worker         return JSONFailure;
594*61046927SAndroid Build Coastguard Worker     }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker     hash = hash_string(name, strlen(name));
597*61046927SAndroid Build Coastguard Worker     found = PARSON_FALSE;
598*61046927SAndroid Build Coastguard Worker     cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
599*61046927SAndroid Build Coastguard Worker     if (found) {
600*61046927SAndroid Build Coastguard Worker         return JSONFailure;
601*61046927SAndroid Build Coastguard Worker     }
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker     if (object->count >= object->item_capacity) {
604*61046927SAndroid Build Coastguard Worker         res = json_object_grow_and_rehash(object);
605*61046927SAndroid Build Coastguard Worker         if (res != JSONSuccess) {
606*61046927SAndroid Build Coastguard Worker             return JSONFailure;
607*61046927SAndroid Build Coastguard Worker         }
608*61046927SAndroid Build Coastguard Worker         cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
609*61046927SAndroid Build Coastguard Worker     }
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker     object->names[object->count] = name;
612*61046927SAndroid Build Coastguard Worker     object->cells[cell_ix] = object->count;
613*61046927SAndroid Build Coastguard Worker     object->values[object->count] = value;
614*61046927SAndroid Build Coastguard Worker     object->cell_ixs[object->count] = cell_ix;
615*61046927SAndroid Build Coastguard Worker     object->hashes[object->count] = hash;
616*61046927SAndroid Build Coastguard Worker     object->count++;
617*61046927SAndroid Build Coastguard Worker     value->parent = json_object_get_wrapping_value(object);
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
620*61046927SAndroid Build Coastguard Worker }
621*61046927SAndroid Build Coastguard Worker 
json_object_getn_value(const JSON_Object * object,const char * name,size_t name_len)622*61046927SAndroid Build Coastguard Worker static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) {
623*61046927SAndroid Build Coastguard Worker     unsigned long hash = 0;
624*61046927SAndroid Build Coastguard Worker     parson_bool_t found = PARSON_FALSE;
625*61046927SAndroid Build Coastguard Worker     size_t cell_ix = 0;
626*61046927SAndroid Build Coastguard Worker     size_t item_ix = 0;
627*61046927SAndroid Build Coastguard Worker     if (!object || !name) {
628*61046927SAndroid Build Coastguard Worker         return NULL;
629*61046927SAndroid Build Coastguard Worker     }
630*61046927SAndroid Build Coastguard Worker     hash = hash_string(name, name_len);
631*61046927SAndroid Build Coastguard Worker     found = PARSON_FALSE;
632*61046927SAndroid Build Coastguard Worker     cell_ix = json_object_get_cell_ix(object, name, name_len, hash, &found);
633*61046927SAndroid Build Coastguard Worker     if (!found) {
634*61046927SAndroid Build Coastguard Worker         return NULL;
635*61046927SAndroid Build Coastguard Worker     }
636*61046927SAndroid Build Coastguard Worker     item_ix = object->cells[cell_ix];
637*61046927SAndroid Build Coastguard Worker     return object->values[item_ix];
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker 
json_object_remove_internal(JSON_Object * object,const char * name,parson_bool_t free_value)640*61046927SAndroid Build Coastguard Worker static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, parson_bool_t free_value) {
641*61046927SAndroid Build Coastguard Worker     unsigned long hash = 0;
642*61046927SAndroid Build Coastguard Worker     parson_bool_t found = PARSON_FALSE;
643*61046927SAndroid Build Coastguard Worker     size_t cell = 0;
644*61046927SAndroid Build Coastguard Worker     size_t item_ix = 0;
645*61046927SAndroid Build Coastguard Worker     size_t last_item_ix = 0;
646*61046927SAndroid Build Coastguard Worker     size_t i = 0;
647*61046927SAndroid Build Coastguard Worker     size_t j = 0;
648*61046927SAndroid Build Coastguard Worker     size_t x = 0;
649*61046927SAndroid Build Coastguard Worker     size_t k = 0;
650*61046927SAndroid Build Coastguard Worker     JSON_Value *val = NULL;
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker     if (object == NULL) {
653*61046927SAndroid Build Coastguard Worker         return JSONFailure;
654*61046927SAndroid Build Coastguard Worker     }
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker     hash = hash_string(name, strlen(name));
657*61046927SAndroid Build Coastguard Worker     found = PARSON_FALSE;
658*61046927SAndroid Build Coastguard Worker     cell = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
659*61046927SAndroid Build Coastguard Worker     if (!found) {
660*61046927SAndroid Build Coastguard Worker         return JSONFailure;
661*61046927SAndroid Build Coastguard Worker     }
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker     item_ix = object->cells[cell];
664*61046927SAndroid Build Coastguard Worker     if (free_value) {
665*61046927SAndroid Build Coastguard Worker         val = object->values[item_ix];
666*61046927SAndroid Build Coastguard Worker         json_value_free(val);
667*61046927SAndroid Build Coastguard Worker         val = NULL;
668*61046927SAndroid Build Coastguard Worker     }
669*61046927SAndroid Build Coastguard Worker 
670*61046927SAndroid Build Coastguard Worker     parson_free(object->names[item_ix]);
671*61046927SAndroid Build Coastguard Worker     last_item_ix = object->count - 1;
672*61046927SAndroid Build Coastguard Worker     if (item_ix < last_item_ix) {
673*61046927SAndroid Build Coastguard Worker         object->names[item_ix] = object->names[last_item_ix];
674*61046927SAndroid Build Coastguard Worker         object->values[item_ix] = object->values[last_item_ix];
675*61046927SAndroid Build Coastguard Worker         object->cell_ixs[item_ix] = object->cell_ixs[last_item_ix];
676*61046927SAndroid Build Coastguard Worker         object->hashes[item_ix] = object->hashes[last_item_ix];
677*61046927SAndroid Build Coastguard Worker         object->cells[object->cell_ixs[item_ix]] = item_ix;
678*61046927SAndroid Build Coastguard Worker     }
679*61046927SAndroid Build Coastguard Worker     object->count--;
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker     i = cell;
682*61046927SAndroid Build Coastguard Worker     j = i;
683*61046927SAndroid Build Coastguard Worker     for (x = 0; x < (object->cell_capacity - 1); x++) {
684*61046927SAndroid Build Coastguard Worker         j = (j + 1) & (object->cell_capacity - 1);
685*61046927SAndroid Build Coastguard Worker         if (object->cells[j] == OBJECT_INVALID_IX) {
686*61046927SAndroid Build Coastguard Worker             break;
687*61046927SAndroid Build Coastguard Worker         }
688*61046927SAndroid Build Coastguard Worker         k = object->hashes[object->cells[j]] & (object->cell_capacity - 1);
689*61046927SAndroid Build Coastguard Worker         if ((j > i && (k <= i || k > j))
690*61046927SAndroid Build Coastguard Worker          || (j < i && (k <= i && k > j))) {
691*61046927SAndroid Build Coastguard Worker             object->cell_ixs[object->cells[j]] = i;
692*61046927SAndroid Build Coastguard Worker             object->cells[i] = object->cells[j];
693*61046927SAndroid Build Coastguard Worker             i = j;
694*61046927SAndroid Build Coastguard Worker         }
695*61046927SAndroid Build Coastguard Worker     }
696*61046927SAndroid Build Coastguard Worker     object->cells[i] = OBJECT_INVALID_IX;
697*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
698*61046927SAndroid Build Coastguard Worker }
699*61046927SAndroid Build Coastguard Worker 
json_object_dotremove_internal(JSON_Object * object,const char * name,parson_bool_t free_value)700*61046927SAndroid Build Coastguard Worker static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, parson_bool_t free_value) {
701*61046927SAndroid Build Coastguard Worker     JSON_Value *temp_value = NULL;
702*61046927SAndroid Build Coastguard Worker     JSON_Object *temp_object = NULL;
703*61046927SAndroid Build Coastguard Worker     const char *dot_pos = strchr(name, '.');
704*61046927SAndroid Build Coastguard Worker     if (!dot_pos) {
705*61046927SAndroid Build Coastguard Worker         return json_object_remove_internal(object, name, free_value);
706*61046927SAndroid Build Coastguard Worker     }
707*61046927SAndroid Build Coastguard Worker     temp_value = json_object_getn_value(object, name, dot_pos - name);
708*61046927SAndroid Build Coastguard Worker     if (json_value_get_type(temp_value) != JSONObject) {
709*61046927SAndroid Build Coastguard Worker         return JSONFailure;
710*61046927SAndroid Build Coastguard Worker     }
711*61046927SAndroid Build Coastguard Worker     temp_object = json_value_get_object(temp_value);
712*61046927SAndroid Build Coastguard Worker     return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value);
713*61046927SAndroid Build Coastguard Worker }
714*61046927SAndroid Build Coastguard Worker 
json_object_free(JSON_Object * object)715*61046927SAndroid Build Coastguard Worker static void json_object_free(JSON_Object *object) {
716*61046927SAndroid Build Coastguard Worker     json_object_deinit(object, PARSON_TRUE, PARSON_TRUE);
717*61046927SAndroid Build Coastguard Worker     parson_free(object);
718*61046927SAndroid Build Coastguard Worker }
719*61046927SAndroid Build Coastguard Worker 
720*61046927SAndroid Build Coastguard Worker /* JSON Array */
json_array_make(JSON_Value * wrapping_value)721*61046927SAndroid Build Coastguard Worker static JSON_Array * json_array_make(JSON_Value *wrapping_value) {
722*61046927SAndroid Build Coastguard Worker     JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
723*61046927SAndroid Build Coastguard Worker     if (new_array == NULL) {
724*61046927SAndroid Build Coastguard Worker         return NULL;
725*61046927SAndroid Build Coastguard Worker     }
726*61046927SAndroid Build Coastguard Worker     new_array->wrapping_value = wrapping_value;
727*61046927SAndroid Build Coastguard Worker     new_array->items = (JSON_Value**)NULL;
728*61046927SAndroid Build Coastguard Worker     new_array->capacity = 0;
729*61046927SAndroid Build Coastguard Worker     new_array->count = 0;
730*61046927SAndroid Build Coastguard Worker     return new_array;
731*61046927SAndroid Build Coastguard Worker }
732*61046927SAndroid Build Coastguard Worker 
json_array_add(JSON_Array * array,JSON_Value * value)733*61046927SAndroid Build Coastguard Worker static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
734*61046927SAndroid Build Coastguard Worker     if (array->count >= array->capacity) {
735*61046927SAndroid Build Coastguard Worker         size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
736*61046927SAndroid Build Coastguard Worker         if (json_array_resize(array, new_capacity) != JSONSuccess) {
737*61046927SAndroid Build Coastguard Worker             return JSONFailure;
738*61046927SAndroid Build Coastguard Worker         }
739*61046927SAndroid Build Coastguard Worker     }
740*61046927SAndroid Build Coastguard Worker     value->parent = json_array_get_wrapping_value(array);
741*61046927SAndroid Build Coastguard Worker     array->items[array->count] = value;
742*61046927SAndroid Build Coastguard Worker     array->count++;
743*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
744*61046927SAndroid Build Coastguard Worker }
745*61046927SAndroid Build Coastguard Worker 
json_array_resize(JSON_Array * array,size_t new_capacity)746*61046927SAndroid Build Coastguard Worker static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) {
747*61046927SAndroid Build Coastguard Worker     JSON_Value **new_items = NULL;
748*61046927SAndroid Build Coastguard Worker     if (new_capacity == 0) {
749*61046927SAndroid Build Coastguard Worker         return JSONFailure;
750*61046927SAndroid Build Coastguard Worker     }
751*61046927SAndroid Build Coastguard Worker     new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
752*61046927SAndroid Build Coastguard Worker     if (new_items == NULL) {
753*61046927SAndroid Build Coastguard Worker         return JSONFailure;
754*61046927SAndroid Build Coastguard Worker     }
755*61046927SAndroid Build Coastguard Worker     if (array->items != NULL && array->count > 0) {
756*61046927SAndroid Build Coastguard Worker         memcpy(new_items, array->items, array->count * sizeof(JSON_Value*));
757*61046927SAndroid Build Coastguard Worker     }
758*61046927SAndroid Build Coastguard Worker     parson_free(array->items);
759*61046927SAndroid Build Coastguard Worker     array->items = new_items;
760*61046927SAndroid Build Coastguard Worker     array->capacity = new_capacity;
761*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
762*61046927SAndroid Build Coastguard Worker }
763*61046927SAndroid Build Coastguard Worker 
json_array_free(JSON_Array * array)764*61046927SAndroid Build Coastguard Worker static void json_array_free(JSON_Array *array) {
765*61046927SAndroid Build Coastguard Worker     size_t i;
766*61046927SAndroid Build Coastguard Worker     for (i = 0; i < array->count; i++) {
767*61046927SAndroid Build Coastguard Worker         json_value_free(array->items[i]);
768*61046927SAndroid Build Coastguard Worker     }
769*61046927SAndroid Build Coastguard Worker     parson_free(array->items);
770*61046927SAndroid Build Coastguard Worker     parson_free(array);
771*61046927SAndroid Build Coastguard Worker }
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker /* JSON Value */
json_value_init_string_no_copy(char * string,size_t length)774*61046927SAndroid Build Coastguard Worker static JSON_Value * json_value_init_string_no_copy(char *string, size_t length) {
775*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
776*61046927SAndroid Build Coastguard Worker     if (!new_value) {
777*61046927SAndroid Build Coastguard Worker         return NULL;
778*61046927SAndroid Build Coastguard Worker     }
779*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
780*61046927SAndroid Build Coastguard Worker     new_value->type = JSONString;
781*61046927SAndroid Build Coastguard Worker     new_value->value.string.chars = string;
782*61046927SAndroid Build Coastguard Worker     new_value->value.string.length = length;
783*61046927SAndroid Build Coastguard Worker     return new_value;
784*61046927SAndroid Build Coastguard Worker }
785*61046927SAndroid Build Coastguard Worker 
786*61046927SAndroid Build Coastguard Worker /* Parser */
skip_quotes(const char ** string)787*61046927SAndroid Build Coastguard Worker static JSON_Status skip_quotes(const char **string) {
788*61046927SAndroid Build Coastguard Worker     if (**string != '\"') {
789*61046927SAndroid Build Coastguard Worker         return JSONFailure;
790*61046927SAndroid Build Coastguard Worker     }
791*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
792*61046927SAndroid Build Coastguard Worker     while (**string != '\"') {
793*61046927SAndroid Build Coastguard Worker         if (**string == '\0') {
794*61046927SAndroid Build Coastguard Worker             return JSONFailure;
795*61046927SAndroid Build Coastguard Worker         } else if (**string == '\\') {
796*61046927SAndroid Build Coastguard Worker             SKIP_CHAR(string);
797*61046927SAndroid Build Coastguard Worker             if (**string == '\0') {
798*61046927SAndroid Build Coastguard Worker                 return JSONFailure;
799*61046927SAndroid Build Coastguard Worker             }
800*61046927SAndroid Build Coastguard Worker         }
801*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
802*61046927SAndroid Build Coastguard Worker     }
803*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
804*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
805*61046927SAndroid Build Coastguard Worker }
806*61046927SAndroid Build Coastguard Worker 
parse_utf16(const char ** unprocessed,char ** processed)807*61046927SAndroid Build Coastguard Worker static JSON_Status parse_utf16(const char **unprocessed, char **processed) {
808*61046927SAndroid Build Coastguard Worker     unsigned int cp, lead, trail;
809*61046927SAndroid Build Coastguard Worker     char *processed_ptr = *processed;
810*61046927SAndroid Build Coastguard Worker     const char *unprocessed_ptr = *unprocessed;
811*61046927SAndroid Build Coastguard Worker     JSON_Status status = JSONFailure;
812*61046927SAndroid Build Coastguard Worker     unprocessed_ptr++; /* skips u */
813*61046927SAndroid Build Coastguard Worker     status = parse_utf16_hex(unprocessed_ptr, &cp);
814*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
815*61046927SAndroid Build Coastguard Worker         return JSONFailure;
816*61046927SAndroid Build Coastguard Worker     }
817*61046927SAndroid Build Coastguard Worker     if (cp < 0x80) {
818*61046927SAndroid Build Coastguard Worker         processed_ptr[0] = (char)cp; /* 0xxxxxxx */
819*61046927SAndroid Build Coastguard Worker     } else if (cp < 0x800) {
820*61046927SAndroid Build Coastguard Worker         processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
821*61046927SAndroid Build Coastguard Worker         processed_ptr[1] = ((cp)      & 0x3F) | 0x80; /* 10xxxxxx */
822*61046927SAndroid Build Coastguard Worker         processed_ptr += 1;
823*61046927SAndroid Build Coastguard Worker     } else if (cp < 0xD800 || cp > 0xDFFF) {
824*61046927SAndroid Build Coastguard Worker         processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
825*61046927SAndroid Build Coastguard Worker         processed_ptr[1] = ((cp >> 6)  & 0x3F) | 0x80; /* 10xxxxxx */
826*61046927SAndroid Build Coastguard Worker         processed_ptr[2] = ((cp)       & 0x3F) | 0x80; /* 10xxxxxx */
827*61046927SAndroid Build Coastguard Worker         processed_ptr += 2;
828*61046927SAndroid Build Coastguard Worker     } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
829*61046927SAndroid Build Coastguard Worker         lead = cp;
830*61046927SAndroid Build Coastguard Worker         unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
831*61046927SAndroid Build Coastguard Worker         if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') {
832*61046927SAndroid Build Coastguard Worker             return JSONFailure;
833*61046927SAndroid Build Coastguard Worker         }
834*61046927SAndroid Build Coastguard Worker         status = parse_utf16_hex(unprocessed_ptr, &trail);
835*61046927SAndroid Build Coastguard Worker         if (status != JSONSuccess || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
836*61046927SAndroid Build Coastguard Worker             return JSONFailure;
837*61046927SAndroid Build Coastguard Worker         }
838*61046927SAndroid Build Coastguard Worker         cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
839*61046927SAndroid Build Coastguard Worker         processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
840*61046927SAndroid Build Coastguard Worker         processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
841*61046927SAndroid Build Coastguard Worker         processed_ptr[2] = (((cp >> 6)  & 0x3F) | 0x80); /* 10xxxxxx */
842*61046927SAndroid Build Coastguard Worker         processed_ptr[3] = (((cp)       & 0x3F) | 0x80); /* 10xxxxxx */
843*61046927SAndroid Build Coastguard Worker         processed_ptr += 3;
844*61046927SAndroid Build Coastguard Worker     } else { /* trail surrogate before lead surrogate */
845*61046927SAndroid Build Coastguard Worker         return JSONFailure;
846*61046927SAndroid Build Coastguard Worker     }
847*61046927SAndroid Build Coastguard Worker     unprocessed_ptr += 3;
848*61046927SAndroid Build Coastguard Worker     *processed = processed_ptr;
849*61046927SAndroid Build Coastguard Worker     *unprocessed = unprocessed_ptr;
850*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
851*61046927SAndroid Build Coastguard Worker }
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker /* Copies and processes passed string up to supplied length.
855*61046927SAndroid Build Coastguard Worker Example: "\u006Corem ipsum" -> lorem ipsum */
process_string(const char * input,size_t input_len,size_t * output_len)856*61046927SAndroid Build Coastguard Worker static char* process_string(const char *input, size_t input_len, size_t *output_len) {
857*61046927SAndroid Build Coastguard Worker     const char *input_ptr = input;
858*61046927SAndroid Build Coastguard Worker     size_t initial_size = (input_len + 1) * sizeof(char);
859*61046927SAndroid Build Coastguard Worker     size_t final_size = 0;
860*61046927SAndroid Build Coastguard Worker     char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
861*61046927SAndroid Build Coastguard Worker     output = (char*)parson_malloc(initial_size);
862*61046927SAndroid Build Coastguard Worker     if (output == NULL) {
863*61046927SAndroid Build Coastguard Worker         goto error;
864*61046927SAndroid Build Coastguard Worker     }
865*61046927SAndroid Build Coastguard Worker     output_ptr = output;
866*61046927SAndroid Build Coastguard Worker     while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < input_len) {
867*61046927SAndroid Build Coastguard Worker         if (*input_ptr == '\\') {
868*61046927SAndroid Build Coastguard Worker             input_ptr++;
869*61046927SAndroid Build Coastguard Worker             switch (*input_ptr) {
870*61046927SAndroid Build Coastguard Worker                 case '\"': *output_ptr = '\"'; break;
871*61046927SAndroid Build Coastguard Worker                 case '\\': *output_ptr = '\\'; break;
872*61046927SAndroid Build Coastguard Worker                 case '/':  *output_ptr = '/';  break;
873*61046927SAndroid Build Coastguard Worker                 case 'b':  *output_ptr = '\b'; break;
874*61046927SAndroid Build Coastguard Worker                 case 'f':  *output_ptr = '\f'; break;
875*61046927SAndroid Build Coastguard Worker                 case 'n':  *output_ptr = '\n'; break;
876*61046927SAndroid Build Coastguard Worker                 case 'r':  *output_ptr = '\r'; break;
877*61046927SAndroid Build Coastguard Worker                 case 't':  *output_ptr = '\t'; break;
878*61046927SAndroid Build Coastguard Worker                 case 'u':
879*61046927SAndroid Build Coastguard Worker                     if (parse_utf16(&input_ptr, &output_ptr) != JSONSuccess) {
880*61046927SAndroid Build Coastguard Worker                         goto error;
881*61046927SAndroid Build Coastguard Worker                     }
882*61046927SAndroid Build Coastguard Worker                     break;
883*61046927SAndroid Build Coastguard Worker                 default:
884*61046927SAndroid Build Coastguard Worker                     goto error;
885*61046927SAndroid Build Coastguard Worker             }
886*61046927SAndroid Build Coastguard Worker         } else if ((unsigned char)*input_ptr < 0x20) {
887*61046927SAndroid Build Coastguard Worker             goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
888*61046927SAndroid Build Coastguard Worker         } else {
889*61046927SAndroid Build Coastguard Worker             *output_ptr = *input_ptr;
890*61046927SAndroid Build Coastguard Worker         }
891*61046927SAndroid Build Coastguard Worker         output_ptr++;
892*61046927SAndroid Build Coastguard Worker         input_ptr++;
893*61046927SAndroid Build Coastguard Worker     }
894*61046927SAndroid Build Coastguard Worker     *output_ptr = '\0';
895*61046927SAndroid Build Coastguard Worker     /* resize to new length */
896*61046927SAndroid Build Coastguard Worker     final_size = (size_t)(output_ptr-output) + 1;
897*61046927SAndroid Build Coastguard Worker     /* todo: don't resize if final_size == initial_size */
898*61046927SAndroid Build Coastguard Worker     resized_output = (char*)parson_malloc(final_size);
899*61046927SAndroid Build Coastguard Worker     if (resized_output == NULL) {
900*61046927SAndroid Build Coastguard Worker         goto error;
901*61046927SAndroid Build Coastguard Worker     }
902*61046927SAndroid Build Coastguard Worker     memcpy(resized_output, output, final_size);
903*61046927SAndroid Build Coastguard Worker     *output_len = final_size - 1;
904*61046927SAndroid Build Coastguard Worker     parson_free(output);
905*61046927SAndroid Build Coastguard Worker     return resized_output;
906*61046927SAndroid Build Coastguard Worker error:
907*61046927SAndroid Build Coastguard Worker     parson_free(output);
908*61046927SAndroid Build Coastguard Worker     return NULL;
909*61046927SAndroid Build Coastguard Worker }
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker /* Return processed contents of a string between quotes and
912*61046927SAndroid Build Coastguard Worker    skips passed argument to a matching quote. */
get_quoted_string(const char ** string,size_t * output_string_len)913*61046927SAndroid Build Coastguard Worker static char * get_quoted_string(const char **string, size_t *output_string_len) {
914*61046927SAndroid Build Coastguard Worker     const char *string_start = *string;
915*61046927SAndroid Build Coastguard Worker     size_t input_string_len = 0;
916*61046927SAndroid Build Coastguard Worker     JSON_Status status = skip_quotes(string);
917*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
918*61046927SAndroid Build Coastguard Worker         return NULL;
919*61046927SAndroid Build Coastguard Worker     }
920*61046927SAndroid Build Coastguard Worker     input_string_len = *string - string_start - 2; /* length without quotes */
921*61046927SAndroid Build Coastguard Worker     return process_string(string_start + 1, input_string_len, output_string_len);
922*61046927SAndroid Build Coastguard Worker }
923*61046927SAndroid Build Coastguard Worker 
parse_value(const char ** string,size_t nesting)924*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_value(const char **string, size_t nesting) {
925*61046927SAndroid Build Coastguard Worker     if (nesting > MAX_NESTING) {
926*61046927SAndroid Build Coastguard Worker         return NULL;
927*61046927SAndroid Build Coastguard Worker     }
928*61046927SAndroid Build Coastguard Worker     SKIP_WHITESPACES(string);
929*61046927SAndroid Build Coastguard Worker     switch (**string) {
930*61046927SAndroid Build Coastguard Worker         case '{':
931*61046927SAndroid Build Coastguard Worker             return parse_object_value(string, nesting + 1);
932*61046927SAndroid Build Coastguard Worker         case '[':
933*61046927SAndroid Build Coastguard Worker             return parse_array_value(string, nesting + 1);
934*61046927SAndroid Build Coastguard Worker         case '\"':
935*61046927SAndroid Build Coastguard Worker             return parse_string_value(string);
936*61046927SAndroid Build Coastguard Worker         case 'f': case 't':
937*61046927SAndroid Build Coastguard Worker             return parse_boolean_value(string);
938*61046927SAndroid Build Coastguard Worker         case '-':
939*61046927SAndroid Build Coastguard Worker         case '0': case '1': case '2': case '3': case '4':
940*61046927SAndroid Build Coastguard Worker         case '5': case '6': case '7': case '8': case '9':
941*61046927SAndroid Build Coastguard Worker             return parse_number_value(string);
942*61046927SAndroid Build Coastguard Worker         case 'n':
943*61046927SAndroid Build Coastguard Worker             return parse_null_value(string);
944*61046927SAndroid Build Coastguard Worker         default:
945*61046927SAndroid Build Coastguard Worker             return NULL;
946*61046927SAndroid Build Coastguard Worker     }
947*61046927SAndroid Build Coastguard Worker }
948*61046927SAndroid Build Coastguard Worker 
parse_object_value(const char ** string,size_t nesting)949*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_object_value(const char **string, size_t nesting) {
950*61046927SAndroid Build Coastguard Worker     JSON_Status status = JSONFailure;
951*61046927SAndroid Build Coastguard Worker     JSON_Value *output_value = NULL, *new_value = NULL;
952*61046927SAndroid Build Coastguard Worker     JSON_Object *output_object = NULL;
953*61046927SAndroid Build Coastguard Worker     char *new_key = NULL;
954*61046927SAndroid Build Coastguard Worker 
955*61046927SAndroid Build Coastguard Worker     output_value = json_value_init_object();
956*61046927SAndroid Build Coastguard Worker     if (output_value == NULL) {
957*61046927SAndroid Build Coastguard Worker         return NULL;
958*61046927SAndroid Build Coastguard Worker     }
959*61046927SAndroid Build Coastguard Worker     if (**string != '{') {
960*61046927SAndroid Build Coastguard Worker         json_value_free(output_value);
961*61046927SAndroid Build Coastguard Worker         return NULL;
962*61046927SAndroid Build Coastguard Worker     }
963*61046927SAndroid Build Coastguard Worker     output_object = json_value_get_object(output_value);
964*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
965*61046927SAndroid Build Coastguard Worker     SKIP_WHITESPACES(string);
966*61046927SAndroid Build Coastguard Worker     if (**string == '}') { /* empty object */
967*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
968*61046927SAndroid Build Coastguard Worker         return output_value;
969*61046927SAndroid Build Coastguard Worker     }
970*61046927SAndroid Build Coastguard Worker     while (**string != '\0') {
971*61046927SAndroid Build Coastguard Worker         size_t key_len = 0;
972*61046927SAndroid Build Coastguard Worker         new_key = get_quoted_string(string, &key_len);
973*61046927SAndroid Build Coastguard Worker         /* We do not support key names with embedded \0 chars */
974*61046927SAndroid Build Coastguard Worker         if (!new_key) {
975*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
976*61046927SAndroid Build Coastguard Worker             return NULL;
977*61046927SAndroid Build Coastguard Worker         }
978*61046927SAndroid Build Coastguard Worker         if (key_len != strlen(new_key)) {
979*61046927SAndroid Build Coastguard Worker             parson_free(new_key);
980*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
981*61046927SAndroid Build Coastguard Worker             return NULL;
982*61046927SAndroid Build Coastguard Worker         }
983*61046927SAndroid Build Coastguard Worker         SKIP_WHITESPACES(string);
984*61046927SAndroid Build Coastguard Worker         if (**string != ':') {
985*61046927SAndroid Build Coastguard Worker             parson_free(new_key);
986*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
987*61046927SAndroid Build Coastguard Worker             return NULL;
988*61046927SAndroid Build Coastguard Worker         }
989*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
990*61046927SAndroid Build Coastguard Worker         new_value = parse_value(string, nesting);
991*61046927SAndroid Build Coastguard Worker         if (new_value == NULL) {
992*61046927SAndroid Build Coastguard Worker             parson_free(new_key);
993*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
994*61046927SAndroid Build Coastguard Worker             return NULL;
995*61046927SAndroid Build Coastguard Worker         }
996*61046927SAndroid Build Coastguard Worker         status = json_object_add(output_object, new_key, new_value);
997*61046927SAndroid Build Coastguard Worker         if (status != JSONSuccess) {
998*61046927SAndroid Build Coastguard Worker             parson_free(new_key);
999*61046927SAndroid Build Coastguard Worker             json_value_free(new_value);
1000*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
1001*61046927SAndroid Build Coastguard Worker             return NULL;
1002*61046927SAndroid Build Coastguard Worker         }
1003*61046927SAndroid Build Coastguard Worker         SKIP_WHITESPACES(string);
1004*61046927SAndroid Build Coastguard Worker         if (**string != ',') {
1005*61046927SAndroid Build Coastguard Worker             break;
1006*61046927SAndroid Build Coastguard Worker         }
1007*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
1008*61046927SAndroid Build Coastguard Worker         SKIP_WHITESPACES(string);
1009*61046927SAndroid Build Coastguard Worker         if (**string == '}') {
1010*61046927SAndroid Build Coastguard Worker             break;
1011*61046927SAndroid Build Coastguard Worker         }
1012*61046927SAndroid Build Coastguard Worker     }
1013*61046927SAndroid Build Coastguard Worker     SKIP_WHITESPACES(string);
1014*61046927SAndroid Build Coastguard Worker     if (**string != '}') {
1015*61046927SAndroid Build Coastguard Worker         json_value_free(output_value);
1016*61046927SAndroid Build Coastguard Worker         return NULL;
1017*61046927SAndroid Build Coastguard Worker     }
1018*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
1019*61046927SAndroid Build Coastguard Worker     return output_value;
1020*61046927SAndroid Build Coastguard Worker }
1021*61046927SAndroid Build Coastguard Worker 
parse_array_value(const char ** string,size_t nesting)1022*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_array_value(const char **string, size_t nesting) {
1023*61046927SAndroid Build Coastguard Worker     JSON_Value *output_value = NULL, *new_array_value = NULL;
1024*61046927SAndroid Build Coastguard Worker     JSON_Array *output_array = NULL;
1025*61046927SAndroid Build Coastguard Worker     output_value = json_value_init_array();
1026*61046927SAndroid Build Coastguard Worker     if (output_value == NULL) {
1027*61046927SAndroid Build Coastguard Worker         return NULL;
1028*61046927SAndroid Build Coastguard Worker     }
1029*61046927SAndroid Build Coastguard Worker     if (**string != '[') {
1030*61046927SAndroid Build Coastguard Worker         json_value_free(output_value);
1031*61046927SAndroid Build Coastguard Worker         return NULL;
1032*61046927SAndroid Build Coastguard Worker     }
1033*61046927SAndroid Build Coastguard Worker     output_array = json_value_get_array(output_value);
1034*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
1035*61046927SAndroid Build Coastguard Worker     SKIP_WHITESPACES(string);
1036*61046927SAndroid Build Coastguard Worker     if (**string == ']') { /* empty array */
1037*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
1038*61046927SAndroid Build Coastguard Worker         return output_value;
1039*61046927SAndroid Build Coastguard Worker     }
1040*61046927SAndroid Build Coastguard Worker     while (**string != '\0') {
1041*61046927SAndroid Build Coastguard Worker         new_array_value = parse_value(string, nesting);
1042*61046927SAndroid Build Coastguard Worker         if (new_array_value == NULL) {
1043*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
1044*61046927SAndroid Build Coastguard Worker             return NULL;
1045*61046927SAndroid Build Coastguard Worker         }
1046*61046927SAndroid Build Coastguard Worker         if (json_array_add(output_array, new_array_value) != JSONSuccess) {
1047*61046927SAndroid Build Coastguard Worker             json_value_free(new_array_value);
1048*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
1049*61046927SAndroid Build Coastguard Worker             return NULL;
1050*61046927SAndroid Build Coastguard Worker         }
1051*61046927SAndroid Build Coastguard Worker         SKIP_WHITESPACES(string);
1052*61046927SAndroid Build Coastguard Worker         if (**string != ',') {
1053*61046927SAndroid Build Coastguard Worker             break;
1054*61046927SAndroid Build Coastguard Worker         }
1055*61046927SAndroid Build Coastguard Worker         SKIP_CHAR(string);
1056*61046927SAndroid Build Coastguard Worker         SKIP_WHITESPACES(string);
1057*61046927SAndroid Build Coastguard Worker         if (**string == ']') {
1058*61046927SAndroid Build Coastguard Worker             break;
1059*61046927SAndroid Build Coastguard Worker         }
1060*61046927SAndroid Build Coastguard Worker     }
1061*61046927SAndroid Build Coastguard Worker     SKIP_WHITESPACES(string);
1062*61046927SAndroid Build Coastguard Worker     if (**string != ']' || /* Trim array after parsing is over */
1063*61046927SAndroid Build Coastguard Worker         json_array_resize(output_array, json_array_get_count(output_array)) != JSONSuccess) {
1064*61046927SAndroid Build Coastguard Worker             json_value_free(output_value);
1065*61046927SAndroid Build Coastguard Worker             return NULL;
1066*61046927SAndroid Build Coastguard Worker     }
1067*61046927SAndroid Build Coastguard Worker     SKIP_CHAR(string);
1068*61046927SAndroid Build Coastguard Worker     return output_value;
1069*61046927SAndroid Build Coastguard Worker }
1070*61046927SAndroid Build Coastguard Worker 
parse_string_value(const char ** string)1071*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_string_value(const char **string) {
1072*61046927SAndroid Build Coastguard Worker     JSON_Value *value = NULL;
1073*61046927SAndroid Build Coastguard Worker     size_t new_string_len = 0;
1074*61046927SAndroid Build Coastguard Worker     char *new_string = get_quoted_string(string, &new_string_len);
1075*61046927SAndroid Build Coastguard Worker     if (new_string == NULL) {
1076*61046927SAndroid Build Coastguard Worker         return NULL;
1077*61046927SAndroid Build Coastguard Worker     }
1078*61046927SAndroid Build Coastguard Worker     value = json_value_init_string_no_copy(new_string, new_string_len);
1079*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1080*61046927SAndroid Build Coastguard Worker         parson_free(new_string);
1081*61046927SAndroid Build Coastguard Worker         return NULL;
1082*61046927SAndroid Build Coastguard Worker     }
1083*61046927SAndroid Build Coastguard Worker     return value;
1084*61046927SAndroid Build Coastguard Worker }
1085*61046927SAndroid Build Coastguard Worker 
parse_boolean_value(const char ** string)1086*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_boolean_value(const char **string) {
1087*61046927SAndroid Build Coastguard Worker     size_t true_token_size = SIZEOF_TOKEN("true");
1088*61046927SAndroid Build Coastguard Worker     size_t false_token_size = SIZEOF_TOKEN("false");
1089*61046927SAndroid Build Coastguard Worker     if (strncmp("true", *string, true_token_size) == 0) {
1090*61046927SAndroid Build Coastguard Worker         *string += true_token_size;
1091*61046927SAndroid Build Coastguard Worker         return json_value_init_boolean(1);
1092*61046927SAndroid Build Coastguard Worker     } else if (strncmp("false", *string, false_token_size) == 0) {
1093*61046927SAndroid Build Coastguard Worker         *string += false_token_size;
1094*61046927SAndroid Build Coastguard Worker         return json_value_init_boolean(0);
1095*61046927SAndroid Build Coastguard Worker     }
1096*61046927SAndroid Build Coastguard Worker     return NULL;
1097*61046927SAndroid Build Coastguard Worker }
1098*61046927SAndroid Build Coastguard Worker 
parse_number_value(const char ** string)1099*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_number_value(const char **string) {
1100*61046927SAndroid Build Coastguard Worker     char *end;
1101*61046927SAndroid Build Coastguard Worker     double number = 0;
1102*61046927SAndroid Build Coastguard Worker     errno = 0;
1103*61046927SAndroid Build Coastguard Worker     number = strtod(*string, &end);
1104*61046927SAndroid Build Coastguard Worker     if (errno == ERANGE && (number <= -HUGE_VAL || number >= HUGE_VAL)) {
1105*61046927SAndroid Build Coastguard Worker         return NULL;
1106*61046927SAndroid Build Coastguard Worker     }
1107*61046927SAndroid Build Coastguard Worker     if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) {
1108*61046927SAndroid Build Coastguard Worker         return NULL;
1109*61046927SAndroid Build Coastguard Worker     }
1110*61046927SAndroid Build Coastguard Worker     *string = end;
1111*61046927SAndroid Build Coastguard Worker     return json_value_init_number(number);
1112*61046927SAndroid Build Coastguard Worker }
1113*61046927SAndroid Build Coastguard Worker 
parse_null_value(const char ** string)1114*61046927SAndroid Build Coastguard Worker static JSON_Value * parse_null_value(const char **string) {
1115*61046927SAndroid Build Coastguard Worker     size_t token_size = SIZEOF_TOKEN("null");
1116*61046927SAndroid Build Coastguard Worker     if (strncmp("null", *string, token_size) == 0) {
1117*61046927SAndroid Build Coastguard Worker         *string += token_size;
1118*61046927SAndroid Build Coastguard Worker         return json_value_init_null();
1119*61046927SAndroid Build Coastguard Worker     }
1120*61046927SAndroid Build Coastguard Worker     return NULL;
1121*61046927SAndroid Build Coastguard Worker }
1122*61046927SAndroid Build Coastguard Worker 
1123*61046927SAndroid Build Coastguard Worker /* Serialization */
1124*61046927SAndroid Build Coastguard Worker 
1125*61046927SAndroid Build Coastguard Worker /*  APPEND_STRING() is only called on string literals.
1126*61046927SAndroid Build Coastguard Worker     It's a bit hacky because it makes plenty of assumptions about the external state
1127*61046927SAndroid Build Coastguard Worker     and should eventually be tidied up into a function (same goes for APPEND_INDENT)
1128*61046927SAndroid Build Coastguard Worker  */
1129*61046927SAndroid Build Coastguard Worker #define APPEND_STRING(str) do {\
1130*61046927SAndroid Build Coastguard Worker                                 written = SIZEOF_TOKEN((str));\
1131*61046927SAndroid Build Coastguard Worker                                 if (buf != NULL) {\
1132*61046927SAndroid Build Coastguard Worker                                     memcpy(buf, (str), written);\
1133*61046927SAndroid Build Coastguard Worker                                     buf[written] = '\0';\
1134*61046927SAndroid Build Coastguard Worker                                     buf += written;\
1135*61046927SAndroid Build Coastguard Worker                                 }\
1136*61046927SAndroid Build Coastguard Worker                                 written_total += written;\
1137*61046927SAndroid Build Coastguard Worker                             } while (0)
1138*61046927SAndroid Build Coastguard Worker 
1139*61046927SAndroid Build Coastguard Worker #define APPEND_INDENT(level) do {\
1140*61046927SAndroid Build Coastguard Worker                                 int level_i = 0;\
1141*61046927SAndroid Build Coastguard Worker                                 for (level_i = 0; level_i < (level); level_i++) {\
1142*61046927SAndroid Build Coastguard Worker                                     APPEND_STRING(PARSON_INDENT_STR);\
1143*61046927SAndroid Build Coastguard Worker                                 }\
1144*61046927SAndroid Build Coastguard Worker                             } while (0)
1145*61046927SAndroid Build Coastguard Worker 
json_serialize_to_buffer_r(const JSON_Value * value,char * buf,int level,parson_bool_t is_pretty,char * num_buf)1146*61046927SAndroid Build Coastguard Worker static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf)
1147*61046927SAndroid Build Coastguard Worker {
1148*61046927SAndroid Build Coastguard Worker     const char *key = NULL, *string = NULL;
1149*61046927SAndroid Build Coastguard Worker     JSON_Value *temp_value = NULL;
1150*61046927SAndroid Build Coastguard Worker     JSON_Array *array = NULL;
1151*61046927SAndroid Build Coastguard Worker     JSON_Object *object = NULL;
1152*61046927SAndroid Build Coastguard Worker     size_t i = 0, count = 0;
1153*61046927SAndroid Build Coastguard Worker     double num = 0.0;
1154*61046927SAndroid Build Coastguard Worker     int written = -1, written_total = 0;
1155*61046927SAndroid Build Coastguard Worker     size_t len = 0;
1156*61046927SAndroid Build Coastguard Worker 
1157*61046927SAndroid Build Coastguard Worker     switch (json_value_get_type(value)) {
1158*61046927SAndroid Build Coastguard Worker         case JSONArray:
1159*61046927SAndroid Build Coastguard Worker             array = json_value_get_array(value);
1160*61046927SAndroid Build Coastguard Worker             count = json_array_get_count(array);
1161*61046927SAndroid Build Coastguard Worker             APPEND_STRING("[");
1162*61046927SAndroid Build Coastguard Worker             if (count > 0 && is_pretty) {
1163*61046927SAndroid Build Coastguard Worker                 APPEND_STRING("\n");
1164*61046927SAndroid Build Coastguard Worker             }
1165*61046927SAndroid Build Coastguard Worker             for (i = 0; i < count; i++) {
1166*61046927SAndroid Build Coastguard Worker                 if (is_pretty) {
1167*61046927SAndroid Build Coastguard Worker                     APPEND_INDENT(level+1);
1168*61046927SAndroid Build Coastguard Worker                 }
1169*61046927SAndroid Build Coastguard Worker                 temp_value = json_array_get_value(array, i);
1170*61046927SAndroid Build Coastguard Worker                 written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
1171*61046927SAndroid Build Coastguard Worker                 if (written < 0) {
1172*61046927SAndroid Build Coastguard Worker                     return -1;
1173*61046927SAndroid Build Coastguard Worker                 }
1174*61046927SAndroid Build Coastguard Worker                 if (buf != NULL) {
1175*61046927SAndroid Build Coastguard Worker                     buf += written;
1176*61046927SAndroid Build Coastguard Worker                 }
1177*61046927SAndroid Build Coastguard Worker                 written_total += written;
1178*61046927SAndroid Build Coastguard Worker                 if (i < (count - 1)) {
1179*61046927SAndroid Build Coastguard Worker                     APPEND_STRING(",");
1180*61046927SAndroid Build Coastguard Worker                 }
1181*61046927SAndroid Build Coastguard Worker                 if (is_pretty) {
1182*61046927SAndroid Build Coastguard Worker                     APPEND_STRING("\n");
1183*61046927SAndroid Build Coastguard Worker                 }
1184*61046927SAndroid Build Coastguard Worker             }
1185*61046927SAndroid Build Coastguard Worker             if (count > 0 && is_pretty) {
1186*61046927SAndroid Build Coastguard Worker                 APPEND_INDENT(level);
1187*61046927SAndroid Build Coastguard Worker             }
1188*61046927SAndroid Build Coastguard Worker             APPEND_STRING("]");
1189*61046927SAndroid Build Coastguard Worker             return written_total;
1190*61046927SAndroid Build Coastguard Worker         case JSONObject:
1191*61046927SAndroid Build Coastguard Worker             object = json_value_get_object(value);
1192*61046927SAndroid Build Coastguard Worker             count  = json_object_get_count(object);
1193*61046927SAndroid Build Coastguard Worker             APPEND_STRING("{");
1194*61046927SAndroid Build Coastguard Worker             if (count > 0 && is_pretty) {
1195*61046927SAndroid Build Coastguard Worker                 APPEND_STRING("\n");
1196*61046927SAndroid Build Coastguard Worker             }
1197*61046927SAndroid Build Coastguard Worker             for (i = 0; i < count; i++) {
1198*61046927SAndroid Build Coastguard Worker                 key = json_object_get_name(object, i);
1199*61046927SAndroid Build Coastguard Worker                 if (key == NULL) {
1200*61046927SAndroid Build Coastguard Worker                     return -1;
1201*61046927SAndroid Build Coastguard Worker                 }
1202*61046927SAndroid Build Coastguard Worker                 if (is_pretty) {
1203*61046927SAndroid Build Coastguard Worker                     APPEND_INDENT(level+1);
1204*61046927SAndroid Build Coastguard Worker                 }
1205*61046927SAndroid Build Coastguard Worker                 /* We do not support key names with embedded \0 chars */
1206*61046927SAndroid Build Coastguard Worker                 written = json_serialize_string(key, strlen(key), buf);
1207*61046927SAndroid Build Coastguard Worker                 if (written < 0) {
1208*61046927SAndroid Build Coastguard Worker                     return -1;
1209*61046927SAndroid Build Coastguard Worker                 }
1210*61046927SAndroid Build Coastguard Worker                 if (buf != NULL) {
1211*61046927SAndroid Build Coastguard Worker                     buf += written;
1212*61046927SAndroid Build Coastguard Worker                 }
1213*61046927SAndroid Build Coastguard Worker                 written_total += written;
1214*61046927SAndroid Build Coastguard Worker                 APPEND_STRING(":");
1215*61046927SAndroid Build Coastguard Worker                 if (is_pretty) {
1216*61046927SAndroid Build Coastguard Worker                     APPEND_STRING(" ");
1217*61046927SAndroid Build Coastguard Worker                 }
1218*61046927SAndroid Build Coastguard Worker                 temp_value = json_object_get_value_at(object, i);
1219*61046927SAndroid Build Coastguard Worker                 written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
1220*61046927SAndroid Build Coastguard Worker                 if (written < 0) {
1221*61046927SAndroid Build Coastguard Worker                     return -1;
1222*61046927SAndroid Build Coastguard Worker                 }
1223*61046927SAndroid Build Coastguard Worker                 if (buf != NULL) {
1224*61046927SAndroid Build Coastguard Worker                     buf += written;
1225*61046927SAndroid Build Coastguard Worker                 }
1226*61046927SAndroid Build Coastguard Worker                 written_total += written;
1227*61046927SAndroid Build Coastguard Worker                 if (i < (count - 1)) {
1228*61046927SAndroid Build Coastguard Worker                     APPEND_STRING(",");
1229*61046927SAndroid Build Coastguard Worker                 }
1230*61046927SAndroid Build Coastguard Worker                 if (is_pretty) {
1231*61046927SAndroid Build Coastguard Worker                     APPEND_STRING("\n");
1232*61046927SAndroid Build Coastguard Worker                 }
1233*61046927SAndroid Build Coastguard Worker             }
1234*61046927SAndroid Build Coastguard Worker             if (count > 0 && is_pretty) {
1235*61046927SAndroid Build Coastguard Worker                 APPEND_INDENT(level);
1236*61046927SAndroid Build Coastguard Worker             }
1237*61046927SAndroid Build Coastguard Worker             APPEND_STRING("}");
1238*61046927SAndroid Build Coastguard Worker             return written_total;
1239*61046927SAndroid Build Coastguard Worker         case JSONString:
1240*61046927SAndroid Build Coastguard Worker             string = json_value_get_string(value);
1241*61046927SAndroid Build Coastguard Worker             if (string == NULL) {
1242*61046927SAndroid Build Coastguard Worker                 return -1;
1243*61046927SAndroid Build Coastguard Worker             }
1244*61046927SAndroid Build Coastguard Worker             len = json_value_get_string_len(value);
1245*61046927SAndroid Build Coastguard Worker             written = json_serialize_string(string, len, buf);
1246*61046927SAndroid Build Coastguard Worker             if (written < 0) {
1247*61046927SAndroid Build Coastguard Worker                 return -1;
1248*61046927SAndroid Build Coastguard Worker             }
1249*61046927SAndroid Build Coastguard Worker             if (buf != NULL) {
1250*61046927SAndroid Build Coastguard Worker                 buf += written;
1251*61046927SAndroid Build Coastguard Worker             }
1252*61046927SAndroid Build Coastguard Worker             written_total += written;
1253*61046927SAndroid Build Coastguard Worker             return written_total;
1254*61046927SAndroid Build Coastguard Worker         case JSONBoolean:
1255*61046927SAndroid Build Coastguard Worker             if (json_value_get_boolean(value)) {
1256*61046927SAndroid Build Coastguard Worker                 APPEND_STRING("true");
1257*61046927SAndroid Build Coastguard Worker             } else {
1258*61046927SAndroid Build Coastguard Worker                 APPEND_STRING("false");
1259*61046927SAndroid Build Coastguard Worker             }
1260*61046927SAndroid Build Coastguard Worker             return written_total;
1261*61046927SAndroid Build Coastguard Worker         case JSONNumber:
1262*61046927SAndroid Build Coastguard Worker             num = json_value_get_number(value);
1263*61046927SAndroid Build Coastguard Worker             if (buf != NULL) {
1264*61046927SAndroid Build Coastguard Worker                 num_buf = buf;
1265*61046927SAndroid Build Coastguard Worker             }
1266*61046927SAndroid Build Coastguard Worker             if (parson_number_serialization_function) {
1267*61046927SAndroid Build Coastguard Worker                 written = parson_number_serialization_function(num, num_buf);
1268*61046927SAndroid Build Coastguard Worker             } else {
1269*61046927SAndroid Build Coastguard Worker                 const char *float_format = parson_float_format ? parson_float_format : PARSON_DEFAULT_FLOAT_FORMAT;
1270*61046927SAndroid Build Coastguard Worker                 written = parson_sprintf(num_buf, float_format, num);
1271*61046927SAndroid Build Coastguard Worker             }
1272*61046927SAndroid Build Coastguard Worker             if (written < 0) {
1273*61046927SAndroid Build Coastguard Worker                 return -1;
1274*61046927SAndroid Build Coastguard Worker             }
1275*61046927SAndroid Build Coastguard Worker             if (buf != NULL) {
1276*61046927SAndroid Build Coastguard Worker                 buf += written;
1277*61046927SAndroid Build Coastguard Worker             }
1278*61046927SAndroid Build Coastguard Worker             written_total += written;
1279*61046927SAndroid Build Coastguard Worker             return written_total;
1280*61046927SAndroid Build Coastguard Worker         case JSONNull:
1281*61046927SAndroid Build Coastguard Worker             APPEND_STRING("null");
1282*61046927SAndroid Build Coastguard Worker             return written_total;
1283*61046927SAndroid Build Coastguard Worker         case JSONError:
1284*61046927SAndroid Build Coastguard Worker             return -1;
1285*61046927SAndroid Build Coastguard Worker         default:
1286*61046927SAndroid Build Coastguard Worker             return -1;
1287*61046927SAndroid Build Coastguard Worker     }
1288*61046927SAndroid Build Coastguard Worker }
1289*61046927SAndroid Build Coastguard Worker 
json_serialize_string(const char * string,size_t len,char * buf)1290*61046927SAndroid Build Coastguard Worker static int json_serialize_string(const char *string, size_t len, char *buf) {
1291*61046927SAndroid Build Coastguard Worker     size_t i = 0;
1292*61046927SAndroid Build Coastguard Worker     char c = '\0';
1293*61046927SAndroid Build Coastguard Worker     int written = -1, written_total = 0;
1294*61046927SAndroid Build Coastguard Worker     APPEND_STRING("\"");
1295*61046927SAndroid Build Coastguard Worker     for (i = 0; i < len; i++) {
1296*61046927SAndroid Build Coastguard Worker         c = string[i];
1297*61046927SAndroid Build Coastguard Worker         switch (c) {
1298*61046927SAndroid Build Coastguard Worker             case '\"': APPEND_STRING("\\\""); break;
1299*61046927SAndroid Build Coastguard Worker             case '\\': APPEND_STRING("\\\\"); break;
1300*61046927SAndroid Build Coastguard Worker             case '\b': APPEND_STRING("\\b"); break;
1301*61046927SAndroid Build Coastguard Worker             case '\f': APPEND_STRING("\\f"); break;
1302*61046927SAndroid Build Coastguard Worker             case '\n': APPEND_STRING("\\n"); break;
1303*61046927SAndroid Build Coastguard Worker             case '\r': APPEND_STRING("\\r"); break;
1304*61046927SAndroid Build Coastguard Worker             case '\t': APPEND_STRING("\\t"); break;
1305*61046927SAndroid Build Coastguard Worker             case '\x00': APPEND_STRING("\\u0000"); break;
1306*61046927SAndroid Build Coastguard Worker             case '\x01': APPEND_STRING("\\u0001"); break;
1307*61046927SAndroid Build Coastguard Worker             case '\x02': APPEND_STRING("\\u0002"); break;
1308*61046927SAndroid Build Coastguard Worker             case '\x03': APPEND_STRING("\\u0003"); break;
1309*61046927SAndroid Build Coastguard Worker             case '\x04': APPEND_STRING("\\u0004"); break;
1310*61046927SAndroid Build Coastguard Worker             case '\x05': APPEND_STRING("\\u0005"); break;
1311*61046927SAndroid Build Coastguard Worker             case '\x06': APPEND_STRING("\\u0006"); break;
1312*61046927SAndroid Build Coastguard Worker             case '\x07': APPEND_STRING("\\u0007"); break;
1313*61046927SAndroid Build Coastguard Worker             /* '\x08' duplicate: '\b' */
1314*61046927SAndroid Build Coastguard Worker             /* '\x09' duplicate: '\t' */
1315*61046927SAndroid Build Coastguard Worker             /* '\x0a' duplicate: '\n' */
1316*61046927SAndroid Build Coastguard Worker             case '\x0b': APPEND_STRING("\\u000b"); break;
1317*61046927SAndroid Build Coastguard Worker             /* '\x0c' duplicate: '\f' */
1318*61046927SAndroid Build Coastguard Worker             /* '\x0d' duplicate: '\r' */
1319*61046927SAndroid Build Coastguard Worker             case '\x0e': APPEND_STRING("\\u000e"); break;
1320*61046927SAndroid Build Coastguard Worker             case '\x0f': APPEND_STRING("\\u000f"); break;
1321*61046927SAndroid Build Coastguard Worker             case '\x10': APPEND_STRING("\\u0010"); break;
1322*61046927SAndroid Build Coastguard Worker             case '\x11': APPEND_STRING("\\u0011"); break;
1323*61046927SAndroid Build Coastguard Worker             case '\x12': APPEND_STRING("\\u0012"); break;
1324*61046927SAndroid Build Coastguard Worker             case '\x13': APPEND_STRING("\\u0013"); break;
1325*61046927SAndroid Build Coastguard Worker             case '\x14': APPEND_STRING("\\u0014"); break;
1326*61046927SAndroid Build Coastguard Worker             case '\x15': APPEND_STRING("\\u0015"); break;
1327*61046927SAndroid Build Coastguard Worker             case '\x16': APPEND_STRING("\\u0016"); break;
1328*61046927SAndroid Build Coastguard Worker             case '\x17': APPEND_STRING("\\u0017"); break;
1329*61046927SAndroid Build Coastguard Worker             case '\x18': APPEND_STRING("\\u0018"); break;
1330*61046927SAndroid Build Coastguard Worker             case '\x19': APPEND_STRING("\\u0019"); break;
1331*61046927SAndroid Build Coastguard Worker             case '\x1a': APPEND_STRING("\\u001a"); break;
1332*61046927SAndroid Build Coastguard Worker             case '\x1b': APPEND_STRING("\\u001b"); break;
1333*61046927SAndroid Build Coastguard Worker             case '\x1c': APPEND_STRING("\\u001c"); break;
1334*61046927SAndroid Build Coastguard Worker             case '\x1d': APPEND_STRING("\\u001d"); break;
1335*61046927SAndroid Build Coastguard Worker             case '\x1e': APPEND_STRING("\\u001e"); break;
1336*61046927SAndroid Build Coastguard Worker             case '\x1f': APPEND_STRING("\\u001f"); break;
1337*61046927SAndroid Build Coastguard Worker             case '/':
1338*61046927SAndroid Build Coastguard Worker                 if (parson_escape_slashes) {
1339*61046927SAndroid Build Coastguard Worker                     APPEND_STRING("\\/");  /* to make json embeddable in xml\/html */
1340*61046927SAndroid Build Coastguard Worker                 } else {
1341*61046927SAndroid Build Coastguard Worker                     APPEND_STRING("/");
1342*61046927SAndroid Build Coastguard Worker                 }
1343*61046927SAndroid Build Coastguard Worker                 break;
1344*61046927SAndroid Build Coastguard Worker             default:
1345*61046927SAndroid Build Coastguard Worker                 if (buf != NULL) {
1346*61046927SAndroid Build Coastguard Worker                     buf[0] = c;
1347*61046927SAndroid Build Coastguard Worker                     buf += 1;
1348*61046927SAndroid Build Coastguard Worker                 }
1349*61046927SAndroid Build Coastguard Worker                 written_total += 1;
1350*61046927SAndroid Build Coastguard Worker                 break;
1351*61046927SAndroid Build Coastguard Worker         }
1352*61046927SAndroid Build Coastguard Worker     }
1353*61046927SAndroid Build Coastguard Worker     APPEND_STRING("\"");
1354*61046927SAndroid Build Coastguard Worker     return written_total;
1355*61046927SAndroid Build Coastguard Worker }
1356*61046927SAndroid Build Coastguard Worker 
1357*61046927SAndroid Build Coastguard Worker #undef APPEND_STRING
1358*61046927SAndroid Build Coastguard Worker #undef APPEND_INDENT
1359*61046927SAndroid Build Coastguard Worker 
1360*61046927SAndroid Build Coastguard Worker /* Parser API */
json_parse_file(const char * filename)1361*61046927SAndroid Build Coastguard Worker JSON_Value * json_parse_file(const char *filename) {
1362*61046927SAndroid Build Coastguard Worker     char *file_contents = read_file(filename);
1363*61046927SAndroid Build Coastguard Worker     JSON_Value *output_value = NULL;
1364*61046927SAndroid Build Coastguard Worker     if (file_contents == NULL) {
1365*61046927SAndroid Build Coastguard Worker         return NULL;
1366*61046927SAndroid Build Coastguard Worker     }
1367*61046927SAndroid Build Coastguard Worker     output_value = json_parse_string(file_contents);
1368*61046927SAndroid Build Coastguard Worker     parson_free(file_contents);
1369*61046927SAndroid Build Coastguard Worker     return output_value;
1370*61046927SAndroid Build Coastguard Worker }
1371*61046927SAndroid Build Coastguard Worker 
json_parse_file_with_comments(const char * filename)1372*61046927SAndroid Build Coastguard Worker JSON_Value * json_parse_file_with_comments(const char *filename) {
1373*61046927SAndroid Build Coastguard Worker     char *file_contents = read_file(filename);
1374*61046927SAndroid Build Coastguard Worker     JSON_Value *output_value = NULL;
1375*61046927SAndroid Build Coastguard Worker     if (file_contents == NULL) {
1376*61046927SAndroid Build Coastguard Worker         return NULL;
1377*61046927SAndroid Build Coastguard Worker     }
1378*61046927SAndroid Build Coastguard Worker     output_value = json_parse_string_with_comments(file_contents);
1379*61046927SAndroid Build Coastguard Worker     parson_free(file_contents);
1380*61046927SAndroid Build Coastguard Worker     return output_value;
1381*61046927SAndroid Build Coastguard Worker }
1382*61046927SAndroid Build Coastguard Worker 
json_parse_string(const char * string)1383*61046927SAndroid Build Coastguard Worker JSON_Value * json_parse_string(const char *string) {
1384*61046927SAndroid Build Coastguard Worker     if (string == NULL) {
1385*61046927SAndroid Build Coastguard Worker         return NULL;
1386*61046927SAndroid Build Coastguard Worker     }
1387*61046927SAndroid Build Coastguard Worker     if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') {
1388*61046927SAndroid Build Coastguard Worker         string = string + 3; /* Support for UTF-8 BOM */
1389*61046927SAndroid Build Coastguard Worker     }
1390*61046927SAndroid Build Coastguard Worker     return parse_value((const char**)&string, 0);
1391*61046927SAndroid Build Coastguard Worker }
1392*61046927SAndroid Build Coastguard Worker 
json_parse_string_with_comments(const char * string)1393*61046927SAndroid Build Coastguard Worker JSON_Value * json_parse_string_with_comments(const char *string) {
1394*61046927SAndroid Build Coastguard Worker     JSON_Value *result = NULL;
1395*61046927SAndroid Build Coastguard Worker     char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
1396*61046927SAndroid Build Coastguard Worker     string_mutable_copy = parson_strdup(string);
1397*61046927SAndroid Build Coastguard Worker     if (string_mutable_copy == NULL) {
1398*61046927SAndroid Build Coastguard Worker         return NULL;
1399*61046927SAndroid Build Coastguard Worker     }
1400*61046927SAndroid Build Coastguard Worker     remove_comments(string_mutable_copy, "/*", "*/");
1401*61046927SAndroid Build Coastguard Worker     remove_comments(string_mutable_copy, "//", "\n");
1402*61046927SAndroid Build Coastguard Worker     string_mutable_copy_ptr = string_mutable_copy;
1403*61046927SAndroid Build Coastguard Worker     result = parse_value((const char**)&string_mutable_copy_ptr, 0);
1404*61046927SAndroid Build Coastguard Worker     parson_free(string_mutable_copy);
1405*61046927SAndroid Build Coastguard Worker     return result;
1406*61046927SAndroid Build Coastguard Worker }
1407*61046927SAndroid Build Coastguard Worker 
1408*61046927SAndroid Build Coastguard Worker /* JSON Object API */
1409*61046927SAndroid Build Coastguard Worker 
json_object_get_value(const JSON_Object * object,const char * name)1410*61046927SAndroid Build Coastguard Worker JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
1411*61046927SAndroid Build Coastguard Worker     if (object == NULL || name == NULL) {
1412*61046927SAndroid Build Coastguard Worker         return NULL;
1413*61046927SAndroid Build Coastguard Worker     }
1414*61046927SAndroid Build Coastguard Worker     return json_object_getn_value(object, name, strlen(name));
1415*61046927SAndroid Build Coastguard Worker }
1416*61046927SAndroid Build Coastguard Worker 
json_object_get_string(const JSON_Object * object,const char * name)1417*61046927SAndroid Build Coastguard Worker const char * json_object_get_string(const JSON_Object *object, const char *name) {
1418*61046927SAndroid Build Coastguard Worker     return json_value_get_string(json_object_get_value(object, name));
1419*61046927SAndroid Build Coastguard Worker }
1420*61046927SAndroid Build Coastguard Worker 
json_object_get_string_len(const JSON_Object * object,const char * name)1421*61046927SAndroid Build Coastguard Worker size_t json_object_get_string_len(const JSON_Object *object, const char *name) {
1422*61046927SAndroid Build Coastguard Worker     return json_value_get_string_len(json_object_get_value(object, name));
1423*61046927SAndroid Build Coastguard Worker }
1424*61046927SAndroid Build Coastguard Worker 
json_object_get_number(const JSON_Object * object,const char * name)1425*61046927SAndroid Build Coastguard Worker double json_object_get_number(const JSON_Object *object, const char *name) {
1426*61046927SAndroid Build Coastguard Worker     return json_value_get_number(json_object_get_value(object, name));
1427*61046927SAndroid Build Coastguard Worker }
1428*61046927SAndroid Build Coastguard Worker 
json_object_get_object(const JSON_Object * object,const char * name)1429*61046927SAndroid Build Coastguard Worker JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
1430*61046927SAndroid Build Coastguard Worker     return json_value_get_object(json_object_get_value(object, name));
1431*61046927SAndroid Build Coastguard Worker }
1432*61046927SAndroid Build Coastguard Worker 
json_object_get_array(const JSON_Object * object,const char * name)1433*61046927SAndroid Build Coastguard Worker JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
1434*61046927SAndroid Build Coastguard Worker     return json_value_get_array(json_object_get_value(object, name));
1435*61046927SAndroid Build Coastguard Worker }
1436*61046927SAndroid Build Coastguard Worker 
json_object_get_boolean(const JSON_Object * object,const char * name)1437*61046927SAndroid Build Coastguard Worker int json_object_get_boolean(const JSON_Object *object, const char *name) {
1438*61046927SAndroid Build Coastguard Worker     return json_value_get_boolean(json_object_get_value(object, name));
1439*61046927SAndroid Build Coastguard Worker }
1440*61046927SAndroid Build Coastguard Worker 
json_object_dotget_value(const JSON_Object * object,const char * name)1441*61046927SAndroid Build Coastguard Worker JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
1442*61046927SAndroid Build Coastguard Worker     const char *dot_position = strchr(name, '.');
1443*61046927SAndroid Build Coastguard Worker     if (!dot_position) {
1444*61046927SAndroid Build Coastguard Worker         return json_object_get_value(object, name);
1445*61046927SAndroid Build Coastguard Worker     }
1446*61046927SAndroid Build Coastguard Worker     object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
1447*61046927SAndroid Build Coastguard Worker     return json_object_dotget_value(object, dot_position + 1);
1448*61046927SAndroid Build Coastguard Worker }
1449*61046927SAndroid Build Coastguard Worker 
json_object_dotget_string(const JSON_Object * object,const char * name)1450*61046927SAndroid Build Coastguard Worker const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
1451*61046927SAndroid Build Coastguard Worker     return json_value_get_string(json_object_dotget_value(object, name));
1452*61046927SAndroid Build Coastguard Worker }
1453*61046927SAndroid Build Coastguard Worker 
json_object_dotget_string_len(const JSON_Object * object,const char * name)1454*61046927SAndroid Build Coastguard Worker size_t json_object_dotget_string_len(const JSON_Object *object, const char *name) {
1455*61046927SAndroid Build Coastguard Worker     return json_value_get_string_len(json_object_dotget_value(object, name));
1456*61046927SAndroid Build Coastguard Worker }
1457*61046927SAndroid Build Coastguard Worker 
json_object_dotget_number(const JSON_Object * object,const char * name)1458*61046927SAndroid Build Coastguard Worker double json_object_dotget_number(const JSON_Object *object, const char *name) {
1459*61046927SAndroid Build Coastguard Worker     return json_value_get_number(json_object_dotget_value(object, name));
1460*61046927SAndroid Build Coastguard Worker }
1461*61046927SAndroid Build Coastguard Worker 
json_object_dotget_object(const JSON_Object * object,const char * name)1462*61046927SAndroid Build Coastguard Worker JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
1463*61046927SAndroid Build Coastguard Worker     return json_value_get_object(json_object_dotget_value(object, name));
1464*61046927SAndroid Build Coastguard Worker }
1465*61046927SAndroid Build Coastguard Worker 
json_object_dotget_array(const JSON_Object * object,const char * name)1466*61046927SAndroid Build Coastguard Worker JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
1467*61046927SAndroid Build Coastguard Worker     return json_value_get_array(json_object_dotget_value(object, name));
1468*61046927SAndroid Build Coastguard Worker }
1469*61046927SAndroid Build Coastguard Worker 
json_object_dotget_boolean(const JSON_Object * object,const char * name)1470*61046927SAndroid Build Coastguard Worker int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
1471*61046927SAndroid Build Coastguard Worker     return json_value_get_boolean(json_object_dotget_value(object, name));
1472*61046927SAndroid Build Coastguard Worker }
1473*61046927SAndroid Build Coastguard Worker 
json_object_get_count(const JSON_Object * object)1474*61046927SAndroid Build Coastguard Worker size_t json_object_get_count(const JSON_Object *object) {
1475*61046927SAndroid Build Coastguard Worker     return object ? object->count : 0;
1476*61046927SAndroid Build Coastguard Worker }
1477*61046927SAndroid Build Coastguard Worker 
json_object_get_name(const JSON_Object * object,size_t index)1478*61046927SAndroid Build Coastguard Worker const char * json_object_get_name(const JSON_Object *object, size_t index) {
1479*61046927SAndroid Build Coastguard Worker     if (object == NULL || index >= json_object_get_count(object)) {
1480*61046927SAndroid Build Coastguard Worker         return NULL;
1481*61046927SAndroid Build Coastguard Worker     }
1482*61046927SAndroid Build Coastguard Worker     return object->names[index];
1483*61046927SAndroid Build Coastguard Worker }
1484*61046927SAndroid Build Coastguard Worker 
json_object_get_value_at(const JSON_Object * object,size_t index)1485*61046927SAndroid Build Coastguard Worker JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) {
1486*61046927SAndroid Build Coastguard Worker     if (object == NULL || index >= json_object_get_count(object)) {
1487*61046927SAndroid Build Coastguard Worker         return NULL;
1488*61046927SAndroid Build Coastguard Worker     }
1489*61046927SAndroid Build Coastguard Worker     return object->values[index];
1490*61046927SAndroid Build Coastguard Worker }
1491*61046927SAndroid Build Coastguard Worker 
json_object_get_wrapping_value(const JSON_Object * object)1492*61046927SAndroid Build Coastguard Worker JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) {
1493*61046927SAndroid Build Coastguard Worker     if (!object) {
1494*61046927SAndroid Build Coastguard Worker         return NULL;
1495*61046927SAndroid Build Coastguard Worker     }
1496*61046927SAndroid Build Coastguard Worker     return object->wrapping_value;
1497*61046927SAndroid Build Coastguard Worker }
1498*61046927SAndroid Build Coastguard Worker 
json_object_has_value(const JSON_Object * object,const char * name)1499*61046927SAndroid Build Coastguard Worker int json_object_has_value (const JSON_Object *object, const char *name) {
1500*61046927SAndroid Build Coastguard Worker     return json_object_get_value(object, name) != NULL;
1501*61046927SAndroid Build Coastguard Worker }
1502*61046927SAndroid Build Coastguard Worker 
json_object_has_value_of_type(const JSON_Object * object,const char * name,JSON_Value_Type type)1503*61046927SAndroid Build Coastguard Worker int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
1504*61046927SAndroid Build Coastguard Worker     JSON_Value *val = json_object_get_value(object, name);
1505*61046927SAndroid Build Coastguard Worker     return val != NULL && json_value_get_type(val) == type;
1506*61046927SAndroid Build Coastguard Worker }
1507*61046927SAndroid Build Coastguard Worker 
json_object_dothas_value(const JSON_Object * object,const char * name)1508*61046927SAndroid Build Coastguard Worker int json_object_dothas_value (const JSON_Object *object, const char *name) {
1509*61046927SAndroid Build Coastguard Worker     return json_object_dotget_value(object, name) != NULL;
1510*61046927SAndroid Build Coastguard Worker }
1511*61046927SAndroid Build Coastguard Worker 
json_object_dothas_value_of_type(const JSON_Object * object,const char * name,JSON_Value_Type type)1512*61046927SAndroid Build Coastguard Worker int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
1513*61046927SAndroid Build Coastguard Worker     JSON_Value *val = json_object_dotget_value(object, name);
1514*61046927SAndroid Build Coastguard Worker     return val != NULL && json_value_get_type(val) == type;
1515*61046927SAndroid Build Coastguard Worker }
1516*61046927SAndroid Build Coastguard Worker 
1517*61046927SAndroid Build Coastguard Worker /* JSON Array API */
json_array_get_value(const JSON_Array * array,size_t index)1518*61046927SAndroid Build Coastguard Worker JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
1519*61046927SAndroid Build Coastguard Worker     if (array == NULL || index >= json_array_get_count(array)) {
1520*61046927SAndroid Build Coastguard Worker         return NULL;
1521*61046927SAndroid Build Coastguard Worker     }
1522*61046927SAndroid Build Coastguard Worker     return array->items[index];
1523*61046927SAndroid Build Coastguard Worker }
1524*61046927SAndroid Build Coastguard Worker 
json_array_get_string(const JSON_Array * array,size_t index)1525*61046927SAndroid Build Coastguard Worker const char * json_array_get_string(const JSON_Array *array, size_t index) {
1526*61046927SAndroid Build Coastguard Worker     return json_value_get_string(json_array_get_value(array, index));
1527*61046927SAndroid Build Coastguard Worker }
1528*61046927SAndroid Build Coastguard Worker 
json_array_get_string_len(const JSON_Array * array,size_t index)1529*61046927SAndroid Build Coastguard Worker size_t json_array_get_string_len(const JSON_Array *array, size_t index) {
1530*61046927SAndroid Build Coastguard Worker     return json_value_get_string_len(json_array_get_value(array, index));
1531*61046927SAndroid Build Coastguard Worker }
1532*61046927SAndroid Build Coastguard Worker 
json_array_get_number(const JSON_Array * array,size_t index)1533*61046927SAndroid Build Coastguard Worker double json_array_get_number(const JSON_Array *array, size_t index) {
1534*61046927SAndroid Build Coastguard Worker     return json_value_get_number(json_array_get_value(array, index));
1535*61046927SAndroid Build Coastguard Worker }
1536*61046927SAndroid Build Coastguard Worker 
json_array_get_object(const JSON_Array * array,size_t index)1537*61046927SAndroid Build Coastguard Worker JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
1538*61046927SAndroid Build Coastguard Worker     return json_value_get_object(json_array_get_value(array, index));
1539*61046927SAndroid Build Coastguard Worker }
1540*61046927SAndroid Build Coastguard Worker 
json_array_get_array(const JSON_Array * array,size_t index)1541*61046927SAndroid Build Coastguard Worker JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
1542*61046927SAndroid Build Coastguard Worker     return json_value_get_array(json_array_get_value(array, index));
1543*61046927SAndroid Build Coastguard Worker }
1544*61046927SAndroid Build Coastguard Worker 
json_array_get_boolean(const JSON_Array * array,size_t index)1545*61046927SAndroid Build Coastguard Worker int json_array_get_boolean(const JSON_Array *array, size_t index) {
1546*61046927SAndroid Build Coastguard Worker     return json_value_get_boolean(json_array_get_value(array, index));
1547*61046927SAndroid Build Coastguard Worker }
1548*61046927SAndroid Build Coastguard Worker 
json_array_get_count(const JSON_Array * array)1549*61046927SAndroid Build Coastguard Worker size_t json_array_get_count(const JSON_Array *array) {
1550*61046927SAndroid Build Coastguard Worker     return array ? array->count : 0;
1551*61046927SAndroid Build Coastguard Worker }
1552*61046927SAndroid Build Coastguard Worker 
json_array_get_wrapping_value(const JSON_Array * array)1553*61046927SAndroid Build Coastguard Worker JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) {
1554*61046927SAndroid Build Coastguard Worker     if (!array) {
1555*61046927SAndroid Build Coastguard Worker         return NULL;
1556*61046927SAndroid Build Coastguard Worker     }
1557*61046927SAndroid Build Coastguard Worker     return array->wrapping_value;
1558*61046927SAndroid Build Coastguard Worker }
1559*61046927SAndroid Build Coastguard Worker 
1560*61046927SAndroid Build Coastguard Worker /* JSON Value API */
json_value_get_type(const JSON_Value * value)1561*61046927SAndroid Build Coastguard Worker JSON_Value_Type json_value_get_type(const JSON_Value *value) {
1562*61046927SAndroid Build Coastguard Worker     return value ? value->type : JSONError;
1563*61046927SAndroid Build Coastguard Worker }
1564*61046927SAndroid Build Coastguard Worker 
json_value_get_object(const JSON_Value * value)1565*61046927SAndroid Build Coastguard Worker JSON_Object * json_value_get_object(const JSON_Value *value) {
1566*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
1567*61046927SAndroid Build Coastguard Worker }
1568*61046927SAndroid Build Coastguard Worker 
json_value_get_array(const JSON_Value * value)1569*61046927SAndroid Build Coastguard Worker JSON_Array * json_value_get_array(const JSON_Value *value) {
1570*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
1571*61046927SAndroid Build Coastguard Worker }
1572*61046927SAndroid Build Coastguard Worker 
json_value_get_string_desc(const JSON_Value * value)1573*61046927SAndroid Build Coastguard Worker static const JSON_String * json_value_get_string_desc(const JSON_Value *value) {
1574*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value) == JSONString ? &value->value.string : NULL;
1575*61046927SAndroid Build Coastguard Worker }
1576*61046927SAndroid Build Coastguard Worker 
json_value_get_string(const JSON_Value * value)1577*61046927SAndroid Build Coastguard Worker const char * json_value_get_string(const JSON_Value *value) {
1578*61046927SAndroid Build Coastguard Worker     const JSON_String *str = json_value_get_string_desc(value);
1579*61046927SAndroid Build Coastguard Worker     return str ? str->chars : NULL;
1580*61046927SAndroid Build Coastguard Worker }
1581*61046927SAndroid Build Coastguard Worker 
json_value_get_string_len(const JSON_Value * value)1582*61046927SAndroid Build Coastguard Worker size_t json_value_get_string_len(const JSON_Value *value) {
1583*61046927SAndroid Build Coastguard Worker     const JSON_String *str = json_value_get_string_desc(value);
1584*61046927SAndroid Build Coastguard Worker     return str ? str->length : 0;
1585*61046927SAndroid Build Coastguard Worker }
1586*61046927SAndroid Build Coastguard Worker 
json_value_get_number(const JSON_Value * value)1587*61046927SAndroid Build Coastguard Worker double json_value_get_number(const JSON_Value *value) {
1588*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
1589*61046927SAndroid Build Coastguard Worker }
1590*61046927SAndroid Build Coastguard Worker 
json_value_get_boolean(const JSON_Value * value)1591*61046927SAndroid Build Coastguard Worker int json_value_get_boolean(const JSON_Value *value) {
1592*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
1593*61046927SAndroid Build Coastguard Worker }
1594*61046927SAndroid Build Coastguard Worker 
json_value_get_parent(const JSON_Value * value)1595*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_get_parent (const JSON_Value *value) {
1596*61046927SAndroid Build Coastguard Worker     return value ? value->parent : NULL;
1597*61046927SAndroid Build Coastguard Worker }
1598*61046927SAndroid Build Coastguard Worker 
json_value_free(JSON_Value * value)1599*61046927SAndroid Build Coastguard Worker void json_value_free(JSON_Value *value) {
1600*61046927SAndroid Build Coastguard Worker     switch (json_value_get_type(value)) {
1601*61046927SAndroid Build Coastguard Worker         case JSONObject:
1602*61046927SAndroid Build Coastguard Worker             json_object_free(value->value.object);
1603*61046927SAndroid Build Coastguard Worker             break;
1604*61046927SAndroid Build Coastguard Worker         case JSONString:
1605*61046927SAndroid Build Coastguard Worker             parson_free(value->value.string.chars);
1606*61046927SAndroid Build Coastguard Worker             break;
1607*61046927SAndroid Build Coastguard Worker         case JSONArray:
1608*61046927SAndroid Build Coastguard Worker             json_array_free(value->value.array);
1609*61046927SAndroid Build Coastguard Worker             break;
1610*61046927SAndroid Build Coastguard Worker         default:
1611*61046927SAndroid Build Coastguard Worker             break;
1612*61046927SAndroid Build Coastguard Worker     }
1613*61046927SAndroid Build Coastguard Worker     parson_free(value);
1614*61046927SAndroid Build Coastguard Worker }
1615*61046927SAndroid Build Coastguard Worker 
json_value_init_object(void)1616*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_object(void) {
1617*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
1618*61046927SAndroid Build Coastguard Worker     if (!new_value) {
1619*61046927SAndroid Build Coastguard Worker         return NULL;
1620*61046927SAndroid Build Coastguard Worker     }
1621*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
1622*61046927SAndroid Build Coastguard Worker     new_value->type = JSONObject;
1623*61046927SAndroid Build Coastguard Worker     new_value->value.object = json_object_make(new_value);
1624*61046927SAndroid Build Coastguard Worker     if (!new_value->value.object) {
1625*61046927SAndroid Build Coastguard Worker         parson_free(new_value);
1626*61046927SAndroid Build Coastguard Worker         return NULL;
1627*61046927SAndroid Build Coastguard Worker     }
1628*61046927SAndroid Build Coastguard Worker     return new_value;
1629*61046927SAndroid Build Coastguard Worker }
1630*61046927SAndroid Build Coastguard Worker 
json_value_init_array(void)1631*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_array(void) {
1632*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
1633*61046927SAndroid Build Coastguard Worker     if (!new_value) {
1634*61046927SAndroid Build Coastguard Worker         return NULL;
1635*61046927SAndroid Build Coastguard Worker     }
1636*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
1637*61046927SAndroid Build Coastguard Worker     new_value->type = JSONArray;
1638*61046927SAndroid Build Coastguard Worker     new_value->value.array = json_array_make(new_value);
1639*61046927SAndroid Build Coastguard Worker     if (!new_value->value.array) {
1640*61046927SAndroid Build Coastguard Worker         parson_free(new_value);
1641*61046927SAndroid Build Coastguard Worker         return NULL;
1642*61046927SAndroid Build Coastguard Worker     }
1643*61046927SAndroid Build Coastguard Worker     return new_value;
1644*61046927SAndroid Build Coastguard Worker }
1645*61046927SAndroid Build Coastguard Worker 
json_value_init_string(const char * string)1646*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_string(const char *string) {
1647*61046927SAndroid Build Coastguard Worker     if (string == NULL) {
1648*61046927SAndroid Build Coastguard Worker         return NULL;
1649*61046927SAndroid Build Coastguard Worker     }
1650*61046927SAndroid Build Coastguard Worker     return json_value_init_string_with_len(string, strlen(string));
1651*61046927SAndroid Build Coastguard Worker }
1652*61046927SAndroid Build Coastguard Worker 
json_value_init_string_with_len(const char * string,size_t length)1653*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_string_with_len(const char *string, size_t length) {
1654*61046927SAndroid Build Coastguard Worker     char *copy = NULL;
1655*61046927SAndroid Build Coastguard Worker     JSON_Value *value;
1656*61046927SAndroid Build Coastguard Worker     if (string == NULL) {
1657*61046927SAndroid Build Coastguard Worker         return NULL;
1658*61046927SAndroid Build Coastguard Worker     }
1659*61046927SAndroid Build Coastguard Worker     if (!is_valid_utf8(string, length)) {
1660*61046927SAndroid Build Coastguard Worker         return NULL;
1661*61046927SAndroid Build Coastguard Worker     }
1662*61046927SAndroid Build Coastguard Worker     copy = parson_strndup(string, length);
1663*61046927SAndroid Build Coastguard Worker     if (copy == NULL) {
1664*61046927SAndroid Build Coastguard Worker         return NULL;
1665*61046927SAndroid Build Coastguard Worker     }
1666*61046927SAndroid Build Coastguard Worker     value = json_value_init_string_no_copy(copy, length);
1667*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1668*61046927SAndroid Build Coastguard Worker         parson_free(copy);
1669*61046927SAndroid Build Coastguard Worker     }
1670*61046927SAndroid Build Coastguard Worker     return value;
1671*61046927SAndroid Build Coastguard Worker }
1672*61046927SAndroid Build Coastguard Worker 
json_value_init_number(double number)1673*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_number(double number) {
1674*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = NULL;
1675*61046927SAndroid Build Coastguard Worker     if (IS_NUMBER_INVALID(number)) {
1676*61046927SAndroid Build Coastguard Worker         return NULL;
1677*61046927SAndroid Build Coastguard Worker     }
1678*61046927SAndroid Build Coastguard Worker     new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
1679*61046927SAndroid Build Coastguard Worker     if (new_value == NULL) {
1680*61046927SAndroid Build Coastguard Worker         return NULL;
1681*61046927SAndroid Build Coastguard Worker     }
1682*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
1683*61046927SAndroid Build Coastguard Worker     new_value->type = JSONNumber;
1684*61046927SAndroid Build Coastguard Worker     new_value->value.number = number;
1685*61046927SAndroid Build Coastguard Worker     return new_value;
1686*61046927SAndroid Build Coastguard Worker }
1687*61046927SAndroid Build Coastguard Worker 
json_value_init_boolean(int boolean)1688*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_boolean(int boolean) {
1689*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
1690*61046927SAndroid Build Coastguard Worker     if (!new_value) {
1691*61046927SAndroid Build Coastguard Worker         return NULL;
1692*61046927SAndroid Build Coastguard Worker     }
1693*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
1694*61046927SAndroid Build Coastguard Worker     new_value->type = JSONBoolean;
1695*61046927SAndroid Build Coastguard Worker     new_value->value.boolean = boolean ? 1 : 0;
1696*61046927SAndroid Build Coastguard Worker     return new_value;
1697*61046927SAndroid Build Coastguard Worker }
1698*61046927SAndroid Build Coastguard Worker 
json_value_init_null(void)1699*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_init_null(void) {
1700*61046927SAndroid Build Coastguard Worker     JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
1701*61046927SAndroid Build Coastguard Worker     if (!new_value) {
1702*61046927SAndroid Build Coastguard Worker         return NULL;
1703*61046927SAndroid Build Coastguard Worker     }
1704*61046927SAndroid Build Coastguard Worker     new_value->parent = NULL;
1705*61046927SAndroid Build Coastguard Worker     new_value->type = JSONNull;
1706*61046927SAndroid Build Coastguard Worker     return new_value;
1707*61046927SAndroid Build Coastguard Worker }
1708*61046927SAndroid Build Coastguard Worker 
json_value_deep_copy(const JSON_Value * value)1709*61046927SAndroid Build Coastguard Worker JSON_Value * json_value_deep_copy(const JSON_Value *value) {
1710*61046927SAndroid Build Coastguard Worker     size_t i = 0;
1711*61046927SAndroid Build Coastguard Worker     JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
1712*61046927SAndroid Build Coastguard Worker     const JSON_String *temp_string = NULL;
1713*61046927SAndroid Build Coastguard Worker     const char *temp_key = NULL;
1714*61046927SAndroid Build Coastguard Worker     char *temp_string_copy = NULL;
1715*61046927SAndroid Build Coastguard Worker     JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
1716*61046927SAndroid Build Coastguard Worker     JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
1717*61046927SAndroid Build Coastguard Worker     JSON_Status res = JSONFailure;
1718*61046927SAndroid Build Coastguard Worker     char *key_copy = NULL;
1719*61046927SAndroid Build Coastguard Worker 
1720*61046927SAndroid Build Coastguard Worker     switch (json_value_get_type(value)) {
1721*61046927SAndroid Build Coastguard Worker         case JSONArray:
1722*61046927SAndroid Build Coastguard Worker             temp_array = json_value_get_array(value);
1723*61046927SAndroid Build Coastguard Worker             return_value = json_value_init_array();
1724*61046927SAndroid Build Coastguard Worker             if (return_value == NULL) {
1725*61046927SAndroid Build Coastguard Worker                 return NULL;
1726*61046927SAndroid Build Coastguard Worker             }
1727*61046927SAndroid Build Coastguard Worker             temp_array_copy = json_value_get_array(return_value);
1728*61046927SAndroid Build Coastguard Worker             for (i = 0; i < json_array_get_count(temp_array); i++) {
1729*61046927SAndroid Build Coastguard Worker                 temp_value = json_array_get_value(temp_array, i);
1730*61046927SAndroid Build Coastguard Worker                 temp_value_copy = json_value_deep_copy(temp_value);
1731*61046927SAndroid Build Coastguard Worker                 if (temp_value_copy == NULL) {
1732*61046927SAndroid Build Coastguard Worker                     json_value_free(return_value);
1733*61046927SAndroid Build Coastguard Worker                     return NULL;
1734*61046927SAndroid Build Coastguard Worker                 }
1735*61046927SAndroid Build Coastguard Worker                 if (json_array_add(temp_array_copy, temp_value_copy) != JSONSuccess) {
1736*61046927SAndroid Build Coastguard Worker                     json_value_free(return_value);
1737*61046927SAndroid Build Coastguard Worker                     json_value_free(temp_value_copy);
1738*61046927SAndroid Build Coastguard Worker                     return NULL;
1739*61046927SAndroid Build Coastguard Worker                 }
1740*61046927SAndroid Build Coastguard Worker             }
1741*61046927SAndroid Build Coastguard Worker             return return_value;
1742*61046927SAndroid Build Coastguard Worker         case JSONObject:
1743*61046927SAndroid Build Coastguard Worker             temp_object = json_value_get_object(value);
1744*61046927SAndroid Build Coastguard Worker             return_value = json_value_init_object();
1745*61046927SAndroid Build Coastguard Worker             if (!return_value) {
1746*61046927SAndroid Build Coastguard Worker                 return NULL;
1747*61046927SAndroid Build Coastguard Worker             }
1748*61046927SAndroid Build Coastguard Worker             temp_object_copy = json_value_get_object(return_value);
1749*61046927SAndroid Build Coastguard Worker             for (i = 0; i < json_object_get_count(temp_object); i++) {
1750*61046927SAndroid Build Coastguard Worker                 temp_key = json_object_get_name(temp_object, i);
1751*61046927SAndroid Build Coastguard Worker                 temp_value = json_object_get_value(temp_object, temp_key);
1752*61046927SAndroid Build Coastguard Worker                 temp_value_copy = json_value_deep_copy(temp_value);
1753*61046927SAndroid Build Coastguard Worker                 if (!temp_value_copy) {
1754*61046927SAndroid Build Coastguard Worker                     json_value_free(return_value);
1755*61046927SAndroid Build Coastguard Worker                     return NULL;
1756*61046927SAndroid Build Coastguard Worker                 }
1757*61046927SAndroid Build Coastguard Worker                 key_copy = parson_strdup(temp_key);
1758*61046927SAndroid Build Coastguard Worker                 if (!key_copy) {
1759*61046927SAndroid Build Coastguard Worker                     json_value_free(temp_value_copy);
1760*61046927SAndroid Build Coastguard Worker                     json_value_free(return_value);
1761*61046927SAndroid Build Coastguard Worker                     return NULL;
1762*61046927SAndroid Build Coastguard Worker                 }
1763*61046927SAndroid Build Coastguard Worker                 res = json_object_add(temp_object_copy, key_copy, temp_value_copy);
1764*61046927SAndroid Build Coastguard Worker                 if (res != JSONSuccess) {
1765*61046927SAndroid Build Coastguard Worker                     parson_free(key_copy);
1766*61046927SAndroid Build Coastguard Worker                     json_value_free(temp_value_copy);
1767*61046927SAndroid Build Coastguard Worker                     json_value_free(return_value);
1768*61046927SAndroid Build Coastguard Worker                     return NULL;
1769*61046927SAndroid Build Coastguard Worker                 }
1770*61046927SAndroid Build Coastguard Worker             }
1771*61046927SAndroid Build Coastguard Worker             return return_value;
1772*61046927SAndroid Build Coastguard Worker         case JSONBoolean:
1773*61046927SAndroid Build Coastguard Worker             return json_value_init_boolean(json_value_get_boolean(value));
1774*61046927SAndroid Build Coastguard Worker         case JSONNumber:
1775*61046927SAndroid Build Coastguard Worker             return json_value_init_number(json_value_get_number(value));
1776*61046927SAndroid Build Coastguard Worker         case JSONString:
1777*61046927SAndroid Build Coastguard Worker             temp_string = json_value_get_string_desc(value);
1778*61046927SAndroid Build Coastguard Worker             if (temp_string == NULL) {
1779*61046927SAndroid Build Coastguard Worker                 return NULL;
1780*61046927SAndroid Build Coastguard Worker             }
1781*61046927SAndroid Build Coastguard Worker             temp_string_copy = parson_strndup(temp_string->chars, temp_string->length);
1782*61046927SAndroid Build Coastguard Worker             if (temp_string_copy == NULL) {
1783*61046927SAndroid Build Coastguard Worker                 return NULL;
1784*61046927SAndroid Build Coastguard Worker             }
1785*61046927SAndroid Build Coastguard Worker             return_value = json_value_init_string_no_copy(temp_string_copy, temp_string->length);
1786*61046927SAndroid Build Coastguard Worker             if (return_value == NULL) {
1787*61046927SAndroid Build Coastguard Worker                 parson_free(temp_string_copy);
1788*61046927SAndroid Build Coastguard Worker             }
1789*61046927SAndroid Build Coastguard Worker             return return_value;
1790*61046927SAndroid Build Coastguard Worker         case JSONNull:
1791*61046927SAndroid Build Coastguard Worker             return json_value_init_null();
1792*61046927SAndroid Build Coastguard Worker         case JSONError:
1793*61046927SAndroid Build Coastguard Worker             return NULL;
1794*61046927SAndroid Build Coastguard Worker         default:
1795*61046927SAndroid Build Coastguard Worker             return NULL;
1796*61046927SAndroid Build Coastguard Worker     }
1797*61046927SAndroid Build Coastguard Worker }
1798*61046927SAndroid Build Coastguard Worker 
json_serialization_size(const JSON_Value * value)1799*61046927SAndroid Build Coastguard Worker size_t json_serialization_size(const JSON_Value *value) {
1800*61046927SAndroid Build Coastguard Worker     char num_buf[PARSON_NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
1801*61046927SAndroid Build Coastguard Worker     int res = json_serialize_to_buffer_r(value, NULL, 0, PARSON_FALSE, num_buf);
1802*61046927SAndroid Build Coastguard Worker     return res < 0 ? 0 : (size_t)(res) + 1;
1803*61046927SAndroid Build Coastguard Worker }
1804*61046927SAndroid Build Coastguard Worker 
json_serialize_to_buffer(const JSON_Value * value,char * buf,size_t buf_size_in_bytes)1805*61046927SAndroid Build Coastguard Worker JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
1806*61046927SAndroid Build Coastguard Worker     int written = -1;
1807*61046927SAndroid Build Coastguard Worker     size_t needed_size_in_bytes = json_serialization_size(value);
1808*61046927SAndroid Build Coastguard Worker     if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
1809*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1810*61046927SAndroid Build Coastguard Worker     }
1811*61046927SAndroid Build Coastguard Worker     written = json_serialize_to_buffer_r(value, buf, 0, PARSON_FALSE, NULL);
1812*61046927SAndroid Build Coastguard Worker     if (written < 0) {
1813*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1814*61046927SAndroid Build Coastguard Worker     }
1815*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1816*61046927SAndroid Build Coastguard Worker }
1817*61046927SAndroid Build Coastguard Worker 
json_serialize_to_file(const JSON_Value * value,const char * filename)1818*61046927SAndroid Build Coastguard Worker JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) {
1819*61046927SAndroid Build Coastguard Worker     JSON_Status return_code = JSONSuccess;
1820*61046927SAndroid Build Coastguard Worker     FILE *fp = NULL;
1821*61046927SAndroid Build Coastguard Worker     char *serialized_string = json_serialize_to_string(value);
1822*61046927SAndroid Build Coastguard Worker     if (serialized_string == NULL) {
1823*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1824*61046927SAndroid Build Coastguard Worker     }
1825*61046927SAndroid Build Coastguard Worker     fp = fopen(filename, "w");
1826*61046927SAndroid Build Coastguard Worker     if (fp == NULL) {
1827*61046927SAndroid Build Coastguard Worker         json_free_serialized_string(serialized_string);
1828*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1829*61046927SAndroid Build Coastguard Worker     }
1830*61046927SAndroid Build Coastguard Worker     if (fputs(serialized_string, fp) == EOF) {
1831*61046927SAndroid Build Coastguard Worker         return_code = JSONFailure;
1832*61046927SAndroid Build Coastguard Worker     }
1833*61046927SAndroid Build Coastguard Worker     if (fclose(fp) == EOF) {
1834*61046927SAndroid Build Coastguard Worker         return_code = JSONFailure;
1835*61046927SAndroid Build Coastguard Worker     }
1836*61046927SAndroid Build Coastguard Worker     json_free_serialized_string(serialized_string);
1837*61046927SAndroid Build Coastguard Worker     return return_code;
1838*61046927SAndroid Build Coastguard Worker }
1839*61046927SAndroid Build Coastguard Worker 
json_serialize_to_string(const JSON_Value * value)1840*61046927SAndroid Build Coastguard Worker char * json_serialize_to_string(const JSON_Value *value) {
1841*61046927SAndroid Build Coastguard Worker     JSON_Status serialization_result = JSONFailure;
1842*61046927SAndroid Build Coastguard Worker     size_t buf_size_bytes = json_serialization_size(value);
1843*61046927SAndroid Build Coastguard Worker     char *buf = NULL;
1844*61046927SAndroid Build Coastguard Worker     if (buf_size_bytes == 0) {
1845*61046927SAndroid Build Coastguard Worker         return NULL;
1846*61046927SAndroid Build Coastguard Worker     }
1847*61046927SAndroid Build Coastguard Worker     buf = (char*)parson_malloc(buf_size_bytes);
1848*61046927SAndroid Build Coastguard Worker     if (buf == NULL) {
1849*61046927SAndroid Build Coastguard Worker         return NULL;
1850*61046927SAndroid Build Coastguard Worker     }
1851*61046927SAndroid Build Coastguard Worker     serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes);
1852*61046927SAndroid Build Coastguard Worker     if (serialization_result != JSONSuccess) {
1853*61046927SAndroid Build Coastguard Worker         json_free_serialized_string(buf);
1854*61046927SAndroid Build Coastguard Worker         return NULL;
1855*61046927SAndroid Build Coastguard Worker     }
1856*61046927SAndroid Build Coastguard Worker     return buf;
1857*61046927SAndroid Build Coastguard Worker }
1858*61046927SAndroid Build Coastguard Worker 
json_serialization_size_pretty(const JSON_Value * value)1859*61046927SAndroid Build Coastguard Worker size_t json_serialization_size_pretty(const JSON_Value *value) {
1860*61046927SAndroid Build Coastguard Worker     char num_buf[PARSON_NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
1861*61046927SAndroid Build Coastguard Worker     int res = json_serialize_to_buffer_r(value, NULL, 0, PARSON_TRUE, num_buf);
1862*61046927SAndroid Build Coastguard Worker     return res < 0 ? 0 : (size_t)(res) + 1;
1863*61046927SAndroid Build Coastguard Worker }
1864*61046927SAndroid Build Coastguard Worker 
json_serialize_to_buffer_pretty(const JSON_Value * value,char * buf,size_t buf_size_in_bytes)1865*61046927SAndroid Build Coastguard Worker JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
1866*61046927SAndroid Build Coastguard Worker     int written = -1;
1867*61046927SAndroid Build Coastguard Worker     size_t needed_size_in_bytes = json_serialization_size_pretty(value);
1868*61046927SAndroid Build Coastguard Worker     if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
1869*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1870*61046927SAndroid Build Coastguard Worker     }
1871*61046927SAndroid Build Coastguard Worker     written = json_serialize_to_buffer_r(value, buf, 0, PARSON_TRUE, NULL);
1872*61046927SAndroid Build Coastguard Worker     if (written < 0) {
1873*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1874*61046927SAndroid Build Coastguard Worker     }
1875*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1876*61046927SAndroid Build Coastguard Worker }
1877*61046927SAndroid Build Coastguard Worker 
json_serialize_to_file_pretty(const JSON_Value * value,const char * filename)1878*61046927SAndroid Build Coastguard Worker JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) {
1879*61046927SAndroid Build Coastguard Worker     JSON_Status return_code = JSONSuccess;
1880*61046927SAndroid Build Coastguard Worker     FILE *fp = NULL;
1881*61046927SAndroid Build Coastguard Worker     char *serialized_string = json_serialize_to_string_pretty(value);
1882*61046927SAndroid Build Coastguard Worker     if (serialized_string == NULL) {
1883*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1884*61046927SAndroid Build Coastguard Worker     }
1885*61046927SAndroid Build Coastguard Worker     fp = fopen(filename, "w");
1886*61046927SAndroid Build Coastguard Worker     if (fp == NULL) {
1887*61046927SAndroid Build Coastguard Worker         json_free_serialized_string(serialized_string);
1888*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1889*61046927SAndroid Build Coastguard Worker     }
1890*61046927SAndroid Build Coastguard Worker     if (fputs(serialized_string, fp) == EOF) {
1891*61046927SAndroid Build Coastguard Worker         return_code = JSONFailure;
1892*61046927SAndroid Build Coastguard Worker     }
1893*61046927SAndroid Build Coastguard Worker     if (fclose(fp) == EOF) {
1894*61046927SAndroid Build Coastguard Worker         return_code = JSONFailure;
1895*61046927SAndroid Build Coastguard Worker     }
1896*61046927SAndroid Build Coastguard Worker     json_free_serialized_string(serialized_string);
1897*61046927SAndroid Build Coastguard Worker     return return_code;
1898*61046927SAndroid Build Coastguard Worker }
1899*61046927SAndroid Build Coastguard Worker 
json_serialize_to_string_pretty(const JSON_Value * value)1900*61046927SAndroid Build Coastguard Worker char * json_serialize_to_string_pretty(const JSON_Value *value) {
1901*61046927SAndroid Build Coastguard Worker     JSON_Status serialization_result = JSONFailure;
1902*61046927SAndroid Build Coastguard Worker     size_t buf_size_bytes = json_serialization_size_pretty(value);
1903*61046927SAndroid Build Coastguard Worker     char *buf = NULL;
1904*61046927SAndroid Build Coastguard Worker     if (buf_size_bytes == 0) {
1905*61046927SAndroid Build Coastguard Worker         return NULL;
1906*61046927SAndroid Build Coastguard Worker     }
1907*61046927SAndroid Build Coastguard Worker     buf = (char*)parson_malloc(buf_size_bytes);
1908*61046927SAndroid Build Coastguard Worker     if (buf == NULL) {
1909*61046927SAndroid Build Coastguard Worker         return NULL;
1910*61046927SAndroid Build Coastguard Worker     }
1911*61046927SAndroid Build Coastguard Worker     serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes);
1912*61046927SAndroid Build Coastguard Worker     if (serialization_result != JSONSuccess) {
1913*61046927SAndroid Build Coastguard Worker         json_free_serialized_string(buf);
1914*61046927SAndroid Build Coastguard Worker         return NULL;
1915*61046927SAndroid Build Coastguard Worker     }
1916*61046927SAndroid Build Coastguard Worker     return buf;
1917*61046927SAndroid Build Coastguard Worker }
1918*61046927SAndroid Build Coastguard Worker 
json_free_serialized_string(char * string)1919*61046927SAndroid Build Coastguard Worker void json_free_serialized_string(char *string) {
1920*61046927SAndroid Build Coastguard Worker     parson_free(string);
1921*61046927SAndroid Build Coastguard Worker }
1922*61046927SAndroid Build Coastguard Worker 
json_array_remove(JSON_Array * array,size_t ix)1923*61046927SAndroid Build Coastguard Worker JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
1924*61046927SAndroid Build Coastguard Worker     size_t to_move_bytes = 0;
1925*61046927SAndroid Build Coastguard Worker     if (array == NULL || ix >= json_array_get_count(array)) {
1926*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1927*61046927SAndroid Build Coastguard Worker     }
1928*61046927SAndroid Build Coastguard Worker     json_value_free(json_array_get_value(array, ix));
1929*61046927SAndroid Build Coastguard Worker     to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value*);
1930*61046927SAndroid Build Coastguard Worker     memmove(array->items + ix, array->items + ix + 1, to_move_bytes);
1931*61046927SAndroid Build Coastguard Worker     array->count -= 1;
1932*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1933*61046927SAndroid Build Coastguard Worker }
1934*61046927SAndroid Build Coastguard Worker 
json_array_replace_value(JSON_Array * array,size_t ix,JSON_Value * value)1935*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) {
1936*61046927SAndroid Build Coastguard Worker     if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) {
1937*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1938*61046927SAndroid Build Coastguard Worker     }
1939*61046927SAndroid Build Coastguard Worker     json_value_free(json_array_get_value(array, ix));
1940*61046927SAndroid Build Coastguard Worker     value->parent = json_array_get_wrapping_value(array);
1941*61046927SAndroid Build Coastguard Worker     array->items[ix] = value;
1942*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1943*61046927SAndroid Build Coastguard Worker }
1944*61046927SAndroid Build Coastguard Worker 
json_array_replace_string(JSON_Array * array,size_t i,const char * string)1945*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) {
1946*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string(string);
1947*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1948*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1949*61046927SAndroid Build Coastguard Worker     }
1950*61046927SAndroid Build Coastguard Worker     if (json_array_replace_value(array, i, value) != JSONSuccess) {
1951*61046927SAndroid Build Coastguard Worker         json_value_free(value);
1952*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1953*61046927SAndroid Build Coastguard Worker     }
1954*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1955*61046927SAndroid Build Coastguard Worker }
1956*61046927SAndroid Build Coastguard Worker 
json_array_replace_string_with_len(JSON_Array * array,size_t i,const char * string,size_t len)1957*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len) {
1958*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string_with_len(string, len);
1959*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1960*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1961*61046927SAndroid Build Coastguard Worker     }
1962*61046927SAndroid Build Coastguard Worker     if (json_array_replace_value(array, i, value) != JSONSuccess) {
1963*61046927SAndroid Build Coastguard Worker         json_value_free(value);
1964*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1965*61046927SAndroid Build Coastguard Worker     }
1966*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1967*61046927SAndroid Build Coastguard Worker }
1968*61046927SAndroid Build Coastguard Worker 
json_array_replace_number(JSON_Array * array,size_t i,double number)1969*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
1970*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_number(number);
1971*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1972*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1973*61046927SAndroid Build Coastguard Worker     }
1974*61046927SAndroid Build Coastguard Worker     if (json_array_replace_value(array, i, value) != JSONSuccess) {
1975*61046927SAndroid Build Coastguard Worker         json_value_free(value);
1976*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1977*61046927SAndroid Build Coastguard Worker     }
1978*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1979*61046927SAndroid Build Coastguard Worker }
1980*61046927SAndroid Build Coastguard Worker 
json_array_replace_boolean(JSON_Array * array,size_t i,int boolean)1981*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) {
1982*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_boolean(boolean);
1983*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1984*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1985*61046927SAndroid Build Coastguard Worker     }
1986*61046927SAndroid Build Coastguard Worker     if (json_array_replace_value(array, i, value) != JSONSuccess) {
1987*61046927SAndroid Build Coastguard Worker         json_value_free(value);
1988*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1989*61046927SAndroid Build Coastguard Worker     }
1990*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
1991*61046927SAndroid Build Coastguard Worker }
1992*61046927SAndroid Build Coastguard Worker 
json_array_replace_null(JSON_Array * array,size_t i)1993*61046927SAndroid Build Coastguard Worker JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
1994*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_null();
1995*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
1996*61046927SAndroid Build Coastguard Worker         return JSONFailure;
1997*61046927SAndroid Build Coastguard Worker     }
1998*61046927SAndroid Build Coastguard Worker     if (json_array_replace_value(array, i, value) != JSONSuccess) {
1999*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2000*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2001*61046927SAndroid Build Coastguard Worker     }
2002*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2003*61046927SAndroid Build Coastguard Worker }
2004*61046927SAndroid Build Coastguard Worker 
json_array_clear(JSON_Array * array)2005*61046927SAndroid Build Coastguard Worker JSON_Status json_array_clear(JSON_Array *array) {
2006*61046927SAndroid Build Coastguard Worker     size_t i = 0;
2007*61046927SAndroid Build Coastguard Worker     if (array == NULL) {
2008*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2009*61046927SAndroid Build Coastguard Worker     }
2010*61046927SAndroid Build Coastguard Worker     for (i = 0; i < json_array_get_count(array); i++) {
2011*61046927SAndroid Build Coastguard Worker         json_value_free(json_array_get_value(array, i));
2012*61046927SAndroid Build Coastguard Worker     }
2013*61046927SAndroid Build Coastguard Worker     array->count = 0;
2014*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2015*61046927SAndroid Build Coastguard Worker }
2016*61046927SAndroid Build Coastguard Worker 
json_array_append_value(JSON_Array * array,JSON_Value * value)2017*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
2018*61046927SAndroid Build Coastguard Worker     if (array == NULL || value == NULL || value->parent != NULL) {
2019*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2020*61046927SAndroid Build Coastguard Worker     }
2021*61046927SAndroid Build Coastguard Worker     return json_array_add(array, value);
2022*61046927SAndroid Build Coastguard Worker }
2023*61046927SAndroid Build Coastguard Worker 
json_array_append_string(JSON_Array * array,const char * string)2024*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
2025*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string(string);
2026*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2027*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2028*61046927SAndroid Build Coastguard Worker     }
2029*61046927SAndroid Build Coastguard Worker     if (json_array_append_value(array, value) != JSONSuccess) {
2030*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2031*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2032*61046927SAndroid Build Coastguard Worker     }
2033*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2034*61046927SAndroid Build Coastguard Worker }
2035*61046927SAndroid Build Coastguard Worker 
json_array_append_string_with_len(JSON_Array * array,const char * string,size_t len)2036*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len) {
2037*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string_with_len(string, len);
2038*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2039*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2040*61046927SAndroid Build Coastguard Worker     }
2041*61046927SAndroid Build Coastguard Worker     if (json_array_append_value(array, value) != JSONSuccess) {
2042*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2043*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2044*61046927SAndroid Build Coastguard Worker     }
2045*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2046*61046927SAndroid Build Coastguard Worker }
2047*61046927SAndroid Build Coastguard Worker 
json_array_append_number(JSON_Array * array,double number)2048*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_number(JSON_Array *array, double number) {
2049*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_number(number);
2050*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2051*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2052*61046927SAndroid Build Coastguard Worker     }
2053*61046927SAndroid Build Coastguard Worker     if (json_array_append_value(array, value) != JSONSuccess) {
2054*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2055*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2056*61046927SAndroid Build Coastguard Worker     }
2057*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2058*61046927SAndroid Build Coastguard Worker }
2059*61046927SAndroid Build Coastguard Worker 
json_array_append_boolean(JSON_Array * array,int boolean)2060*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
2061*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_boolean(boolean);
2062*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2063*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2064*61046927SAndroid Build Coastguard Worker     }
2065*61046927SAndroid Build Coastguard Worker     if (json_array_append_value(array, value) != JSONSuccess) {
2066*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2067*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2068*61046927SAndroid Build Coastguard Worker     }
2069*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2070*61046927SAndroid Build Coastguard Worker }
2071*61046927SAndroid Build Coastguard Worker 
json_array_append_null(JSON_Array * array)2072*61046927SAndroid Build Coastguard Worker JSON_Status json_array_append_null(JSON_Array *array) {
2073*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_null();
2074*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2075*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2076*61046927SAndroid Build Coastguard Worker     }
2077*61046927SAndroid Build Coastguard Worker     if (json_array_append_value(array, value) != JSONSuccess) {
2078*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2079*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2080*61046927SAndroid Build Coastguard Worker     }
2081*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2082*61046927SAndroid Build Coastguard Worker }
2083*61046927SAndroid Build Coastguard Worker 
json_object_set_value(JSON_Object * object,const char * name,JSON_Value * value)2084*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) {
2085*61046927SAndroid Build Coastguard Worker     unsigned long hash = 0;
2086*61046927SAndroid Build Coastguard Worker     parson_bool_t found = PARSON_FALSE;
2087*61046927SAndroid Build Coastguard Worker     size_t cell_ix = 0;
2088*61046927SAndroid Build Coastguard Worker     size_t item_ix = 0;
2089*61046927SAndroid Build Coastguard Worker     JSON_Value *old_value = NULL;
2090*61046927SAndroid Build Coastguard Worker     char *key_copy = NULL;
2091*61046927SAndroid Build Coastguard Worker 
2092*61046927SAndroid Build Coastguard Worker     if (!object || !name || !value || value->parent) {
2093*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2094*61046927SAndroid Build Coastguard Worker     }
2095*61046927SAndroid Build Coastguard Worker     hash = hash_string(name, strlen(name));
2096*61046927SAndroid Build Coastguard Worker     found = PARSON_FALSE;
2097*61046927SAndroid Build Coastguard Worker     cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
2098*61046927SAndroid Build Coastguard Worker     if (found) {
2099*61046927SAndroid Build Coastguard Worker         item_ix = object->cells[cell_ix];
2100*61046927SAndroid Build Coastguard Worker         old_value = object->values[item_ix];
2101*61046927SAndroid Build Coastguard Worker         json_value_free(old_value);
2102*61046927SAndroid Build Coastguard Worker         object->values[item_ix] = value;
2103*61046927SAndroid Build Coastguard Worker         value->parent = json_object_get_wrapping_value(object);
2104*61046927SAndroid Build Coastguard Worker         return JSONSuccess;
2105*61046927SAndroid Build Coastguard Worker     }
2106*61046927SAndroid Build Coastguard Worker     if (object->count >= object->item_capacity) {
2107*61046927SAndroid Build Coastguard Worker         JSON_Status res = json_object_grow_and_rehash(object);
2108*61046927SAndroid Build Coastguard Worker         if (res != JSONSuccess) {
2109*61046927SAndroid Build Coastguard Worker             return JSONFailure;
2110*61046927SAndroid Build Coastguard Worker         }
2111*61046927SAndroid Build Coastguard Worker         cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
2112*61046927SAndroid Build Coastguard Worker     }
2113*61046927SAndroid Build Coastguard Worker     key_copy = parson_strdup(name);
2114*61046927SAndroid Build Coastguard Worker     if (!key_copy) {
2115*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2116*61046927SAndroid Build Coastguard Worker     }
2117*61046927SAndroid Build Coastguard Worker     object->names[object->count] = key_copy;
2118*61046927SAndroid Build Coastguard Worker     object->cells[cell_ix] = object->count;
2119*61046927SAndroid Build Coastguard Worker     object->values[object->count] = value;
2120*61046927SAndroid Build Coastguard Worker     object->cell_ixs[object->count] = cell_ix;
2121*61046927SAndroid Build Coastguard Worker     object->hashes[object->count] = hash;
2122*61046927SAndroid Build Coastguard Worker     object->count++;
2123*61046927SAndroid Build Coastguard Worker     value->parent = json_object_get_wrapping_value(object);
2124*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2125*61046927SAndroid Build Coastguard Worker }
2126*61046927SAndroid Build Coastguard Worker 
json_object_set_string(JSON_Object * object,const char * name,const char * string)2127*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) {
2128*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string(string);
2129*61046927SAndroid Build Coastguard Worker     JSON_Status status = json_object_set_value(object, name, value);
2130*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2131*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2132*61046927SAndroid Build Coastguard Worker     }
2133*61046927SAndroid Build Coastguard Worker     return status;
2134*61046927SAndroid Build Coastguard Worker }
2135*61046927SAndroid Build Coastguard Worker 
json_object_set_string_with_len(JSON_Object * object,const char * name,const char * string,size_t len)2136*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) {
2137*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string_with_len(string, len);
2138*61046927SAndroid Build Coastguard Worker     JSON_Status status = json_object_set_value(object, name, value);
2139*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2140*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2141*61046927SAndroid Build Coastguard Worker     }
2142*61046927SAndroid Build Coastguard Worker     return status;
2143*61046927SAndroid Build Coastguard Worker }
2144*61046927SAndroid Build Coastguard Worker 
json_object_set_number(JSON_Object * object,const char * name,double number)2145*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
2146*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_number(number);
2147*61046927SAndroid Build Coastguard Worker     JSON_Status status = json_object_set_value(object, name, value);
2148*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2149*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2150*61046927SAndroid Build Coastguard Worker     }
2151*61046927SAndroid Build Coastguard Worker     return status;
2152*61046927SAndroid Build Coastguard Worker }
2153*61046927SAndroid Build Coastguard Worker 
json_object_set_boolean(JSON_Object * object,const char * name,int boolean)2154*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) {
2155*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_boolean(boolean);
2156*61046927SAndroid Build Coastguard Worker     JSON_Status status = json_object_set_value(object, name, value);
2157*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2158*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2159*61046927SAndroid Build Coastguard Worker     }
2160*61046927SAndroid Build Coastguard Worker     return status;
2161*61046927SAndroid Build Coastguard Worker }
2162*61046927SAndroid Build Coastguard Worker 
json_object_set_null(JSON_Object * object,const char * name)2163*61046927SAndroid Build Coastguard Worker JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
2164*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_null();
2165*61046927SAndroid Build Coastguard Worker     JSON_Status status = json_object_set_value(object, name, value);
2166*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2167*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2168*61046927SAndroid Build Coastguard Worker     }
2169*61046927SAndroid Build Coastguard Worker     return status;
2170*61046927SAndroid Build Coastguard Worker }
2171*61046927SAndroid Build Coastguard Worker 
json_object_dotset_value(JSON_Object * object,const char * name,JSON_Value * value)2172*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) {
2173*61046927SAndroid Build Coastguard Worker     const char *dot_pos = NULL;
2174*61046927SAndroid Build Coastguard Worker     JSON_Value *temp_value = NULL, *new_value = NULL;
2175*61046927SAndroid Build Coastguard Worker     JSON_Object *temp_object = NULL, *new_object = NULL;
2176*61046927SAndroid Build Coastguard Worker     JSON_Status status = JSONFailure;
2177*61046927SAndroid Build Coastguard Worker     size_t name_len = 0;
2178*61046927SAndroid Build Coastguard Worker     char *name_copy = NULL;
2179*61046927SAndroid Build Coastguard Worker 
2180*61046927SAndroid Build Coastguard Worker     if (object == NULL || name == NULL || value == NULL) {
2181*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2182*61046927SAndroid Build Coastguard Worker     }
2183*61046927SAndroid Build Coastguard Worker     dot_pos = strchr(name, '.');
2184*61046927SAndroid Build Coastguard Worker     if (dot_pos == NULL) {
2185*61046927SAndroid Build Coastguard Worker         return json_object_set_value(object, name, value);
2186*61046927SAndroid Build Coastguard Worker     }
2187*61046927SAndroid Build Coastguard Worker     name_len = dot_pos - name;
2188*61046927SAndroid Build Coastguard Worker     temp_value = json_object_getn_value(object, name, name_len);
2189*61046927SAndroid Build Coastguard Worker     if (temp_value) {
2190*61046927SAndroid Build Coastguard Worker         /* Don't overwrite existing non-object (unlike json_object_set_value, but it shouldn't be changed at this point) */
2191*61046927SAndroid Build Coastguard Worker         if (json_value_get_type(temp_value) != JSONObject) {
2192*61046927SAndroid Build Coastguard Worker             return JSONFailure;
2193*61046927SAndroid Build Coastguard Worker         }
2194*61046927SAndroid Build Coastguard Worker         temp_object = json_value_get_object(temp_value);
2195*61046927SAndroid Build Coastguard Worker         return json_object_dotset_value(temp_object, dot_pos + 1, value);
2196*61046927SAndroid Build Coastguard Worker     }
2197*61046927SAndroid Build Coastguard Worker     new_value = json_value_init_object();
2198*61046927SAndroid Build Coastguard Worker     if (new_value == NULL) {
2199*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2200*61046927SAndroid Build Coastguard Worker     }
2201*61046927SAndroid Build Coastguard Worker     new_object = json_value_get_object(new_value);
2202*61046927SAndroid Build Coastguard Worker     status = json_object_dotset_value(new_object, dot_pos + 1, value);
2203*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2204*61046927SAndroid Build Coastguard Worker         json_value_free(new_value);
2205*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2206*61046927SAndroid Build Coastguard Worker     }
2207*61046927SAndroid Build Coastguard Worker     name_copy = parson_strndup(name, name_len);
2208*61046927SAndroid Build Coastguard Worker     if (!name_copy) {
2209*61046927SAndroid Build Coastguard Worker         json_object_dotremove_internal(new_object, dot_pos + 1, 0);
2210*61046927SAndroid Build Coastguard Worker         json_value_free(new_value);
2211*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2212*61046927SAndroid Build Coastguard Worker     }
2213*61046927SAndroid Build Coastguard Worker     status = json_object_add(object, name_copy, new_value);
2214*61046927SAndroid Build Coastguard Worker     if (status != JSONSuccess) {
2215*61046927SAndroid Build Coastguard Worker         parson_free(name_copy);
2216*61046927SAndroid Build Coastguard Worker         json_object_dotremove_internal(new_object, dot_pos + 1, 0);
2217*61046927SAndroid Build Coastguard Worker         json_value_free(new_value);
2218*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2219*61046927SAndroid Build Coastguard Worker     }
2220*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2221*61046927SAndroid Build Coastguard Worker }
2222*61046927SAndroid Build Coastguard Worker 
json_object_dotset_string(JSON_Object * object,const char * name,const char * string)2223*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) {
2224*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string(string);
2225*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2226*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2227*61046927SAndroid Build Coastguard Worker     }
2228*61046927SAndroid Build Coastguard Worker     if (json_object_dotset_value(object, name, value) != JSONSuccess) {
2229*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2230*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2231*61046927SAndroid Build Coastguard Worker     }
2232*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2233*61046927SAndroid Build Coastguard Worker }
2234*61046927SAndroid Build Coastguard Worker 
json_object_dotset_string_with_len(JSON_Object * object,const char * name,const char * string,size_t len)2235*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) {
2236*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_string_with_len(string, len);
2237*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2238*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2239*61046927SAndroid Build Coastguard Worker     }
2240*61046927SAndroid Build Coastguard Worker     if (json_object_dotset_value(object, name, value) != JSONSuccess) {
2241*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2242*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2243*61046927SAndroid Build Coastguard Worker     }
2244*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2245*61046927SAndroid Build Coastguard Worker }
2246*61046927SAndroid Build Coastguard Worker 
json_object_dotset_number(JSON_Object * object,const char * name,double number)2247*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
2248*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_number(number);
2249*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2250*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2251*61046927SAndroid Build Coastguard Worker     }
2252*61046927SAndroid Build Coastguard Worker     if (json_object_dotset_value(object, name, value) != JSONSuccess) {
2253*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2254*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2255*61046927SAndroid Build Coastguard Worker     }
2256*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2257*61046927SAndroid Build Coastguard Worker }
2258*61046927SAndroid Build Coastguard Worker 
json_object_dotset_boolean(JSON_Object * object,const char * name,int boolean)2259*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) {
2260*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_boolean(boolean);
2261*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2262*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2263*61046927SAndroid Build Coastguard Worker     }
2264*61046927SAndroid Build Coastguard Worker     if (json_object_dotset_value(object, name, value) != JSONSuccess) {
2265*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2266*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2267*61046927SAndroid Build Coastguard Worker     }
2268*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2269*61046927SAndroid Build Coastguard Worker }
2270*61046927SAndroid Build Coastguard Worker 
json_object_dotset_null(JSON_Object * object,const char * name)2271*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) {
2272*61046927SAndroid Build Coastguard Worker     JSON_Value *value = json_value_init_null();
2273*61046927SAndroid Build Coastguard Worker     if (value == NULL) {
2274*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2275*61046927SAndroid Build Coastguard Worker     }
2276*61046927SAndroid Build Coastguard Worker     if (json_object_dotset_value(object, name, value) != JSONSuccess) {
2277*61046927SAndroid Build Coastguard Worker         json_value_free(value);
2278*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2279*61046927SAndroid Build Coastguard Worker     }
2280*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2281*61046927SAndroid Build Coastguard Worker }
2282*61046927SAndroid Build Coastguard Worker 
json_object_remove(JSON_Object * object,const char * name)2283*61046927SAndroid Build Coastguard Worker JSON_Status json_object_remove(JSON_Object *object, const char *name) {
2284*61046927SAndroid Build Coastguard Worker     return json_object_remove_internal(object, name, PARSON_TRUE);
2285*61046927SAndroid Build Coastguard Worker }
2286*61046927SAndroid Build Coastguard Worker 
json_object_dotremove(JSON_Object * object,const char * name)2287*61046927SAndroid Build Coastguard Worker JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
2288*61046927SAndroid Build Coastguard Worker     return json_object_dotremove_internal(object, name, PARSON_TRUE);
2289*61046927SAndroid Build Coastguard Worker }
2290*61046927SAndroid Build Coastguard Worker 
json_object_clear(JSON_Object * object)2291*61046927SAndroid Build Coastguard Worker JSON_Status json_object_clear(JSON_Object *object) {
2292*61046927SAndroid Build Coastguard Worker     size_t i = 0;
2293*61046927SAndroid Build Coastguard Worker     if (object == NULL) {
2294*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2295*61046927SAndroid Build Coastguard Worker     }
2296*61046927SAndroid Build Coastguard Worker     for (i = 0; i < json_object_get_count(object); i++) {
2297*61046927SAndroid Build Coastguard Worker         parson_free(object->names[i]);
2298*61046927SAndroid Build Coastguard Worker         object->names[i] = NULL;
2299*61046927SAndroid Build Coastguard Worker 
2300*61046927SAndroid Build Coastguard Worker         json_value_free(object->values[i]);
2301*61046927SAndroid Build Coastguard Worker         object->values[i] = NULL;
2302*61046927SAndroid Build Coastguard Worker     }
2303*61046927SAndroid Build Coastguard Worker     object->count = 0;
2304*61046927SAndroid Build Coastguard Worker     for (i = 0; i < object->cell_capacity; i++) {
2305*61046927SAndroid Build Coastguard Worker         object->cells[i] = OBJECT_INVALID_IX;
2306*61046927SAndroid Build Coastguard Worker     }
2307*61046927SAndroid Build Coastguard Worker     return JSONSuccess;
2308*61046927SAndroid Build Coastguard Worker }
2309*61046927SAndroid Build Coastguard Worker 
json_validate(const JSON_Value * schema,const JSON_Value * value)2310*61046927SAndroid Build Coastguard Worker JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
2311*61046927SAndroid Build Coastguard Worker     JSON_Value *temp_schema_value = NULL, *temp_value = NULL;
2312*61046927SAndroid Build Coastguard Worker     JSON_Array *schema_array = NULL, *value_array = NULL;
2313*61046927SAndroid Build Coastguard Worker     JSON_Object *schema_object = NULL, *value_object = NULL;
2314*61046927SAndroid Build Coastguard Worker     JSON_Value_Type schema_type = JSONError, value_type = JSONError;
2315*61046927SAndroid Build Coastguard Worker     const char *key = NULL;
2316*61046927SAndroid Build Coastguard Worker     size_t i = 0, count = 0;
2317*61046927SAndroid Build Coastguard Worker     if (schema == NULL || value == NULL) {
2318*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2319*61046927SAndroid Build Coastguard Worker     }
2320*61046927SAndroid Build Coastguard Worker     schema_type = json_value_get_type(schema);
2321*61046927SAndroid Build Coastguard Worker     value_type = json_value_get_type(value);
2322*61046927SAndroid Build Coastguard Worker     if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */
2323*61046927SAndroid Build Coastguard Worker         return JSONFailure;
2324*61046927SAndroid Build Coastguard Worker     }
2325*61046927SAndroid Build Coastguard Worker     switch (schema_type) {
2326*61046927SAndroid Build Coastguard Worker         case JSONArray:
2327*61046927SAndroid Build Coastguard Worker             schema_array = json_value_get_array(schema);
2328*61046927SAndroid Build Coastguard Worker             value_array = json_value_get_array(value);
2329*61046927SAndroid Build Coastguard Worker             count = json_array_get_count(schema_array);
2330*61046927SAndroid Build Coastguard Worker             if (count == 0) {
2331*61046927SAndroid Build Coastguard Worker                 return JSONSuccess; /* Empty array allows all types */
2332*61046927SAndroid Build Coastguard Worker             }
2333*61046927SAndroid Build Coastguard Worker             /* Get first value from array, rest is ignored */
2334*61046927SAndroid Build Coastguard Worker             temp_schema_value = json_array_get_value(schema_array, 0);
2335*61046927SAndroid Build Coastguard Worker             for (i = 0; i < json_array_get_count(value_array); i++) {
2336*61046927SAndroid Build Coastguard Worker                 temp_value = json_array_get_value(value_array, i);
2337*61046927SAndroid Build Coastguard Worker                 if (json_validate(temp_schema_value, temp_value) != JSONSuccess) {
2338*61046927SAndroid Build Coastguard Worker                     return JSONFailure;
2339*61046927SAndroid Build Coastguard Worker                 }
2340*61046927SAndroid Build Coastguard Worker             }
2341*61046927SAndroid Build Coastguard Worker             return JSONSuccess;
2342*61046927SAndroid Build Coastguard Worker         case JSONObject:
2343*61046927SAndroid Build Coastguard Worker             schema_object = json_value_get_object(schema);
2344*61046927SAndroid Build Coastguard Worker             value_object = json_value_get_object(value);
2345*61046927SAndroid Build Coastguard Worker             count = json_object_get_count(schema_object);
2346*61046927SAndroid Build Coastguard Worker             if (count == 0) {
2347*61046927SAndroid Build Coastguard Worker                 return JSONSuccess; /* Empty object allows all objects */
2348*61046927SAndroid Build Coastguard Worker             } else if (json_object_get_count(value_object) < count) {
2349*61046927SAndroid Build Coastguard Worker                 return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */
2350*61046927SAndroid Build Coastguard Worker             }
2351*61046927SAndroid Build Coastguard Worker             for (i = 0; i < count; i++) {
2352*61046927SAndroid Build Coastguard Worker                 key = json_object_get_name(schema_object, i);
2353*61046927SAndroid Build Coastguard Worker                 temp_schema_value = json_object_get_value(schema_object, key);
2354*61046927SAndroid Build Coastguard Worker                 temp_value = json_object_get_value(value_object, key);
2355*61046927SAndroid Build Coastguard Worker                 if (temp_value == NULL) {
2356*61046927SAndroid Build Coastguard Worker                     return JSONFailure;
2357*61046927SAndroid Build Coastguard Worker                 }
2358*61046927SAndroid Build Coastguard Worker                 if (json_validate(temp_schema_value, temp_value) != JSONSuccess) {
2359*61046927SAndroid Build Coastguard Worker                     return JSONFailure;
2360*61046927SAndroid Build Coastguard Worker                 }
2361*61046927SAndroid Build Coastguard Worker             }
2362*61046927SAndroid Build Coastguard Worker             return JSONSuccess;
2363*61046927SAndroid Build Coastguard Worker         case JSONString: case JSONNumber: case JSONBoolean: case JSONNull:
2364*61046927SAndroid Build Coastguard Worker             return JSONSuccess; /* equality already tested before switch */
2365*61046927SAndroid Build Coastguard Worker         case JSONError: default:
2366*61046927SAndroid Build Coastguard Worker             return JSONFailure;
2367*61046927SAndroid Build Coastguard Worker     }
2368*61046927SAndroid Build Coastguard Worker }
2369*61046927SAndroid Build Coastguard Worker 
json_value_equals(const JSON_Value * a,const JSON_Value * b)2370*61046927SAndroid Build Coastguard Worker int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
2371*61046927SAndroid Build Coastguard Worker     JSON_Object *a_object = NULL, *b_object = NULL;
2372*61046927SAndroid Build Coastguard Worker     JSON_Array *a_array = NULL, *b_array = NULL;
2373*61046927SAndroid Build Coastguard Worker     const JSON_String *a_string = NULL, *b_string = NULL;
2374*61046927SAndroid Build Coastguard Worker     const char *key = NULL;
2375*61046927SAndroid Build Coastguard Worker     size_t a_count = 0, b_count = 0, i = 0;
2376*61046927SAndroid Build Coastguard Worker     JSON_Value_Type a_type, b_type;
2377*61046927SAndroid Build Coastguard Worker     a_type = json_value_get_type(a);
2378*61046927SAndroid Build Coastguard Worker     b_type = json_value_get_type(b);
2379*61046927SAndroid Build Coastguard Worker     if (a_type != b_type) {
2380*61046927SAndroid Build Coastguard Worker         return PARSON_FALSE;
2381*61046927SAndroid Build Coastguard Worker     }
2382*61046927SAndroid Build Coastguard Worker     switch (a_type) {
2383*61046927SAndroid Build Coastguard Worker         case JSONArray:
2384*61046927SAndroid Build Coastguard Worker             a_array = json_value_get_array(a);
2385*61046927SAndroid Build Coastguard Worker             b_array = json_value_get_array(b);
2386*61046927SAndroid Build Coastguard Worker             a_count = json_array_get_count(a_array);
2387*61046927SAndroid Build Coastguard Worker             b_count = json_array_get_count(b_array);
2388*61046927SAndroid Build Coastguard Worker             if (a_count != b_count) {
2389*61046927SAndroid Build Coastguard Worker                 return PARSON_FALSE;
2390*61046927SAndroid Build Coastguard Worker             }
2391*61046927SAndroid Build Coastguard Worker             for (i = 0; i < a_count; i++) {
2392*61046927SAndroid Build Coastguard Worker                 if (!json_value_equals(json_array_get_value(a_array, i),
2393*61046927SAndroid Build Coastguard Worker                                        json_array_get_value(b_array, i))) {
2394*61046927SAndroid Build Coastguard Worker                     return PARSON_FALSE;
2395*61046927SAndroid Build Coastguard Worker                 }
2396*61046927SAndroid Build Coastguard Worker             }
2397*61046927SAndroid Build Coastguard Worker             return PARSON_TRUE;
2398*61046927SAndroid Build Coastguard Worker         case JSONObject:
2399*61046927SAndroid Build Coastguard Worker             a_object = json_value_get_object(a);
2400*61046927SAndroid Build Coastguard Worker             b_object = json_value_get_object(b);
2401*61046927SAndroid Build Coastguard Worker             a_count = json_object_get_count(a_object);
2402*61046927SAndroid Build Coastguard Worker             b_count = json_object_get_count(b_object);
2403*61046927SAndroid Build Coastguard Worker             if (a_count != b_count) {
2404*61046927SAndroid Build Coastguard Worker                 return PARSON_FALSE;
2405*61046927SAndroid Build Coastguard Worker             }
2406*61046927SAndroid Build Coastguard Worker             for (i = 0; i < a_count; i++) {
2407*61046927SAndroid Build Coastguard Worker                 key = json_object_get_name(a_object, i);
2408*61046927SAndroid Build Coastguard Worker                 if (!json_value_equals(json_object_get_value(a_object, key),
2409*61046927SAndroid Build Coastguard Worker                                        json_object_get_value(b_object, key))) {
2410*61046927SAndroid Build Coastguard Worker                     return PARSON_FALSE;
2411*61046927SAndroid Build Coastguard Worker                 }
2412*61046927SAndroid Build Coastguard Worker             }
2413*61046927SAndroid Build Coastguard Worker             return PARSON_TRUE;
2414*61046927SAndroid Build Coastguard Worker         case JSONString:
2415*61046927SAndroid Build Coastguard Worker             a_string = json_value_get_string_desc(a);
2416*61046927SAndroid Build Coastguard Worker             b_string = json_value_get_string_desc(b);
2417*61046927SAndroid Build Coastguard Worker             if (a_string == NULL || b_string == NULL) {
2418*61046927SAndroid Build Coastguard Worker                 return PARSON_FALSE; /* shouldn't happen */
2419*61046927SAndroid Build Coastguard Worker             }
2420*61046927SAndroid Build Coastguard Worker             return a_string->length == b_string->length &&
2421*61046927SAndroid Build Coastguard Worker                    memcmp(a_string->chars, b_string->chars, a_string->length) == 0;
2422*61046927SAndroid Build Coastguard Worker         case JSONBoolean:
2423*61046927SAndroid Build Coastguard Worker             return json_value_get_boolean(a) == json_value_get_boolean(b);
2424*61046927SAndroid Build Coastguard Worker         case JSONNumber:
2425*61046927SAndroid Build Coastguard Worker             return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */
2426*61046927SAndroid Build Coastguard Worker         case JSONError:
2427*61046927SAndroid Build Coastguard Worker             return PARSON_TRUE;
2428*61046927SAndroid Build Coastguard Worker         case JSONNull:
2429*61046927SAndroid Build Coastguard Worker             return PARSON_TRUE;
2430*61046927SAndroid Build Coastguard Worker         default:
2431*61046927SAndroid Build Coastguard Worker             return PARSON_TRUE;
2432*61046927SAndroid Build Coastguard Worker     }
2433*61046927SAndroid Build Coastguard Worker }
2434*61046927SAndroid Build Coastguard Worker 
json_type(const JSON_Value * value)2435*61046927SAndroid Build Coastguard Worker JSON_Value_Type json_type(const JSON_Value *value) {
2436*61046927SAndroid Build Coastguard Worker     return json_value_get_type(value);
2437*61046927SAndroid Build Coastguard Worker }
2438*61046927SAndroid Build Coastguard Worker 
json_object(const JSON_Value * value)2439*61046927SAndroid Build Coastguard Worker JSON_Object * json_object (const JSON_Value *value) {
2440*61046927SAndroid Build Coastguard Worker     return json_value_get_object(value);
2441*61046927SAndroid Build Coastguard Worker }
2442*61046927SAndroid Build Coastguard Worker 
json_array(const JSON_Value * value)2443*61046927SAndroid Build Coastguard Worker JSON_Array * json_array(const JSON_Value *value) {
2444*61046927SAndroid Build Coastguard Worker     return json_value_get_array(value);
2445*61046927SAndroid Build Coastguard Worker }
2446*61046927SAndroid Build Coastguard Worker 
json_string(const JSON_Value * value)2447*61046927SAndroid Build Coastguard Worker const char * json_string(const JSON_Value *value) {
2448*61046927SAndroid Build Coastguard Worker     return json_value_get_string(value);
2449*61046927SAndroid Build Coastguard Worker }
2450*61046927SAndroid Build Coastguard Worker 
json_string_len(const JSON_Value * value)2451*61046927SAndroid Build Coastguard Worker size_t json_string_len(const JSON_Value *value) {
2452*61046927SAndroid Build Coastguard Worker     return json_value_get_string_len(value);
2453*61046927SAndroid Build Coastguard Worker }
2454*61046927SAndroid Build Coastguard Worker 
json_number(const JSON_Value * value)2455*61046927SAndroid Build Coastguard Worker double json_number(const JSON_Value *value) {
2456*61046927SAndroid Build Coastguard Worker     return json_value_get_number(value);
2457*61046927SAndroid Build Coastguard Worker }
2458*61046927SAndroid Build Coastguard Worker 
json_boolean(const JSON_Value * value)2459*61046927SAndroid Build Coastguard Worker int json_boolean(const JSON_Value *value) {
2460*61046927SAndroid Build Coastguard Worker     return json_value_get_boolean(value);
2461*61046927SAndroid Build Coastguard Worker }
2462*61046927SAndroid Build Coastguard Worker 
json_set_allocation_functions(JSON_Malloc_Function malloc_fun,JSON_Free_Function free_fun)2463*61046927SAndroid Build Coastguard Worker void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) {
2464*61046927SAndroid Build Coastguard Worker     parson_malloc = malloc_fun;
2465*61046927SAndroid Build Coastguard Worker     parson_free = free_fun;
2466*61046927SAndroid Build Coastguard Worker }
2467*61046927SAndroid Build Coastguard Worker 
json_set_escape_slashes(int escape_slashes)2468*61046927SAndroid Build Coastguard Worker void json_set_escape_slashes(int escape_slashes) {
2469*61046927SAndroid Build Coastguard Worker     parson_escape_slashes = escape_slashes;
2470*61046927SAndroid Build Coastguard Worker }
2471*61046927SAndroid Build Coastguard Worker 
json_set_float_serialization_format(const char * format)2472*61046927SAndroid Build Coastguard Worker void json_set_float_serialization_format(const char *format) {
2473*61046927SAndroid Build Coastguard Worker     if (parson_float_format) {
2474*61046927SAndroid Build Coastguard Worker         parson_free(parson_float_format);
2475*61046927SAndroid Build Coastguard Worker         parson_float_format = NULL;
2476*61046927SAndroid Build Coastguard Worker     }
2477*61046927SAndroid Build Coastguard Worker     if (!format) {
2478*61046927SAndroid Build Coastguard Worker         parson_float_format = NULL;
2479*61046927SAndroid Build Coastguard Worker         return;
2480*61046927SAndroid Build Coastguard Worker     }
2481*61046927SAndroid Build Coastguard Worker     parson_float_format = parson_strdup(format);
2482*61046927SAndroid Build Coastguard Worker }
2483*61046927SAndroid Build Coastguard Worker 
json_set_number_serialization_function(JSON_Number_Serialization_Function func)2484*61046927SAndroid Build Coastguard Worker void json_set_number_serialization_function(JSON_Number_Serialization_Function func) {
2485*61046927SAndroid Build Coastguard Worker     parson_number_serialization_function = func;
2486*61046927SAndroid Build Coastguard Worker }
2487