1 /*
2 Parson ( http://kgabis.github.com/parson/ )
3 Copyright (c) 2012 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
24 #include "parson.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30
31 #define ERROR 0
32 #define SUCCESS 1
33 #define STARTING_CAPACITY 15
34 #define ARRAY_MAX_CAPACITY 122880 /* 15*(2^13) */
35 #define OBJECT_MAX_CAPACITY 960 /* 15*(2^6) */
36 #define MAX_NESTING 19
37 #define sizeof_token(a) (sizeof(a) - 1)
38 #define skip_char(str) ((*str)++)
39 #define skip_whitespaces(str) while (isspace(**string)) { skip_char(string); }
40
41 #define parson_malloc(a) malloc(a)
42 #define parson_free(a) free((void*)a)
43 #define parson_realloc(a, b) realloc(a, b)
44
45 /* Type definitions */
46 typedef union json_value_value {
47 const char *string;
48 double number;
49 JSON_Object *object;
50 JSON_Array *array;
51 int boolean;
52 int null;
53 } JSON_Value_Value;
54
55 struct json_value_t {
56 JSON_Value_Type type;
57 JSON_Value_Value value;
58 };
59
60 struct json_object_t {
61 const char **names;
62 JSON_Value **values;
63 size_t count;
64 size_t capacity;
65 };
66
67 struct json_array_t {
68 JSON_Value **items;
69 size_t count;
70 size_t capacity;
71 };
72
73 /* Various */
74 static int try_realloc(void **ptr, size_t new_size);
75 static char * parson_strndup(const char *string, size_t n);
76 static int is_utf(const char *string);
77 static int is_decimal(const char *string, size_t length);
78
79 /* JSON Object */
80 static JSON_Object * json_object_init(void);
81 static int json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
82 static int json_object_resize(JSON_Object *object, size_t capacity);
83 static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n);
84 static void json_object_free(JSON_Object *object);
85
86 /* JSON Array */
87 static JSON_Array * json_array_init(void);
88 static int json_array_add(JSON_Array *array, JSON_Value *value);
89 static int json_array_resize(JSON_Array *array, size_t capacity);
90 static void json_array_free(JSON_Array *array);
91
92 /* JSON Value */
93 static JSON_Value * json_value_init_object(void);
94 static JSON_Value * json_value_init_array(void);
95 static JSON_Value * json_value_init_string(const char *string);
96 static JSON_Value * json_value_init_number(double number);
97 static JSON_Value * json_value_init_boolean(int boolean);
98 static JSON_Value * json_value_init_null(void);
99
100 /* Parser */
101 static void skip_quotes(const char **string);
102 static const char * get_processed_string(const char **string);
103 static JSON_Value * parse_object_value(const char **string, size_t nesting);
104 static JSON_Value * parse_array_value(const char **string, size_t nesting);
105 static JSON_Value * parse_string_value(const char **string);
106 static JSON_Value * parse_boolean_value(const char **string);
107 static JSON_Value * parse_number_value(const char **string);
108 static JSON_Value * parse_null_value(const char **string);
109 static JSON_Value * parse_value(const char **string, size_t nesting);
110
111 /* Various */
try_realloc(void ** ptr,size_t new_size)112 static int try_realloc(void **ptr, size_t new_size) {
113 void *reallocated_ptr = parson_realloc(*ptr, new_size);
114 if (!reallocated_ptr) { return ERROR; }
115 *ptr = reallocated_ptr;
116 return SUCCESS;
117 }
118
parson_strndup(const char * string,size_t n)119 static char * parson_strndup(const char *string, size_t n) {
120 char *output_string = (char*)parson_malloc(n + 1);
121 if (!output_string) { return NULL; }
122 output_string[n] = '\0';
123 strncpy(output_string, string, n);
124 return output_string;
125 }
126
is_utf(const char * s)127 static int is_utf(const char *s) {
128 return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]);
129 }
130
is_decimal(const char * string,size_t length)131 static int is_decimal(const char *string, size_t length) {
132 if (length > 1 && string[0] == '0' && string[1] != '.') { return 0; }
133 if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') { return 0; }
134 while (length--) { if (strchr("xX", string[length])) { return 0; } }
135 return 1;
136 }
137
138 /* JSON Object */
json_object_init(void)139 static JSON_Object * json_object_init(void) {
140 JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
141 if (!new_obj) { return NULL; }
142 new_obj->names = (const char**)parson_malloc(sizeof(char*) * STARTING_CAPACITY);
143 if (!new_obj->names) { parson_free(new_obj); return NULL; }
144 new_obj->values = (JSON_Value**)parson_malloc(sizeof(JSON_Value*) * STARTING_CAPACITY);
145 if (!new_obj->values) { parson_free(new_obj->names); parson_free(new_obj); return NULL; }
146 new_obj->capacity = STARTING_CAPACITY;
147 new_obj->count = 0;
148 return new_obj;
149 }
150
json_object_add(JSON_Object * object,const char * name,JSON_Value * value)151 static int json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
152 size_t index;
153 if (object->count >= object->capacity) {
154 size_t new_capacity = object->capacity * 2;
155 if (new_capacity > OBJECT_MAX_CAPACITY) { return ERROR; }
156 if (json_object_resize(object, new_capacity) == ERROR) { return ERROR; }
157 }
158 if (json_object_get_value(object, name) != NULL) { return ERROR; }
159 index = object->count;
160 object->names[index] = parson_strndup(name, strlen(name));
161 if (!object->names[index]) { return ERROR; }
162 object->values[index] = value;
163 object->count++;
164 return SUCCESS;
165 }
166
json_object_resize(JSON_Object * object,size_t capacity)167 static int json_object_resize(JSON_Object *object, size_t capacity) {
168 if (try_realloc((void**)&object->names, capacity * sizeof(char*)) == ERROR) { return ERROR; }
169 if (try_realloc((void**)&object->values, capacity * sizeof(JSON_Value*)) == ERROR) { return ERROR; }
170 object->capacity = capacity;
171 return SUCCESS;
172 }
173
json_object_nget_value(const JSON_Object * object,const char * name,size_t n)174 static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) {
175 size_t i, name_length;
176 for (i = 0; i < json_object_get_count(object); i++) {
177 name_length = strlen(object->names[i]);
178 if (name_length != n) { continue; }
179 if (strncmp(object->names[i], name, n) == 0) { return object->values[i]; }
180 }
181 return NULL;
182 }
183
json_object_free(JSON_Object * object)184 static void json_object_free(JSON_Object *object) {
185 while(object->count--) {
186 parson_free(object->names[object->count]);
187 json_value_free(object->values[object->count]);
188 }
189 parson_free(object->names);
190 parson_free(object->values);
191 parson_free(object);
192 }
193
194 /* JSON Array */
json_array_init(void)195 static JSON_Array * json_array_init(void) {
196 JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
197 if (!new_array) { return NULL; }
198 new_array->items = (JSON_Value**)parson_malloc(STARTING_CAPACITY * sizeof(JSON_Value*));
199 if (!new_array->items) { parson_free(new_array); return NULL; }
200 new_array->capacity = STARTING_CAPACITY;
201 new_array->count = 0;
202 return new_array;
203 }
204
json_array_add(JSON_Array * array,JSON_Value * value)205 static int json_array_add(JSON_Array *array, JSON_Value *value) {
206 if (array->count >= array->capacity) {
207 size_t new_capacity = array->capacity * 2;
208 if (new_capacity > ARRAY_MAX_CAPACITY) { return ERROR; }
209 if (!json_array_resize(array, new_capacity)) { return ERROR; }
210 }
211 array->items[array->count] = value;
212 array->count++;
213 return SUCCESS;
214 }
215
json_array_resize(JSON_Array * array,size_t capacity)216 static int json_array_resize(JSON_Array *array, size_t capacity) {
217 if (try_realloc((void**)&array->items, capacity * sizeof(JSON_Value*)) == ERROR) { return ERROR; }
218 array->capacity = capacity;
219 return SUCCESS;
220 }
221
json_array_free(JSON_Array * array)222 static void json_array_free(JSON_Array *array) {
223 while (array->count--) { json_value_free(array->items[array->count]); }
224 parson_free(array->items);
225 parson_free(array);
226 }
227
228 /* JSON Value */
json_value_init_object(void)229 static JSON_Value * json_value_init_object(void) {
230 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
231 if (!new_value) { return NULL; }
232 new_value->type = JSONObject;
233 new_value->value.object = json_object_init();
234 if (!new_value->value.object) { parson_free(new_value); return NULL; }
235 return new_value;
236 }
237
json_value_init_array(void)238 static JSON_Value * json_value_init_array(void) {
239 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
240 if (!new_value) { return NULL; }
241 new_value->type = JSONArray;
242 new_value->value.array = json_array_init();
243 if (!new_value->value.array) { parson_free(new_value); return NULL; }
244 return new_value;
245 }
246
json_value_init_string(const char * string)247 static JSON_Value * json_value_init_string(const char *string) {
248 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
249 if (!new_value) { return NULL; }
250 new_value->type = JSONString;
251 new_value->value.string = string;
252 return new_value;
253 }
254
json_value_init_number(double number)255 static JSON_Value * json_value_init_number(double number) {
256 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
257 if (!new_value) { return NULL; }
258 new_value->type = JSONNumber;
259 new_value->value.number = number;
260 return new_value;
261 }
262
json_value_init_boolean(int boolean)263 static JSON_Value * json_value_init_boolean(int boolean) {
264 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
265 if (!new_value) { return NULL; }
266 new_value->type = JSONBoolean;
267 new_value->value.boolean = boolean;
268 return new_value;
269 }
270
json_value_init_null(void)271 static JSON_Value * json_value_init_null(void) {
272 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
273 if (!new_value) { return NULL; }
274 new_value->type = JSONNull;
275 return new_value;
276 }
277
278 /* Parser */
skip_quotes(const char ** string)279 static void skip_quotes(const char **string) {
280 skip_char(string);
281 while (**string != '\"') {
282 if (**string == '\0') { return; }
283 if (**string == '\\') { skip_char(string); if (**string == '\0') { return; }}
284 skip_char(string);
285 }
286 skip_char(string);
287 }
288
289 /* Returns contents of a string inside double quotes and parses escaped
290 characters inside.
291 Example: "\u006Corem ipsum" -> lorem ipsum */
get_processed_string(const char ** string)292 static const char * get_processed_string(const char **string) {
293 const char *string_start = *string;
294 char *output, *processed_ptr, *unprocessed_ptr, current_char;
295 unsigned int utf_val;
296 skip_quotes(string);
297 if (**string == '\0') { return NULL; }
298 output = parson_strndup(string_start + 1, *string - string_start - 2);
299 if (!output) { return NULL; }
300 processed_ptr = unprocessed_ptr = output;
301 while (*unprocessed_ptr) {
302 current_char = *unprocessed_ptr;
303 if (current_char == '\\') {
304 unprocessed_ptr++;
305 current_char = *unprocessed_ptr;
306 switch (current_char) {
307 case '\"': case '\\': case '/': break;
308 case 'b': current_char = '\b'; break;
309 case 'f': current_char = '\f'; break;
310 case 'n': current_char = '\n'; break;
311 case 'r': current_char = '\r'; break;
312 case 't': current_char = '\t'; break;
313 case 'u':
314 unprocessed_ptr++;
315 if (!is_utf(unprocessed_ptr) ||
316 sscanf(unprocessed_ptr, "%4x", &utf_val) == EOF) {
317 parson_free(output); return NULL;
318 }
319 if (utf_val < 0x80) {
320 current_char = utf_val;
321 } else if (utf_val < 0x800) {
322 *processed_ptr++ = (utf_val >> 6) | 0xC0;
323 current_char = ((utf_val | 0x80) & 0xBF);
324 } else {
325 *processed_ptr++ = (utf_val >> 12) | 0xE0;
326 *processed_ptr++ = (((utf_val >> 6) | 0x80) & 0xBF);
327 current_char = ((utf_val | 0x80) & 0xBF);
328 }
329 unprocessed_ptr += 3;
330 break;
331 default:
332 parson_free(output);
333 return NULL;
334 break;
335 }
336 } else if (iscntrl(current_char)) { /* no control characters allowed */
337 parson_free(output);
338 return NULL;
339 }
340 *processed_ptr = current_char;
341 processed_ptr++;
342 unprocessed_ptr++;
343 }
344 *processed_ptr = '\0';
345 if (try_realloc((void**)&output, strlen(output) + 1) == ERROR) { return NULL; }
346 return output;
347 }
348
parse_value(const char ** string,size_t nesting)349 static JSON_Value * parse_value(const char **string, size_t nesting) {
350 if (nesting > MAX_NESTING) { return NULL; }
351 skip_whitespaces(string);
352 switch (**string) {
353 case '{':
354 return parse_object_value(string, nesting + 1);
355 case '[':
356 return parse_array_value(string, nesting + 1);
357 case '\"':
358 return parse_string_value(string);
359 case 'f': case 't':
360 return parse_boolean_value(string);
361 case '-':
362 case '0': case '1': case '2': case '3': case '4':
363 case '5': case '6': case '7': case '8': case '9':
364 return parse_number_value(string);
365 case 'n':
366 return parse_null_value(string);
367 default:
368 return NULL;
369 }
370 }
371
parse_object_value(const char ** string,size_t nesting)372 static JSON_Value * parse_object_value(const char **string, size_t nesting) {
373 JSON_Value *output_value = json_value_init_object(), *new_value = NULL;
374 JSON_Object *output_object = json_value_get_object(output_value);
375 const char *new_key = NULL;
376 if (!output_value) { return NULL; }
377 skip_char(string);
378 skip_whitespaces(string);
379 if (**string == '}') { skip_char(string); return output_value; } /* empty object */
380 while (**string != '\0') {
381 new_key = get_processed_string(string);
382 skip_whitespaces(string);
383 if (!new_key || **string != ':') {
384 json_value_free(output_value);
385 return NULL;
386 }
387 skip_char(string);
388 new_value = parse_value(string, nesting);
389 if (!new_value) {
390 parson_free(new_key);
391 json_value_free(output_value);
392 return NULL;
393 }
394 if(!json_object_add(output_object, new_key, new_value)) {
395 parson_free(new_key);
396 parson_free(new_value);
397 json_value_free(output_value);
398 return NULL;
399 }
400 parson_free(new_key);
401 skip_whitespaces(string);
402 if (**string != ',') { break; }
403 skip_char(string);
404 skip_whitespaces(string);
405 }
406 skip_whitespaces(string);
407 if (**string != '}' || /* Trim object after parsing is over */
408 json_object_resize(output_object, json_object_get_count(output_object)) == ERROR) {
409 json_value_free(output_value);
410 return NULL;
411 }
412 skip_char(string);
413 return output_value;
414 }
415
parse_array_value(const char ** string,size_t nesting)416 static JSON_Value * parse_array_value(const char **string, size_t nesting) {
417 JSON_Value *output_value = json_value_init_array(), *new_array_value = NULL;
418 JSON_Array *output_array = json_value_get_array(output_value);
419 if (!output_value) { return NULL; }
420 skip_char(string);
421 skip_whitespaces(string);
422 if (**string == ']') { /* empty array */
423 skip_char(string);
424 return output_value;
425 }
426 while (**string != '\0') {
427 new_array_value = parse_value(string, nesting);
428 if (!new_array_value) {
429 json_value_free(output_value);
430 return NULL;
431 }
432 if(json_array_add(output_array, new_array_value) == ERROR) {
433 parson_free(new_array_value);
434 json_value_free(output_value);
435 return NULL;
436 }
437 skip_whitespaces(string);
438 if (**string != ',') { break; }
439 skip_char(string);
440 skip_whitespaces(string);
441 }
442 skip_whitespaces(string);
443 if (**string != ']' || /* Trim array after parsing is over */
444 json_array_resize(output_array, json_array_get_count(output_array)) == ERROR) {
445 json_value_free(output_value);
446 return NULL;
447 }
448 skip_char(string);
449 return output_value;
450 }
451
parse_string_value(const char ** string)452 static JSON_Value * parse_string_value(const char **string) {
453 const char *new_string = get_processed_string(string);
454 if (!new_string) { return NULL; }
455 return json_value_init_string(new_string);
456 }
457
parse_boolean_value(const char ** string)458 static JSON_Value * parse_boolean_value(const char **string) {
459 size_t true_token_size = sizeof_token("true");
460 size_t false_token_size = sizeof_token("false");
461 if (strncmp("true", *string, true_token_size) == 0) {
462 *string += true_token_size;
463 return json_value_init_boolean(1);
464 } else if (strncmp("false", *string, false_token_size) == 0) {
465 *string += false_token_size;
466 return json_value_init_boolean(0);
467 }
468 return NULL;
469 }
470
parse_number_value(const char ** string)471 static JSON_Value * parse_number_value(const char **string) {
472 char *end;
473 double number = strtod(*string, &end);
474 JSON_Value *output_value;
475 if (is_decimal(*string, end - *string)) {
476 *string = end;
477 output_value = json_value_init_number(number);
478 } else {
479 output_value = NULL;
480 }
481 return output_value;
482 }
483
parse_null_value(const char ** string)484 static JSON_Value * parse_null_value(const char **string) {
485 size_t token_size = sizeof_token("null");
486 if (strncmp("null", *string, token_size) == 0) {
487 *string += token_size;
488 return json_value_init_null();
489 }
490 return NULL;
491 }
492
493 /* Parser API */
json_parse_file(const char * filename)494 JSON_Value * json_parse_file(const char *filename) {
495 FILE *fp = fopen(filename, "r");
496 size_t file_size;
497 char *file_contents;
498 JSON_Value *output_value;
499 if (!fp) { return NULL; }
500 fseek(fp, 0L, SEEK_END);
501 file_size = ftell(fp);
502 rewind(fp);
503 file_contents = (char*)parson_malloc(sizeof(char) * (file_size + 1));
504 if (!file_contents) { fclose(fp); return NULL; }
505 if (fread(file_contents, 1, file_size, fp) != file_size) {
506 abort();
507 }
508 fclose(fp);
509 file_contents[file_size] = '\0';
510 output_value = json_parse_string(file_contents);
511 parson_free(file_contents);
512 return output_value;
513 }
514
json_parse_string(const char * string)515 JSON_Value * json_parse_string(const char *string) {
516 if (string && (*string == '{' || *string == '[')) {
517 return parse_value((const char**)&string, 0);
518 } else {
519 return NULL;
520 }
521 }
522
523 /* JSON Object API */
json_object_get_value(const JSON_Object * object,const char * name)524 JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
525 return json_object_nget_value(object, name, strlen(name));
526 }
527
json_object_get_string(const JSON_Object * object,const char * name)528 const char * json_object_get_string(const JSON_Object *object, const char *name) {
529 return json_value_get_string(json_object_get_value(object, name));
530 }
531
json_object_get_number(const JSON_Object * object,const char * name)532 double json_object_get_number(const JSON_Object *object, const char *name) {
533 return json_value_get_number(json_object_get_value(object, name));
534 }
535
json_object_get_object(const JSON_Object * object,const char * name)536 JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
537 return json_value_get_object(json_object_get_value(object, name));
538 }
539
json_object_get_array(const JSON_Object * object,const char * name)540 JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
541 return json_value_get_array(json_object_get_value(object, name));
542 }
543
json_object_get_boolean(const JSON_Object * object,const char * name)544 int json_object_get_boolean(const JSON_Object *object, const char *name) {
545 return json_value_get_boolean(json_object_get_value(object, name));
546 }
547
json_object_dotget_value(const JSON_Object * object,const char * name)548 JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
549 const char *dot_position = strchr(name, '.');
550 if (!dot_position) { return json_object_get_value(object, name); }
551 object = json_value_get_object(json_object_nget_value(object, name, dot_position - name));
552 return json_object_dotget_value(object, dot_position + 1);
553 }
554
json_object_dotget_string(const JSON_Object * object,const char * name)555 const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
556 return json_value_get_string(json_object_dotget_value(object, name));
557 }
558
json_object_dotget_number(const JSON_Object * object,const char * name)559 double json_object_dotget_number(const JSON_Object *object, const char *name) {
560 return json_value_get_number(json_object_dotget_value(object, name));
561 }
562
json_object_dotget_object(const JSON_Object * object,const char * name)563 JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
564 return json_value_get_object(json_object_dotget_value(object, name));
565 }
566
json_object_dotget_array(const JSON_Object * object,const char * name)567 JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
568 return json_value_get_array(json_object_dotget_value(object, name));
569 }
570
json_object_dotget_boolean(const JSON_Object * object,const char * name)571 int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
572 return json_value_get_boolean(json_object_dotget_value(object, name));
573 }
574
json_object_get_count(const JSON_Object * object)575 size_t json_object_get_count(const JSON_Object *object) {
576 return object ? object->count : 0;
577 }
578
json_object_get_name(const JSON_Object * object,size_t index)579 const char * json_object_get_name(const JSON_Object *object, size_t index) {
580 if (index >= json_object_get_count(object)) { return NULL; }
581 return object->names[index];
582 }
583
584 /* JSON Array API */
json_array_get_value(const JSON_Array * array,size_t index)585 JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
586 if (index >= json_array_get_count(array)) { return NULL; }
587 return array->items[index];
588 }
589
json_array_get_string(const JSON_Array * array,size_t index)590 const char * json_array_get_string(const JSON_Array *array, size_t index) {
591 return json_value_get_string(json_array_get_value(array, index));
592 }
593
json_array_get_number(const JSON_Array * array,size_t index)594 double json_array_get_number(const JSON_Array *array, size_t index) {
595 return json_value_get_number(json_array_get_value(array, index));
596 }
597
json_array_get_object(const JSON_Array * array,size_t index)598 JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
599 return json_value_get_object(json_array_get_value(array, index));
600 }
601
json_array_get_array(const JSON_Array * array,size_t index)602 JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
603 return json_value_get_array(json_array_get_value(array, index));
604 }
605
json_array_get_boolean(const JSON_Array * array,size_t index)606 int json_array_get_boolean(const JSON_Array *array, size_t index) {
607 return json_value_get_boolean(json_array_get_value(array, index));
608 }
609
json_array_get_count(const JSON_Array * array)610 size_t json_array_get_count(const JSON_Array *array) {
611 return array ? array->count : 0;
612 }
613
614 /* JSON Value API */
json_value_get_type(const JSON_Value * value)615 JSON_Value_Type json_value_get_type(const JSON_Value *value) {
616 return value ? value->type : JSONError;
617 }
618
json_value_get_object(const JSON_Value * value)619 JSON_Object * json_value_get_object(const JSON_Value *value) {
620 return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
621 }
622
json_value_get_array(const JSON_Value * value)623 JSON_Array * json_value_get_array(const JSON_Value *value) {
624 return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
625 }
626
json_value_get_string(const JSON_Value * value)627 const char * json_value_get_string(const JSON_Value *value) {
628 return json_value_get_type(value) == JSONString ? value->value.string : NULL;
629 }
630
json_value_get_number(const JSON_Value * value)631 double json_value_get_number(const JSON_Value *value) {
632 return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
633 }
634
json_value_get_boolean(const JSON_Value * value)635 int json_value_get_boolean(const JSON_Value *value) {
636 return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
637 }
638
json_value_free(JSON_Value * value)639 void json_value_free(JSON_Value *value) {
640 switch (json_value_get_type(value)) {
641 case JSONObject:
642 json_object_free(value->value.object);
643 break;
644 case JSONString:
645 if (value->value.string) { parson_free(value->value.string); }
646 break;
647 case JSONArray:
648 json_array_free(value->value.array);
649 break;
650 default:
651 break;
652 }
653 parson_free(value);
654 }
655