Back to home page

Enduro/X

 
 

    


0001 /*
0002  Exparson
0003  based on parson ( http://kgabis.github.com/parson/ )
0004  Copyright (c) 2012 - 2017 Krzysztof Gabis
0005 
0006  Permission is hereby granted, free of charge, to any person obtaining a copy
0007  of this software and associated documentation files (the "Software"), to deal
0008  in the Software without restriction, including without limitation the rights
0009  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0010  copies of the Software, and to permit persons to whom the Software is
0011  furnished to do so, subject to the following conditions:
0012 
0013  The above copyright notice and this permission notice shall be included in
0014  all copies or substantial portions of the Software.
0015 
0016  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0017  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0018  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0019  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0020  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0021  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
0022  THE SOFTWARE.
0023 */
0024 #ifdef _MSC_VER
0025 #ifndef _CRT_SECURE_NO_WARNINGS
0026 #define _CRT_SECURE_NO_WARNINGS
0027 #endif /* _CRT_SECURE_NO_WARNINGS */
0028 #endif /* _MSC_VER */
0029 
0030 #include "exparson.h"
0031 
0032 #include <stdio.h>
0033 #include <stdlib.h>
0034 #include <string.h>
0035 #include <ctype.h>
0036 #include <math.h>
0037 #include <errno.h>
0038 #include <ubf_int.h>
0039 
0040 /* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you
0041  * don't have to. */
0042 #define sscanf THINK_TWICE_ABOUT_USING_SSCANF
0043 
0044 #define STARTING_CAPACITY 16
0045 #define MAX_NESTING       2048
0046 #define FLOAT_FORMAT      "%1.17g"
0047 
0048 #define SIZEOF_TOKEN(a)       (sizeof(a) - 1)
0049 #define SKIP_CHAR(str)        ((*str)++)
0050 #define SKIP_WHITESPACES(str) while (isspace(**str)) { SKIP_CHAR(str); }
0051 #define MAX(a, b)             ((a) > (b) ? (a) : (b))
0052 
0053 #undef malloc
0054 #undef free
0055 
0056 static EXJSON_Malloc_Function exparson_malloc = malloc;
0057 static EXJSON_Free_Function exparson_free = free;
0058 
0059 #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
0060 
0061 /* Type definitions */
0062 typedef union exjson_value_value {
0063     char        *string;
0064     double       number;
0065     EXJSON_Object *object;
0066     EXJSON_Array  *array;
0067     int          boolean;
0068     int          null;
0069 } EXJSON_Value_Value;
0070 
0071 struct exjson_value_t {
0072     EXJSON_Value      *parent;
0073     EXJSON_Value_Type  type;
0074     EXJSON_Value_Value value;
0075 };
0076 
0077 struct exjson_object_t {
0078     EXJSON_Value  *wrapping_value;
0079     char       **names;
0080     EXJSON_Value **values;
0081     size_t       count;
0082     size_t       capacity;
0083 };
0084 
0085 struct exjson_array_t {
0086     EXJSON_Value  *wrapping_value;
0087     EXJSON_Value **items;
0088     size_t       count;
0089     size_t       capacity;
0090 };
0091 
0092 /* Various */
0093 static char * read_file(const char *filename);
0094 static void   remove_comments(char *string, const char *start_token, const char *end_token);
0095 static char * exparson_strndup(const char *string, size_t n);
0096 static char * exparson_strdup(const char *string);
0097 static int    hex_char_to_int(char c);
0098 static int    parse_utf16_hex(const char *string, unsigned int *result);
0099 static int    num_bytes_in_utf8_sequence(unsigned char c);
0100 static int    verify_utf8_sequence(const unsigned char *string, int *len);
0101 static int    is_valid_utf8(const char *string, size_t string_len);
0102 static int    is_decimal(const char *string, size_t length);
0103 
0104 /* EXJSON Object */
0105 static EXJSON_Object * exjson_object_init(EXJSON_Value *wrapping_value);
0106 static EXJSON_Status   exjson_object_add(EXJSON_Object *object, const char *name, EXJSON_Value *value);
0107 static EXJSON_Status   exjson_object_resize(EXJSON_Object *object, size_t new_capacity);
0108 static EXJSON_Value  * exjson_object_nget_value(const EXJSON_Object *object, const char *name, size_t n);
0109 static void          exjson_object_free(EXJSON_Object *object);
0110 
0111 /* EXJSON Array */
0112 static EXJSON_Array * exjson_array_init(EXJSON_Value *wrapping_value);
0113 static EXJSON_Status  exjson_array_add(EXJSON_Array *array, EXJSON_Value *value);
0114 static EXJSON_Status  exjson_array_resize(EXJSON_Array *array, size_t new_capacity);
0115 static void         exjson_array_free(EXJSON_Array *array);
0116 
0117 /* EXJSON Value */
0118 static EXJSON_Value * exjson_value_init_string_no_copy(char *string);
0119 
0120 /* Parser */
0121 static EXJSON_Status  skip_quotes(const char **string);
0122 static int          parse_utf16(const char **unprocessed, char **processed);
0123 static char *       process_string(const char *input, size_t len);
0124 static char *       get_quoted_string(const char **string);
0125 static EXJSON_Value * parse_object_value(const char **string, size_t nesting);
0126 static EXJSON_Value * parse_array_value(const char **string, size_t nesting);
0127 static EXJSON_Value * parse_string_value(const char **string);
0128 static EXJSON_Value * parse_boolean_value(const char **string);
0129 static EXJSON_Value * parse_number_value(const char **string);
0130 static EXJSON_Value * parse_null_value(const char **string);
0131 static EXJSON_Value * parse_value(const char **string, size_t nesting);
0132 
0133 /* Serialization */
0134 static int    exjson_serialize_to_buffer_r(const EXJSON_Value *value, char *buf, int level, int is_pretty, char *num_buf);
0135 static int    exjson_serialize_string(const char *string, char *buf);
0136 static int    append_indent(char *buf, int level);
0137 static int    append_string(char *buf, const char *string);
0138 
0139 /* Various */
0140 static char * exparson_strndup(const char *string, size_t n) {
0141     char *output_string = (char*)exparson_malloc(n + 1);
0142     if (!output_string) {
0143         return NULL;
0144     }
0145     output_string[n] = '\0';
0146     strncpy(output_string, string, n);
0147     return output_string;
0148 }
0149 
0150 static char * exparson_strdup(const char *string) {
0151     return exparson_strndup(string, strlen(string));
0152 }
0153 
0154 static int hex_char_to_int(char c) {
0155     if (c >= '0' && c <= '9') {
0156         return c - '0';
0157     } else if (c >= 'a' && c <= 'f') {
0158         return c - 'a' + 10;
0159     } else if (c >= 'A' && c <= 'F') {
0160         return c - 'A' + 10;
0161     }
0162     return -1;
0163 }
0164 
0165 static int parse_utf16_hex(const char *s, unsigned int *result) {
0166     int x1, x2, x3, x4;
0167     if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') {
0168         return 0;
0169     }
0170     x1 = hex_char_to_int(s[0]);
0171     x2 = hex_char_to_int(s[1]);
0172     x3 = hex_char_to_int(s[2]);
0173     x4 = hex_char_to_int(s[3]);
0174     if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) {
0175         return 0;
0176     }
0177     *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4);
0178     return 1;
0179 }
0180 
0181 static int num_bytes_in_utf8_sequence(unsigned char c) {
0182     if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
0183         return 0;
0184     } else if ((c & 0x80) == 0) {    /* 0xxxxxxx */
0185         return 1;
0186     } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
0187         return 2;
0188     } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
0189         return 3;
0190     } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
0191         return 4;
0192     }
0193     return 0; /* won't happen */
0194 }
0195 
0196 static int verify_utf8_sequence(const unsigned char *string, int *len) {
0197     unsigned int cp = 0;
0198     *len = num_bytes_in_utf8_sequence(string[0]);
0199 
0200     if (*len == 1) {
0201         cp = string[0];
0202     } else if (*len == 2 && IS_CONT(string[1])) {
0203         cp = string[0] & 0x1F;
0204         cp = (cp << 6) | (string[1] & 0x3F);
0205     } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
0206         cp = ((unsigned char)string[0]) & 0xF;
0207         cp = (cp << 6) | (string[1] & 0x3F);
0208         cp = (cp << 6) | (string[2] & 0x3F);
0209     } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
0210         cp = string[0] & 0x7;
0211         cp = (cp << 6) | (string[1] & 0x3F);
0212         cp = (cp << 6) | (string[2] & 0x3F);
0213         cp = (cp << 6) | (string[3] & 0x3F);
0214     } else {
0215         return 0;
0216     }
0217 
0218     /* overlong encodings */
0219     if ((cp < 0x80    && *len > 1) ||
0220         (cp < 0x800   && *len > 2) ||
0221         (cp < 0x10000 && *len > 3)) {
0222         return 0;
0223     }
0224 
0225     /* invalid unicode */
0226     if (cp > 0x10FFFF) {
0227         return 0;
0228     }
0229 
0230     /* surrogate halves */
0231     if (cp >= 0xD800 && cp <= 0xDFFF) {
0232         return 0;
0233     }
0234 
0235     return 1;
0236 }
0237 
0238 static int is_valid_utf8(const char *string, size_t string_len) {
0239     int len = 0;
0240     const char *string_end =  string + string_len;
0241     while (string < string_end) {
0242         if (!verify_utf8_sequence((const unsigned char*)string, &len)) {
0243             return 0;
0244         }
0245         string += len;
0246     }
0247     return 1;
0248 }
0249 
0250 static int is_decimal(const char *string, size_t length) {
0251     if (length > 1 && string[0] == '0' && string[1] != '.') {
0252         return 0;
0253     }
0254     if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
0255         return 0;
0256     }
0257     while (length--) {
0258         if (strchr("xX", string[length])) {
0259             return 0;
0260         }
0261     }
0262     return 1;
0263 }
0264 
0265 static char * read_file(const char * filename) {
0266     FILE *fp = fopen(filename, "r");
0267     size_t file_size;
0268     long pos;
0269     char *file_contents;
0270     if (!fp) {
0271         return NULL;
0272     }
0273     fseek(fp, 0L, SEEK_END);
0274     pos = ftell(fp);
0275     if (pos < 0) {
0276         fclose(fp);
0277         return NULL;
0278     }
0279     file_size = pos;
0280     rewind(fp);
0281     file_contents = (char*)exparson_malloc(sizeof(char) * (file_size + 1));
0282     if (!file_contents) {
0283         fclose(fp);
0284         return NULL;
0285     }
0286     if (fread(file_contents, file_size, 1, fp) < 1) {
0287         if (ferror(fp)) {
0288             fclose(fp);
0289             exparson_free(file_contents);
0290             return NULL;
0291         }
0292     }
0293     fclose(fp);
0294     file_contents[file_size] = '\0';
0295     return file_contents;
0296 }
0297 
0298 static void remove_comments(char *string, const char *start_token, const char *end_token) {
0299     int in_string = 0, escaped = 0;
0300     size_t i;
0301     char *ptr = NULL, current_char;
0302     size_t start_token_len = strlen(start_token);
0303     size_t end_token_len = strlen(end_token);
0304     if (start_token_len == 0 || end_token_len == 0) {
0305         return;
0306     }
0307     while ((current_char = *string) != '\0') {
0308         if (current_char == '\\' && !escaped) {
0309             escaped = 1;
0310             string++;
0311             continue;
0312         } else if (current_char == '\"' && !escaped) {
0313             in_string = !in_string;
0314         } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
0315             for(i = 0; i < start_token_len; i++) {
0316                 string[i] = ' ';
0317             }
0318             string = string + start_token_len;
0319             ptr = strstr(string, end_token);
0320             if (!ptr) {
0321                 return;
0322             }
0323             for (i = 0; i < (ptr - string) + end_token_len; i++) {
0324                 string[i] = ' ';
0325             }
0326             string = ptr + end_token_len - 1;
0327         }
0328         escaped = 0;
0329         string++;
0330     }
0331 }
0332 
0333 /* EXJSON Object */
0334 static EXJSON_Object * exjson_object_init(EXJSON_Value *wrapping_value) {
0335     EXJSON_Object *new_obj = (EXJSON_Object*)exparson_malloc(sizeof(EXJSON_Object));
0336     if (new_obj == NULL) {
0337         return NULL;
0338     }
0339     new_obj->wrapping_value = wrapping_value;
0340     new_obj->names = (char**)NULL;
0341     new_obj->values = (EXJSON_Value**)NULL;
0342     new_obj->capacity = 0;
0343     new_obj->count = 0;
0344     return new_obj;
0345 }
0346 
0347 static EXJSON_Status exjson_object_add(EXJSON_Object *object, const char *name, EXJSON_Value *value) {
0348     size_t index = 0;
0349     if (object == NULL || name == NULL || value == NULL) {
0350         return EXJSONFailure;
0351     }
0352     if (exjson_object_get_value(object, name) != NULL) {
0353         return EXJSONFailure;
0354     }
0355     if (object->count >= object->capacity) {
0356         size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
0357         if (exjson_object_resize(object, new_capacity) == EXJSONFailure) {
0358             return EXJSONFailure;
0359         }
0360     }
0361     index = object->count;
0362     object->names[index] = exparson_strdup(name);
0363     if (object->names[index] == NULL) {
0364         return EXJSONFailure;
0365     }
0366     value->parent = exjson_object_get_wrapping_value(object);
0367     object->values[index] = value;
0368     object->count++;
0369     return EXJSONSuccess;
0370 }
0371 
0372 static EXJSON_Status exjson_object_resize(EXJSON_Object *object, size_t new_capacity) {
0373     char **temp_names = NULL;
0374     EXJSON_Value **temp_values = NULL;
0375 
0376     if ((object->names == NULL && object->values != NULL) ||
0377         (object->names != NULL && object->values == NULL) ||
0378         new_capacity == 0) {
0379             return EXJSONFailure; /* Shouldn't happen */
0380     }
0381     temp_names = (char**)exparson_malloc(new_capacity * sizeof(char*));
0382     if (temp_names == NULL) {
0383         return EXJSONFailure;
0384     }
0385     temp_values = (EXJSON_Value**)exparson_malloc(new_capacity * sizeof(EXJSON_Value*));
0386     if (temp_values == NULL) {
0387         exparson_free(temp_names);
0388         return EXJSONFailure;
0389     }
0390     if (object->names != NULL && object->values != NULL && object->count > 0) {
0391         memcpy(temp_names, object->names, object->count * sizeof(char*));
0392         memcpy(temp_values, object->values, object->count * sizeof(EXJSON_Value*));
0393     }
0394     exparson_free(object->names);
0395     exparson_free(object->values);
0396     object->names = temp_names;
0397     object->values = temp_values;
0398     object->capacity = new_capacity;
0399     return EXJSONSuccess;
0400 }
0401 
0402 static EXJSON_Value * exjson_object_nget_value(const EXJSON_Object *object, const char *name, size_t n) {
0403     size_t i, name_length;
0404     for (i = 0; i < exjson_object_get_count(object); i++) {
0405         name_length = strlen(object->names[i]);
0406         if (name_length != n) {
0407             continue;
0408         }
0409         if (strncmp(object->names[i], name, n) == 0) {
0410             return object->values[i];
0411         }
0412     }
0413     return NULL;
0414 }
0415 
0416 static void exjson_object_free(EXJSON_Object *object) {
0417     size_t i;
0418     for (i = 0; i < object->count; i++) {
0419         exparson_free(object->names[i]);
0420         exjson_value_free(object->values[i]);
0421     }
0422     exparson_free(object->names);
0423     exparson_free(object->values);
0424     exparson_free(object);
0425 }
0426 
0427 /* EXJSON Array */
0428 static EXJSON_Array * exjson_array_init(EXJSON_Value *wrapping_value) {
0429     EXJSON_Array *new_array = (EXJSON_Array*)exparson_malloc(sizeof(EXJSON_Array));
0430     if (new_array == NULL) {
0431         return NULL;
0432     }
0433     new_array->wrapping_value = wrapping_value;
0434     new_array->items = (EXJSON_Value**)NULL;
0435     new_array->capacity = 0;
0436     new_array->count = 0;
0437     return new_array;
0438 }
0439 
0440 static EXJSON_Status exjson_array_add(EXJSON_Array *array, EXJSON_Value *value) {
0441     if (array->count >= array->capacity) {
0442         size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
0443         if (exjson_array_resize(array, new_capacity) == EXJSONFailure) {
0444             return EXJSONFailure;
0445         }
0446     }
0447     value->parent = exjson_array_get_wrapping_value(array);
0448     array->items[array->count] = value;
0449     array->count++;
0450     return EXJSONSuccess;
0451 }
0452 
0453 static EXJSON_Status exjson_array_resize(EXJSON_Array *array, size_t new_capacity) {
0454     EXJSON_Value **new_items = NULL;
0455     if (new_capacity == 0) {
0456         return EXJSONFailure;
0457     }
0458     new_items = (EXJSON_Value**)exparson_malloc(new_capacity * sizeof(EXJSON_Value*));
0459     if (new_items == NULL) {
0460         return EXJSONFailure;
0461     }
0462     if (array->items != NULL && array->count > 0) {
0463         memcpy(new_items, array->items, array->count * sizeof(EXJSON_Value*));
0464     }
0465     exparson_free(array->items);
0466     array->items = new_items;
0467     array->capacity = new_capacity;
0468     return EXJSONSuccess;
0469 }
0470 
0471 static void exjson_array_free(EXJSON_Array *array) {
0472     size_t i;
0473     for (i = 0; i < array->count; i++) {
0474         exjson_value_free(array->items[i]);
0475     }
0476     exparson_free(array->items);
0477     exparson_free(array);
0478 }
0479 
0480 /* EXJSON Value */
0481 static EXJSON_Value * exjson_value_init_string_no_copy(char *string) {
0482     EXJSON_Value *new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
0483     if (!new_value) {
0484         return NULL;
0485     }
0486     new_value->parent = NULL;
0487     new_value->type = EXJSONString;
0488     new_value->value.string = string;
0489     return new_value;
0490 }
0491 
0492 /* Parser */
0493 static EXJSON_Status skip_quotes(const char **string) {
0494     if (**string != '\"') {
0495         return EXJSONFailure;
0496     }
0497     SKIP_CHAR(string);
0498     while (**string != '\"') {
0499         if (**string == '\0') {
0500             return EXJSONFailure;
0501         } else if (**string == '\\') {
0502             SKIP_CHAR(string);
0503             if (**string == '\0') {
0504                 return EXJSONFailure;
0505             }
0506         }
0507         SKIP_CHAR(string);
0508     }
0509     SKIP_CHAR(string);
0510     return EXJSONSuccess;
0511 }
0512 
0513 static int parse_utf16(const char **unprocessed, char **processed) {
0514     unsigned int cp, lead, trail;
0515     int parse_succeeded = 0;
0516     char *processed_ptr = *processed;
0517     const char *unprocessed_ptr = *unprocessed;
0518     unprocessed_ptr++; /* skips u */
0519     parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp);
0520     if (!parse_succeeded) {
0521         return EXJSONFailure;
0522     }
0523     if (cp < 0x80) {
0524         processed_ptr[0] = (char)cp; /* 0xxxxxxx */
0525     } else if (cp < 0x800) {
0526         processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
0527         processed_ptr[1] = ((cp)      & 0x3F) | 0x80; /* 10xxxxxx */
0528         processed_ptr += 1;
0529     } else if (cp < 0xD800 || cp > 0xDFFF) {
0530         processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
0531         processed_ptr[1] = ((cp >> 6)  & 0x3F) | 0x80; /* 10xxxxxx */
0532         processed_ptr[2] = ((cp)       & 0x3F) | 0x80; /* 10xxxxxx */
0533         processed_ptr += 2;
0534     } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
0535         lead = cp;
0536         unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
0537         if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') {
0538             return EXJSONFailure;
0539         }
0540         parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail);
0541         if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
0542             return EXJSONFailure;
0543         }
0544         cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
0545         processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
0546         processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
0547         processed_ptr[2] = (((cp >> 6)  & 0x3F) | 0x80); /* 10xxxxxx */
0548         processed_ptr[3] = (((cp)       & 0x3F) | 0x80); /* 10xxxxxx */
0549         processed_ptr += 3;
0550     } else { /* trail surrogate before lead surrogate */
0551         return EXJSONFailure;
0552     }
0553     unprocessed_ptr += 3;
0554     *processed = processed_ptr;
0555     *unprocessed = unprocessed_ptr;
0556     return EXJSONSuccess;
0557 }
0558 
0559 
0560 /* Copies and processes passed string up to supplied length.
0561 Example: "\u006Corem ipsum" -> lorem ipsum */
0562 static char* process_string(const char *input, size_t len) {
0563     const char *input_ptr = input;
0564     size_t initial_size = (len + 1) * sizeof(char);
0565     size_t final_size = 0;
0566     char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
0567     output = (char*)exparson_malloc(initial_size);
0568     if (output == NULL) {
0569         goto error;
0570     }
0571     output_ptr = output;
0572     while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
0573         if (*input_ptr == '\\') {
0574             input_ptr++;
0575             switch (*input_ptr) {
0576                 case '\"': *output_ptr = '\"'; break;
0577                 case '\\': *output_ptr = '\\'; break;
0578                 case '/':  *output_ptr = '/';  break;
0579                 case 'b':  *output_ptr = '\b'; break;
0580                 case 'f':  *output_ptr = '\f'; break;
0581                 case 'n':  *output_ptr = '\n'; break;
0582                 case 'r':  *output_ptr = '\r'; break;
0583                 case 't':  *output_ptr = '\t'; break;
0584                 case 'u':
0585                     if (parse_utf16(&input_ptr, &output_ptr) == EXJSONFailure) {
0586                         goto error;
0587                     }
0588                     break;
0589                 default:
0590                     goto error;
0591             }
0592         } else if ((unsigned char)*input_ptr < 0x20) {
0593             goto error; /* 0x00-0x19 are invalid characters for exjson string (http://www.ietf.org/rfc/rfc4627.txt) */
0594         } else {
0595             *output_ptr = *input_ptr;
0596         }
0597         output_ptr++;
0598         input_ptr++;
0599     }
0600     *output_ptr = '\0';
0601     /* resize to new length */
0602     final_size = (size_t)(output_ptr-output) + 1;
0603     /* todo: don't resize if final_size == initial_size */
0604     resized_output = (char*)exparson_malloc(final_size);
0605     if (resized_output == NULL) {
0606         goto error;
0607     }
0608     memcpy(resized_output, output, final_size);
0609     exparson_free(output);
0610     return resized_output;
0611 error:
0612     exparson_free(output);
0613     return NULL;
0614 }
0615 
0616 /* Return processed contents of a string between quotes and
0617    skips passed argument to a matching quote. */
0618 static char * get_quoted_string(const char **string) {
0619     const char *string_start = *string;
0620     size_t string_len = 0;
0621     EXJSON_Status status = skip_quotes(string);
0622     if (status != EXJSONSuccess) {
0623         return NULL;
0624     }
0625     string_len = *string - string_start - 2; /* length without quotes */
0626     return process_string(string_start + 1, string_len);
0627 }
0628 
0629 static EXJSON_Value * parse_value(const char **string, size_t nesting) {
0630     if (nesting > MAX_NESTING) {
0631         return NULL;
0632     }
0633     SKIP_WHITESPACES(string);
0634     switch (**string) {
0635         case '{':
0636             return parse_object_value(string, nesting + 1);
0637         case '[':
0638             return parse_array_value(string, nesting + 1);
0639         case '\"':
0640             return parse_string_value(string);
0641         case 'f': case 't':
0642             return parse_boolean_value(string);
0643         case '-':
0644         case '0': case '1': case '2': case '3': case '4':
0645         case '5': case '6': case '7': case '8': case '9':
0646             return parse_number_value(string);
0647         case 'n':
0648             return parse_null_value(string);
0649         default:
0650             return NULL;
0651     }
0652 }
0653 
0654 static EXJSON_Value * parse_object_value(const char **string, size_t nesting) {
0655     EXJSON_Value *output_value = exjson_value_init_object(), *new_value = NULL;
0656     EXJSON_Object *output_object = exjson_value_get_object(output_value);
0657     char *new_key = NULL;
0658     if (output_value == NULL || **string != '{') {
0659         return NULL;
0660     }
0661     SKIP_CHAR(string);
0662     SKIP_WHITESPACES(string);
0663     if (**string == '}') { /* empty object */
0664         SKIP_CHAR(string);
0665         return output_value;
0666     }
0667     while (**string != '\0') {
0668         new_key = get_quoted_string(string);
0669         if (new_key == NULL) {
0670             exjson_value_free(output_value);
0671             return NULL;
0672         }
0673         SKIP_WHITESPACES(string);
0674         if (**string != ':') {
0675             exparson_free(new_key);
0676             exjson_value_free(output_value);
0677             return NULL;
0678         }
0679         SKIP_CHAR(string);
0680         new_value = parse_value(string, nesting);
0681         if (new_value == NULL) {
0682             exparson_free(new_key);
0683             exjson_value_free(output_value);
0684             return NULL;
0685         }
0686         if (exjson_object_add(output_object, new_key, new_value) == EXJSONFailure) {
0687             exparson_free(new_key);
0688             exjson_value_free(new_value);
0689             exjson_value_free(output_value);
0690             return NULL;
0691         }
0692         exparson_free(new_key);
0693         SKIP_WHITESPACES(string);
0694         if (**string != ',') {
0695             break;
0696         }
0697         SKIP_CHAR(string);
0698         SKIP_WHITESPACES(string);
0699     }
0700     SKIP_WHITESPACES(string);
0701     if (**string != '}' || /* Trim object after parsing is over */
0702         exjson_object_resize(output_object, exjson_object_get_count(output_object)) == EXJSONFailure) {
0703             exjson_value_free(output_value);
0704             return NULL;
0705     }
0706     SKIP_CHAR(string);
0707     return output_value;
0708 }
0709 
0710 static EXJSON_Value * parse_array_value(const char **string, size_t nesting) {
0711     EXJSON_Value *output_value = exjson_value_init_array(), *new_array_value = NULL;
0712     EXJSON_Array *output_array = exjson_value_get_array(output_value);
0713     if (!output_value || **string != '[') {
0714         return NULL;
0715     }
0716     SKIP_CHAR(string);
0717     SKIP_WHITESPACES(string);
0718     if (**string == ']') { /* empty array */
0719         SKIP_CHAR(string);
0720         return output_value;
0721     }
0722     while (**string != '\0') {
0723         new_array_value = parse_value(string, nesting);
0724         if (new_array_value == NULL) {
0725             exjson_value_free(output_value);
0726             return NULL;
0727         }
0728         if (exjson_array_add(output_array, new_array_value) == EXJSONFailure) {
0729             exjson_value_free(new_array_value);
0730             exjson_value_free(output_value);
0731             return NULL;
0732         }
0733         SKIP_WHITESPACES(string);
0734         if (**string != ',') {
0735             break;
0736         }
0737         SKIP_CHAR(string);
0738         SKIP_WHITESPACES(string);
0739     }
0740     SKIP_WHITESPACES(string);
0741     if (**string != ']' || /* Trim array after parsing is over */
0742         exjson_array_resize(output_array, exjson_array_get_count(output_array)) == EXJSONFailure) {
0743             exjson_value_free(output_value);
0744             return NULL;
0745     }
0746     SKIP_CHAR(string);
0747     return output_value;
0748 }
0749 
0750 static EXJSON_Value * parse_string_value(const char **string) {
0751     EXJSON_Value *value = NULL;
0752     char *new_string = get_quoted_string(string);
0753     if (new_string == NULL) {
0754         return NULL;
0755     }
0756     value = exjson_value_init_string_no_copy(new_string);
0757     if (value == NULL) {
0758         exparson_free(new_string);
0759         return NULL;
0760     }
0761     return value;
0762 }
0763 
0764 static EXJSON_Value * parse_boolean_value(const char **string) {
0765     size_t true_token_size = SIZEOF_TOKEN("true");
0766     size_t false_token_size = SIZEOF_TOKEN("false");
0767     if (strncmp("true", *string, true_token_size) == 0) {
0768         *string += true_token_size;
0769         return exjson_value_init_boolean(1);
0770     } else if (strncmp("false", *string, false_token_size) == 0) {
0771         *string += false_token_size;
0772         return exjson_value_init_boolean(0);
0773     }
0774     return NULL;
0775 }
0776 
0777 static EXJSON_Value * parse_number_value(const char **string) {
0778     char *end;
0779     double number = 0;
0780     errno = 0;
0781     number = strtod(*string, &end);
0782     if (errno || !is_decimal(*string, end - *string)) {
0783         return NULL;
0784     }
0785     *string = end;
0786     return exjson_value_init_number(number);
0787 }
0788 
0789 static EXJSON_Value * parse_null_value(const char **string) {
0790     size_t token_size = SIZEOF_TOKEN("null");
0791     if (strncmp("null", *string, token_size) == 0) {
0792         *string += token_size;
0793         return exjson_value_init_null();
0794     }
0795     return NULL;
0796 }
0797 
0798 /* Serialization */
0799 #define APPEND_STRING(str) do { written = append_string(buf, (str));\
0800                                 if (written < 0) { return -1; }\
0801                                 if (buf != NULL) { buf += written; }\
0802                                 written_total += written; } while(0)
0803 
0804 #define APPEND_INDENT(level) do { written = append_indent(buf, (level));\
0805                                   if (written < 0) { return -1; }\
0806                                   if (buf != NULL) { buf += written; }\
0807                                   written_total += written; } while(0)
0808 
0809 static int exjson_serialize_to_buffer_r(const EXJSON_Value *value, char *buf, int level, int is_pretty, char *num_buf)
0810 {
0811     const char *key = NULL, *string = NULL;
0812     EXJSON_Value *temp_value = NULL;
0813     EXJSON_Array *array = NULL;
0814     EXJSON_Object *object = NULL;
0815     size_t i = 0, count = 0;
0816     double num = 0.0;
0817     int written = -1, written_total = 0;
0818 
0819     switch (exjson_value_get_type(value)) {
0820         case EXJSONArray:
0821             array = exjson_value_get_array(value);
0822             count = exjson_array_get_count(array);
0823             APPEND_STRING("[");
0824             if (count > 0 && is_pretty) {
0825                 APPEND_STRING("\n");
0826             }
0827             for (i = 0; i < count; i++) {
0828                 if (is_pretty) {
0829                     APPEND_INDENT(level+1);
0830                 }
0831                 temp_value = exjson_array_get_value(array, i);
0832                 written = exjson_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
0833                 if (written < 0) {
0834                     return -1;
0835                 }
0836                 if (buf != NULL) {
0837                     buf += written;
0838                 }
0839                 written_total += written;
0840                 if (i < (count - 1)) {
0841                     APPEND_STRING(",");
0842                 }
0843                 if (is_pretty) {
0844                     APPEND_STRING("\n");
0845                 }
0846             }
0847             if (count > 0 && is_pretty) {
0848                 APPEND_INDENT(level);
0849             }
0850             APPEND_STRING("]");
0851             return written_total;
0852         case EXJSONObject:
0853             object = exjson_value_get_object(value);
0854             count  = exjson_object_get_count(object);
0855             APPEND_STRING("{");
0856             if (count > 0 && is_pretty) {
0857                 APPEND_STRING("\n");
0858             }
0859             for (i = 0; i < count; i++) {
0860                 key = exjson_object_get_name(object, i);
0861                 if (key == NULL) {
0862                     return -1;
0863                 }
0864                 if (is_pretty) {
0865                     APPEND_INDENT(level+1);
0866                 }
0867                 written = exjson_serialize_string(key, buf);
0868                 if (written < 0) {
0869                     return -1;
0870                 }
0871                 if (buf != NULL) {
0872                     buf += written;
0873                 }
0874                 written_total += written;
0875                 APPEND_STRING(":");
0876                 if (is_pretty) {
0877                     APPEND_STRING(" ");
0878                 }
0879                 temp_value = exjson_object_get_value(object, key);
0880                 written = exjson_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
0881                 if (written < 0) {
0882                     return -1;
0883                 }
0884                 if (buf != NULL) {
0885                     buf += written;
0886                 }
0887                 written_total += written;
0888                 if (i < (count - 1)) {
0889                     APPEND_STRING(",");
0890                 }
0891                 if (is_pretty) {
0892                     APPEND_STRING("\n");
0893                 }
0894             }
0895             if (count > 0 && is_pretty) {
0896                 APPEND_INDENT(level);
0897             }
0898             APPEND_STRING("}");
0899             return written_total;
0900         case EXJSONString:
0901             string = exjson_value_get_string(value);
0902             if (string == NULL) {
0903                 return -1;
0904             }
0905             written = exjson_serialize_string(string, buf);
0906             if (written < 0) {
0907                 return -1;
0908             }
0909             if (buf != NULL) {
0910                 buf += written;
0911             }
0912             written_total += written;
0913             return written_total;
0914         case EXJSONBoolean:
0915             if (exjson_value_get_boolean(value)) {
0916                 APPEND_STRING("true");
0917             } else {
0918                 APPEND_STRING("false");
0919             }
0920             return written_total;
0921         case EXJSONNumber:
0922             num = exjson_value_get_number(value);
0923             if (buf != NULL) {
0924                 num_buf = buf;
0925             }
0926             
0927             if (num == ((double)(long)num)) /*  check if num is integer */
0928                 written = sprintf(num_buf, "%ld", (long)num);
0929             else /* Enduro/X specific: */
0930                 written = sprintf(num_buf, "%.*lf", DOUBLE_RESOLUTION, num);
0931 
0932             if (written < 0) {
0933                 return -1;
0934             }
0935             if (buf != NULL) {
0936                 buf += written;
0937             }
0938             written_total += written;
0939             return written_total;
0940         case EXJSONNull:
0941             APPEND_STRING("null");
0942             return written_total;
0943         case EXJSONError:
0944             return -1;
0945         default:
0946             return -1;
0947     }
0948 }
0949 
0950 static int exjson_serialize_string(const char *string, char *buf) {
0951     size_t i = 0, len = strlen(string);
0952     char c = '\0';
0953     int written = -1, written_total = 0;
0954     APPEND_STRING("\"");
0955     for (i = 0; i < len; i++) {
0956         c = string[i];
0957         switch (c) {
0958             case '\"': APPEND_STRING("\\\""); break;
0959             case '\\': APPEND_STRING("\\\\"); break;
0960             case '/':  APPEND_STRING("\\/"); break; /* to make exjson embeddable in xml\/html */
0961             case '\b': APPEND_STRING("\\b"); break;
0962             case '\f': APPEND_STRING("\\f"); break;
0963             case '\n': APPEND_STRING("\\n"); break;
0964             case '\r': APPEND_STRING("\\r"); break;
0965             case '\t': APPEND_STRING("\\t"); break;
0966             case '\x00': APPEND_STRING("\\u0000"); break;
0967             case '\x01': APPEND_STRING("\\u0001"); break;
0968             case '\x02': APPEND_STRING("\\u0002"); break;
0969             case '\x03': APPEND_STRING("\\u0003"); break;
0970             case '\x04': APPEND_STRING("\\u0004"); break;
0971             case '\x05': APPEND_STRING("\\u0005"); break;
0972             case '\x06': APPEND_STRING("\\u0006"); break;
0973             case '\x07': APPEND_STRING("\\u0007"); break;
0974             /* '\x08' duplicate: '\b' */
0975             /* '\x09' duplicate: '\t' */
0976             /* '\x0a' duplicate: '\n' */
0977             case '\x0b': APPEND_STRING("\\u000b"); break;
0978             /* '\x0c' duplicate: '\f' */
0979             /* '\x0d' duplicate: '\r' */
0980             case '\x0e': APPEND_STRING("\\u000e"); break;
0981             case '\x0f': APPEND_STRING("\\u000f"); break;
0982             case '\x10': APPEND_STRING("\\u0010"); break;
0983             case '\x11': APPEND_STRING("\\u0011"); break;
0984             case '\x12': APPEND_STRING("\\u0012"); break;
0985             case '\x13': APPEND_STRING("\\u0013"); break;
0986             case '\x14': APPEND_STRING("\\u0014"); break;
0987             case '\x15': APPEND_STRING("\\u0015"); break;
0988             case '\x16': APPEND_STRING("\\u0016"); break;
0989             case '\x17': APPEND_STRING("\\u0017"); break;
0990             case '\x18': APPEND_STRING("\\u0018"); break;
0991             case '\x19': APPEND_STRING("\\u0019"); break;
0992             case '\x1a': APPEND_STRING("\\u001a"); break;
0993             case '\x1b': APPEND_STRING("\\u001b"); break;
0994             case '\x1c': APPEND_STRING("\\u001c"); break;
0995             case '\x1d': APPEND_STRING("\\u001d"); break;
0996             case '\x1e': APPEND_STRING("\\u001e"); break;
0997             case '\x1f': APPEND_STRING("\\u001f"); break;
0998             default:
0999                 if (buf != NULL) {
1000                     buf[0] = c;
1001                     buf += 1;
1002                 }
1003                 written_total += 1;
1004                 break;
1005         }
1006     }
1007     APPEND_STRING("\"");
1008     return written_total;
1009 }
1010 
1011 static int append_indent(char *buf, int level) {
1012     int i;
1013     int written = -1, written_total = 0;
1014     for (i = 0; i < level; i++) {
1015         APPEND_STRING("    ");
1016     }
1017     return written_total;
1018 }
1019 
1020 static int append_string(char *buf, const char *string) {
1021     if (buf == NULL) {
1022         return (int)strlen(string);
1023     }
1024     return sprintf(buf, "%s", string);
1025 }
1026 
1027 #undef APPEND_STRING
1028 #undef APPEND_INDENT
1029 
1030 /* Parser API */
1031 EXJSON_Value * exjson_parse_file(const char *filename) {
1032     char *file_contents = read_file(filename);
1033     EXJSON_Value *output_value = NULL;
1034     if (file_contents == NULL) {
1035         return NULL;
1036     }
1037     output_value = exjson_parse_string(file_contents);
1038     exparson_free(file_contents);
1039     return output_value;
1040 }
1041 
1042 EXJSON_Value * exjson_parse_file_with_comments(const char *filename) {
1043     char *file_contents = read_file(filename);
1044     EXJSON_Value *output_value = NULL;
1045     if (file_contents == NULL) {
1046         return NULL;
1047     }
1048     output_value = exjson_parse_string_with_comments(file_contents);
1049     exparson_free(file_contents);
1050     return output_value;
1051 }
1052 
1053 EXJSON_Value * exjson_parse_string(const char *string) {
1054     if (string == NULL) {
1055         return NULL;
1056     }
1057     if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') {
1058         string = string + 3; /* Support for UTF-8 BOM */
1059     }
1060     return parse_value((const char**)&string, 0);
1061 }
1062 
1063 EXJSON_Value * exjson_parse_string_with_comments(const char *string) {
1064     EXJSON_Value *result = NULL;
1065     char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
1066     string_mutable_copy = exparson_strdup(string);
1067     if (string_mutable_copy == NULL) {
1068         return NULL;
1069     }
1070     remove_comments(string_mutable_copy, "/*", "*/");
1071     remove_comments(string_mutable_copy, "//", "\n");
1072     string_mutable_copy_ptr = string_mutable_copy;
1073     result = parse_value((const char**)&string_mutable_copy_ptr, 0);
1074     exparson_free(string_mutable_copy);
1075     return result;
1076 }
1077 
1078 /* EXJSON Object API */
1079 
1080 EXJSON_Value * exjson_object_get_value(const EXJSON_Object *object, const char *name) {
1081     if (object == NULL || name == NULL) {
1082         return NULL;
1083     }
1084     return exjson_object_nget_value(object, name, strlen(name));
1085 }
1086 
1087 const char * exjson_object_get_string(const EXJSON_Object *object, const char *name) {
1088     return exjson_value_get_string(exjson_object_get_value(object, name));
1089 }
1090 
1091 double exjson_object_get_number(const EXJSON_Object *object, const char *name) {
1092     return exjson_value_get_number(exjson_object_get_value(object, name));
1093 }
1094 
1095 EXJSON_Object * exjson_object_get_object(const EXJSON_Object *object, const char *name) {
1096     return exjson_value_get_object(exjson_object_get_value(object, name));
1097 }
1098 
1099 EXJSON_Array * exjson_object_get_array(const EXJSON_Object *object, const char *name) {
1100     return exjson_value_get_array(exjson_object_get_value(object, name));
1101 }
1102 
1103 int exjson_object_get_boolean(const EXJSON_Object *object, const char *name) {
1104     return exjson_value_get_boolean(exjson_object_get_value(object, name));
1105 }
1106 
1107 EXJSON_Value * exjson_object_dotget_value(const EXJSON_Object *object, const char *name) {
1108     const char *dot_position = strchr(name, '.');
1109     if (!dot_position) {
1110         return exjson_object_get_value(object, name);
1111     }
1112     object = exjson_value_get_object(exjson_object_nget_value(object, name, dot_position - name));
1113     return exjson_object_dotget_value(object, dot_position + 1);
1114 }
1115 
1116 const char * exjson_object_dotget_string(const EXJSON_Object *object, const char *name) {
1117     return exjson_value_get_string(exjson_object_dotget_value(object, name));
1118 }
1119 
1120 double exjson_object_dotget_number(const EXJSON_Object *object, const char *name) {
1121     return exjson_value_get_number(exjson_object_dotget_value(object, name));
1122 }
1123 
1124 EXJSON_Object * exjson_object_dotget_object(const EXJSON_Object *object, const char *name) {
1125     return exjson_value_get_object(exjson_object_dotget_value(object, name));
1126 }
1127 
1128 EXJSON_Array * exjson_object_dotget_array(const EXJSON_Object *object, const char *name) {
1129     return exjson_value_get_array(exjson_object_dotget_value(object, name));
1130 }
1131 
1132 int exjson_object_dotget_boolean(const EXJSON_Object *object, const char *name) {
1133     return exjson_value_get_boolean(exjson_object_dotget_value(object, name));
1134 }
1135 
1136 size_t exjson_object_get_count(const EXJSON_Object *object) {
1137     return object ? object->count : 0;
1138 }
1139 
1140 const char * exjson_object_get_name(const EXJSON_Object *object, size_t index) {
1141     if (object == NULL || index >= exjson_object_get_count(object)) {
1142         return NULL;
1143     }
1144     return object->names[index];
1145 }
1146 
1147 EXJSON_Value * exjson_object_get_value_at(const EXJSON_Object *object, size_t index) {
1148     if (object == NULL || index >= exjson_object_get_count(object)) {
1149         return NULL;
1150     }
1151     return object->values[index];
1152 }
1153 
1154 EXJSON_Value *exjson_object_get_wrapping_value(const EXJSON_Object *object) {
1155     return object->wrapping_value;
1156 }
1157 
1158 int exjson_object_has_value (const EXJSON_Object *object, const char *name) {
1159     return exjson_object_get_value(object, name) != NULL;
1160 }
1161 
1162 int exjson_object_has_value_of_type(const EXJSON_Object *object, const char *name, EXJSON_Value_Type type) {
1163     EXJSON_Value *val = exjson_object_get_value(object, name);
1164     return val != NULL && exjson_value_get_type(val) == type;
1165 }
1166 
1167 int exjson_object_dothas_value (const EXJSON_Object *object, const char *name) {
1168     return exjson_object_dotget_value(object, name) != NULL;
1169 }
1170 
1171 int exjson_object_dothas_value_of_type(const EXJSON_Object *object, const char *name, EXJSON_Value_Type type) {
1172     EXJSON_Value *val = exjson_object_dotget_value(object, name);
1173     return val != NULL && exjson_value_get_type(val) == type;
1174 }
1175 
1176 /* EXJSON Array API */
1177 EXJSON_Value * exjson_array_get_value(const EXJSON_Array *array, size_t index) {
1178     if (array == NULL || index >= exjson_array_get_count(array)) {
1179         return NULL;
1180     }
1181     return array->items[index];
1182 }
1183 
1184 const char * exjson_array_get_string(const EXJSON_Array *array, size_t index) {
1185     return exjson_value_get_string(exjson_array_get_value(array, index));
1186 }
1187 
1188 double exjson_array_get_number(const EXJSON_Array *array, size_t index) {
1189     return exjson_value_get_number(exjson_array_get_value(array, index));
1190 }
1191 
1192 EXJSON_Object * exjson_array_get_object(const EXJSON_Array *array, size_t index) {
1193     return exjson_value_get_object(exjson_array_get_value(array, index));
1194 }
1195 
1196 EXJSON_Array * exjson_array_get_array(const EXJSON_Array *array, size_t index) {
1197     return exjson_value_get_array(exjson_array_get_value(array, index));
1198 }
1199 
1200 int exjson_array_get_boolean(const EXJSON_Array *array, size_t index) {
1201     return exjson_value_get_boolean(exjson_array_get_value(array, index));
1202 }
1203 
1204 size_t exjson_array_get_count(const EXJSON_Array *array) {
1205     return array ? array->count : 0;
1206 }
1207 
1208 EXJSON_Value * exjson_array_get_wrapping_value(const EXJSON_Array *array) {
1209     return array->wrapping_value;
1210 }
1211 
1212 /* EXJSON Value API */
1213 EXJSON_Value_Type exjson_value_get_type(const EXJSON_Value *value) {
1214     return value ? value->type : EXJSONError;
1215 }
1216 
1217 EXJSON_Object * exjson_value_get_object(const EXJSON_Value *value) {
1218     return exjson_value_get_type(value) == EXJSONObject ? value->value.object : NULL;
1219 }
1220 
1221 EXJSON_Array * exjson_value_get_array(const EXJSON_Value *value) {
1222     return exjson_value_get_type(value) == EXJSONArray ? value->value.array : NULL;
1223 }
1224 
1225 const char * exjson_value_get_string(const EXJSON_Value *value) {
1226     return exjson_value_get_type(value) == EXJSONString ? value->value.string : NULL;
1227 }
1228 
1229 double exjson_value_get_number(const EXJSON_Value *value) {
1230     return exjson_value_get_type(value) == EXJSONNumber ? value->value.number : 0;
1231 }
1232 
1233 int exjson_value_get_boolean(const EXJSON_Value *value) {
1234     return exjson_value_get_type(value) == EXJSONBoolean ? value->value.boolean : -1;
1235 }
1236 
1237 EXJSON_Value * exjson_value_get_parent (const EXJSON_Value *value) {
1238     return value ? value->parent : NULL;
1239 }
1240 
1241 void exjson_value_free(EXJSON_Value *value) {
1242     switch (exjson_value_get_type(value)) {
1243         case EXJSONObject:
1244             exjson_object_free(value->value.object);
1245             break;
1246         case EXJSONString:
1247             exparson_free(value->value.string);
1248             break;
1249         case EXJSONArray:
1250             exjson_array_free(value->value.array);
1251             break;
1252         default:
1253             break;
1254     }
1255     exparson_free(value);
1256 }
1257 
1258 EXJSON_Value * exjson_value_init_object(void) {
1259     EXJSON_Value *new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
1260     if (!new_value) {
1261         return NULL;
1262     }
1263     new_value->parent = NULL;
1264     new_value->type = EXJSONObject;
1265     new_value->value.object = exjson_object_init(new_value);
1266     if (!new_value->value.object) {
1267         exparson_free(new_value);
1268         return NULL;
1269     }
1270     return new_value;
1271 }
1272 
1273 EXJSON_Value * exjson_value_init_array(void) {
1274     EXJSON_Value *new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
1275     if (!new_value) {
1276         return NULL;
1277     }
1278     new_value->parent = NULL;
1279     new_value->type = EXJSONArray;
1280     new_value->value.array = exjson_array_init(new_value);
1281     if (!new_value->value.array) {
1282         exparson_free(new_value);
1283         return NULL;
1284     }
1285     return new_value;
1286 }
1287 
1288 EXJSON_Value * exjson_value_init_string(const char *string) {
1289     char *copy = NULL;
1290     EXJSON_Value *value;
1291     size_t string_len = 0;
1292     if (string == NULL) {
1293         return NULL;
1294     }
1295     string_len = strlen(string);
1296     if (!is_valid_utf8(string, string_len)) {
1297         return NULL;
1298     }
1299     copy = exparson_strndup(string, string_len);
1300     if (copy == NULL) {
1301         return NULL;
1302     }
1303     value = exjson_value_init_string_no_copy(copy);
1304     if (value == NULL) {
1305         exparson_free(copy);
1306     }
1307     return value;
1308 }
1309 
1310 EXJSON_Value * exjson_value_init_number(double number) {
1311     EXJSON_Value *new_value = NULL;
1312     if ((number * 0.0) != 0.0) { /* nan and inf test */
1313         return NULL;
1314     }
1315     new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
1316     if (new_value == NULL) {
1317         return NULL;
1318     }
1319     new_value->parent = NULL;
1320     new_value->type = EXJSONNumber;
1321     new_value->value.number = number;
1322     return new_value;
1323 }
1324 
1325 EXJSON_Value * exjson_value_init_boolean(int boolean) {
1326     EXJSON_Value *new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
1327     if (!new_value) {
1328         return NULL;
1329     }
1330     new_value->parent = NULL;
1331     new_value->type = EXJSONBoolean;
1332     new_value->value.boolean = boolean ? 1 : 0;
1333     return new_value;
1334 }
1335 
1336 EXJSON_Value * exjson_value_init_null(void) {
1337     EXJSON_Value *new_value = (EXJSON_Value*)exparson_malloc(sizeof(EXJSON_Value));
1338     if (!new_value) {
1339         return NULL;
1340     }
1341     new_value->parent = NULL;
1342     new_value->type = EXJSONNull;
1343     return new_value;
1344 }
1345 
1346 EXJSON_Value * exjson_value_deep_copy(const EXJSON_Value *value) {
1347     size_t i = 0;
1348     EXJSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
1349     const char *temp_string = NULL, *temp_key = NULL;
1350     char *temp_string_copy = NULL;
1351     EXJSON_Array *temp_array = NULL, *temp_array_copy = NULL;
1352     EXJSON_Object *temp_object = NULL, *temp_object_copy = NULL;
1353 
1354     switch (exjson_value_get_type(value)) {
1355         case EXJSONArray:
1356             temp_array = exjson_value_get_array(value);
1357             return_value = exjson_value_init_array();
1358             if (return_value == NULL) {
1359                 return NULL;
1360             }
1361             temp_array_copy = exjson_value_get_array(return_value);
1362             for (i = 0; i < exjson_array_get_count(temp_array); i++) {
1363                 temp_value = exjson_array_get_value(temp_array, i);
1364                 temp_value_copy = exjson_value_deep_copy(temp_value);
1365                 if (temp_value_copy == NULL) {
1366                     exjson_value_free(return_value);
1367                     return NULL;
1368                 }
1369                 if (exjson_array_add(temp_array_copy, temp_value_copy) == EXJSONFailure) {
1370                     exjson_value_free(return_value);
1371                     exjson_value_free(temp_value_copy);
1372                     return NULL;
1373                 }
1374             }
1375             return return_value;
1376         case EXJSONObject:
1377             temp_object = exjson_value_get_object(value);
1378             return_value = exjson_value_init_object();
1379             if (return_value == NULL) {
1380                 return NULL;
1381             }
1382             temp_object_copy = exjson_value_get_object(return_value);
1383             for (i = 0; i < exjson_object_get_count(temp_object); i++) {
1384                 temp_key = exjson_object_get_name(temp_object, i);
1385                 temp_value = exjson_object_get_value(temp_object, temp_key);
1386                 temp_value_copy = exjson_value_deep_copy(temp_value);
1387                 if (temp_value_copy == NULL) {
1388                     exjson_value_free(return_value);
1389                     return NULL;
1390                 }
1391                 if (exjson_object_add(temp_object_copy, temp_key, temp_value_copy) == EXJSONFailure) {
1392                     exjson_value_free(return_value);
1393                     exjson_value_free(temp_value_copy);
1394                     return NULL;
1395                 }
1396             }
1397             return return_value;
1398         case EXJSONBoolean:
1399             return exjson_value_init_boolean(exjson_value_get_boolean(value));
1400         case EXJSONNumber:
1401             return exjson_value_init_number(exjson_value_get_number(value));
1402         case EXJSONString:
1403             temp_string = exjson_value_get_string(value);
1404             if (temp_string == NULL) {
1405                 return NULL;
1406             }
1407             temp_string_copy = exparson_strdup(temp_string);
1408             if (temp_string_copy == NULL) {
1409                 return NULL;
1410             }
1411             return_value = exjson_value_init_string_no_copy(temp_string_copy);
1412             if (return_value == NULL) {
1413                 exparson_free(temp_string_copy);
1414             }
1415             return return_value;
1416         case EXJSONNull:
1417             return exjson_value_init_null();
1418         case EXJSONError:
1419             return NULL;
1420         default:
1421             return NULL;
1422     }
1423 }
1424 
1425 size_t exjson_serialization_size(const EXJSON_Value *value) {
1426     char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
1427     int res = exjson_serialize_to_buffer_r(value, NULL, 0, 0, num_buf);
1428     return res < 0 ? 0 : (size_t)(res + 1);
1429 }
1430 
1431 EXJSON_Status exjson_serialize_to_buffer(const EXJSON_Value *value, char *buf, size_t buf_size_in_bytes) {
1432     int written = -1;
1433     size_t needed_size_in_bytes = exjson_serialization_size(value);
1434     if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
1435         return EXJSONFailure;
1436     }
1437     written = exjson_serialize_to_buffer_r(value, buf, 0, 0, NULL);
1438     if (written < 0) {
1439         return EXJSONFailure;
1440     }
1441     return EXJSONSuccess;
1442 }
1443 
1444 EXJSON_Status exjson_serialize_to_file(const EXJSON_Value *value, const char *filename) {
1445     EXJSON_Status return_code = EXJSONSuccess;
1446     FILE *fp = NULL;
1447     char *serialized_string = exjson_serialize_to_string(value);
1448     if (serialized_string == NULL) {
1449         return EXJSONFailure;
1450     }
1451     fp = fopen (filename, "w");
1452     if (fp == NULL) {
1453         exjson_free_serialized_string(serialized_string);
1454         return EXJSONFailure;
1455     }
1456     if (fputs(serialized_string, fp) == EOF) {
1457         return_code = EXJSONFailure;
1458     }
1459     if (fclose(fp) == EOF) {
1460         return_code = EXJSONFailure;
1461     }
1462     exjson_free_serialized_string(serialized_string);
1463     return return_code;
1464 }
1465 
1466 char * exjson_serialize_to_string(const EXJSON_Value *value) {
1467     EXJSON_Status serialization_result = EXJSONFailure;
1468     size_t buf_size_bytes = exjson_serialization_size(value);
1469     char *buf = NULL;
1470     if (buf_size_bytes == 0) {
1471         return NULL;
1472     }
1473     buf = (char*)exparson_malloc(buf_size_bytes);
1474     if (buf == NULL) {
1475         return NULL;
1476     }
1477     serialization_result = exjson_serialize_to_buffer(value, buf, buf_size_bytes);
1478     if (serialization_result == EXJSONFailure) {
1479         exjson_free_serialized_string(buf);
1480         return NULL;
1481     }
1482     return buf;
1483 }
1484 
1485 size_t exjson_serialization_size_pretty(const EXJSON_Value *value) {
1486     char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
1487     int res = exjson_serialize_to_buffer_r(value, NULL, 0, 1, num_buf);
1488     return res < 0 ? 0 : (size_t)(res + 1);
1489 }
1490 
1491 EXJSON_Status exjson_serialize_to_buffer_pretty(const EXJSON_Value *value, char *buf, size_t buf_size_in_bytes) {
1492     int written = -1;
1493     size_t needed_size_in_bytes = exjson_serialization_size_pretty(value);
1494     if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
1495         return EXJSONFailure;
1496     }
1497     written = exjson_serialize_to_buffer_r(value, buf, 0, 1, NULL);
1498     if (written < 0) {
1499         return EXJSONFailure;
1500     }
1501     return EXJSONSuccess;
1502 }
1503 
1504 EXJSON_Status exjson_serialize_to_file_pretty(const EXJSON_Value *value, const char *filename) {
1505     EXJSON_Status return_code = EXJSONSuccess;
1506     FILE *fp = NULL;
1507     char *serialized_string = exjson_serialize_to_string_pretty(value);
1508     if (serialized_string == NULL) {
1509         return EXJSONFailure;
1510     }
1511     fp = fopen (filename, "w");
1512     if (fp == NULL) {
1513         exjson_free_serialized_string(serialized_string);
1514         return EXJSONFailure;
1515     }
1516     if (fputs(serialized_string, fp) == EOF) {
1517         return_code = EXJSONFailure;
1518     }
1519     if (fclose(fp) == EOF) {
1520         return_code = EXJSONFailure;
1521     }
1522     exjson_free_serialized_string(serialized_string);
1523     return return_code;
1524 }
1525 
1526 char * exjson_serialize_to_string_pretty(const EXJSON_Value *value) {
1527     EXJSON_Status serialization_result = EXJSONFailure;
1528     size_t buf_size_bytes = exjson_serialization_size_pretty(value);
1529     char *buf = NULL;
1530     if (buf_size_bytes == 0) {
1531         return NULL;
1532     }
1533     buf = (char*)exparson_malloc(buf_size_bytes);
1534     if (buf == NULL) {
1535         return NULL;
1536     }
1537     serialization_result = exjson_serialize_to_buffer_pretty(value, buf, buf_size_bytes);
1538     if (serialization_result == EXJSONFailure) {
1539         exjson_free_serialized_string(buf);
1540         return NULL;
1541     }
1542     return buf;
1543 }
1544 
1545 void exjson_free_serialized_string(char *string) {
1546     exparson_free(string);
1547 }
1548 
1549 EXJSON_Status exjson_array_remove(EXJSON_Array *array, size_t ix) {
1550     size_t to_move_bytes = 0;
1551     if (array == NULL || ix >= exjson_array_get_count(array)) {
1552         return EXJSONFailure;
1553     }
1554     exjson_value_free(exjson_array_get_value(array, ix));
1555     to_move_bytes = (exjson_array_get_count(array) - 1 - ix) * sizeof(EXJSON_Value*);
1556     memmove(array->items + ix, array->items + ix + 1, to_move_bytes);
1557     array->count -= 1;
1558     return EXJSONSuccess;
1559 }
1560 
1561 EXJSON_Status exjson_array_replace_value(EXJSON_Array *array, size_t ix, EXJSON_Value *value) {
1562     if (array == NULL || value == NULL || value->parent != NULL || ix >= exjson_array_get_count(array)) {
1563         return EXJSONFailure;
1564     }
1565     exjson_value_free(exjson_array_get_value(array, ix));
1566     value->parent = exjson_array_get_wrapping_value(array);
1567     array->items[ix] = value;
1568     return EXJSONSuccess;
1569 }
1570 
1571 EXJSON_Status exjson_array_replace_string(EXJSON_Array *array, size_t i, const char* string) {
1572     EXJSON_Value *value = exjson_value_init_string(string);
1573     if (value == NULL) {
1574         return EXJSONFailure;
1575     }
1576     if (exjson_array_replace_value(array, i, value) == EXJSONFailure) {
1577         exjson_value_free(value);
1578         return EXJSONFailure;
1579     }
1580     return EXJSONSuccess;
1581 }
1582 
1583 EXJSON_Status exjson_array_replace_number(EXJSON_Array *array, size_t i, double number) {
1584     EXJSON_Value *value = exjson_value_init_number(number);
1585     if (value == NULL) {
1586         return EXJSONFailure;
1587     }
1588     if (exjson_array_replace_value(array, i, value) == EXJSONFailure) {
1589         exjson_value_free(value);
1590         return EXJSONFailure;
1591     }
1592     return EXJSONSuccess;
1593 }
1594 
1595 EXJSON_Status exjson_array_replace_boolean(EXJSON_Array *array, size_t i, int boolean) {
1596     EXJSON_Value *value = exjson_value_init_boolean(boolean);
1597     if (value == NULL) {
1598         return EXJSONFailure;
1599     }
1600     if (exjson_array_replace_value(array, i, value) == EXJSONFailure) {
1601         exjson_value_free(value);
1602         return EXJSONFailure;
1603     }
1604     return EXJSONSuccess;
1605 }
1606 
1607 EXJSON_Status exjson_array_replace_null(EXJSON_Array *array, size_t i) {
1608     EXJSON_Value *value = exjson_value_init_null();
1609     if (value == NULL) {
1610         return EXJSONFailure;
1611     }
1612     if (exjson_array_replace_value(array, i, value) == EXJSONFailure) {
1613         exjson_value_free(value);
1614         return EXJSONFailure;
1615     }
1616     return EXJSONSuccess;
1617 }
1618 
1619 EXJSON_Status exjson_array_clear(EXJSON_Array *array) {
1620     size_t i = 0;
1621     if (array == NULL) {
1622         return EXJSONFailure;
1623     }
1624     for (i = 0; i < exjson_array_get_count(array); i++) {
1625         exjson_value_free(exjson_array_get_value(array, i));
1626     }
1627     array->count = 0;
1628     return EXJSONSuccess;
1629 }
1630 
1631 EXJSON_Status exjson_array_append_value(EXJSON_Array *array, EXJSON_Value *value) {
1632     if (array == NULL || value == NULL || value->parent != NULL) {
1633         return EXJSONFailure;
1634     }
1635     return exjson_array_add(array, value);
1636 }
1637 
1638 EXJSON_Status exjson_array_append_string(EXJSON_Array *array, const char *string) {
1639     EXJSON_Value *value = exjson_value_init_string(string);
1640     if (value == NULL) {
1641         return EXJSONFailure;
1642     }
1643     if (exjson_array_append_value(array, value) == EXJSONFailure) {
1644         exjson_value_free(value);
1645         return EXJSONFailure;
1646     }
1647     return EXJSONSuccess;
1648 }
1649 
1650 EXJSON_Status exjson_array_append_number(EXJSON_Array *array, double number) {
1651     EXJSON_Value *value = exjson_value_init_number(number);
1652     if (value == NULL) {
1653         return EXJSONFailure;
1654     }
1655     if (exjson_array_append_value(array, value) == EXJSONFailure) {
1656         exjson_value_free(value);
1657         return EXJSONFailure;
1658     }
1659     return EXJSONSuccess;
1660 }
1661 
1662 EXJSON_Status exjson_array_append_boolean(EXJSON_Array *array, int boolean) {
1663     EXJSON_Value *value = exjson_value_init_boolean(boolean);
1664     if (value == NULL) {
1665         return EXJSONFailure;
1666     }
1667     if (exjson_array_append_value(array, value) == EXJSONFailure) {
1668         exjson_value_free(value);
1669         return EXJSONFailure;
1670     }
1671     return EXJSONSuccess;
1672 }
1673 
1674 EXJSON_Status exjson_array_append_null(EXJSON_Array *array) {
1675     EXJSON_Value *value = exjson_value_init_null();
1676     if (value == NULL) {
1677         return EXJSONFailure;
1678     }
1679     if (exjson_array_append_value(array, value) == EXJSONFailure) {
1680         exjson_value_free(value);
1681         return EXJSONFailure;
1682     }
1683     return EXJSONSuccess;
1684 }
1685 
1686 EXJSON_Status exjson_object_set_value(EXJSON_Object *object, const char *name, EXJSON_Value *value) {
1687     size_t i = 0;
1688     EXJSON_Value *old_value;
1689     if (object == NULL || name == NULL || value == NULL || value->parent != NULL) {
1690         return EXJSONFailure;
1691     }
1692     old_value = exjson_object_get_value(object, name);
1693     if (old_value != NULL) { /* free and overwrite old value */
1694         exjson_value_free(old_value);
1695         for (i = 0; i < exjson_object_get_count(object); i++) {
1696             if (strcmp(object->names[i], name) == 0) {
1697                 value->parent = exjson_object_get_wrapping_value(object);
1698                 object->values[i] = value;
1699                 return EXJSONSuccess;
1700             }
1701         }
1702     }
1703     /* add new key value pair */
1704     return exjson_object_add(object, name, value);
1705 }
1706 
1707 EXJSON_Status exjson_object_set_string(EXJSON_Object *object, const char *name, const char *string) {
1708     return exjson_object_set_value(object, name, exjson_value_init_string(string));
1709 }
1710 
1711 EXJSON_Status exjson_object_set_number(EXJSON_Object *object, const char *name, double number) {
1712     return exjson_object_set_value(object, name, exjson_value_init_number(number));
1713 }
1714 
1715 EXJSON_Status exjson_object_set_boolean(EXJSON_Object *object, const char *name, int boolean) {
1716     return exjson_object_set_value(object, name, exjson_value_init_boolean(boolean));
1717 }
1718 
1719 EXJSON_Status exjson_object_set_null(EXJSON_Object *object, const char *name) {
1720     return exjson_object_set_value(object, name, exjson_value_init_null());
1721 }
1722 
1723 EXJSON_Status exjson_object_dotset_value(EXJSON_Object *object, const char *name, EXJSON_Value *value) {
1724     const char *dot_pos = NULL;
1725     char *current_name = NULL;
1726     EXJSON_Object *temp_obj = NULL;
1727     EXJSON_Value *new_value = NULL;
1728     if (object == NULL || name == NULL || value == NULL) {
1729         return EXJSONFailure;
1730     }
1731     dot_pos = strchr(name, '.');
1732     if (dot_pos == NULL) {
1733         return exjson_object_set_value(object, name, value);
1734     } else {
1735         current_name = exparson_strndup(name, dot_pos - name);
1736         temp_obj = exjson_object_get_object(object, current_name);
1737         if (temp_obj == NULL) {
1738             new_value = exjson_value_init_object();
1739             if (new_value == NULL) {
1740                 exparson_free(current_name);
1741                 return EXJSONFailure;
1742             }
1743             if (exjson_object_add(object, current_name, new_value) == EXJSONFailure) {
1744                 exjson_value_free(new_value);
1745                 exparson_free(current_name);
1746                 return EXJSONFailure;
1747             }
1748             temp_obj = exjson_object_get_object(object, current_name);
1749         }
1750         exparson_free(current_name);
1751         return exjson_object_dotset_value(temp_obj, dot_pos + 1, value);
1752     }
1753 }
1754 
1755 EXJSON_Status exjson_object_dotset_string(EXJSON_Object *object, const char *name, const char *string) {
1756     EXJSON_Value *value = exjson_value_init_string(string);
1757     if (value == NULL) {
1758         return EXJSONFailure;
1759     }
1760     if (exjson_object_dotset_value(object, name, value) == EXJSONFailure) {
1761         exjson_value_free(value);
1762         return EXJSONFailure;
1763     }
1764     return EXJSONSuccess;
1765 }
1766 
1767 EXJSON_Status exjson_object_dotset_number(EXJSON_Object *object, const char *name, double number) {
1768     EXJSON_Value *value = exjson_value_init_number(number);
1769     if (value == NULL) {
1770         return EXJSONFailure;
1771     }
1772     if (exjson_object_dotset_value(object, name, value) == EXJSONFailure) {
1773         exjson_value_free(value);
1774         return EXJSONFailure;
1775     }
1776     return EXJSONSuccess;
1777 }
1778 
1779 EXJSON_Status exjson_object_dotset_boolean(EXJSON_Object *object, const char *name, int boolean) {
1780     EXJSON_Value *value = exjson_value_init_boolean(boolean);
1781     if (value == NULL) {
1782         return EXJSONFailure;
1783     }
1784     if (exjson_object_dotset_value(object, name, value) == EXJSONFailure) {
1785         exjson_value_free(value);
1786         return EXJSONFailure;
1787     }
1788     return EXJSONSuccess;
1789 }
1790 
1791 EXJSON_Status exjson_object_dotset_null(EXJSON_Object *object, const char *name) {
1792     EXJSON_Value *value = exjson_value_init_null();
1793     if (value == NULL) {
1794         return EXJSONFailure;
1795     }
1796     if (exjson_object_dotset_value(object, name, value) == EXJSONFailure) {
1797         exjson_value_free(value);
1798         return EXJSONFailure;
1799     }
1800     return EXJSONSuccess;
1801 }
1802 
1803 EXJSON_Status exjson_object_remove(EXJSON_Object *object, const char *name) {
1804     size_t i = 0, last_item_index = 0;
1805     if (object == NULL || exjson_object_get_value(object, name) == NULL) {
1806         return EXJSONFailure;
1807     }
1808     last_item_index = exjson_object_get_count(object) - 1;
1809     for (i = 0; i < exjson_object_get_count(object); i++) {
1810         if (strcmp(object->names[i], name) == 0) {
1811             exparson_free(object->names[i]);
1812             exjson_value_free(object->values[i]);
1813             if (i != last_item_index) { /* Replace key value pair with one from the end */
1814                 object->names[i] = object->names[last_item_index];
1815                 object->values[i] = object->values[last_item_index];
1816             }
1817             object->count -= 1;
1818             return EXJSONSuccess;
1819         }
1820     }
1821     return EXJSONFailure; /* No execution path should end here */
1822 }
1823 
1824 EXJSON_Status exjson_object_dotremove(EXJSON_Object *object, const char *name) {
1825     const char *dot_pos = strchr(name, '.');
1826     char *current_name = NULL;
1827     EXJSON_Object *temp_obj = NULL;
1828     if (dot_pos == NULL) {
1829         return exjson_object_remove(object, name);
1830     } else {
1831         current_name = exparson_strndup(name, dot_pos - name);
1832         temp_obj = exjson_object_get_object(object, current_name);
1833         exparson_free(current_name);
1834         if (temp_obj == NULL) {
1835             return EXJSONFailure;
1836         }
1837         return exjson_object_dotremove(temp_obj, dot_pos + 1);
1838     }
1839 }
1840 
1841 EXJSON_Status exjson_object_clear(EXJSON_Object *object) {
1842     size_t i = 0;
1843     if (object == NULL) {
1844         return EXJSONFailure;
1845     }
1846     for (i = 0; i < exjson_object_get_count(object); i++) {
1847         exparson_free(object->names[i]);
1848         exjson_value_free(object->values[i]);
1849     }
1850     object->count = 0;
1851     return EXJSONSuccess;
1852 }
1853 
1854 EXJSON_Status exjson_validate(const EXJSON_Value *schema, const EXJSON_Value *value) {
1855     EXJSON_Value *temp_schema_value = NULL, *temp_value = NULL;
1856     EXJSON_Array *schema_array = NULL, *value_array = NULL;
1857     EXJSON_Object *schema_object = NULL, *value_object = NULL;
1858     EXJSON_Value_Type schema_type = EXJSONError, value_type = EXJSONError;
1859     const char *key = NULL;
1860     size_t i = 0, count = 0;
1861     if (schema == NULL || value == NULL) {
1862         return EXJSONFailure;
1863     }
1864     schema_type = exjson_value_get_type(schema);
1865     value_type = exjson_value_get_type(value);
1866     if (schema_type != value_type && schema_type != EXJSONNull) { /* null represents all values */
1867         return EXJSONFailure;
1868     }
1869     switch (schema_type) {
1870         case EXJSONArray:
1871             schema_array = exjson_value_get_array(schema);
1872             value_array = exjson_value_get_array(value);
1873             count = exjson_array_get_count(schema_array);
1874             if (count == 0) {
1875                 return EXJSONSuccess; /* Empty array allows all types */
1876             }
1877             /* Get first value from array, rest is ignored */
1878             temp_schema_value = exjson_array_get_value(schema_array, 0);
1879             for (i = 0; i < exjson_array_get_count(value_array); i++) {
1880                 temp_value = exjson_array_get_value(value_array, i);
1881                 if (exjson_validate(temp_schema_value, temp_value) == EXJSONFailure) {
1882                     return EXJSONFailure;
1883                 }
1884             }
1885             return EXJSONSuccess;
1886         case EXJSONObject:
1887             schema_object = exjson_value_get_object(schema);
1888             value_object = exjson_value_get_object(value);
1889             count = exjson_object_get_count(schema_object);
1890             if (count == 0) {
1891                 return EXJSONSuccess; /* Empty object allows all objects */
1892             } else if (exjson_object_get_count(value_object) < count) {
1893                 return EXJSONFailure; /* Tested object mustn't have less name-value pairs than schema */
1894             }
1895             for (i = 0; i < count; i++) {
1896                 key = exjson_object_get_name(schema_object, i);
1897                 temp_schema_value = exjson_object_get_value(schema_object, key);
1898                 temp_value = exjson_object_get_value(value_object, key);
1899                 if (temp_value == NULL) {
1900                     return EXJSONFailure;
1901                 }
1902                 if (exjson_validate(temp_schema_value, temp_value) == EXJSONFailure) {
1903                     return EXJSONFailure;
1904                 }
1905             }
1906             return EXJSONSuccess;
1907         case EXJSONString: case EXJSONNumber: case EXJSONBoolean: case EXJSONNull:
1908             return EXJSONSuccess; /* equality already tested before switch */
1909         case EXJSONError: default:
1910             return EXJSONFailure;
1911     }
1912 }
1913 
1914 int exjson_value_equals(const EXJSON_Value *a, const EXJSON_Value *b) {
1915     EXJSON_Object *a_object = NULL, *b_object = NULL;
1916     EXJSON_Array *a_array = NULL, *b_array = NULL;
1917     const char *a_string = NULL, *b_string = NULL;
1918     const char *key = NULL;
1919     size_t a_count = 0, b_count = 0, i = 0;
1920     EXJSON_Value_Type a_type, b_type;
1921     a_type = exjson_value_get_type(a);
1922     b_type = exjson_value_get_type(b);
1923     if (a_type != b_type) {
1924         return 0;
1925     }
1926     switch (a_type) {
1927         case EXJSONArray:
1928             a_array = exjson_value_get_array(a);
1929             b_array = exjson_value_get_array(b);
1930             a_count = exjson_array_get_count(a_array);
1931             b_count = exjson_array_get_count(b_array);
1932             if (a_count != b_count) {
1933                 return 0;
1934             }
1935             for (i = 0; i < a_count; i++) {
1936                 if (!exjson_value_equals(exjson_array_get_value(a_array, i),
1937                                        exjson_array_get_value(b_array, i))) {
1938                     return 0;
1939                 }
1940             }
1941             return 1;
1942         case EXJSONObject:
1943             a_object = exjson_value_get_object(a);
1944             b_object = exjson_value_get_object(b);
1945             a_count = exjson_object_get_count(a_object);
1946             b_count = exjson_object_get_count(b_object);
1947             if (a_count != b_count) {
1948                 return 0;
1949             }
1950             for (i = 0; i < a_count; i++) {
1951                 key = exjson_object_get_name(a_object, i);
1952                 if (!exjson_value_equals(exjson_object_get_value(a_object, key),
1953                                        exjson_object_get_value(b_object, key))) {
1954                     return 0;
1955                 }
1956             }
1957             return 1;
1958         case EXJSONString:
1959             a_string = exjson_value_get_string(a);
1960             b_string = exjson_value_get_string(b);
1961             if (a_string == NULL || b_string == NULL) {
1962                 return 0; /* shouldn't happen */
1963             }
1964             return strcmp(a_string, b_string) == 0;
1965         case EXJSONBoolean:
1966             return exjson_value_get_boolean(a) == exjson_value_get_boolean(b);
1967         case EXJSONNumber:
1968             return fabs(exjson_value_get_number(a) - exjson_value_get_number(b)) < 0.000001; /* EPSILON */
1969         case EXJSONError:
1970             return 1;
1971         case EXJSONNull:
1972             return 1;
1973         default:
1974             return 1;
1975     }
1976 }
1977 
1978 EXJSON_Value_Type exjson_type(const EXJSON_Value *value) {
1979     return exjson_value_get_type(value);
1980 }
1981 
1982 EXJSON_Object * exjson_object (const EXJSON_Value *value) {
1983     return exjson_value_get_object(value);
1984 }
1985 
1986 EXJSON_Array * exjson_array  (const EXJSON_Value *value) {
1987     return exjson_value_get_array(value);
1988 }
1989 
1990 const char * exjson_string (const EXJSON_Value *value) {
1991     return exjson_value_get_string(value);
1992 }
1993 
1994 double exjson_number (const EXJSON_Value *value) {
1995     return exjson_value_get_number(value);
1996 }
1997 
1998 int exjson_boolean(const EXJSON_Value *value) {
1999     return exjson_value_get_boolean(value);
2000 }
2001 
2002 void exjson_set_allocation_functions(EXJSON_Malloc_Function malloc_fun, EXJSON_Free_Function free_fun) {
2003     exparson_malloc = malloc_fun;
2004     exparson_free = free_fun;
2005 }