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