/src/clib/deps/parson/parson.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Parson ( http://kgabis.github.com/parson/ ) |
3 | | Copyright (c) 2012 - 2015 Krzysztof Gabis |
4 | | |
5 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
6 | | of this software and associated documentation files (the "Software"), to deal |
7 | | in the Software without restriction, including without limitation the rights |
8 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | | copies of the Software, and to permit persons to whom the Software is |
10 | | furnished to do so, subject to the following conditions: |
11 | | |
12 | | The above copyright notice and this permission notice shall be included in |
13 | | all copies or substantial portions of the Software. |
14 | | |
15 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
18 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
20 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
21 | | THE SOFTWARE. |
22 | | */ |
23 | | #ifdef _MSC_VER |
24 | | #define _CRT_SECURE_NO_WARNINGS |
25 | | #endif |
26 | | |
27 | | #include "parson.h" |
28 | | |
29 | | #include <stdio.h> |
30 | | #include <stdlib.h> |
31 | | #include <string.h> |
32 | | #include <ctype.h> |
33 | | #include <math.h> |
34 | | |
35 | | #define STARTING_CAPACITY 15 |
36 | 4 | #define ARRAY_MAX_CAPACITY 122880 /* 15*(2^13) */ |
37 | 4 | #define OBJECT_MAX_CAPACITY 960 /* 15*(2^6) */ |
38 | 18 | #define MAX_NESTING 19 |
39 | 0 | #define DOUBLE_SERIALIZATION_FORMAT "%f" |
40 | | |
41 | 0 | #define SIZEOF_TOKEN(a) (sizeof(a) - 1) |
42 | 4.22M | #define SKIP_CHAR(str) ((*str)++) |
43 | 62 | #define SKIP_WHITESPACES(str) while (isspace(**str)) { SKIP_CHAR(str); } |
44 | 8 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
45 | | |
46 | | #undef malloc |
47 | | #undef free |
48 | | |
49 | | static JSON_Malloc_Function parson_malloc = malloc; |
50 | | static JSON_Free_Function parson_free = free; |
51 | | |
52 | 0 | #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ |
53 | | |
54 | | /* Type definitions */ |
55 | | typedef union json_value_value { |
56 | | char *string; |
57 | | double number; |
58 | | JSON_Object *object; |
59 | | JSON_Array *array; |
60 | | int boolean; |
61 | | int null; |
62 | | } JSON_Value_Value; |
63 | | |
64 | | struct json_value_t { |
65 | | JSON_Value_Type type; |
66 | | JSON_Value_Value value; |
67 | | }; |
68 | | |
69 | | struct json_object_t { |
70 | | char **names; |
71 | | JSON_Value **values; |
72 | | size_t count; |
73 | | size_t capacity; |
74 | | }; |
75 | | |
76 | | struct json_array_t { |
77 | | JSON_Value **items; |
78 | | size_t count; |
79 | | size_t capacity; |
80 | | }; |
81 | | |
82 | | /* Various */ |
83 | | static char * read_file(const char *filename); |
84 | | static void remove_comments(char *string, const char *start_token, const char *end_token); |
85 | | static char * parson_strndup(const char *string, size_t n); |
86 | | static char * parson_strdup(const char *string); |
87 | | static int is_utf16_hex(const unsigned char *string); |
88 | | static int num_bytes_in_utf8_sequence(unsigned char c); |
89 | | static int verify_utf8_sequence(const unsigned char *string, int *len); |
90 | | static int is_valid_utf8(const char *string, size_t string_len); |
91 | | static int is_decimal(const char *string, size_t length); |
92 | | |
93 | | /* JSON Object */ |
94 | | static JSON_Object * json_object_init(void); |
95 | | static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value); |
96 | | static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity); |
97 | | static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n); |
98 | | static void json_object_free(JSON_Object *object); |
99 | | |
100 | | /* JSON Array */ |
101 | | static JSON_Array * json_array_init(void); |
102 | | static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value); |
103 | | static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity); |
104 | | static void json_array_free(JSON_Array *array); |
105 | | |
106 | | /* JSON Value */ |
107 | | static JSON_Value * json_value_init_string_no_copy(char *string); |
108 | | |
109 | | /* Parser */ |
110 | | static void skip_quotes(const char **string); |
111 | | static int parse_utf_16(const char **unprocessed, char **processed); |
112 | | static char * process_string(const char *input, size_t len); |
113 | | static char * get_quoted_string(const char **string); |
114 | | static JSON_Value * parse_object_value(const char **string, size_t nesting); |
115 | | static JSON_Value * parse_array_value(const char **string, size_t nesting); |
116 | | static JSON_Value * parse_string_value(const char **string); |
117 | | static JSON_Value * parse_boolean_value(const char **string); |
118 | | static JSON_Value * parse_number_value(const char **string); |
119 | | static JSON_Value * parse_null_value(const char **string); |
120 | | static JSON_Value * parse_value(const char **string, size_t nesting); |
121 | | |
122 | | /* Serialization */ |
123 | | static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); |
124 | | static int json_serialize_string(const char *string, char *buf); |
125 | | static int append_indent(char *buf, int level); |
126 | | static int append_string(char *buf, const char *string); |
127 | | |
128 | | /* Various */ |
129 | 4 | static char * parson_strndup(const char *string, size_t n) { |
130 | 4 | char *output_string = (char*)parson_malloc(n + 1); |
131 | 4 | if (!output_string) |
132 | 0 | return NULL; |
133 | 4 | output_string[n] = '\0'; |
134 | 4 | strncpy(output_string, string, n); |
135 | 4 | return output_string; |
136 | 4 | } |
137 | | |
138 | 4 | static char * parson_strdup(const char *string) { |
139 | 4 | return parson_strndup(string, strlen(string)); |
140 | 4 | } |
141 | | |
142 | 0 | static int is_utf16_hex(const unsigned char *s) { |
143 | 0 | return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]); |
144 | 0 | } |
145 | | |
146 | 0 | static int num_bytes_in_utf8_sequence(unsigned char c) { |
147 | 0 | if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) { |
148 | 0 | return 0; |
149 | 0 | } else if ((c & 0x80) == 0) { /* 0xxxxxxx */ |
150 | 0 | return 1; |
151 | 0 | } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ |
152 | 0 | return 2; |
153 | 0 | } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ |
154 | 0 | return 3; |
155 | 0 | } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ |
156 | 0 | return 4; |
157 | 0 | } |
158 | 0 | return 0; /* won't happen */ |
159 | 0 | } |
160 | | |
161 | 0 | static int verify_utf8_sequence(const unsigned char *string, int *len) { |
162 | 0 | unsigned int cp = 0; |
163 | 0 | *len = num_bytes_in_utf8_sequence(string[0]); |
164 | |
|
165 | 0 | if (*len == 1) { |
166 | 0 | cp = string[0]; |
167 | 0 | } else if (*len == 2 && IS_CONT(string[1])) { |
168 | 0 | cp = string[0] & 0x1F; |
169 | 0 | cp = (cp << 6) | (string[1] & 0x3F); |
170 | 0 | } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) { |
171 | 0 | cp = ((unsigned char)string[0]) & 0xF; |
172 | 0 | cp = (cp << 6) | (string[1] & 0x3F); |
173 | 0 | cp = (cp << 6) | (string[2] & 0x3F); |
174 | 0 | } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) { |
175 | 0 | cp = string[0] & 0x7; |
176 | 0 | cp = (cp << 6) | (string[1] & 0x3F); |
177 | 0 | cp = (cp << 6) | (string[2] & 0x3F); |
178 | 0 | cp = (cp << 6) | (string[3] & 0x3F); |
179 | 0 | } else { |
180 | 0 | return 0; |
181 | 0 | } |
182 | | |
183 | | /* overlong encodings */ |
184 | 0 | if ((cp < 0x80 && *len > 1) || |
185 | 0 | (cp < 0x800 && *len > 2) || |
186 | 0 | (cp < 0x10000 && *len > 3)) { |
187 | 0 | return 0; |
188 | 0 | } |
189 | | |
190 | | /* invalid unicode */ |
191 | 0 | if (cp > 0x10FFFF) { |
192 | 0 | return 0; |
193 | 0 | } |
194 | | |
195 | | /* surrogate halves */ |
196 | 0 | if (cp >= 0xD800 && cp <= 0xDFFF) { |
197 | 0 | return 0; |
198 | 0 | } |
199 | | |
200 | 0 | return 1; |
201 | 0 | } |
202 | | |
203 | 0 | static int is_valid_utf8(const char *string, size_t string_len) { |
204 | 0 | int len = 0; |
205 | 0 | const char *string_end = string + string_len; |
206 | 0 | while (string < string_end) { |
207 | 0 | if (!verify_utf8_sequence((const unsigned char*)string, &len)) { |
208 | 0 | return 0; |
209 | 0 | } |
210 | 0 | string += len; |
211 | 0 | } |
212 | 0 | return 1; |
213 | 0 | } |
214 | | |
215 | 8 | static int is_decimal(const char *string, size_t length) { |
216 | 8 | if (length > 1 && string[0] == '0' && string[1] != '.') |
217 | 0 | return 0; |
218 | 8 | if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') |
219 | 0 | return 0; |
220 | 4.19M | while (length--) |
221 | 4.19M | if (strchr("xX", string[length])) |
222 | 0 | return 0; |
223 | 8 | return 1; |
224 | 8 | } |
225 | | |
226 | 0 | static char * read_file(const char * filename) { |
227 | 0 | FILE *fp = fopen(filename, "r"); |
228 | 0 | size_t file_size; |
229 | 0 | long pos; |
230 | 0 | char *file_contents; |
231 | 0 | if (!fp) |
232 | 0 | return NULL; |
233 | 0 | fseek(fp, 0L, SEEK_END); |
234 | 0 | pos = ftell(fp); |
235 | 0 | if (pos < 0) { |
236 | 0 | fclose(fp); |
237 | 0 | return NULL; |
238 | 0 | } |
239 | 0 | file_size = pos; |
240 | 0 | rewind(fp); |
241 | 0 | file_contents = (char*)parson_malloc(sizeof(char) * (file_size + 1)); |
242 | 0 | if (!file_contents) { |
243 | 0 | fclose(fp); |
244 | 0 | return NULL; |
245 | 0 | } |
246 | 0 | if (fread(file_contents, file_size, 1, fp) < 1) { |
247 | 0 | if (ferror(fp)) { |
248 | 0 | fclose(fp); |
249 | 0 | parson_free(file_contents); |
250 | 0 | return NULL; |
251 | 0 | } |
252 | 0 | } |
253 | 0 | fclose(fp); |
254 | 0 | file_contents[file_size] = '\0'; |
255 | 0 | return file_contents; |
256 | 0 | } |
257 | | |
258 | 0 | static void remove_comments(char *string, const char *start_token, const char *end_token) { |
259 | 0 | int in_string = 0, escaped = 0; |
260 | 0 | size_t i; |
261 | 0 | char *ptr = NULL, current_char; |
262 | 0 | size_t start_token_len = strlen(start_token); |
263 | 0 | size_t end_token_len = strlen(end_token); |
264 | 0 | if (start_token_len == 0 || end_token_len == 0) |
265 | 0 | return; |
266 | 0 | while ((current_char = *string) != '\0') { |
267 | 0 | if (current_char == '\\' && !escaped) { |
268 | 0 | escaped = 1; |
269 | 0 | string++; |
270 | 0 | continue; |
271 | 0 | } else if (current_char == '\"' && !escaped) { |
272 | 0 | in_string = !in_string; |
273 | 0 | } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) { |
274 | 0 | for(i = 0; i < start_token_len; i++) |
275 | 0 | string[i] = ' '; |
276 | 0 | string = string + start_token_len; |
277 | 0 | ptr = strstr(string, end_token); |
278 | 0 | if (!ptr) |
279 | 0 | return; |
280 | 0 | for (i = 0; i < (ptr - string) + end_token_len; i++) |
281 | 0 | string[i] = ' '; |
282 | 0 | string = ptr + end_token_len - 1; |
283 | 0 | } |
284 | 0 | escaped = 0; |
285 | 0 | string++; |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | /* JSON Object */ |
290 | 6 | static JSON_Object * json_object_init(void) { |
291 | 6 | JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object)); |
292 | 6 | if (!new_obj) |
293 | 0 | return NULL; |
294 | 6 | new_obj->names = (char**)NULL; |
295 | 6 | new_obj->values = (JSON_Value**)NULL; |
296 | 6 | new_obj->capacity = 0; |
297 | 6 | new_obj->count = 0; |
298 | 6 | return new_obj; |
299 | 6 | } |
300 | | |
301 | 4 | static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) { |
302 | 4 | size_t index = 0; |
303 | 4 | if (object == NULL || name == NULL || value == NULL) { |
304 | 0 | return JSONFailure; |
305 | 0 | } |
306 | 4 | if (object->count >= object->capacity) { |
307 | 4 | size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY); |
308 | 4 | if (new_capacity > OBJECT_MAX_CAPACITY) |
309 | 0 | return JSONFailure; |
310 | 4 | if (json_object_resize(object, new_capacity) == JSONFailure) |
311 | 0 | return JSONFailure; |
312 | 4 | } |
313 | 4 | if (json_object_get_value(object, name) != NULL) |
314 | 0 | return JSONFailure; |
315 | 4 | index = object->count; |
316 | 4 | object->names[index] = parson_strdup(name); |
317 | 4 | if (object->names[index] == NULL) |
318 | 0 | return JSONFailure; |
319 | 4 | object->values[index] = value; |
320 | 4 | object->count++; |
321 | 4 | return JSONSuccess; |
322 | 4 | } |
323 | | |
324 | 7 | static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) { |
325 | 7 | char **temp_names = NULL; |
326 | 7 | JSON_Value **temp_values = NULL; |
327 | | |
328 | 7 | if ((object->names == NULL && object->values != NULL) || |
329 | 7 | (object->names != NULL && object->values == NULL) || |
330 | 7 | new_capacity == 0) { |
331 | 0 | return JSONFailure; /* Shouldn't happen */ |
332 | 0 | } |
333 | | |
334 | 7 | temp_names = (char**)parson_malloc(new_capacity * sizeof(char*)); |
335 | 7 | if (temp_names == NULL) |
336 | 0 | return JSONFailure; |
337 | | |
338 | 7 | temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); |
339 | 7 | if (temp_names == NULL) { |
340 | 0 | parson_free(temp_names); |
341 | 0 | return JSONFailure; |
342 | 0 | } |
343 | | |
344 | 7 | if (object->names != NULL && object->values != NULL && object->count > 0) { |
345 | 3 | memcpy(temp_names, object->names, object->count * sizeof(char*)); |
346 | 3 | memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*)); |
347 | 3 | } |
348 | 7 | parson_free(object->names); |
349 | 7 | parson_free(object->values); |
350 | 7 | object->names = temp_names; |
351 | 7 | object->values = temp_values; |
352 | 7 | object->capacity = new_capacity; |
353 | 7 | return JSONSuccess; |
354 | 7 | } |
355 | | |
356 | 55 | static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) { |
357 | 55 | size_t i, name_length; |
358 | 106 | for (i = 0; i < json_object_get_count(object); i++) { |
359 | 51 | name_length = strlen(object->names[i]); |
360 | 51 | if (name_length != n) |
361 | 51 | continue; |
362 | 0 | if (strncmp(object->names[i], name, n) == 0) |
363 | 0 | return object->values[i]; |
364 | 0 | } |
365 | 55 | return NULL; |
366 | 55 | } |
367 | | |
368 | 6 | static void json_object_free(JSON_Object *object) { |
369 | 10 | while(object->count--) { |
370 | 4 | parson_free(object->names[object->count]); |
371 | 4 | json_value_free(object->values[object->count]); |
372 | 4 | } |
373 | 6 | parson_free(object->names); |
374 | 6 | parson_free(object->values); |
375 | 6 | parson_free(object); |
376 | 6 | } |
377 | | |
378 | | /* JSON Array */ |
379 | 4 | static JSON_Array * json_array_init(void) { |
380 | 4 | JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array)); |
381 | 4 | if (!new_array) |
382 | 0 | return NULL; |
383 | 4 | new_array->items = (JSON_Value**)NULL; |
384 | 4 | new_array->capacity = 0; |
385 | 4 | new_array->count = 0; |
386 | 4 | return new_array; |
387 | 4 | } |
388 | | |
389 | 4 | static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) { |
390 | 4 | if (array->count >= array->capacity) { |
391 | 4 | size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY); |
392 | 4 | if (new_capacity > ARRAY_MAX_CAPACITY) |
393 | 0 | return JSONFailure; |
394 | 4 | if (json_array_resize(array, new_capacity) == JSONFailure) |
395 | 0 | return JSONFailure; |
396 | 4 | } |
397 | 4 | array->items[array->count] = value; |
398 | 4 | array->count++; |
399 | 4 | return JSONSuccess; |
400 | 4 | } |
401 | | |
402 | 4 | static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) { |
403 | 4 | JSON_Value **new_items = NULL; |
404 | 4 | if (new_capacity == 0) { |
405 | 0 | return JSONFailure; |
406 | 0 | } |
407 | 4 | new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); |
408 | 4 | if (new_items == NULL) { |
409 | 0 | return JSONFailure; |
410 | 0 | } |
411 | 4 | if (array->items != NULL && array->count > 0) { |
412 | 0 | memcpy(new_items, array->items, array->count * sizeof(JSON_Value*)); |
413 | 0 | } |
414 | 4 | parson_free(array->items); |
415 | 4 | array->items = new_items; |
416 | 4 | array->capacity = new_capacity; |
417 | 4 | return JSONSuccess; |
418 | 4 | } |
419 | | |
420 | 4 | static void json_array_free(JSON_Array *array) { |
421 | 8 | while (array->count--) |
422 | 4 | json_value_free(array->items[array->count]); |
423 | 4 | parson_free(array->items); |
424 | 4 | parson_free(array); |
425 | 4 | } |
426 | | |
427 | | /* JSON Value */ |
428 | 0 | static JSON_Value * json_value_init_string_no_copy(char *string) { |
429 | 0 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
430 | 0 | if (!new_value) |
431 | 0 | return NULL; |
432 | 0 | new_value->type = JSONString; |
433 | 0 | new_value->value.string = string; |
434 | 0 | return new_value; |
435 | 0 | } |
436 | | |
437 | | /* Parser */ |
438 | 7 | static void skip_quotes(const char **string) { |
439 | 7 | SKIP_CHAR(string); |
440 | 4.22M | while (**string != '\"') { |
441 | 4.22M | if (**string == '\0') |
442 | 2 | return; |
443 | 4.22M | if (**string == '\\') { |
444 | 0 | SKIP_CHAR(string); |
445 | 0 | if (**string == '\0') |
446 | 0 | return; |
447 | 0 | } |
448 | 4.22M | SKIP_CHAR(string); |
449 | 4.22M | } |
450 | 5 | SKIP_CHAR(string); |
451 | 5 | } |
452 | | |
453 | 0 | static int parse_utf_16(const char **unprocessed, char **processed) { |
454 | 0 | unsigned int cp, lead, trail; |
455 | 0 | char *processed_ptr = *processed; |
456 | 0 | const char *unprocessed_ptr = *unprocessed; |
457 | 0 | unprocessed_ptr++; /* skips u */ |
458 | 0 | if (!is_utf16_hex((const unsigned char*)unprocessed_ptr) || sscanf(unprocessed_ptr, "%4x", &cp) == EOF) |
459 | 0 | return JSONFailure; |
460 | 0 | if (cp < 0x80) { |
461 | 0 | *processed_ptr = cp; /* 0xxxxxxx */ |
462 | 0 | } else if (cp < 0x800) { |
463 | 0 | *processed_ptr++ = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */ |
464 | 0 | *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */ |
465 | 0 | } else if (cp < 0xD800 || cp > 0xDFFF) { |
466 | 0 | *processed_ptr++ = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */ |
467 | 0 | *processed_ptr++ = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */ |
468 | 0 | *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */ |
469 | 0 | } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */ |
470 | 0 | lead = cp; |
471 | 0 | unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */ |
472 | 0 | if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u' || /* starts with \u? */ |
473 | 0 | !is_utf16_hex((const unsigned char*)unprocessed_ptr) || |
474 | 0 | sscanf(unprocessed_ptr, "%4x", &trail) == EOF || |
475 | 0 | trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */ |
476 | 0 | return JSONFailure; |
477 | 0 | } |
478 | 0 | cp = ((((lead-0xD800)&0x3FF)<<10)|((trail-0xDC00)&0x3FF))+0x010000; |
479 | 0 | *processed_ptr++ = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */ |
480 | 0 | *processed_ptr++ = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */ |
481 | 0 | *processed_ptr++ = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */ |
482 | 0 | *processed_ptr = (((cp ) & 0x3F) | 0x80); /* 10xxxxxx */ |
483 | 0 | } else { /* trail surrogate before lead surrogate */ |
484 | 0 | return JSONFailure; |
485 | 0 | } |
486 | 0 | unprocessed_ptr += 3; |
487 | 0 | *processed = processed_ptr; |
488 | 0 | *unprocessed = unprocessed_ptr; |
489 | 0 | return JSONSuccess; |
490 | 0 | } |
491 | | |
492 | | |
493 | | /* Copies and processes passed string up to supplied length. |
494 | | Example: "\u006Corem ipsum" -> lorem ipsum */ |
495 | 5 | static char* process_string(const char *input, size_t len) { |
496 | 5 | const char *input_ptr = input; |
497 | 5 | size_t initial_size = (len + 1) * sizeof(char); |
498 | 5 | size_t final_size = 0; |
499 | 5 | char *output = (char*)parson_malloc(initial_size); |
500 | 5 | char *output_ptr = output; |
501 | 5 | char *resized_output = NULL; |
502 | 3.14M | while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) { |
503 | 3.14M | if (*input_ptr == '\\') { |
504 | 0 | input_ptr++; |
505 | 0 | switch (*input_ptr) { |
506 | 0 | case '\"': *output_ptr = '\"'; break; |
507 | 0 | case '\\': *output_ptr = '\\'; break; |
508 | 0 | case '/': *output_ptr = '/'; break; |
509 | 0 | case 'b': *output_ptr = '\b'; break; |
510 | 0 | case 'f': *output_ptr = '\f'; break; |
511 | 0 | case 'n': *output_ptr = '\n'; break; |
512 | 0 | case 'r': *output_ptr = '\r'; break; |
513 | 0 | case 't': *output_ptr = '\t'; break; |
514 | 0 | case 'u': |
515 | 0 | if (parse_utf_16(&input_ptr, &output_ptr) == JSONFailure) |
516 | 0 | goto error; |
517 | 0 | break; |
518 | 0 | default: |
519 | 0 | goto error; |
520 | 0 | } |
521 | 3.14M | } else if ((unsigned char)*input_ptr < 0x20) { |
522 | 0 | goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */ |
523 | 3.14M | } else { |
524 | 3.14M | *output_ptr = *input_ptr; |
525 | 3.14M | } |
526 | 3.14M | output_ptr++; |
527 | 3.14M | input_ptr++; |
528 | 3.14M | } |
529 | 5 | *output_ptr = '\0'; |
530 | | /* resize to new length */ |
531 | 5 | final_size = (size_t)(output_ptr-output) + 1; |
532 | 5 | resized_output = (char*)parson_malloc(final_size); |
533 | 5 | if (resized_output == NULL) |
534 | 0 | goto error; |
535 | 5 | memcpy(resized_output, output, final_size); |
536 | 5 | parson_free(output); |
537 | 5 | return resized_output; |
538 | 0 | error: |
539 | 0 | parson_free(output); |
540 | 0 | return NULL; |
541 | 5 | } |
542 | | |
543 | | /* Return processed contents of a string between quotes and |
544 | | skips passed argument to a matching quote. */ |
545 | 7 | static char * get_quoted_string(const char **string) { |
546 | 7 | const char *string_start = *string; |
547 | 7 | size_t string_len = 0; |
548 | 7 | skip_quotes(string); |
549 | 7 | if (**string == '\0') |
550 | 2 | return NULL; |
551 | 5 | string_len = *string - string_start - 2; /* length without quotes */ |
552 | 5 | return process_string(string_start + 1, string_len); |
553 | 7 | } |
554 | | |
555 | 18 | static JSON_Value * parse_value(const char **string, size_t nesting) { |
556 | 18 | if (nesting > MAX_NESTING) |
557 | 0 | return NULL; |
558 | 18 | SKIP_WHITESPACES(string); |
559 | 18 | switch (**string) { |
560 | 6 | case '{': |
561 | 6 | return parse_object_value(string, nesting + 1); |
562 | 4 | case '[': |
563 | 4 | return parse_array_value(string, nesting + 1); |
564 | 0 | case '\"': |
565 | 0 | return parse_string_value(string); |
566 | 0 | case 'f': case 't': |
567 | 0 | return parse_boolean_value(string); |
568 | 4 | case '-': |
569 | 7 | case '0': case '1': case '2': case '3': case '4': |
570 | 8 | case '5': case '6': case '7': case '8': case '9': |
571 | 8 | return parse_number_value(string); |
572 | 0 | case 'n': |
573 | 0 | return parse_null_value(string); |
574 | 0 | default: |
575 | 0 | return NULL; |
576 | 18 | } |
577 | 18 | } |
578 | | |
579 | 6 | static JSON_Value * parse_object_value(const char **string, size_t nesting) { |
580 | 6 | JSON_Value *output_value = json_value_init_object(), *new_value = NULL; |
581 | 6 | JSON_Object *output_object = json_value_get_object(output_value); |
582 | 6 | char *new_key = NULL; |
583 | 6 | if (output_value == NULL) |
584 | 0 | return NULL; |
585 | 6 | SKIP_CHAR(string); |
586 | 6 | SKIP_WHITESPACES(string); |
587 | 6 | if (**string == '}') { /* empty object */ |
588 | 0 | SKIP_CHAR(string); |
589 | 0 | return output_value; |
590 | 0 | } |
591 | 7 | while (**string != '\0') { |
592 | 7 | new_key = get_quoted_string(string); |
593 | 7 | SKIP_WHITESPACES(string); |
594 | 7 | if (new_key == NULL || **string != ':') { |
595 | 2 | json_value_free(output_value); |
596 | 2 | return NULL; |
597 | 2 | } |
598 | 5 | SKIP_CHAR(string); |
599 | 5 | new_value = parse_value(string, nesting); |
600 | 5 | if (new_value == NULL) { |
601 | 1 | parson_free(new_key); |
602 | 1 | json_value_free(output_value); |
603 | 1 | return NULL; |
604 | 1 | } |
605 | 4 | if(json_object_add(output_object, new_key, new_value) == JSONFailure) { |
606 | 0 | parson_free(new_key); |
607 | 0 | parson_free(new_value); |
608 | 0 | json_value_free(output_value); |
609 | 0 | return NULL; |
610 | 0 | } |
611 | 4 | parson_free(new_key); |
612 | 4 | SKIP_WHITESPACES(string); |
613 | 4 | if (**string != ',') |
614 | 3 | break; |
615 | 1 | SKIP_CHAR(string); |
616 | 1 | SKIP_WHITESPACES(string); |
617 | 1 | } |
618 | 3 | SKIP_WHITESPACES(string); |
619 | 3 | if (**string != '}' || /* Trim object after parsing is over */ |
620 | 3 | json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) { |
621 | 0 | json_value_free(output_value); |
622 | 0 | return NULL; |
623 | 0 | } |
624 | 3 | SKIP_CHAR(string); |
625 | 3 | return output_value; |
626 | 3 | } |
627 | | |
628 | 4 | static JSON_Value * parse_array_value(const char **string, size_t nesting) { |
629 | 4 | JSON_Value *output_value = json_value_init_array(), *new_array_value = NULL; |
630 | 4 | JSON_Array *output_array = json_value_get_array(output_value); |
631 | 4 | if (!output_value) |
632 | 0 | return NULL; |
633 | 4 | SKIP_CHAR(string); |
634 | 4 | SKIP_WHITESPACES(string); |
635 | 4 | if (**string == ']') { /* empty array */ |
636 | 0 | SKIP_CHAR(string); |
637 | 0 | return output_value; |
638 | 0 | } |
639 | 4 | while (**string != '\0') { |
640 | 4 | new_array_value = parse_value(string, nesting); |
641 | 4 | if (!new_array_value) { |
642 | 0 | json_value_free(output_value); |
643 | 0 | return NULL; |
644 | 0 | } |
645 | 4 | if(json_array_add(output_array, new_array_value) == JSONFailure) { |
646 | 0 | parson_free(new_array_value); |
647 | 0 | json_value_free(output_value); |
648 | 0 | return NULL; |
649 | 0 | } |
650 | 4 | SKIP_WHITESPACES(string); |
651 | 4 | if (**string != ',') |
652 | 4 | break; |
653 | 0 | SKIP_CHAR(string); |
654 | 0 | SKIP_WHITESPACES(string); |
655 | 0 | } |
656 | 4 | SKIP_WHITESPACES(string); |
657 | 4 | if (**string != ']' || /* Trim array after parsing is over */ |
658 | 4 | json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) { |
659 | 4 | json_value_free(output_value); |
660 | 4 | return NULL; |
661 | 4 | } |
662 | 0 | SKIP_CHAR(string); |
663 | 0 | return output_value; |
664 | 4 | } |
665 | | |
666 | 0 | static JSON_Value * parse_string_value(const char **string) { |
667 | 0 | JSON_Value *value = NULL; |
668 | 0 | char *new_string = get_quoted_string(string); |
669 | 0 | if (new_string == NULL) |
670 | 0 | return NULL; |
671 | 0 | value = json_value_init_string_no_copy(new_string); |
672 | 0 | if (value == NULL) { |
673 | 0 | parson_free(new_string); |
674 | 0 | return NULL; |
675 | 0 | } |
676 | 0 | return value; |
677 | 0 | } |
678 | | |
679 | 0 | static JSON_Value * parse_boolean_value(const char **string) { |
680 | 0 | size_t true_token_size = SIZEOF_TOKEN("true"); |
681 | 0 | size_t false_token_size = SIZEOF_TOKEN("false"); |
682 | 0 | if (strncmp("true", *string, true_token_size) == 0) { |
683 | 0 | *string += true_token_size; |
684 | 0 | return json_value_init_boolean(1); |
685 | 0 | } else if (strncmp("false", *string, false_token_size) == 0) { |
686 | 0 | *string += false_token_size; |
687 | 0 | return json_value_init_boolean(0); |
688 | 0 | } |
689 | 0 | return NULL; |
690 | 0 | } |
691 | | |
692 | 8 | static JSON_Value * parse_number_value(const char **string) { |
693 | 8 | char *end; |
694 | 8 | double number = strtod(*string, &end); |
695 | 8 | JSON_Value *output_value; |
696 | 8 | if (is_decimal(*string, end - *string)) { |
697 | 8 | *string = end; |
698 | 8 | output_value = json_value_init_number(number); |
699 | 8 | } else { |
700 | 0 | output_value = NULL; |
701 | 0 | } |
702 | 8 | return output_value; |
703 | 8 | } |
704 | | |
705 | 0 | static JSON_Value * parse_null_value(const char **string) { |
706 | 0 | size_t token_size = SIZEOF_TOKEN("null"); |
707 | 0 | if (strncmp("null", *string, token_size) == 0) { |
708 | 0 | *string += token_size; |
709 | 0 | return json_value_init_null(); |
710 | 0 | } |
711 | 0 | return NULL; |
712 | 0 | } |
713 | | |
714 | | /* Serialization */ |
715 | 0 | #define APPEND_STRING(str) do { written = append_string(buf, (str)); \ |
716 | 0 | if (written < 0) { return -1; } \ |
717 | 0 | if (buf != NULL) { buf += written; } \ |
718 | 0 | written_total += written; } while(0) |
719 | | |
720 | 0 | #define APPEND_INDENT(level) do { written = append_indent(buf, (level)); \ |
721 | 0 | if (written < 0) { return -1; } \ |
722 | 0 | if (buf != NULL) { buf += written; } \ |
723 | 0 | written_total += written; } while(0) |
724 | | |
725 | | static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) |
726 | 0 | { |
727 | 0 | const char *key = NULL, *string = NULL; |
728 | 0 | JSON_Value *temp_value = NULL; |
729 | 0 | JSON_Array *array = NULL; |
730 | 0 | JSON_Object *object = NULL; |
731 | 0 | size_t i = 0, count = 0; |
732 | 0 | double num = 0.0; |
733 | 0 | int written = -1, written_total = 0; |
734 | |
|
735 | 0 | switch (json_value_get_type(value)) { |
736 | 0 | case JSONArray: |
737 | 0 | array = json_value_get_array(value); |
738 | 0 | count = json_array_get_count(array); |
739 | 0 | APPEND_STRING("["); |
740 | 0 | if (count > 0 && is_pretty) |
741 | 0 | APPEND_STRING("\n"); |
742 | 0 | for (i = 0; i < count; i++) { |
743 | 0 | if (is_pretty) |
744 | 0 | APPEND_INDENT(level+1); |
745 | 0 | temp_value = json_array_get_value(array, i); |
746 | 0 | written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); |
747 | 0 | if (written < 0) |
748 | 0 | return -1; |
749 | 0 | if (buf != NULL) |
750 | 0 | buf += written; |
751 | 0 | written_total += written; |
752 | 0 | if (i < (count - 1)) |
753 | 0 | APPEND_STRING(","); |
754 | 0 | if (is_pretty) |
755 | 0 | APPEND_STRING("\n"); |
756 | 0 | } |
757 | 0 | if (count > 0 && is_pretty) |
758 | 0 | APPEND_INDENT(level); |
759 | 0 | APPEND_STRING("]"); |
760 | 0 | return written_total; |
761 | 0 | case JSONObject: |
762 | 0 | object = json_value_get_object(value); |
763 | 0 | count = json_object_get_count(object); |
764 | 0 | APPEND_STRING("{"); |
765 | 0 | if (count > 0 && is_pretty) |
766 | 0 | APPEND_STRING("\n"); |
767 | 0 | for (i = 0; i < count; i++) { |
768 | 0 | key = json_object_get_name(object, i); |
769 | 0 | if (is_pretty) |
770 | 0 | APPEND_INDENT(level+1); |
771 | 0 | written = json_serialize_string(key, buf); |
772 | 0 | if (written < 0) |
773 | 0 | return -1; |
774 | 0 | if (buf != NULL) |
775 | 0 | buf += written; |
776 | 0 | written_total += written; |
777 | 0 | APPEND_STRING(":"); |
778 | 0 | if (is_pretty) |
779 | 0 | APPEND_STRING(" "); |
780 | 0 | temp_value = json_object_get_value(object, key); |
781 | 0 | written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); |
782 | 0 | if (written < 0) |
783 | 0 | return -1; |
784 | 0 | if (buf != NULL) |
785 | 0 | buf += written; |
786 | 0 | written_total += written; |
787 | 0 | if (i < (count - 1)) |
788 | 0 | APPEND_STRING(","); |
789 | 0 | if (is_pretty) |
790 | 0 | APPEND_STRING("\n"); |
791 | 0 | } |
792 | 0 | if (count > 0 && is_pretty) |
793 | 0 | APPEND_INDENT(level); |
794 | 0 | APPEND_STRING("}"); |
795 | 0 | return written_total; |
796 | 0 | case JSONString: |
797 | 0 | string = json_value_get_string(value); |
798 | 0 | written = json_serialize_string(string, buf); |
799 | 0 | if (written < 0) |
800 | 0 | return -1; |
801 | 0 | if (buf != NULL) |
802 | 0 | buf += written; |
803 | 0 | written_total += written; |
804 | 0 | return written_total; |
805 | 0 | case JSONBoolean: |
806 | 0 | if (json_value_get_boolean(value)) |
807 | 0 | APPEND_STRING("true"); |
808 | 0 | else |
809 | 0 | APPEND_STRING("false"); |
810 | 0 | return written_total; |
811 | 0 | case JSONNumber: |
812 | 0 | num = json_value_get_number(value); |
813 | 0 | if (buf != NULL) |
814 | 0 | num_buf = buf; |
815 | 0 | if (num == ((double)(int)num)) /* check if num is integer */ |
816 | 0 | written = sprintf(num_buf, "%d", (int)num); |
817 | 0 | else |
818 | 0 | written = sprintf(num_buf, DOUBLE_SERIALIZATION_FORMAT, num); |
819 | 0 | if (written < 0) |
820 | 0 | return -1; |
821 | 0 | if (buf != NULL) |
822 | 0 | buf += written; |
823 | 0 | written_total += written; |
824 | 0 | return written_total; |
825 | 0 | case JSONNull: |
826 | 0 | APPEND_STRING("null"); |
827 | 0 | return written_total; |
828 | 0 | case JSONError: |
829 | 0 | return -1; |
830 | 0 | default: |
831 | 0 | return -1; |
832 | 0 | } |
833 | 0 | } |
834 | | |
835 | 0 | static int json_serialize_string(const char *string, char *buf) { |
836 | 0 | size_t i = 0, len = strlen(string); |
837 | 0 | char c = '\0'; |
838 | 0 | int written = -1, written_total = 0; |
839 | 0 | APPEND_STRING("\""); |
840 | 0 | for (i = 0; i < len; i++) { |
841 | 0 | c = string[i]; |
842 | 0 | switch (c) { |
843 | 0 | case '\"': APPEND_STRING("\\\""); break; |
844 | 0 | case '\\': APPEND_STRING("\\\\"); break; |
845 | 0 | case '\b': APPEND_STRING("\\b"); break; |
846 | 0 | case '\f': APPEND_STRING("\\f"); break; |
847 | 0 | case '\n': APPEND_STRING("\\n"); break; |
848 | 0 | case '\r': APPEND_STRING("\\r"); break; |
849 | 0 | case '\t': APPEND_STRING("\\t"); break; |
850 | 0 | default: |
851 | 0 | if (buf != NULL) { |
852 | 0 | buf[0] = c; |
853 | 0 | buf += 1; |
854 | 0 | } |
855 | 0 | written_total += 1; |
856 | 0 | break; |
857 | 0 | } |
858 | 0 | } |
859 | 0 | APPEND_STRING("\""); |
860 | 0 | return written_total; |
861 | 0 | } |
862 | | |
863 | 0 | static int append_indent(char *buf, int level) { |
864 | 0 | int i; |
865 | 0 | int written = -1, written_total = 0; |
866 | 0 | for (i = 0; i < level; i++) { |
867 | 0 | APPEND_STRING(" "); |
868 | 0 | } |
869 | 0 | return written_total; |
870 | 0 | } |
871 | | |
872 | 0 | static int append_string(char *buf, const char *string) { |
873 | 0 | if (buf == NULL) { |
874 | 0 | return (int)strlen(string); |
875 | 0 | } |
876 | 0 | return sprintf(buf, "%s", string); |
877 | 0 | } |
878 | | |
879 | | #undef APPEND_STRING |
880 | | #undef APPEND_INDENT |
881 | | |
882 | | /* Parser API */ |
883 | 0 | JSON_Value * json_parse_file(const char *filename) { |
884 | 0 | char *file_contents = read_file(filename); |
885 | 0 | JSON_Value *output_value = NULL; |
886 | 0 | if (file_contents == NULL) |
887 | 0 | return NULL; |
888 | 0 | output_value = json_parse_string(file_contents); |
889 | 0 | parson_free(file_contents); |
890 | 0 | return output_value; |
891 | 0 | } |
892 | | |
893 | 0 | JSON_Value * json_parse_file_with_comments(const char *filename) { |
894 | 0 | char *file_contents = read_file(filename); |
895 | 0 | JSON_Value *output_value = NULL; |
896 | 0 | if (file_contents == NULL) |
897 | 0 | return NULL; |
898 | 0 | output_value = json_parse_string_with_comments(file_contents); |
899 | 0 | parson_free(file_contents); |
900 | 0 | return output_value; |
901 | 0 | } |
902 | | |
903 | 11 | JSON_Value * json_parse_string(const char *string) { |
904 | 11 | if (string == NULL) |
905 | 0 | return NULL; |
906 | 11 | SKIP_WHITESPACES(&string); |
907 | 11 | if (*string != '{' && *string != '[') |
908 | 2 | return NULL; |
909 | 9 | return parse_value((const char**)&string, 0); |
910 | 11 | } |
911 | | |
912 | 0 | JSON_Value * json_parse_string_with_comments(const char *string) { |
913 | 0 | JSON_Value *result = NULL; |
914 | 0 | char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL; |
915 | 0 | string_mutable_copy = parson_strdup(string); |
916 | 0 | if (string_mutable_copy == NULL) |
917 | 0 | return NULL; |
918 | 0 | remove_comments(string_mutable_copy, "/*", "*/"); |
919 | 0 | remove_comments(string_mutable_copy, "//", "\n"); |
920 | 0 | string_mutable_copy_ptr = string_mutable_copy; |
921 | 0 | SKIP_WHITESPACES(&string_mutable_copy_ptr); |
922 | 0 | if (*string_mutable_copy_ptr != '{' && *string_mutable_copy_ptr != '[') { |
923 | 0 | parson_free(string_mutable_copy); |
924 | 0 | return NULL; |
925 | 0 | } |
926 | 0 | result = parse_value((const char**)&string_mutable_copy_ptr, 0); |
927 | 0 | parson_free(string_mutable_copy); |
928 | 0 | return result; |
929 | 0 | } |
930 | | |
931 | | |
932 | | /* JSON Object API */ |
933 | | |
934 | 55 | JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) { |
935 | 55 | if (object == NULL || name == NULL) |
936 | 0 | return NULL; |
937 | 55 | return json_object_nget_value(object, name, strlen(name)); |
938 | 55 | } |
939 | | |
940 | 33 | const char * json_object_get_string(const JSON_Object *object, const char *name) { |
941 | 33 | return json_value_get_string(json_object_get_value(object, name)); |
942 | 33 | } |
943 | | |
944 | 0 | double json_object_get_number(const JSON_Object *object, const char *name) { |
945 | 0 | return json_value_get_number(json_object_get_value(object, name)); |
946 | 0 | } |
947 | | |
948 | 6 | JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) { |
949 | 6 | return json_value_get_object(json_object_get_value(object, name)); |
950 | 6 | } |
951 | | |
952 | 12 | JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) { |
953 | 12 | return json_value_get_array(json_object_get_value(object, name)); |
954 | 12 | } |
955 | | |
956 | 0 | int json_object_get_boolean(const JSON_Object *object, const char *name) { |
957 | 0 | return json_value_get_boolean(json_object_get_value(object, name)); |
958 | 0 | } |
959 | | |
960 | 0 | JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) { |
961 | 0 | const char *dot_position = strchr(name, '.'); |
962 | 0 | if (!dot_position) |
963 | 0 | return json_object_get_value(object, name); |
964 | 0 | object = json_value_get_object(json_object_nget_value(object, name, dot_position - name)); |
965 | 0 | return json_object_dotget_value(object, dot_position + 1); |
966 | 0 | } |
967 | | |
968 | 0 | const char * json_object_dotget_string(const JSON_Object *object, const char *name) { |
969 | 0 | return json_value_get_string(json_object_dotget_value(object, name)); |
970 | 0 | } |
971 | | |
972 | 0 | double json_object_dotget_number(const JSON_Object *object, const char *name) { |
973 | 0 | return json_value_get_number(json_object_dotget_value(object, name)); |
974 | 0 | } |
975 | | |
976 | 0 | JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) { |
977 | 0 | return json_value_get_object(json_object_dotget_value(object, name)); |
978 | 0 | } |
979 | | |
980 | 0 | JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) { |
981 | 0 | return json_value_get_array(json_object_dotget_value(object, name)); |
982 | 0 | } |
983 | | |
984 | 0 | int json_object_dotget_boolean(const JSON_Object *object, const char *name) { |
985 | 0 | return json_value_get_boolean(json_object_dotget_value(object, name)); |
986 | 0 | } |
987 | | |
988 | 109 | size_t json_object_get_count(const JSON_Object *object) { |
989 | 109 | return object ? object->count : 0; |
990 | 109 | } |
991 | | |
992 | 0 | const char * json_object_get_name(const JSON_Object *object, size_t index) { |
993 | 0 | if (index >= json_object_get_count(object)) |
994 | 0 | return NULL; |
995 | 0 | return object->names[index]; |
996 | 0 | } |
997 | | |
998 | | /* JSON Array API */ |
999 | 0 | JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) { |
1000 | 0 | if (index >= json_array_get_count(array)) |
1001 | 0 | return NULL; |
1002 | 0 | return array->items[index]; |
1003 | 0 | } |
1004 | | |
1005 | 0 | const char * json_array_get_string(const JSON_Array *array, size_t index) { |
1006 | 0 | return json_value_get_string(json_array_get_value(array, index)); |
1007 | 0 | } |
1008 | | |
1009 | 0 | double json_array_get_number(const JSON_Array *array, size_t index) { |
1010 | 0 | return json_value_get_number(json_array_get_value(array, index)); |
1011 | 0 | } |
1012 | | |
1013 | 0 | JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) { |
1014 | 0 | return json_value_get_object(json_array_get_value(array, index)); |
1015 | 0 | } |
1016 | | |
1017 | 0 | JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) { |
1018 | 0 | return json_value_get_array(json_array_get_value(array, index)); |
1019 | 0 | } |
1020 | | |
1021 | 0 | int json_array_get_boolean(const JSON_Array *array, size_t index) { |
1022 | 0 | return json_value_get_boolean(json_array_get_value(array, index)); |
1023 | 0 | } |
1024 | | |
1025 | 0 | size_t json_array_get_count(const JSON_Array *array) { |
1026 | 0 | return array ? array->count : 0; |
1027 | 0 | } |
1028 | | |
1029 | | /* JSON Value API */ |
1030 | 82 | JSON_Value_Type json_value_get_type(const JSON_Value *value) { |
1031 | 82 | return value ? value->type : JSONError; |
1032 | 82 | } |
1033 | | |
1034 | 15 | JSON_Object * json_value_get_object(const JSON_Value *value) { |
1035 | 15 | return json_value_get_type(value) == JSONObject ? value->value.object : NULL; |
1036 | 15 | } |
1037 | | |
1038 | 16 | JSON_Array * json_value_get_array(const JSON_Value *value) { |
1039 | 16 | return json_value_get_type(value) == JSONArray ? value->value.array : NULL; |
1040 | 16 | } |
1041 | | |
1042 | 33 | const char * json_value_get_string(const JSON_Value *value) { |
1043 | 33 | return json_value_get_type(value) == JSONString ? value->value.string : NULL; |
1044 | 33 | } |
1045 | | |
1046 | 0 | double json_value_get_number(const JSON_Value *value) { |
1047 | 0 | return json_value_get_type(value) == JSONNumber ? value->value.number : 0; |
1048 | 0 | } |
1049 | | |
1050 | 0 | int json_value_get_boolean(const JSON_Value *value) { |
1051 | 0 | return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1; |
1052 | 0 | } |
1053 | | |
1054 | 18 | void json_value_free(JSON_Value *value) { |
1055 | 18 | switch (json_value_get_type(value)) { |
1056 | 6 | case JSONObject: |
1057 | 6 | json_object_free(value->value.object); |
1058 | 6 | break; |
1059 | 0 | case JSONString: |
1060 | 0 | if (value->value.string) { parson_free(value->value.string); } |
1061 | 0 | break; |
1062 | 4 | case JSONArray: |
1063 | 4 | json_array_free(value->value.array); |
1064 | 4 | break; |
1065 | 8 | default: |
1066 | 8 | break; |
1067 | 18 | } |
1068 | 18 | parson_free(value); |
1069 | 18 | } |
1070 | | |
1071 | 6 | JSON_Value * json_value_init_object(void) { |
1072 | 6 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
1073 | 6 | if (!new_value) |
1074 | 0 | return NULL; |
1075 | 6 | new_value->type = JSONObject; |
1076 | 6 | new_value->value.object = json_object_init(); |
1077 | 6 | if (!new_value->value.object) { |
1078 | 0 | parson_free(new_value); |
1079 | 0 | return NULL; |
1080 | 0 | } |
1081 | 6 | return new_value; |
1082 | 6 | } |
1083 | | |
1084 | 4 | JSON_Value * json_value_init_array(void) { |
1085 | 4 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
1086 | 4 | if (!new_value) |
1087 | 0 | return NULL; |
1088 | 4 | new_value->type = JSONArray; |
1089 | 4 | new_value->value.array = json_array_init(); |
1090 | 4 | if (!new_value->value.array) { |
1091 | 0 | parson_free(new_value); |
1092 | 0 | return NULL; |
1093 | 0 | } |
1094 | 4 | return new_value; |
1095 | 4 | } |
1096 | | |
1097 | 0 | JSON_Value * json_value_init_string(const char *string) { |
1098 | 0 | char *copy = NULL; |
1099 | 0 | JSON_Value *value; |
1100 | 0 | size_t string_len = 0; |
1101 | 0 | if (string == NULL) |
1102 | 0 | return NULL; |
1103 | 0 | string_len = strlen(string); |
1104 | 0 | if (!is_valid_utf8(string, string_len)) |
1105 | 0 | return NULL; |
1106 | 0 | copy = parson_strndup(string, string_len); |
1107 | 0 | if (copy == NULL) |
1108 | 0 | return NULL; |
1109 | 0 | value = json_value_init_string_no_copy(copy); |
1110 | 0 | if (value == NULL) |
1111 | 0 | parson_free(copy); |
1112 | 0 | return value; |
1113 | 0 | } |
1114 | | |
1115 | 8 | JSON_Value * json_value_init_number(double number) { |
1116 | 8 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
1117 | 8 | if (!new_value) |
1118 | 0 | return NULL; |
1119 | 8 | new_value->type = JSONNumber; |
1120 | 8 | new_value->value.number = number; |
1121 | 8 | return new_value; |
1122 | 8 | } |
1123 | | |
1124 | 0 | JSON_Value * json_value_init_boolean(int boolean) { |
1125 | 0 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
1126 | 0 | if (!new_value) |
1127 | 0 | return NULL; |
1128 | 0 | new_value->type = JSONBoolean; |
1129 | 0 | new_value->value.boolean = boolean ? 1 : 0; |
1130 | 0 | return new_value; |
1131 | 0 | } |
1132 | | |
1133 | 0 | JSON_Value * json_value_init_null(void) { |
1134 | 0 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); |
1135 | 0 | if (!new_value) |
1136 | 0 | return NULL; |
1137 | 0 | new_value->type = JSONNull; |
1138 | 0 | return new_value; |
1139 | 0 | } |
1140 | | |
1141 | 0 | JSON_Value * json_value_deep_copy(const JSON_Value *value) { |
1142 | 0 | size_t i = 0; |
1143 | 0 | JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL; |
1144 | 0 | const char *temp_string = NULL, *temp_key = NULL; |
1145 | 0 | char *temp_string_copy = NULL; |
1146 | 0 | JSON_Array *temp_array = NULL, *temp_array_copy = NULL; |
1147 | 0 | JSON_Object *temp_object = NULL, *temp_object_copy = NULL; |
1148 | |
|
1149 | 0 | switch (json_value_get_type(value)) { |
1150 | 0 | case JSONArray: |
1151 | 0 | temp_array = json_value_get_array(value); |
1152 | 0 | return_value = json_value_init_array(); |
1153 | 0 | if (return_value == NULL) |
1154 | 0 | return NULL; |
1155 | 0 | temp_array_copy = json_value_get_array(return_value); |
1156 | 0 | for (i = 0; i < json_array_get_count(temp_array); i++) { |
1157 | 0 | temp_value = json_array_get_value(temp_array, i); |
1158 | 0 | temp_value_copy = json_value_deep_copy(temp_value); |
1159 | 0 | if (temp_value_copy == NULL) { |
1160 | 0 | json_value_free(return_value); |
1161 | 0 | return NULL; |
1162 | 0 | } |
1163 | 0 | if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) { |
1164 | 0 | json_value_free(return_value); |
1165 | 0 | json_value_free(temp_value_copy); |
1166 | 0 | return NULL; |
1167 | 0 | } |
1168 | 0 | } |
1169 | 0 | return return_value; |
1170 | 0 | case JSONObject: |
1171 | 0 | temp_object = json_value_get_object(value); |
1172 | 0 | return_value = json_value_init_object(); |
1173 | 0 | if (return_value == NULL) |
1174 | 0 | return NULL; |
1175 | 0 | temp_object_copy = json_value_get_object(return_value); |
1176 | 0 | for (i = 0; i < json_object_get_count(temp_object); i++) { |
1177 | 0 | temp_key = json_object_get_name(temp_object, i); |
1178 | 0 | temp_value = json_object_get_value(temp_object, temp_key); |
1179 | 0 | temp_value_copy = json_value_deep_copy(temp_value); |
1180 | 0 | if (temp_value_copy == NULL) { |
1181 | 0 | json_value_free(return_value); |
1182 | 0 | return NULL; |
1183 | 0 | } |
1184 | 0 | if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) { |
1185 | 0 | json_value_free(return_value); |
1186 | 0 | json_value_free(temp_value_copy); |
1187 | 0 | return NULL; |
1188 | 0 | } |
1189 | 0 | } |
1190 | 0 | return return_value; |
1191 | 0 | case JSONBoolean: |
1192 | 0 | return json_value_init_boolean(json_value_get_boolean(value)); |
1193 | 0 | case JSONNumber: |
1194 | 0 | return json_value_init_number(json_value_get_number(value)); |
1195 | 0 | case JSONString: |
1196 | 0 | temp_string = json_value_get_string(value); |
1197 | 0 | temp_string_copy = parson_strdup(temp_string); |
1198 | 0 | if (temp_string_copy == NULL) |
1199 | 0 | return NULL; |
1200 | 0 | return_value = json_value_init_string_no_copy(temp_string_copy); |
1201 | 0 | if (return_value == NULL) |
1202 | 0 | parson_free(temp_string_copy); |
1203 | 0 | return return_value; |
1204 | 0 | case JSONNull: |
1205 | 0 | return json_value_init_null(); |
1206 | 0 | case JSONError: |
1207 | 0 | return NULL; |
1208 | 0 | default: |
1209 | 0 | return NULL; |
1210 | 0 | } |
1211 | 0 | } |
1212 | | |
1213 | 0 | size_t json_serialization_size(const JSON_Value *value) { |
1214 | 0 | char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
1215 | 0 | int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf); |
1216 | 0 | return res < 0 ? 0 : (size_t)(res + 1); |
1217 | 0 | } |
1218 | | |
1219 | 0 | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
1220 | 0 | int written = -1; |
1221 | 0 | size_t needed_size_in_bytes = json_serialization_size(value); |
1222 | 0 | if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { |
1223 | 0 | return JSONFailure; |
1224 | 0 | } |
1225 | 0 | written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL); |
1226 | 0 | if (written < 0) |
1227 | 0 | return JSONFailure; |
1228 | 0 | return JSONSuccess; |
1229 | 0 | } |
1230 | | |
1231 | 0 | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) { |
1232 | 0 | JSON_Status return_code = JSONSuccess; |
1233 | 0 | FILE *fp = NULL; |
1234 | 0 | char *serialized_string = json_serialize_to_string(value); |
1235 | 0 | if (serialized_string == NULL) { |
1236 | 0 | return JSONFailure; |
1237 | 0 | } |
1238 | 0 | fp = fopen (filename, "w"); |
1239 | 0 | if (fp != NULL) { |
1240 | 0 | if (fputs (serialized_string, fp) == EOF) { |
1241 | 0 | return_code = JSONFailure; |
1242 | 0 | } |
1243 | 0 | if (fclose (fp) == EOF) { |
1244 | 0 | return_code = JSONFailure; |
1245 | 0 | } |
1246 | 0 | } |
1247 | 0 | json_free_serialized_string(serialized_string); |
1248 | 0 | return return_code; |
1249 | 0 | } |
1250 | | |
1251 | 0 | char * json_serialize_to_string(const JSON_Value *value) { |
1252 | 0 | JSON_Status serialization_result = JSONFailure; |
1253 | 0 | size_t buf_size_bytes = json_serialization_size(value); |
1254 | 0 | char *buf = NULL; |
1255 | 0 | if (buf_size_bytes == 0) { |
1256 | 0 | return NULL; |
1257 | 0 | } |
1258 | 0 | buf = (char*)parson_malloc(buf_size_bytes); |
1259 | 0 | if (buf == NULL) |
1260 | 0 | return NULL; |
1261 | 0 | serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes); |
1262 | 0 | if (serialization_result == JSONFailure) { |
1263 | 0 | json_free_serialized_string(buf); |
1264 | 0 | return NULL; |
1265 | 0 | } |
1266 | 0 | return buf; |
1267 | 0 | } |
1268 | | |
1269 | 0 | size_t json_serialization_size_pretty(const JSON_Value *value) { |
1270 | 0 | char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
1271 | 0 | int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf); |
1272 | 0 | return res < 0 ? 0 : (size_t)(res + 1); |
1273 | 0 | } |
1274 | | |
1275 | 0 | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
1276 | 0 | int written = -1; |
1277 | 0 | size_t needed_size_in_bytes = json_serialization_size_pretty(value); |
1278 | 0 | if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) |
1279 | 0 | return JSONFailure; |
1280 | 0 | written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL); |
1281 | 0 | if (written < 0) |
1282 | 0 | return JSONFailure; |
1283 | 0 | return JSONSuccess; |
1284 | 0 | } |
1285 | | |
1286 | 0 | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) { |
1287 | 0 | JSON_Status return_code = JSONSuccess; |
1288 | 0 | FILE *fp = NULL; |
1289 | 0 | char *serialized_string = json_serialize_to_string_pretty(value); |
1290 | 0 | if (serialized_string == NULL) { |
1291 | 0 | return JSONFailure; |
1292 | 0 | } |
1293 | 0 | fp = fopen (filename, "w"); |
1294 | 0 | if (fp != NULL) { |
1295 | 0 | if (fputs (serialized_string, fp) == EOF) { |
1296 | 0 | return_code = JSONFailure; |
1297 | 0 | } |
1298 | 0 | if (fclose (fp) == EOF) { |
1299 | 0 | return_code = JSONFailure; |
1300 | 0 | } |
1301 | 0 | } |
1302 | 0 | json_free_serialized_string(serialized_string); |
1303 | 0 | return return_code; |
1304 | 0 | } |
1305 | | |
1306 | 0 | char * json_serialize_to_string_pretty(const JSON_Value *value) { |
1307 | 0 | JSON_Status serialization_result = JSONFailure; |
1308 | 0 | size_t buf_size_bytes = json_serialization_size_pretty(value); |
1309 | 0 | char *buf = NULL; |
1310 | 0 | if (buf_size_bytes == 0) { |
1311 | 0 | return NULL; |
1312 | 0 | } |
1313 | 0 | buf = (char*)parson_malloc(buf_size_bytes); |
1314 | 0 | if (buf == NULL) |
1315 | 0 | return NULL; |
1316 | 0 | serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes); |
1317 | 0 | if (serialization_result == JSONFailure) { |
1318 | 0 | json_free_serialized_string(buf); |
1319 | 0 | return NULL; |
1320 | 0 | } |
1321 | 0 | return buf; |
1322 | 0 | } |
1323 | | |
1324 | | |
1325 | 0 | void json_free_serialized_string(char *string) { |
1326 | 0 | parson_free(string); |
1327 | 0 | } |
1328 | | |
1329 | 0 | JSON_Status json_array_remove(JSON_Array *array, size_t ix) { |
1330 | 0 | size_t last_element_ix = 0; |
1331 | 0 | if (array == NULL || ix >= json_array_get_count(array)) { |
1332 | 0 | return JSONFailure; |
1333 | 0 | } |
1334 | 0 | last_element_ix = json_array_get_count(array) - 1; |
1335 | 0 | json_value_free(json_array_get_value(array, ix)); |
1336 | 0 | array->count -= 1; |
1337 | 0 | if (ix != last_element_ix) /* Replace value with one from the end of array */ |
1338 | 0 | array->items[ix] = json_array_get_value(array, last_element_ix); |
1339 | 0 | return JSONSuccess; |
1340 | 0 | } |
1341 | | |
1342 | 0 | JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) { |
1343 | 0 | if (array == NULL || value == NULL || ix >= json_array_get_count(array)) { |
1344 | 0 | return JSONFailure; |
1345 | 0 | } |
1346 | 0 | json_value_free(json_array_get_value(array, ix)); |
1347 | 0 | array->items[ix] = value; |
1348 | 0 | return JSONSuccess; |
1349 | 0 | } |
1350 | | |
1351 | 0 | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) { |
1352 | 0 | JSON_Value *value = json_value_init_string(string); |
1353 | 0 | if (value == NULL) |
1354 | 0 | return JSONFailure; |
1355 | 0 | if (json_array_replace_value(array, i, value) == JSONFailure) { |
1356 | 0 | json_value_free(value); |
1357 | 0 | return JSONFailure; |
1358 | 0 | } |
1359 | 0 | return JSONSuccess; |
1360 | 0 | } |
1361 | | |
1362 | 0 | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) { |
1363 | 0 | JSON_Value *value = json_value_init_number(number); |
1364 | 0 | if (value == NULL) |
1365 | 0 | return JSONFailure; |
1366 | 0 | if (json_array_replace_value(array, i, value) == JSONFailure) { |
1367 | 0 | json_value_free(value); |
1368 | 0 | return JSONFailure; |
1369 | 0 | } |
1370 | 0 | return JSONSuccess; |
1371 | 0 | } |
1372 | | |
1373 | 0 | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) { |
1374 | 0 | JSON_Value *value = json_value_init_boolean(boolean); |
1375 | 0 | if (value == NULL) |
1376 | 0 | return JSONFailure; |
1377 | 0 | if (json_array_replace_value(array, i, value) == JSONFailure) { |
1378 | 0 | json_value_free(value); |
1379 | 0 | return JSONFailure; |
1380 | 0 | } |
1381 | 0 | return JSONSuccess; |
1382 | 0 | } |
1383 | | |
1384 | 0 | JSON_Status json_array_replace_null(JSON_Array *array, size_t i) { |
1385 | 0 | JSON_Value *value = json_value_init_null(); |
1386 | 0 | if (value == NULL) |
1387 | 0 | return JSONFailure; |
1388 | 0 | if (json_array_replace_value(array, i, value) == JSONFailure) { |
1389 | 0 | json_value_free(value); |
1390 | 0 | return JSONFailure; |
1391 | 0 | } |
1392 | 0 | return JSONSuccess; |
1393 | 0 | } |
1394 | | |
1395 | 0 | JSON_Status json_array_clear(JSON_Array *array) { |
1396 | 0 | size_t i = 0; |
1397 | 0 | if (array == NULL) |
1398 | 0 | return JSONFailure; |
1399 | 0 | for (i = 0; i < json_array_get_count(array); i++) { |
1400 | 0 | json_value_free(json_array_get_value(array, i)); |
1401 | 0 | } |
1402 | 0 | array->count = 0; |
1403 | 0 | return JSONSuccess; |
1404 | 0 | } |
1405 | | |
1406 | 0 | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) { |
1407 | 0 | if (array == NULL || value == NULL) |
1408 | 0 | return JSONFailure; |
1409 | 0 | return json_array_add(array, value); |
1410 | 0 | } |
1411 | | |
1412 | 0 | JSON_Status json_array_append_string(JSON_Array *array, const char *string) { |
1413 | 0 | JSON_Value *value = json_value_init_string(string); |
1414 | 0 | if (value == NULL) |
1415 | 0 | return JSONFailure; |
1416 | 0 | if (json_array_append_value(array, value) == JSONFailure) { |
1417 | 0 | json_value_free(value); |
1418 | 0 | return JSONFailure; |
1419 | 0 | } |
1420 | 0 | return JSONSuccess; |
1421 | 0 | } |
1422 | | |
1423 | 0 | JSON_Status json_array_append_number(JSON_Array *array, double number) { |
1424 | 0 | JSON_Value *value = json_value_init_number(number); |
1425 | 0 | if (value == NULL) |
1426 | 0 | return JSONFailure; |
1427 | 0 | if (json_array_append_value(array, value) == JSONFailure) { |
1428 | 0 | json_value_free(value); |
1429 | 0 | return JSONFailure; |
1430 | 0 | } |
1431 | 0 | return JSONSuccess; |
1432 | 0 | } |
1433 | | |
1434 | 0 | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) { |
1435 | 0 | JSON_Value *value = json_value_init_boolean(boolean); |
1436 | 0 | if (value == NULL) |
1437 | 0 | return JSONFailure; |
1438 | 0 | if (json_array_append_value(array, value) == JSONFailure) { |
1439 | 0 | json_value_free(value); |
1440 | 0 | return JSONFailure; |
1441 | 0 | } |
1442 | 0 | return JSONSuccess; |
1443 | 0 | } |
1444 | | |
1445 | 0 | JSON_Status json_array_append_null(JSON_Array *array) { |
1446 | 0 | JSON_Value *value = json_value_init_null(); |
1447 | 0 | if (value == NULL) |
1448 | 0 | return JSONFailure; |
1449 | 0 | if (json_array_append_value(array, value) == JSONFailure) { |
1450 | 0 | json_value_free(value); |
1451 | 0 | return JSONFailure; |
1452 | 0 | } |
1453 | 0 | return JSONSuccess; |
1454 | 0 | } |
1455 | | |
1456 | 0 | JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) { |
1457 | 0 | size_t i = 0; |
1458 | 0 | JSON_Value *old_value; |
1459 | 0 | if (object == NULL || name == NULL || value == NULL) |
1460 | 0 | return JSONFailure; |
1461 | 0 | old_value = json_object_get_value(object, name); |
1462 | 0 | if (old_value != NULL) { /* free and overwrite old value */ |
1463 | 0 | json_value_free(old_value); |
1464 | 0 | for (i = 0; i < json_object_get_count(object); i++) { |
1465 | 0 | if (strcmp(object->names[i], name) == 0) { |
1466 | 0 | object->values[i] = value; |
1467 | 0 | return JSONSuccess; |
1468 | 0 | } |
1469 | 0 | } |
1470 | 0 | } |
1471 | | /* add new key value pair */ |
1472 | 0 | return json_object_add(object, name, value); |
1473 | 0 | } |
1474 | | |
1475 | 0 | JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) { |
1476 | 0 | return json_object_set_value(object, name, json_value_init_string(string)); |
1477 | 0 | } |
1478 | | |
1479 | 0 | JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) { |
1480 | 0 | return json_object_set_value(object, name, json_value_init_number(number)); |
1481 | 0 | } |
1482 | | |
1483 | 0 | JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) { |
1484 | 0 | return json_object_set_value(object, name, json_value_init_boolean(boolean)); |
1485 | 0 | } |
1486 | | |
1487 | 0 | JSON_Status json_object_set_null(JSON_Object *object, const char *name) { |
1488 | 0 | return json_object_set_value(object, name, json_value_init_null()); |
1489 | 0 | } |
1490 | | |
1491 | 0 | JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) { |
1492 | 0 | const char *dot_pos = NULL; |
1493 | 0 | char *current_name = NULL; |
1494 | 0 | JSON_Object *temp_obj = NULL; |
1495 | 0 | JSON_Value *new_value = NULL; |
1496 | 0 | if (value == NULL || name == NULL || value == NULL) |
1497 | 0 | return JSONFailure; |
1498 | 0 | dot_pos = strchr(name, '.'); |
1499 | 0 | if (dot_pos == NULL) { |
1500 | 0 | return json_object_set_value(object, name, value); |
1501 | 0 | } else { |
1502 | 0 | current_name = parson_strndup(name, dot_pos - name); |
1503 | 0 | temp_obj = json_object_get_object(object, current_name); |
1504 | 0 | if (temp_obj == NULL) { |
1505 | 0 | new_value = json_value_init_object(); |
1506 | 0 | if (new_value == NULL) { |
1507 | 0 | parson_free(current_name); |
1508 | 0 | return JSONFailure; |
1509 | 0 | } |
1510 | 0 | if (json_object_add(object, current_name, new_value) == JSONFailure) { |
1511 | 0 | json_value_free(new_value); |
1512 | 0 | parson_free(current_name); |
1513 | 0 | return JSONFailure; |
1514 | 0 | } |
1515 | 0 | temp_obj = json_object_get_object(object, current_name); |
1516 | 0 | } |
1517 | 0 | parson_free(current_name); |
1518 | 0 | return json_object_dotset_value(temp_obj, dot_pos + 1, value); |
1519 | 0 | } |
1520 | 0 | } |
1521 | | |
1522 | 0 | JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) { |
1523 | 0 | JSON_Value *value = json_value_init_string(string); |
1524 | 0 | if (value == NULL) |
1525 | 0 | return JSONFailure; |
1526 | 0 | if (json_object_dotset_value(object, name, value) == JSONFailure) { |
1527 | 0 | json_value_free(value); |
1528 | 0 | return JSONFailure; |
1529 | 0 | } |
1530 | 0 | return JSONSuccess; |
1531 | 0 | } |
1532 | | |
1533 | 0 | JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) { |
1534 | 0 | JSON_Value *value = json_value_init_number(number); |
1535 | 0 | if (value == NULL) |
1536 | 0 | return JSONFailure; |
1537 | 0 | if (json_object_dotset_value(object, name, value) == JSONFailure) { |
1538 | 0 | json_value_free(value); |
1539 | 0 | return JSONFailure; |
1540 | 0 | } |
1541 | 0 | return JSONSuccess; |
1542 | 0 | } |
1543 | | |
1544 | 0 | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) { |
1545 | 0 | JSON_Value *value = json_value_init_boolean(boolean); |
1546 | 0 | if (value == NULL) |
1547 | 0 | return JSONFailure; |
1548 | 0 | if (json_object_dotset_value(object, name, value) == JSONFailure) { |
1549 | 0 | json_value_free(value); |
1550 | 0 | return JSONFailure; |
1551 | 0 | } |
1552 | 0 | return JSONSuccess; |
1553 | 0 | } |
1554 | | |
1555 | 0 | JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) { |
1556 | 0 | JSON_Value *value = json_value_init_null(); |
1557 | 0 | if (value == NULL) |
1558 | 0 | return JSONFailure; |
1559 | 0 | if (json_object_dotset_value(object, name, value) == JSONFailure) { |
1560 | 0 | json_value_free(value); |
1561 | 0 | return JSONFailure; |
1562 | 0 | } |
1563 | 0 | return JSONSuccess; |
1564 | 0 | } |
1565 | | |
1566 | 0 | JSON_Status json_object_remove(JSON_Object *object, const char *name) { |
1567 | 0 | size_t i = 0, last_item_index = 0; |
1568 | 0 | if (object == NULL || json_object_get_value(object, name) == NULL) |
1569 | 0 | return JSONFailure; |
1570 | 0 | last_item_index = json_object_get_count(object) - 1; |
1571 | 0 | for (i = 0; i < json_object_get_count(object); i++) { |
1572 | 0 | if (strcmp(object->names[i], name) == 0) { |
1573 | 0 | parson_free(object->names[i]); |
1574 | 0 | json_value_free(object->values[i]); |
1575 | 0 | if (i != last_item_index) { /* Replace key value pair with one from the end */ |
1576 | 0 | object->names[i] = object->names[last_item_index]; |
1577 | 0 | object->values[i] = object->values[last_item_index]; |
1578 | 0 | } |
1579 | 0 | object->count -= 1; |
1580 | 0 | return JSONSuccess; |
1581 | 0 | } |
1582 | 0 | } |
1583 | 0 | return JSONFailure; /* No execution path should end here */ |
1584 | 0 | } |
1585 | | |
1586 | 0 | JSON_Status json_object_dotremove(JSON_Object *object, const char *name) { |
1587 | 0 | const char *dot_pos = strchr(name, '.'); |
1588 | 0 | char *current_name = NULL; |
1589 | 0 | JSON_Object *temp_obj = NULL; |
1590 | 0 | if (dot_pos == NULL) { |
1591 | 0 | return json_object_remove(object, name); |
1592 | 0 | } else { |
1593 | 0 | current_name = parson_strndup(name, dot_pos - name); |
1594 | 0 | temp_obj = json_object_get_object(object, current_name); |
1595 | 0 | if (temp_obj == NULL) { |
1596 | 0 | parson_free(current_name); |
1597 | 0 | return JSONFailure; |
1598 | 0 | } |
1599 | 0 | parson_free(current_name); |
1600 | 0 | return json_object_dotremove(temp_obj, dot_pos + 1); |
1601 | 0 | } |
1602 | 0 | } |
1603 | | |
1604 | 0 | JSON_Status json_object_clear(JSON_Object *object) { |
1605 | 0 | size_t i = 0; |
1606 | 0 | if (object == NULL) { |
1607 | 0 | return JSONFailure; |
1608 | 0 | } |
1609 | 0 | for (i = 0; i < json_object_get_count(object); i++) { |
1610 | 0 | parson_free(object->names[i]); |
1611 | 0 | json_value_free(object->values[i]); |
1612 | 0 | } |
1613 | 0 | object->count = 0; |
1614 | 0 | return JSONSuccess; |
1615 | 0 | } |
1616 | | |
1617 | 0 | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) { |
1618 | 0 | JSON_Value *temp_schema_value = NULL, *temp_value = NULL; |
1619 | 0 | JSON_Array *schema_array = NULL, *value_array = NULL; |
1620 | 0 | JSON_Object *schema_object = NULL, *value_object = NULL; |
1621 | 0 | JSON_Value_Type schema_type = JSONError, value_type = JSONError; |
1622 | 0 | const char *key = NULL; |
1623 | 0 | size_t i = 0, count = 0; |
1624 | 0 | if (schema == NULL || value == NULL) |
1625 | 0 | return JSONFailure; |
1626 | 0 | schema_type = json_value_get_type(schema); |
1627 | 0 | value_type = json_value_get_type(value); |
1628 | 0 | if (schema_type != value_type && schema_type != JSONNull) /* null represents all values */ |
1629 | 0 | return JSONFailure; |
1630 | 0 | switch (schema_type) { |
1631 | 0 | case JSONArray: |
1632 | 0 | schema_array = json_value_get_array(schema); |
1633 | 0 | value_array = json_value_get_array(value); |
1634 | 0 | count = json_array_get_count(schema_array); |
1635 | 0 | if (count == 0) |
1636 | 0 | return JSONSuccess; /* Empty array allows all types */ |
1637 | | /* Get first value from array, rest is ignored */ |
1638 | 0 | temp_schema_value = json_array_get_value(schema_array, 0); |
1639 | 0 | for (i = 0; i < json_array_get_count(value_array); i++) { |
1640 | 0 | temp_value = json_array_get_value(value_array, i); |
1641 | 0 | if (json_validate(temp_schema_value, temp_value) == 0) { |
1642 | 0 | return JSONFailure; |
1643 | 0 | } |
1644 | 0 | } |
1645 | 0 | return JSONSuccess; |
1646 | 0 | case JSONObject: |
1647 | 0 | schema_object = json_value_get_object(schema); |
1648 | 0 | value_object = json_value_get_object(value); |
1649 | 0 | count = json_object_get_count(schema_object); |
1650 | 0 | if (count == 0) |
1651 | 0 | return JSONSuccess; /* Empty object allows all objects */ |
1652 | 0 | else if (json_object_get_count(value_object) < count) |
1653 | 0 | return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */ |
1654 | 0 | for (i = 0; i < count; i++) { |
1655 | 0 | key = json_object_get_name(schema_object, i); |
1656 | 0 | temp_schema_value = json_object_get_value(schema_object, key); |
1657 | 0 | temp_value = json_object_get_value(value_object, key); |
1658 | 0 | if (temp_value == NULL) |
1659 | 0 | return JSONFailure; |
1660 | 0 | if (json_validate(temp_schema_value, temp_value) == JSONFailure) |
1661 | 0 | return JSONFailure; |
1662 | 0 | } |
1663 | 0 | return JSONSuccess; |
1664 | 0 | case JSONString: case JSONNumber: case JSONBoolean: case JSONNull: |
1665 | 0 | return JSONSuccess; /* equality already tested before switch */ |
1666 | 0 | case JSONError: default: |
1667 | 0 | return JSONFailure; |
1668 | 0 | } |
1669 | 0 | } |
1670 | | |
1671 | 0 | JSON_Status json_value_equals(const JSON_Value *a, const JSON_Value *b) { |
1672 | 0 | JSON_Object *a_object = NULL, *b_object = NULL; |
1673 | 0 | JSON_Array *a_array = NULL, *b_array = NULL; |
1674 | 0 | const char *a_string = NULL, *b_string = NULL; |
1675 | 0 | const char *key = NULL; |
1676 | 0 | size_t a_count = 0, b_count = 0, i = 0; |
1677 | 0 | JSON_Value_Type a_type, b_type; |
1678 | 0 | a_type = json_value_get_type(a); |
1679 | 0 | b_type = json_value_get_type(b); |
1680 | 0 | if (a_type != b_type) { |
1681 | 0 | return 0; |
1682 | 0 | } |
1683 | 0 | switch (a_type) { |
1684 | 0 | case JSONArray: |
1685 | 0 | a_array = json_value_get_array(a); |
1686 | 0 | b_array = json_value_get_array(b); |
1687 | 0 | a_count = json_array_get_count(a_array); |
1688 | 0 | b_count = json_array_get_count(b_array); |
1689 | 0 | if (a_count != b_count) { |
1690 | 0 | return 0; |
1691 | 0 | } |
1692 | 0 | for (i = 0; i < a_count; i++) { |
1693 | 0 | if (!json_value_equals(json_array_get_value(a_array, i), |
1694 | 0 | json_array_get_value(b_array, i))) { |
1695 | 0 | return 0; |
1696 | 0 | } |
1697 | 0 | } |
1698 | 0 | return 1; |
1699 | 0 | case JSONObject: |
1700 | 0 | a_object = json_value_get_object(a); |
1701 | 0 | b_object = json_value_get_object(b); |
1702 | 0 | a_count = json_object_get_count(a_object); |
1703 | 0 | b_count = json_object_get_count(b_object); |
1704 | 0 | if (a_count != b_count) { |
1705 | 0 | return 0; |
1706 | 0 | } |
1707 | 0 | for (i = 0; i < a_count; i++) { |
1708 | 0 | key = json_object_get_name(a_object, i); |
1709 | 0 | if (!json_value_equals(json_object_get_value(a_object, key), |
1710 | 0 | json_object_get_value(b_object, key))) { |
1711 | 0 | return 0; |
1712 | 0 | } |
1713 | 0 | } |
1714 | 0 | return 1; |
1715 | 0 | case JSONString: |
1716 | 0 | a_string = json_value_get_string(a); |
1717 | 0 | b_string = json_value_get_string(b); |
1718 | 0 | return strcmp(a_string, b_string) == 0; |
1719 | 0 | case JSONBoolean: |
1720 | 0 | return json_value_get_boolean(a) == json_value_get_boolean(b); |
1721 | 0 | case JSONNumber: |
1722 | 0 | return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */ |
1723 | 0 | case JSONError: |
1724 | 0 | return 1; |
1725 | 0 | case JSONNull: |
1726 | 0 | return 1; |
1727 | 0 | default: |
1728 | 0 | return 1; |
1729 | 0 | } |
1730 | 0 | } |
1731 | | |
1732 | 0 | JSON_Value_Type json_type(const JSON_Value *value) { |
1733 | 0 | return json_value_get_type(value); |
1734 | 0 | } |
1735 | | |
1736 | 0 | JSON_Object * json_object (const JSON_Value *value) { |
1737 | 0 | return json_value_get_object(value); |
1738 | 0 | } |
1739 | | |
1740 | 0 | JSON_Array * json_array (const JSON_Value *value) { |
1741 | 0 | return json_value_get_array(value); |
1742 | 0 | } |
1743 | | |
1744 | 0 | const char * json_string (const JSON_Value *value) { |
1745 | 0 | return json_value_get_string(value); |
1746 | 0 | } |
1747 | | |
1748 | 0 | double json_number (const JSON_Value *value) { |
1749 | 0 | return json_value_get_number(value); |
1750 | 0 | } |
1751 | | |
1752 | 0 | int json_boolean(const JSON_Value *value) { |
1753 | 0 | return json_value_get_boolean(value); |
1754 | 0 | } |
1755 | | |
1756 | 0 | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) { |
1757 | 0 | parson_malloc = malloc_fun; |
1758 | 0 | parson_free = free_fun; |
1759 | 0 | } |