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