source: lib/parson.c @ 782a6ee

Last change on this file since 782a6ee was 782a6ee, checked in by Wilmer van der Gaast <wilmer@…>, at 2015-02-22T16:12:13Z

Remove old JSON library, replace it with Parson. No other code changes so
this won't even compile yet.

  • Property mode set to 100644
File size: 51.1 KB
Line 
1/*
2 Parson ( http://kgabis.github.com/parson/ )
3 Copyright (c) 2012 - 2014 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#define ARRAY_MAX_CAPACITY    122880 /* 15*(2^13) */
37#define OBJECT_MAX_CAPACITY      960 /* 15*(2^6)  */
38#define MAX_NESTING               19
39#define DOUBLE_SERIALIZATION_FORMAT "%f"
40
41#define SIZEOF_TOKEN(a)       (sizeof(a) - 1)
42#define SKIP_CHAR(str)        ((*str)++)
43#define SKIP_WHITESPACES(str) while (isspace(**str)) { SKIP_CHAR(str); }
44#define MAX(a, b)             ((a) > (b) ? (a) : (b))
45
46#define PARSON_MALLOC(a)     malloc(a)
47#define PARSON_FREE(a)       free((void*)(a))
48#define PARSON_REALLOC(a, b) realloc((a), (b))
49
50#define PRINT_AND_SKIP(str, to_append) str += sprintf(str, to_append);
51#define PRINTF_AND_SKIP(str, format, to_append) str += sprintf(str, format, to_append);
52
53/* Type definitions */
54typedef union json_value_value {
55    const char  *string;
56    double       number;
57    JSON_Object *object;
58    JSON_Array  *array;
59    int          boolean;
60    int          null;
61} JSON_Value_Value;
62
63struct json_value_t {
64    JSON_Value_Type     type;
65    JSON_Value_Value    value;
66};
67
68struct json_object_t {
69    const char **names;
70    JSON_Value **values;
71    size_t       count;
72    size_t       capacity;
73};
74
75struct json_array_t {
76    JSON_Value **items;
77    size_t       count;
78    size_t       capacity;
79};
80
81/* Various */
82static char * read_file(const char *filename);
83static void   remove_comments(char *string, const char *start_token, const char *end_token);
84static int    try_realloc(void **ptr, size_t new_size);
85static char * parson_strndup(const char *string, size_t n);
86static char * parson_strdup(const char *string);
87static int    is_utf(const unsigned char *string);
88static int    is_decimal(const char *string, size_t length);
89static size_t parson_strlen(const char *string);
90
91/* JSON Object */
92static JSON_Object * json_object_init(void);
93static JSON_Status   json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
94static JSON_Status   json_object_resize(JSON_Object *object, size_t capacity);
95static JSON_Value  * json_object_nget_value(const JSON_Object *object, const char *name, size_t n);
96static void          json_object_free(JSON_Object *object);
97
98/* JSON Array */
99static JSON_Array * json_array_init(void);
100static JSON_Status  json_array_add(JSON_Array *array, JSON_Value *value);
101static JSON_Status  json_array_resize(JSON_Array *array, size_t capacity);
102static void         json_array_free(JSON_Array *array);
103
104/* JSON Value */
105static JSON_Value * json_value_init_string_no_copy(const char *string);
106
107/* Parser */
108static void         skip_quotes(const char **string);
109static int          parse_utf_16(const char **unprocessed, char **processed);
110static char*        process_string(const char *input, size_t len);
111static const char * get_quoted_string(const char **string);
112static JSON_Value * parse_object_value(const char **string, size_t nesting);
113static JSON_Value * parse_array_value(const char **string, size_t nesting);
114static JSON_Value * parse_string_value(const char **string);
115static JSON_Value * parse_boolean_value(const char **string);
116static JSON_Value * parse_number_value(const char **string);
117static JSON_Value * parse_null_value(const char **string);
118static JSON_Value * parse_value(const char **string, size_t nesting);
119
120/* Serialization */
121static size_t json_serialization_size_r(const JSON_Value *value, char *buf);
122static char * json_serialize_to_buffer_r(const JSON_Value *value, char *buf);
123static char * json_serialize_string(const char *string, char *buf);
124
125/* Various */
126static int try_realloc(void **ptr, size_t new_size) {
127    void *reallocated_ptr = NULL;
128    if (new_size == 0) {
129        return JSONFailure;
130    }
131    reallocated_ptr = PARSON_REALLOC(*ptr, new_size);
132    if (reallocated_ptr == NULL) {
133        return JSONFailure;
134    }
135    *ptr = reallocated_ptr;
136    return JSONSuccess;
137}
138
139static char * parson_strndup(const char *string, size_t n) {
140    char *output_string = (char*)PARSON_MALLOC(n + 1);
141    if (!output_string)
142        return NULL;
143    output_string[n] = '\0';
144    strncpy(output_string, string, n);
145    return output_string;
146}
147
148static char * parson_strdup(const char *string) {
149    return parson_strndup(string, strlen(string));
150}
151
152static int is_utf(const unsigned char *s) {
153    return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]);
154}
155
156static int is_decimal(const char *string, size_t length) {
157    if (length > 1 && string[0] == '0' && string[1] != '.')
158        return 0;
159    if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.')
160        return 0;
161    while (length--)
162        if (strchr("xX", string[length]))
163            return 0;
164    return 1;
165}
166
167static size_t parson_strlen(const char *string) {
168    size_t result = 0;
169    size_t i = 0, len = strlen(string);
170    for (i = 0; i < len; i++) {
171        if (strchr("\"\\\b\f\n\r\t", string[i])) /* must be escaped */
172            result += 2;
173        else
174            result += 1;
175    }
176    return result;
177}
178
179static char * read_file(const char * filename) {
180    FILE *fp = fopen(filename, "r");
181    size_t file_size;
182    char *file_contents;
183    if (!fp)
184        return NULL;
185    fseek(fp, 0L, SEEK_END);
186    file_size = ftell(fp);
187    rewind(fp);
188    file_contents = (char*)PARSON_MALLOC(sizeof(char) * (file_size + 1));
189    if (!file_contents) {
190        fclose(fp);
191        return NULL;
192    }
193    if (fread(file_contents, file_size, 1, fp) < 1) {
194        if (ferror(fp)) {
195            fclose(fp);
196            PARSON_FREE(file_contents);
197            return NULL;
198        }
199    }
200    fclose(fp);
201    file_contents[file_size] = '\0';
202    return file_contents;
203}
204
205static void remove_comments(char *string, const char *start_token, const char *end_token) {
206    int in_string = 0, escaped = 0;
207    size_t i;
208    char *ptr = NULL, current_char;
209    size_t start_token_len = strlen(start_token);
210    size_t end_token_len = strlen(end_token);
211    if (start_token_len == 0 || end_token_len == 0)
212        return;
213    while ((current_char = *string) != '\0') {
214        if (current_char == '\\' && !escaped) {
215            escaped = 1;
216            string++;
217            continue;
218        } else if (current_char == '\"' && !escaped) {
219            in_string = !in_string;
220        } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
221                        for(i = 0; i < start_token_len; i++)
222                string[i] = ' ';
223                string = string + start_token_len;
224            ptr = strstr(string, end_token);
225            if (!ptr)
226                return;
227            for (i = 0; i < (ptr - string) + end_token_len; i++)
228                string[i] = ' ';
229                string = ptr + end_token_len - 1;
230        }
231        escaped = 0;
232        string++;
233    }
234}
235
236/* JSON Object */
237static JSON_Object * json_object_init(void) {
238    JSON_Object *new_obj = (JSON_Object*)PARSON_MALLOC(sizeof(JSON_Object));
239    if (!new_obj)
240        return NULL;
241    new_obj->names = (const char**)NULL;
242    new_obj->values = (JSON_Value**)NULL;
243    new_obj->capacity = 0;
244    new_obj->count = 0;
245    return new_obj;
246}
247
248static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
249    size_t index;
250    if (object->count >= object->capacity) {
251        size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
252        if (new_capacity > OBJECT_MAX_CAPACITY)
253            return JSONFailure;
254        if (json_object_resize(object, new_capacity) == JSONFailure)
255            return JSONFailure;
256    }
257    if (json_object_get_value(object, name) != NULL)
258        return JSONFailure;
259    index = object->count;
260    object->names[index] = parson_strdup(name);
261    if (!object->names[index])
262        return JSONFailure;
263    object->values[index] = value;
264    object->count++;
265    return JSONSuccess;
266}
267
268static JSON_Status json_object_resize(JSON_Object *object, size_t capacity) {
269    if (try_realloc((void**)&object->names, capacity * sizeof(char*)) == JSONFailure)
270        return JSONFailure;
271    if (try_realloc((void**)&object->values, capacity * sizeof(JSON_Value*)) == JSONFailure)
272        return JSONFailure;
273    object->capacity = capacity;
274    return JSONSuccess;
275}
276
277static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) {
278    size_t i, name_length;
279    for (i = 0; i < json_object_get_count(object); i++) {
280        name_length = strlen(object->names[i]);
281        if (name_length != n)
282            continue;
283        if (strncmp(object->names[i], name, n) == 0)
284            return object->values[i];
285    }
286    return NULL;
287}
288
289static void json_object_free(JSON_Object *object) {
290    while(object->count--) {
291        PARSON_FREE(object->names[object->count]);
292        json_value_free(object->values[object->count]);
293    }
294    PARSON_FREE(object->names);
295    PARSON_FREE(object->values);
296    PARSON_FREE(object);
297}
298
299/* JSON Array */
300static JSON_Array * json_array_init(void) {
301    JSON_Array *new_array = (JSON_Array*)PARSON_MALLOC(sizeof(JSON_Array));
302    if (!new_array)
303        return NULL;
304    new_array->items = (JSON_Value**)NULL;
305    new_array->capacity = 0;
306    new_array->count = 0;
307    return new_array;
308}
309
310static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
311    if (array->count >= array->capacity) {
312        size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
313        if (new_capacity > ARRAY_MAX_CAPACITY)
314            return JSONFailure;
315        if (json_array_resize(array, new_capacity) == JSONFailure)
316            return JSONFailure;
317    }
318    array->items[array->count] = value;
319    array->count++;
320    return JSONSuccess;
321}
322
323static JSON_Status json_array_resize(JSON_Array *array, size_t capacity) {
324    if (try_realloc((void**)&array->items, capacity * sizeof(JSON_Value*)) == JSONFailure)
325        return JSONFailure;
326    array->capacity = capacity;
327    return JSONSuccess;
328}
329
330static void json_array_free(JSON_Array *array) {
331    while (array->count--)
332        json_value_free(array->items[array->count]);
333    PARSON_FREE(array->items);
334    PARSON_FREE(array);
335}
336
337/* JSON Value */
338static JSON_Value * json_value_init_string_no_copy(const char *string) {
339    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
340    if (!new_value)
341        return NULL;
342    new_value->type = JSONString;
343    new_value->value.string = string;
344    return new_value;
345}
346
347/* Parser */
348static void skip_quotes(const char **string) {
349    SKIP_CHAR(string);
350    while (**string != '\"') {
351        if (**string == '\0')
352            return;
353        if (**string == '\\') {
354            SKIP_CHAR(string);
355            if (**string == '\0')
356                return;
357        }
358        SKIP_CHAR(string);
359    }
360    SKIP_CHAR(string);
361}
362
363static int parse_utf_16(const char **unprocessed, char **processed) {
364    unsigned int cp, lead, trail;
365    char *processed_ptr = *processed;
366    const char *unprocessed_ptr = *unprocessed;
367    unprocessed_ptr++; /* skips u */
368    if (!is_utf((const unsigned char*)unprocessed_ptr) || sscanf(unprocessed_ptr, "%4x", &cp) == EOF)
369            return JSONFailure;
370    if (cp < 0x80) {
371        *processed_ptr = cp; /* 0xxxxxxx */
372    } else if (cp < 0x800) {
373        *processed_ptr++ = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
374        *processed_ptr   = ((cp     ) & 0x3F) | 0x80; /* 10xxxxxx */
375    } else if (cp < 0xD800 || cp > 0xDFFF) {
376        *processed_ptr++ = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
377        *processed_ptr++ = ((cp >> 6)  & 0x3F) | 0x80; /* 10xxxxxx */
378        *processed_ptr   = ((cp     )  & 0x3F) | 0x80; /* 10xxxxxx */
379    } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
380        lead = cp;
381        unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
382        if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u' || /* starts with \u? */
383            !is_utf((const unsigned char*)unprocessed_ptr)          ||
384            sscanf(unprocessed_ptr, "%4x", &trail) == EOF           ||
385            trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
386                return JSONFailure;
387        }
388        cp = ((((lead-0xD800)&0x3FF)<<10)|((trail-0xDC00)&0x3FF))+0x010000;
389        *processed_ptr++ = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
390        *processed_ptr++ = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
391        *processed_ptr++ = (((cp >> 6)  & 0x3F) | 0x80); /* 10xxxxxx */
392        *processed_ptr   = (((cp     )  & 0x3F) | 0x80); /* 10xxxxxx */
393    } else { /* trail surrogate before lead surrogate */
394        return JSONFailure;
395    }
396    unprocessed_ptr += 3;
397    *processed = processed_ptr;
398    *unprocessed = unprocessed_ptr;
399    return JSONSuccess;
400}
401
402
403/* Copies and processes passed string up to supplied length.
404Example: "\u006Corem ipsum" -> lorem ipsum */
405static char* process_string(const char *input, size_t len) {
406    const char *input_ptr = input;
407    char *output = (char*)PARSON_MALLOC((len + 1) * sizeof(char));
408    char *output_ptr = output;
409    while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
410        if (*input_ptr == '\\') {
411            input_ptr++;
412            switch (*input_ptr) {
413                case '\"': *output_ptr = '\"'; break;
414                case '\\': *output_ptr = '\\'; break;
415                case '/':  *output_ptr = '/';  break;
416                case 'b':  *output_ptr = '\b'; break;
417                case 'f':  *output_ptr = '\f'; break;
418                case 'n':  *output_ptr = '\n'; break;
419                case 'r':  *output_ptr = '\r'; break;
420                case 't':  *output_ptr = '\t'; break;
421                case 'u':
422                    if (parse_utf_16(&input_ptr, &output_ptr) == JSONFailure)
423                        goto error;
424                    break;
425                default:
426                    goto error;
427            }
428        } else if ((unsigned char)*input_ptr < 0x20) {
429            goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
430        } else {
431            *output_ptr = *input_ptr;
432        }
433        output_ptr++;
434        input_ptr++;
435    }
436    *output_ptr = '\0';
437    if (try_realloc((void**)&output, strlen(output) + 1) == JSONFailure)
438        goto error;
439    return output;
440error:
441    free(output);
442    return NULL;
443}
444
445/* Return processed contents of a string between quotes and
446   skips passed argument to a matching quote. */
447static const char * get_quoted_string(const char **string) {
448    const char *string_start = *string;
449    size_t string_len = 0;
450    skip_quotes(string);
451    if (**string == '\0')
452        return NULL;
453    string_len = *string - string_start - 2; /* length without quotes */
454    return process_string(string_start + 1, string_len);
455}
456
457static JSON_Value * parse_value(const char **string, size_t nesting) {
458    if (nesting > MAX_NESTING)
459        return NULL;
460    SKIP_WHITESPACES(string);
461    switch (**string) {
462        case '{':
463            return parse_object_value(string, nesting + 1);
464        case '[':
465            return parse_array_value(string, nesting + 1);
466        case '\"':
467            return parse_string_value(string);
468        case 'f': case 't':
469            return parse_boolean_value(string);
470        case '-':
471        case '0': case '1': case '2': case '3': case '4':
472        case '5': case '6': case '7': case '8': case '9':
473            return parse_number_value(string);
474        case 'n':
475            return parse_null_value(string);
476        default:
477            return NULL;
478    }
479}
480
481static JSON_Value * parse_object_value(const char **string, size_t nesting) {
482    JSON_Value *output_value = json_value_init_object(), *new_value = NULL;
483    JSON_Object *output_object = json_value_get_object(output_value);
484    const char *new_key = NULL;
485    if (output_value == NULL)
486        return NULL;
487    SKIP_CHAR(string);
488    SKIP_WHITESPACES(string);
489    if (**string == '}') { /* empty object */
490        SKIP_CHAR(string);
491        return output_value;
492    }
493    while (**string != '\0') {
494        new_key = get_quoted_string(string);
495        SKIP_WHITESPACES(string);
496        if (new_key == NULL || **string != ':') {
497            json_value_free(output_value);
498            return NULL;
499        }
500        SKIP_CHAR(string);
501        new_value = parse_value(string, nesting);
502        if (new_value == NULL) {
503            PARSON_FREE(new_key);
504            json_value_free(output_value);
505            return NULL;
506        }
507        if(json_object_add(output_object, new_key, new_value) == JSONFailure) {
508            PARSON_FREE(new_key);
509            PARSON_FREE(new_value);
510            json_value_free(output_value);
511            return NULL;
512        }
513        PARSON_FREE(new_key);
514        SKIP_WHITESPACES(string);
515        if (**string != ',')
516            break;
517        SKIP_CHAR(string);
518        SKIP_WHITESPACES(string);
519    }
520    SKIP_WHITESPACES(string);
521    if (**string != '}' || /* Trim object after parsing is over */
522        json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) {
523            json_value_free(output_value);
524            return NULL;
525    }
526    SKIP_CHAR(string);
527    return output_value;
528}
529
530static JSON_Value * parse_array_value(const char **string, size_t nesting) {
531    JSON_Value *output_value = json_value_init_array(), *new_array_value = NULL;
532    JSON_Array *output_array = json_value_get_array(output_value);
533    if (!output_value)
534        return NULL;
535    SKIP_CHAR(string);
536    SKIP_WHITESPACES(string);
537    if (**string == ']') { /* empty array */
538        SKIP_CHAR(string);
539        return output_value;
540    }
541    while (**string != '\0') {
542        new_array_value = parse_value(string, nesting);
543        if (!new_array_value) {
544            json_value_free(output_value);
545            return NULL;
546        }
547        if(json_array_add(output_array, new_array_value) == JSONFailure) {
548            PARSON_FREE(new_array_value);
549            json_value_free(output_value);
550            return NULL;
551        }
552        SKIP_WHITESPACES(string);
553        if (**string != ',')
554            break;
555        SKIP_CHAR(string);
556        SKIP_WHITESPACES(string);
557    }
558    SKIP_WHITESPACES(string);
559    if (**string != ']' || /* Trim array after parsing is over */
560        json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) {
561            json_value_free(output_value);
562            return NULL;
563    }
564    SKIP_CHAR(string);
565    return output_value;
566}
567
568static JSON_Value * parse_string_value(const char **string) {
569    const char *new_string = get_quoted_string(string);
570    if (!new_string)
571        return NULL;
572    return json_value_init_string_no_copy(new_string);
573}
574
575static JSON_Value * parse_boolean_value(const char **string) {
576    size_t true_token_size = SIZEOF_TOKEN("true");
577    size_t false_token_size = SIZEOF_TOKEN("false");
578    if (strncmp("true", *string, true_token_size) == 0) {
579        *string += true_token_size;
580        return json_value_init_boolean(1);
581    } else if (strncmp("false", *string, false_token_size) == 0) {
582        *string += false_token_size;
583        return json_value_init_boolean(0);
584    }
585    return NULL;
586}
587
588static JSON_Value * parse_number_value(const char **string) {
589    char *end;
590    double number = strtod(*string, &end);
591    JSON_Value *output_value;
592    if (is_decimal(*string, end - *string)) {
593        *string = end;
594        output_value = json_value_init_number(number);
595    } else {
596        output_value = NULL;
597    }
598    return output_value;
599}
600
601static JSON_Value * parse_null_value(const char **string) {
602    size_t token_size = SIZEOF_TOKEN("null");
603    if (strncmp("null", *string, token_size) == 0) {
604        *string += token_size;
605        return json_value_init_null();
606    }
607    return NULL;
608}
609
610/* Serialization */
611static size_t json_serialization_size_r(const JSON_Value *value, char *buf) {
612    size_t result_size = 0;
613    const char *key = NULL;
614    JSON_Value *temp_value = NULL;
615    JSON_Array *array = NULL;
616    JSON_Object *object = NULL;
617    size_t i = 0, count = 0;
618    double num = 0.0;
619    switch (json_value_get_type(value)) {
620        case JSONArray:
621            array = json_value_get_array(value);
622            count = json_array_get_count(array);
623            result_size += 2; /* [ and ] brackets */
624            if (count > 0)
625                result_size += count - 1; /* , between items */
626            for (i = 0; i < count; i++) {
627                temp_value = json_array_get_value(array, i);
628                result_size += json_serialization_size_r(temp_value, buf);
629            }
630            return result_size;
631        case JSONObject:
632            object = json_value_get_object(value);
633            count  = json_object_get_count(object);
634            result_size += 2; /* { and } brackets */
635            if (count > 0)
636                result_size += (count * 2) - 1; /* : between keys and values and , between items */
637            for (i = 0; i < count; i++) {
638                key = json_object_get_name(object, i);
639                result_size += parson_strlen(key) + 2; /* string and quotes */
640                result_size += json_serialization_size_r(json_object_get_value(object, key), buf);
641            }
642            return result_size;
643        case JSONString:
644            return parson_strlen(json_value_get_string(value)) + 2; /* string and quotes */
645        case JSONBoolean:
646            if (json_value_get_boolean(value))
647                return 4; /* strlen("true"); */
648            else
649                return 5; /* strlen("false"); */
650        case JSONNumber:
651            num = json_value_get_number(value);
652            if (num == ((double)(int)num) ) /*  check if num is integer */
653                return (size_t)sprintf(buf, "%d", (int)num);
654            return (size_t)sprintf(buf, DOUBLE_SERIALIZATION_FORMAT, num);
655        case JSONNull:
656            return 4; /* strlen("null"); */
657        case JSONError:
658            return 0;
659        default:
660            return 0;
661    }
662}
663
664char* json_serialize_to_buffer_r(const JSON_Value *value, char *buf)
665{
666    const char *key = NULL, *string = NULL;
667    JSON_Value *temp_value = NULL;
668    JSON_Array *array = NULL;
669    JSON_Object *object = NULL;
670    size_t i = 0, count = 0;
671    double num = 0.0;
672    switch (json_value_get_type(value)) {
673        case JSONArray:
674            array = json_value_get_array(value);
675            count = json_array_get_count(array);
676            PRINT_AND_SKIP(buf, "[");
677            for (i = 0; i < count; i++) {
678                temp_value = json_array_get_value(array, i);
679                buf = json_serialize_to_buffer_r(temp_value, buf);
680                if (i < (count - 1))
681                    PRINT_AND_SKIP(buf, ",");
682            }
683            PRINT_AND_SKIP(buf, "]");
684            return buf;
685        case JSONObject:
686            object = json_value_get_object(value);
687            count  = json_object_get_count(object);
688            PRINT_AND_SKIP(buf, "{");
689            for (i = 0; i < count; i++) {
690                key = json_object_get_name(object, i);
691                buf = json_serialize_string(key, buf);
692                PRINT_AND_SKIP(buf, ":");
693                temp_value = json_object_get_value(object, key);
694                buf = json_serialize_to_buffer_r(temp_value, buf);
695                if (i < (count - 1))
696                    PRINT_AND_SKIP(buf, ",");
697            }
698            PRINT_AND_SKIP(buf, "}");
699            return buf;
700        case JSONString:
701            string = json_value_get_string(value);
702            buf = json_serialize_string(string, buf);
703            return buf;
704        case JSONBoolean:
705            if (json_value_get_boolean(value)) {
706                PRINT_AND_SKIP(buf, "true");
707            } else {
708                PRINT_AND_SKIP(buf, "false");
709            }
710            return buf;
711        case JSONNumber:
712            num = json_value_get_number(value);
713            if (num == ((double)(int)num)) { /*  check if num is integer */
714                PRINTF_AND_SKIP(buf, "%d", (int)num);
715            } else {
716                PRINTF_AND_SKIP(buf, DOUBLE_SERIALIZATION_FORMAT, num);
717            }
718            return buf;
719        case JSONNull:
720            PRINT_AND_SKIP(buf, "null");
721            return buf;
722        case JSONError:
723            return NULL;
724        default:
725            return NULL;
726    }
727}
728
729static char * json_serialize_string(const char *string, char *buf) {
730    size_t i = 0, len = strlen(string);
731    char c = '\0';
732    PRINT_AND_SKIP(buf, "\"")
733    for (i = 0; i < len; i++) {
734        c = string[i];
735        switch (c) {
736            case '\"': PRINT_AND_SKIP(buf, "\\\"");   break;
737            case '\\': PRINT_AND_SKIP(buf, "\\\\");   break;
738            case '\b': PRINT_AND_SKIP(buf, "\\b");    break;
739            case '\f': PRINT_AND_SKIP(buf, "\\f");    break;
740            case '\n': PRINT_AND_SKIP(buf, "\\n");    break;
741            case '\r': PRINT_AND_SKIP(buf, "\\r");    break;
742            case '\t': PRINT_AND_SKIP(buf, "\\t");    break;
743            default:   PRINTF_AND_SKIP(buf, "%c", c); break;
744        }
745    }
746    PRINT_AND_SKIP(buf, "\"");
747    return buf;
748}
749
750/* Parser API */
751JSON_Value * json_parse_file(const char *filename) {
752    char *file_contents = read_file(filename);
753    JSON_Value *output_value = NULL;
754    if (!file_contents)
755        return NULL;
756    output_value = json_parse_string(file_contents);
757    PARSON_FREE(file_contents);
758    return output_value;
759}
760
761JSON_Value * json_parse_file_with_comments(const char *filename) {
762    char *file_contents = read_file(filename);
763    JSON_Value *output_value = NULL;
764    if (!file_contents)
765        return NULL;
766    output_value = json_parse_string_with_comments(file_contents);
767    PARSON_FREE(file_contents);
768    return output_value;
769}
770
771JSON_Value * json_parse_string(const char *string) {
772    if (!string)
773        return NULL;
774    SKIP_WHITESPACES(&string);
775    if (*string != '{' && *string != '[')
776        return NULL;
777    return parse_value((const char**)&string, 0);
778}
779
780JSON_Value * json_parse_string_with_comments(const char *string) {
781    JSON_Value *result = NULL;
782    char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
783    string_mutable_copy = parson_strdup(string);
784    if (!string_mutable_copy)
785        return NULL;
786    remove_comments(string_mutable_copy, "/*", "*/");
787    remove_comments(string_mutable_copy, "//", "\n");
788    string_mutable_copy_ptr = string_mutable_copy;
789    SKIP_WHITESPACES(&string_mutable_copy_ptr);
790    if (*string_mutable_copy_ptr != '{' && *string_mutable_copy_ptr != '[') {
791        PARSON_FREE(string_mutable_copy);
792        return NULL;
793    }
794    result = parse_value((const char**)&string_mutable_copy_ptr, 0);
795    PARSON_FREE(string_mutable_copy);
796    return result;
797}
798
799
800/* JSON Object API */
801
802JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
803    return json_object_nget_value(object, name, strlen(name));
804}
805
806const char * json_object_get_string(const JSON_Object *object, const char *name) {
807    return json_value_get_string(json_object_get_value(object, name));
808}
809
810double json_object_get_number(const JSON_Object *object, const char *name) {
811    return json_value_get_number(json_object_get_value(object, name));
812}
813
814JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
815    return json_value_get_object(json_object_get_value(object, name));
816}
817
818JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
819    return json_value_get_array(json_object_get_value(object, name));
820}
821
822int json_object_get_boolean(const JSON_Object *object, const char *name) {
823    return json_value_get_boolean(json_object_get_value(object, name));
824}
825
826JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
827    const char *dot_position = strchr(name, '.');
828    if (!dot_position)
829        return json_object_get_value(object, name);
830    object = json_value_get_object(json_object_nget_value(object, name, dot_position - name));
831    return json_object_dotget_value(object, dot_position + 1);
832}
833
834const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
835    return json_value_get_string(json_object_dotget_value(object, name));
836}
837
838double json_object_dotget_number(const JSON_Object *object, const char *name) {
839    return json_value_get_number(json_object_dotget_value(object, name));
840}
841
842JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
843    return json_value_get_object(json_object_dotget_value(object, name));
844}
845
846JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
847    return json_value_get_array(json_object_dotget_value(object, name));
848}
849
850int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
851    return json_value_get_boolean(json_object_dotget_value(object, name));
852}
853
854size_t json_object_get_count(const JSON_Object *object) {
855    return object ? object->count : 0;
856}
857
858const char * json_object_get_name(const JSON_Object *object, size_t index) {
859    if (index >= json_object_get_count(object))
860        return NULL;
861    return object->names[index];
862}
863
864/* JSON Array API */
865JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
866    if (index >= json_array_get_count(array))
867        return NULL;
868    return array->items[index];
869}
870
871const char * json_array_get_string(const JSON_Array *array, size_t index) {
872    return json_value_get_string(json_array_get_value(array, index));
873}
874
875double json_array_get_number(const JSON_Array *array, size_t index) {
876    return json_value_get_number(json_array_get_value(array, index));
877}
878
879JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
880    return json_value_get_object(json_array_get_value(array, index));
881}
882
883JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
884    return json_value_get_array(json_array_get_value(array, index));
885}
886
887int json_array_get_boolean(const JSON_Array *array, size_t index) {
888    return json_value_get_boolean(json_array_get_value(array, index));
889}
890
891size_t json_array_get_count(const JSON_Array *array) {
892    return array ? array->count : 0;
893}
894
895/* JSON Value API */
896JSON_Value_Type json_value_get_type(const JSON_Value *value) {
897    return value ? value->type : JSONError;
898}
899
900JSON_Object * json_value_get_object(const JSON_Value *value) {
901    return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
902}
903
904JSON_Array * json_value_get_array(const JSON_Value *value) {
905    return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
906}
907
908const char * json_value_get_string(const JSON_Value *value) {
909    return json_value_get_type(value) == JSONString ? value->value.string : NULL;
910}
911
912double json_value_get_number(const JSON_Value *value) {
913    return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
914}
915
916int json_value_get_boolean(const JSON_Value *value) {
917    return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
918}
919
920void json_value_free(JSON_Value *value) {
921    switch (json_value_get_type(value)) {
922        case JSONObject:
923            json_object_free(value->value.object);
924            break;
925        case JSONString:
926            if (value->value.string) { PARSON_FREE(value->value.string); }
927            break;
928        case JSONArray:
929            json_array_free(value->value.array);
930            break;
931        default:
932            break;
933    }
934    PARSON_FREE(value);
935}
936
937JSON_Value * json_value_init_object(void) {
938    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
939    if (!new_value)
940        return NULL;
941    new_value->type = JSONObject;
942    new_value->value.object = json_object_init();
943    if (!new_value->value.object) {
944        PARSON_FREE(new_value);
945        return NULL;
946    }
947    return new_value;
948}
949
950JSON_Value * json_value_init_array(void) {
951    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
952    if (!new_value)
953        return NULL;
954    new_value->type = JSONArray;
955    new_value->value.array = json_array_init();
956    if (!new_value->value.array) {
957        PARSON_FREE(new_value);
958        return NULL;
959    }
960    return new_value;
961}
962
963JSON_Value * json_value_init_string(const char *string) {
964    char *processed_copy = process_string(string, strlen(string));
965    if (processed_copy == NULL)
966        return NULL;
967    return json_value_init_string_no_copy(processed_copy);
968}
969
970JSON_Value * json_value_init_number(double number) {
971    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
972    if (!new_value)
973        return NULL;
974    new_value->type = JSONNumber;
975    new_value->value.number = number;
976    return new_value;
977}
978
979JSON_Value * json_value_init_boolean(int boolean) {
980    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
981    if (!new_value)
982        return NULL;
983    new_value->type = JSONBoolean;
984    new_value->value.boolean = boolean ? 1 : 0;
985    return new_value;
986}
987
988JSON_Value * json_value_init_null(void) {
989    JSON_Value *new_value = (JSON_Value*)PARSON_MALLOC(sizeof(JSON_Value));
990    if (!new_value)
991        return NULL;
992    new_value->type = JSONNull;
993    return new_value;
994}
995
996JSON_Value * json_value_deep_copy(const JSON_Value *value) {
997    size_t i = 0;
998    JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
999    const char *temp_string = NULL, *temp_string_copy = NULL, *temp_key = NULL;
1000    JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
1001    JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
1002   
1003    switch (json_value_get_type(value)) {
1004        case JSONArray:
1005            temp_array = json_value_get_array(value);
1006            return_value = json_value_init_array();
1007            if (return_value == NULL)
1008                return NULL;
1009            temp_array_copy = json_value_get_array(return_value);
1010            for (i = 0; i < json_array_get_count(temp_array); i++) {
1011                temp_value = json_array_get_value(temp_array, i);
1012                temp_value_copy = json_value_deep_copy(temp_value);
1013                if (temp_value_copy == NULL) {
1014                    json_value_free(return_value);
1015                    return NULL;
1016                }
1017                if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) {
1018                    json_value_free(return_value);
1019                    json_value_free(temp_value_copy);
1020                    return NULL;
1021                }
1022            }
1023            return return_value;
1024        case JSONObject:
1025            temp_object = json_value_get_object(value);
1026            return_value = json_value_init_object();
1027            if (return_value == NULL)
1028                return NULL;
1029            temp_object_copy = json_value_get_object(return_value);
1030            for (i = 0; i < json_object_get_count(temp_object); i++) {
1031                temp_key = json_object_get_name(temp_object, i);
1032                temp_value = json_object_get_value(temp_object, temp_key);
1033                temp_value_copy = json_value_deep_copy(temp_value);
1034                if (temp_value_copy == NULL) {
1035                    json_value_free(return_value);
1036                    return NULL;
1037                }
1038                if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) {
1039                    json_value_free(return_value);
1040                    json_value_free(temp_value_copy);
1041                    return NULL;
1042                }
1043            }
1044            return return_value;
1045        case JSONBoolean:
1046            return json_value_init_boolean(json_value_get_boolean(value));
1047        case JSONNumber:
1048            return json_value_init_number(json_value_get_number(value));
1049        case JSONString:
1050            temp_string = json_value_get_string(value);
1051            temp_string_copy = parson_strdup(temp_string);
1052            if (temp_string_copy == NULL)
1053                return NULL;
1054            return json_value_init_string_no_copy(temp_string_copy);
1055        case JSONNull:
1056            return json_value_init_null();
1057        case JSONError:
1058            return NULL;
1059        default:
1060            return NULL;
1061    }
1062}
1063
1064size_t json_serialization_size(const JSON_Value *value) {
1065    char buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
1066    return json_serialization_size_r(value, buf) + 1;
1067}
1068
1069JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
1070    char *serialization_result = NULL;
1071    size_t needed_size_in_bytes = json_serialization_size(value);
1072    if (buf_size_in_bytes < needed_size_in_bytes) {
1073        return JSONFailure;
1074    }
1075    serialization_result = json_serialize_to_buffer_r(value, buf);
1076    if(serialization_result == NULL)
1077        return JSONFailure;
1078    return JSONSuccess;
1079}
1080
1081JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) {
1082    JSON_Status return_code = JSONSuccess;
1083    FILE *fp = NULL;
1084    char *serialized_string = json_serialize_to_string(value);
1085    if (serialized_string == NULL) {
1086        return JSONFailure;
1087    }
1088    fp = fopen (filename, "w");
1089    if (fp != NULL) {
1090        if (fputs (serialized_string, fp) == EOF) {
1091            return_code = JSONFailure;
1092        }
1093        if (fclose (fp) == EOF) {
1094            return_code = JSONFailure;
1095        }
1096    }
1097    json_free_serialized_string(serialized_string);
1098    return return_code;
1099}
1100
1101char * json_serialize_to_string(const JSON_Value *value) {
1102    JSON_Status serialization_result = JSONFailure;
1103    size_t buf_size_bytes = json_serialization_size(value);
1104    char *buf = (char*)PARSON_MALLOC(buf_size_bytes);
1105    if (buf == NULL)
1106        return NULL;
1107    serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes);
1108    if (serialization_result == JSONFailure) {
1109        json_free_serialized_string(buf);
1110        return NULL;
1111    }
1112    return buf;
1113}
1114
1115void json_free_serialized_string(char *string) {
1116    PARSON_FREE(string);
1117}
1118
1119JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
1120    size_t last_element_ix = 0;
1121    if (array == NULL || ix >= json_array_get_count(array)) {
1122        return JSONFailure;
1123    }
1124    last_element_ix = json_array_get_count(array) - 1;
1125    json_value_free(json_array_get_value(array, ix));
1126    array->count -= 1;
1127    if (ix != last_element_ix) /* Replace value with one from the end of array */
1128        array->items[ix] = json_array_get_value(array, last_element_ix);
1129    return JSONSuccess;
1130}
1131
1132JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) {
1133    if (array == NULL || value == NULL || ix >= json_array_get_count(array)) {
1134        return JSONFailure;
1135    }
1136    json_value_free(json_array_get_value(array, ix));
1137    array->items[ix] = value;
1138    return JSONSuccess;
1139}
1140
1141JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) {
1142    return json_array_replace_value(array, i, json_value_init_string(string));
1143}
1144
1145JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
1146    return json_array_replace_value(array, i, json_value_init_number(number));
1147}
1148
1149JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) {
1150    return json_array_replace_value(array, i, json_value_init_boolean(boolean));
1151}
1152
1153JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
1154    return json_array_replace_value(array, i, json_value_init_null());
1155}
1156
1157JSON_Status json_array_clear(JSON_Array *array) {
1158    size_t i = 0;
1159    if (array == NULL)
1160        return JSONFailure;
1161    for (i = 0; i < json_array_get_count(array); i++) {
1162        json_value_free(json_array_get_value(array, i));
1163    }
1164    array->count = 0;
1165    return JSONSuccess;
1166}
1167
1168JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
1169    if (array == NULL || value == NULL)
1170        return JSONFailure;
1171    return json_array_add(array, value);
1172}
1173
1174JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
1175    return json_array_append_value(array, json_value_init_string(string));
1176}
1177
1178JSON_Status json_array_append_number(JSON_Array *array, double number) {
1179    return json_array_append_value(array, json_value_init_number(number));
1180}
1181
1182JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
1183    return json_array_append_value(array, json_value_init_boolean(boolean));
1184}
1185
1186JSON_Status json_array_append_null(JSON_Array *array) {
1187    return json_array_append_value(array, json_value_init_null());
1188}
1189
1190JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) {
1191    size_t i = 0;
1192    JSON_Value *old_value;
1193    if (object == NULL)
1194        return JSONFailure;
1195    old_value = json_object_get_value(object, name);
1196    if (old_value != NULL) { /* free and overwrite old value */
1197        json_value_free(old_value);
1198        for (i = 0; i < json_object_get_count(object); i++) {
1199            if (strcmp(object->names[i], name) == 0) {
1200                object->values[i] = value;
1201                return JSONSuccess;
1202            }
1203        }
1204    }
1205    json_object_add(object, name, value); /* add new key value pair */
1206    return JSONSuccess;
1207}
1208
1209JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) {
1210    return json_object_set_value(object, name, json_value_init_string(string));
1211}
1212
1213JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
1214    return json_object_set_value(object, name, json_value_init_number(number));
1215}
1216
1217JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) {
1218    return json_object_set_value(object, name, json_value_init_boolean(boolean));
1219}
1220
1221JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
1222    return json_object_set_value(object, name, json_value_init_null());
1223}
1224
1225JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) {
1226    const char *dot_pos = strchr(name, '.');
1227    const char *current_name = NULL;
1228    JSON_Object *temp_obj = NULL;
1229    JSON_Value *new_value = NULL;
1230    if (value == NULL) {
1231        return JSONFailure;
1232    } else if (dot_pos == NULL) {
1233        return json_object_set_value(object, name, value);
1234    } else {
1235        current_name = parson_strndup(name, dot_pos - name);
1236        temp_obj = json_object_get_object(object, current_name);
1237        if (temp_obj == NULL) {
1238            new_value = json_value_init_object();
1239            if (new_value == NULL) {
1240                PARSON_FREE(current_name);
1241                return JSONFailure;
1242            }
1243            if (json_object_add(object, current_name, new_value) == JSONFailure) {
1244                json_value_free(new_value);
1245                PARSON_FREE(current_name);
1246                return JSONFailure;
1247            }
1248            temp_obj = json_object_get_object(object, current_name);
1249        }
1250        PARSON_FREE(current_name);
1251        return json_object_dotset_value(temp_obj, dot_pos + 1, value);
1252    }
1253    return JSONFailure;
1254}
1255
1256JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) {
1257    return json_object_dotset_value(object, name, json_value_init_string(string));
1258}
1259
1260JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
1261    return json_object_dotset_value(object, name, json_value_init_number(number));
1262}
1263
1264JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) {
1265    return json_object_dotset_value(object, name, json_value_init_boolean(boolean));
1266}
1267
1268JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) {
1269    return json_object_dotset_value(object, name, json_value_init_null());
1270}
1271
1272JSON_Status json_object_remove(JSON_Object *object, const char *name) {
1273    size_t i = 0, last_item_index = 0;
1274    if (object == NULL || json_object_get_value(object, name) == NULL)
1275        return JSONFailure;
1276    last_item_index = json_object_get_count(object) - 1;
1277    for (i = 0; i < json_object_get_count(object); i++) {
1278        if (strcmp(object->names[i], name) == 0) {
1279            PARSON_FREE(object->names[i]);
1280            json_value_free(object->values[i]);
1281            if (i != last_item_index) { /* Replace key value pair with one from the end */
1282                object->names[i] = object->names[last_item_index];
1283                object->values[i] = object->values[last_item_index];
1284            }
1285            object->count -= 1;
1286            return JSONSuccess;
1287        }
1288    }
1289    return JSONFailure; /* No execution path should end here */
1290}
1291
1292JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
1293    const char *dot_pos = strchr(name, '.');
1294    const char *current_name = NULL;
1295    JSON_Object *temp_obj = NULL;
1296    if (dot_pos == NULL) {
1297        return json_object_remove(object, name);
1298    } else {
1299        current_name = parson_strndup(name, dot_pos - name);
1300        temp_obj = json_object_get_object(object, current_name);
1301        if (temp_obj == NULL) {
1302            PARSON_FREE(current_name);
1303            return JSONFailure;
1304        }
1305        PARSON_FREE(current_name);
1306        return json_object_dotremove(temp_obj, dot_pos + 1);
1307    }
1308    return JSONFailure;
1309}
1310
1311JSON_Status json_object_clear(JSON_Object *object) {
1312    size_t i = 0;
1313    if (object == NULL) {
1314        return JSONFailure;
1315    }
1316    for (i = 0; i < json_object_get_count(object); i++) {       
1317        PARSON_FREE(object->names[i]);
1318        json_value_free(object->values[i]);
1319    }
1320    object->count = 0;
1321    return JSONSuccess;
1322}
1323
1324JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
1325    JSON_Value *temp_schema_value = NULL, *temp_value = NULL;
1326    JSON_Array *schema_array = NULL, *value_array = NULL;
1327    JSON_Object *schema_object = NULL, *value_object = NULL;
1328    JSON_Value_Type schema_type = JSONError, value_type = JSONError;
1329    const char *key = NULL;
1330    size_t i = 0, count = 0;
1331    if (schema == NULL || value == NULL)
1332        return JSONFailure;
1333    schema_type = json_value_get_type(schema);
1334    value_type = json_value_get_type(value);
1335    if (schema_type != value_type && schema_type != JSONNull) /* null represents all values */
1336        return JSONFailure;
1337    switch (schema_type) {
1338        case JSONArray:
1339            schema_array = json_value_get_array(schema);
1340            value_array = json_value_get_array(value);
1341            count = json_array_get_count(schema_array);
1342            if (count == 0)
1343                return JSONSuccess; /* Empty array allows all types */
1344            /* Get first value from array, rest is ignored */
1345            temp_schema_value = json_array_get_value(schema_array, 0);
1346            for (i = 0; i < json_array_get_count(value_array); i++) {
1347                temp_value = json_array_get_value(value_array, i);
1348                if (json_validate(temp_schema_value, temp_value) == 0) {
1349                    return JSONFailure;
1350                }
1351            }
1352            return JSONSuccess;
1353        case JSONObject:
1354            schema_object = json_value_get_object(schema);
1355            value_object = json_value_get_object(value);
1356            count = json_object_get_count(schema_object);
1357            if (count == 0)
1358                return JSONSuccess; /* Empty object allows all objects */
1359            else if (json_object_get_count(value_object) < count)
1360                return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */
1361            for (i = 0; i < count; i++) {
1362                key = json_object_get_name(schema_object, i);
1363                temp_schema_value = json_object_get_value(schema_object, key);
1364                temp_value = json_object_get_value(value_object, key);
1365                if (temp_value == NULL)
1366                    return JSONFailure;
1367                if (json_validate(temp_schema_value, temp_value) == JSONFailure)
1368                    return JSONFailure;
1369            }
1370            return JSONSuccess;
1371        case JSONString: case JSONNumber: case JSONBoolean: case JSONNull:
1372            return JSONSuccess; /* equality already tested before switch */
1373        case JSONError: default:
1374            return JSONFailure;
1375    }
1376}
1377
1378JSON_Status json_value_equals(const JSON_Value *a, const JSON_Value *b) {
1379    JSON_Object *a_object = NULL, *b_object = NULL;
1380    JSON_Array *a_array = NULL, *b_array = NULL;
1381    const char *a_string = NULL, *b_string = NULL;
1382    const char *key = NULL;
1383    size_t a_count = 0, b_count = 0, i = 0;
1384    JSON_Value_Type a_type, b_type;
1385    a_type = json_value_get_type(a);
1386    b_type = json_value_get_type(b);
1387    if (a_type != b_type) {
1388        return 0;
1389    }
1390    switch (a_type) {
1391        case JSONArray:
1392            a_array = json_value_get_array(a);
1393            b_array = json_value_get_array(b);
1394            a_count = json_array_get_count(a_array);
1395            b_count = json_array_get_count(b_array);
1396            if (a_count != b_count) {
1397                return 0;
1398            }
1399            for (i = 0; i < a_count; i++) {
1400                if (!json_value_equals(json_array_get_value(a_array, i),
1401                                       json_array_get_value(b_array, i))) {
1402                    return 0;
1403                }
1404            }
1405            return 1;
1406        case JSONObject:
1407            a_object = json_value_get_object(a);
1408            b_object = json_value_get_object(b);
1409            a_count = json_object_get_count(a_object);
1410            b_count = json_object_get_count(b_object);
1411            if (a_count != b_count) {
1412                return 0;
1413            }
1414            for (i = 0; i < a_count; i++) {
1415                key = json_object_get_name(a_object, i);
1416                if (!json_value_equals(json_object_get_value(a_object, key),
1417                                       json_object_get_value(b_object, key))) {
1418                    return 0;
1419                }
1420            }
1421            return 1;
1422        case JSONString:
1423            a_string = json_value_get_string(a);
1424            b_string = json_value_get_string(b);
1425            return strcmp(a_string, b_string) == 0;
1426        case JSONBoolean:
1427            return json_value_get_boolean(a) == json_value_get_boolean(b);
1428        case JSONNumber:
1429            return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */
1430        case JSONError:
1431            return 1;
1432        case JSONNull:
1433            return 1;
1434        default:
1435            return 1;
1436    }
1437}
1438
1439JSON_Value_Type json_type(const JSON_Value *value) {
1440    return json_value_get_type(value);
1441}
1442
1443JSON_Object * json_object (const JSON_Value *value) {
1444    return json_value_get_object(value);
1445}
1446
1447JSON_Array * json_array  (const JSON_Value *value) {
1448    return json_value_get_array(value);
1449}
1450
1451const char * json_string (const JSON_Value *value) {
1452    return json_value_get_string(value);
1453}
1454
1455double json_number (const JSON_Value *value) {
1456    return json_value_get_number(value);
1457}
1458
1459int json_boolean(const JSON_Value *value) {
1460    return json_value_get_boolean(value);
1461}
Note: See TracBrowser for help on using the repository browser.