mirror of
				https://github.com/taigrr/tplinkController
				synced 2025-01-18 04:43:13 -08:00 
			
		
		
		
	Remove unused JSON stuff.
This commit is contained in:
		
							parent
							
								
									b42c1e293c
								
							
						
					
					
						commit
						60cc5c8bb5
					
				
							
								
								
									
										994
									
								
								json-builder.c
									
									
									
									
									
								
							
							
						
						
									
										994
									
								
								json-builder.c
									
									
									
									
									
								
							| @ -1,994 +0,0 @@ | ||||
| 
 | ||||
| /* vim: set et ts=3 sw=3 sts=3 ft=c:
 | ||||
|  * | ||||
|  * Copyright (C) 2014 James McLaughlin.  All rights reserved. | ||||
|  * https://github.com/udp/json-builder
 | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer in the | ||||
|  *   documentation and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #include "json-builder.h" | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
|     #define snprintf _snprintf | ||||
| #endif | ||||
| 
 | ||||
| static const json_serialize_opts default_opts = | ||||
| { | ||||
|    json_serialize_mode_single_line, | ||||
|    0, | ||||
|    3  /* indent_size */ | ||||
| }; | ||||
| 
 | ||||
| typedef struct json_builder_value | ||||
| { | ||||
|    json_value value; | ||||
| 
 | ||||
|    int is_builder_value; | ||||
| 
 | ||||
|    size_t additional_length_allocated; | ||||
|    size_t length_iterated; | ||||
| 
 | ||||
| } json_builder_value; | ||||
| 
 | ||||
| static int builderize (json_value * value) | ||||
| { | ||||
|    if (((json_builder_value *) value)->is_builder_value) | ||||
|       return 1; | ||||
|     | ||||
|    if (value->type == json_object) | ||||
|    { | ||||
|       unsigned int i; | ||||
| 
 | ||||
|       /* Values straight out of the parser have the names of object entries
 | ||||
|        * allocated in the same allocation as the values array itself.  This is | ||||
|        * not desirable when manipulating values because the names would be easy | ||||
|        * to clobber. | ||||
|        */ | ||||
|       for (i = 0; i < value->u.object.length; ++ i) | ||||
|       { | ||||
|          json_char * name_copy; | ||||
|          json_object_entry * entry = &value->u.object.values [i]; | ||||
| 
 | ||||
|          if (! (name_copy = (json_char *) malloc ((entry->name_length + 1) * sizeof (json_char)))) | ||||
|             return 0; | ||||
| 
 | ||||
|          memcpy (name_copy, entry->name, entry->name_length + 1); | ||||
|          entry->name = name_copy; | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    return 1; | ||||
| } | ||||
| 
 | ||||
| const size_t json_builder_extra = sizeof(json_builder_value) - sizeof(json_value); | ||||
| 
 | ||||
| /* These flags are set up from the opts before serializing to make the
 | ||||
|  * serializer conditions simpler. | ||||
|  */ | ||||
| const int f_spaces_around_brackets = (1 << 0); | ||||
| const int f_spaces_after_commas    = (1 << 1); | ||||
| const int f_spaces_after_colons    = (1 << 2); | ||||
| const int f_tabs                   = (1 << 3); | ||||
| 
 | ||||
| static int get_serialize_flags (json_serialize_opts opts) | ||||
| { | ||||
|    int flags = 0; | ||||
| 
 | ||||
|    if (opts.mode == json_serialize_mode_packed) | ||||
|       return 0; | ||||
| 
 | ||||
|    if (opts.mode == json_serialize_mode_multiline) | ||||
|    { | ||||
|       if (opts.opts & json_serialize_opt_use_tabs) | ||||
|          flags |= f_tabs; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       if (! (opts.opts & json_serialize_opt_pack_brackets)) | ||||
|          flags |= f_spaces_around_brackets; | ||||
| 
 | ||||
|       if (! (opts.opts & json_serialize_opt_no_space_after_comma)) | ||||
|          flags |= f_spaces_after_commas; | ||||
|    } | ||||
| 
 | ||||
|    if (! (opts.opts & json_serialize_opt_no_space_after_colon)) | ||||
|       flags |= f_spaces_after_colons; | ||||
| 
 | ||||
|    return flags; | ||||
| } | ||||
| 
 | ||||
| json_value * json_array_new (size_t length) | ||||
| { | ||||
|     json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
| 
 | ||||
|     if (!value) | ||||
|        return NULL; | ||||
| 
 | ||||
|     ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|     value->type = json_array; | ||||
| 
 | ||||
|     if (! (value->u.array.values = (json_value **) malloc (length * sizeof (json_value *)))) | ||||
|     { | ||||
|        free (value); | ||||
|        return NULL; | ||||
|     } | ||||
| 
 | ||||
|     ((json_builder_value *) value)->additional_length_allocated = length; | ||||
| 
 | ||||
|     return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_array_push (json_value * array, json_value * value) | ||||
| { | ||||
|    assert (array->type == json_array); | ||||
| 
 | ||||
|    if (!builderize (array) || !builderize (value)) | ||||
|       return NULL; | ||||
| 
 | ||||
|    if (((json_builder_value *) array)->additional_length_allocated > 0) | ||||
|    { | ||||
|       -- ((json_builder_value *) array)->additional_length_allocated; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       json_value ** values_new = (json_value **) realloc | ||||
|             (array->u.array.values, sizeof (json_value *) * (array->u.array.length + 1)); | ||||
| 
 | ||||
|       if (!values_new) | ||||
|          return NULL; | ||||
| 
 | ||||
|       array->u.array.values = values_new; | ||||
|    } | ||||
| 
 | ||||
|    array->u.array.values [array->u.array.length] = value; | ||||
|    ++ array->u.array.length; | ||||
| 
 | ||||
|    value->parent = array; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_object_new (size_t length) | ||||
| { | ||||
|     json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
| 
 | ||||
|     if (!value) | ||||
|        return NULL; | ||||
| 
 | ||||
|     ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|     value->type = json_object; | ||||
| 
 | ||||
|     if (! (value->u.object.values = (json_object_entry *) calloc | ||||
|            (length, sizeof (*value->u.object.values)))) | ||||
|     { | ||||
|        free (value); | ||||
|        return NULL; | ||||
|     } | ||||
| 
 | ||||
|     ((json_builder_value *) value)->additional_length_allocated = length; | ||||
| 
 | ||||
|     return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_object_push (json_value * object, | ||||
|                                const json_char * name, | ||||
|                                json_value * value) | ||||
| { | ||||
|    return json_object_push_length (object, strlen (name), name, value); | ||||
| } | ||||
| 
 | ||||
| json_value * json_object_push_length (json_value * object, | ||||
|                                       unsigned int name_length, const json_char * name, | ||||
|                                       json_value * value) | ||||
| { | ||||
|    json_char * name_copy; | ||||
| 
 | ||||
|    assert (object->type == json_object); | ||||
| 
 | ||||
|    if (! (name_copy = (json_char *) malloc ((name_length + 1) * sizeof (json_char)))) | ||||
|       return NULL; | ||||
|     | ||||
|    memcpy (name_copy, name, name_length * sizeof (json_char)); | ||||
|    name_copy [name_length] = 0; | ||||
| 
 | ||||
|    if (!json_object_push_nocopy (object, name_length, name_copy, value)) | ||||
|    { | ||||
|       free (name_copy); | ||||
|       return NULL; | ||||
|    } | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_object_push_nocopy (json_value * object, | ||||
|                                       unsigned int name_length, json_char * name, | ||||
|                                       json_value * value) | ||||
| { | ||||
|    json_object_entry * entry; | ||||
| 
 | ||||
|    assert (object->type == json_object); | ||||
| 
 | ||||
|    if (!builderize (object) || !builderize (value)) | ||||
|       return NULL; | ||||
| 
 | ||||
|    if (((json_builder_value *) object)->additional_length_allocated > 0) | ||||
|    { | ||||
|       -- ((json_builder_value *) object)->additional_length_allocated; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       json_object_entry * values_new = (json_object_entry *) | ||||
|             realloc (object->u.object.values, sizeof (*object->u.object.values) | ||||
|                             * (object->u.object.length + 1)); | ||||
| 
 | ||||
|       if (!values_new) | ||||
|          return NULL; | ||||
| 
 | ||||
|       object->u.object.values = values_new; | ||||
|    } | ||||
| 
 | ||||
|    entry = object->u.object.values + object->u.object.length; | ||||
| 
 | ||||
|    entry->name_length = name_length; | ||||
|    entry->name = name; | ||||
|    entry->value = value; | ||||
| 
 | ||||
|    ++ object->u.object.length; | ||||
| 
 | ||||
|    value->parent = object; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_string_new (const json_char * buf) | ||||
| { | ||||
|    return json_string_new_length (strlen (buf), buf); | ||||
| } | ||||
| 
 | ||||
| json_value * json_string_new_length (unsigned int length, const json_char * buf) | ||||
| { | ||||
|    json_value * value; | ||||
|    json_char * copy = (json_char *) malloc ((length + 1) * sizeof (json_char)); | ||||
| 
 | ||||
|    if (!copy) | ||||
|       return NULL; | ||||
|     | ||||
|    memcpy (copy, buf, length * sizeof (json_char)); | ||||
|    copy [length] = 0; | ||||
| 
 | ||||
|    if (! (value = json_string_new_nocopy (length, copy))) | ||||
|    { | ||||
|       free (copy); | ||||
|       return NULL; | ||||
|    } | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_string_new_nocopy (unsigned int length, json_char * buf) | ||||
| { | ||||
|    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
|     | ||||
|    if (!value) | ||||
|       return NULL; | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    value->type = json_string; | ||||
|    value->u.string.length = length; | ||||
|    value->u.string.ptr = buf; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_integer_new (json_int_t integer) | ||||
| { | ||||
|    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
|     | ||||
|    if (!value) | ||||
|       return NULL; | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    value->type = json_integer; | ||||
|    value->u.integer = integer; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_double_new (double dbl) | ||||
| { | ||||
|    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
|     | ||||
|    if (!value) | ||||
|       return NULL; | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    value->type = json_double; | ||||
|    value->u.dbl = dbl; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_boolean_new (int b) | ||||
| { | ||||
|    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
|     | ||||
|    if (!value) | ||||
|       return NULL; | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    value->type = json_boolean; | ||||
|    value->u.boolean = b; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| json_value * json_null_new (void) | ||||
| { | ||||
|    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value)); | ||||
|     | ||||
|    if (!value) | ||||
|       return NULL; | ||||
| 
 | ||||
|    ((json_builder_value *) value)->is_builder_value = 1; | ||||
| 
 | ||||
|    value->type = json_null; | ||||
| 
 | ||||
|    return value; | ||||
| } | ||||
| 
 | ||||
| void json_object_sort (json_value * object, json_value * proto) | ||||
| { | ||||
|    unsigned int i, out_index = 0; | ||||
| 
 | ||||
|    if (!builderize (object)) | ||||
|       return;  /* TODO error */ | ||||
| 
 | ||||
|    assert (object->type == json_object); | ||||
|    assert (proto->type == json_object); | ||||
| 
 | ||||
|    for (i = 0; i < proto->u.object.length; ++ i) | ||||
|    { | ||||
|       unsigned int j; | ||||
|       json_object_entry proto_entry = proto->u.object.values [i]; | ||||
| 
 | ||||
|       for (j = 0; j < object->u.object.length; ++ j) | ||||
|       { | ||||
|          json_object_entry entry = object->u.object.values [j]; | ||||
| 
 | ||||
|          if (entry.name_length != proto_entry.name_length) | ||||
|             continue; | ||||
| 
 | ||||
|          if (memcmp (entry.name, proto_entry.name, entry.name_length) != 0) | ||||
|             continue; | ||||
| 
 | ||||
|          object->u.object.values [j] = object->u.object.values [out_index]; | ||||
|          object->u.object.values [out_index] = entry; | ||||
| 
 | ||||
|          ++ out_index; | ||||
|       } | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| json_value * json_object_merge (json_value * objectA, json_value * objectB) | ||||
| { | ||||
|    unsigned int i; | ||||
| 
 | ||||
|    assert (objectA->type == json_object); | ||||
|    assert (objectB->type == json_object); | ||||
|    assert (objectA != objectB); | ||||
| 
 | ||||
|    if (!builderize (objectA) || !builderize (objectB)) | ||||
|       return NULL; | ||||
| 
 | ||||
|    if (objectB->u.object.length <= | ||||
|         ((json_builder_value *) objectA)->additional_length_allocated) | ||||
|    { | ||||
|       ((json_builder_value *) objectA)->additional_length_allocated | ||||
|           -= objectB->u.object.length; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       json_object_entry * values_new; | ||||
| 
 | ||||
|       unsigned int alloc = | ||||
|           objectA->u.object.length | ||||
|               + ((json_builder_value *) objectA)->additional_length_allocated | ||||
|               + objectB->u.object.length; | ||||
| 
 | ||||
|       if (! (values_new = (json_object_entry *) | ||||
|             realloc (objectA->u.object.values, sizeof (json_object_entry) * alloc))) | ||||
|       { | ||||
|           return NULL; | ||||
|       } | ||||
| 
 | ||||
|       objectA->u.object.values = values_new; | ||||
|    } | ||||
| 
 | ||||
|    for (i = 0; i < objectB->u.object.length; ++ i) | ||||
|    { | ||||
|       json_object_entry * entry = &objectA->u.object.values[objectA->u.object.length + i]; | ||||
| 
 | ||||
|       *entry = objectB->u.object.values[i]; | ||||
|       entry->value->parent = objectA; | ||||
|    } | ||||
| 
 | ||||
|    objectA->u.object.length += objectB->u.object.length; | ||||
| 
 | ||||
|    free (objectB->u.object.values); | ||||
|    free (objectB); | ||||
| 
 | ||||
|    return objectA; | ||||
| } | ||||
| 
 | ||||
| static size_t measure_string (unsigned int length, | ||||
|                               const json_char * str) | ||||
| { | ||||
|    unsigned int i; | ||||
|    size_t measured_length = 0; | ||||
| 
 | ||||
|    for(i = 0; i < length; ++ i) | ||||
|    { | ||||
|       json_char c = str [i]; | ||||
| 
 | ||||
|       switch (c) | ||||
|       { | ||||
|       case '"': | ||||
|       case '\\': | ||||
|       case '\b': | ||||
|       case '\f': | ||||
|       case '\n': | ||||
|       case '\r': | ||||
|       case '\t': | ||||
| 
 | ||||
|          measured_length += 2; | ||||
|          break; | ||||
| 
 | ||||
|       default: | ||||
| 
 | ||||
|          ++ measured_length; | ||||
|          break; | ||||
|       }; | ||||
|    }; | ||||
| 
 | ||||
|    return measured_length; | ||||
| } | ||||
| 
 | ||||
| #define PRINT_ESCAPED(c) do {  \ | ||||
|    *buf ++ = '\\';             \ | ||||
|    *buf ++ = (c);              \ | ||||
| } while(0);                    \ | ||||
| 
 | ||||
| static size_t serialize_string (json_char * buf, | ||||
|                                 unsigned int length, | ||||
|                                 const json_char * str) | ||||
| { | ||||
|    json_char * orig_buf = buf; | ||||
|    unsigned int i; | ||||
| 
 | ||||
|    for(i = 0; i < length; ++ i) | ||||
|    { | ||||
|       json_char c = str [i]; | ||||
| 
 | ||||
|       switch (c) | ||||
|       { | ||||
|       case '"':   PRINT_ESCAPED ('\"');  continue; | ||||
|       case '\\':  PRINT_ESCAPED ('\\');  continue; | ||||
|       case '\b':  PRINT_ESCAPED ('b');   continue; | ||||
|       case '\f':  PRINT_ESCAPED ('f');   continue; | ||||
|       case '\n':  PRINT_ESCAPED ('n');   continue; | ||||
|       case '\r':  PRINT_ESCAPED ('r');   continue; | ||||
|       case '\t':  PRINT_ESCAPED ('t');   continue; | ||||
| 
 | ||||
|       default: | ||||
| 
 | ||||
|          *buf ++ = c; | ||||
|          break; | ||||
|       }; | ||||
|    }; | ||||
| 
 | ||||
|    return buf - orig_buf; | ||||
| } | ||||
| 
 | ||||
| size_t json_measure (json_value * value) | ||||
| { | ||||
|    return json_measure_ex (value, default_opts); | ||||
| } | ||||
| 
 | ||||
| #define MEASURE_NEWLINE() do {                     \ | ||||
|    ++ newlines;                                    \ | ||||
|    indents += depth;                               \ | ||||
| } while(0);                                        \ | ||||
| 
 | ||||
| size_t json_measure_ex (json_value * value, json_serialize_opts opts) | ||||
| { | ||||
|    size_t total = 1;  /* null terminator */ | ||||
|    size_t newlines = 0; | ||||
|    size_t depth = 0; | ||||
|    size_t indents = 0; | ||||
|    int flags; | ||||
|    int bracket_size, comma_size, colon_size; | ||||
| 
 | ||||
|    flags = get_serialize_flags (opts); | ||||
| 
 | ||||
|    /* to reduce branching
 | ||||
|     */ | ||||
|    bracket_size = flags & f_spaces_around_brackets ? 2 : 1; | ||||
|    comma_size = flags & f_spaces_after_commas ? 2 : 1; | ||||
|    colon_size = flags & f_spaces_after_colons ? 2 : 1; | ||||
| 
 | ||||
|    while (value) | ||||
|    { | ||||
|       json_int_t integer; | ||||
|       json_object_entry * entry; | ||||
| 
 | ||||
|       switch (value->type) | ||||
|       { | ||||
|          case json_array: | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == 0) | ||||
|             { | ||||
|                if (value->u.array.length == 0) | ||||
|                { | ||||
|                   total += 2;  /* `[]` */ | ||||
|                   break; | ||||
|                } | ||||
| 
 | ||||
|                total += bracket_size;  /* `[` */ | ||||
| 
 | ||||
|                ++ depth; | ||||
|                MEASURE_NEWLINE(); /* \n after [ */ | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == value->u.array.length) | ||||
|             { | ||||
|                -- depth; | ||||
|                MEASURE_NEWLINE(); | ||||
|                total += bracket_size;  /* `]` */ | ||||
| 
 | ||||
|                ((json_builder_value *) value)->length_iterated = 0; | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated > 0) | ||||
|             { | ||||
|                total += comma_size;  /* `, ` */ | ||||
| 
 | ||||
|                MEASURE_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             ((json_builder_value *) value)->length_iterated++; | ||||
|             value = value->u.array.values [((json_builder_value *) value)->length_iterated - 1]; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_object: | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == 0) | ||||
|             { | ||||
|                if (value->u.object.length == 0) | ||||
|                { | ||||
|                   total += 2;  /* `{}` */ | ||||
|                   break; | ||||
|                } | ||||
| 
 | ||||
|                total += bracket_size;  /* `{` */ | ||||
| 
 | ||||
|                ++ depth; | ||||
|                MEASURE_NEWLINE(); /* \n after { */ | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == value->u.object.length) | ||||
|             { | ||||
|                -- depth; | ||||
|                MEASURE_NEWLINE(); | ||||
|                total += bracket_size;  /* `}` */ | ||||
| 
 | ||||
|                ((json_builder_value *) value)->length_iterated = 0; | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated > 0) | ||||
|             { | ||||
|                total += comma_size;  /* `, ` */ | ||||
|                MEASURE_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             entry = value->u.object.values + (((json_builder_value *) value)->length_iterated ++); | ||||
| 
 | ||||
|             total += 2 + colon_size;  /* `"": ` */ | ||||
|             total += measure_string (entry->name_length, entry->name); | ||||
| 
 | ||||
|             value = entry->value; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_string: | ||||
| 
 | ||||
|             total += 2;  /* `""` */ | ||||
|             total += measure_string (value->u.string.length, value->u.string.ptr); | ||||
|             break; | ||||
| 
 | ||||
|          case json_integer: | ||||
| 
 | ||||
|             integer = value->u.integer; | ||||
| 
 | ||||
|             if (integer < 0) | ||||
|             { | ||||
|                total += 1;  /* `-` */ | ||||
|                integer = - integer; | ||||
|             } | ||||
| 
 | ||||
|             ++ total;  /* first digit */ | ||||
| 
 | ||||
|             while (integer >= 10) | ||||
|             { | ||||
|                ++ total;  /* another digit */ | ||||
|                integer /= 10; | ||||
|             } | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_double: | ||||
| 
 | ||||
|             total += snprintf (NULL, 0, "%g", value->u.dbl); | ||||
| 
 | ||||
|             /* Because sometimes we need to add ".0" if sprintf does not do it
 | ||||
|              * for us. Downside is that we allocate more bytes than strictly | ||||
|              * needed for serialization. | ||||
|              */ | ||||
|             total += 2; | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_boolean: | ||||
| 
 | ||||
|             total += value->u.boolean ?  | ||||
|                4:  /* `true` */ | ||||
|                5;  /* `false` */ | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_null: | ||||
| 
 | ||||
|             total += 4;  /* `null` */ | ||||
|             break; | ||||
| 
 | ||||
|          default: | ||||
|             break; | ||||
|       }; | ||||
| 
 | ||||
|       value = value->parent; | ||||
|    } | ||||
| 
 | ||||
|    if (opts.mode == json_serialize_mode_multiline) | ||||
|    { | ||||
|       total += newlines * (((opts.opts & json_serialize_opt_CRLF) ? 2 : 1) + opts.indent_size); | ||||
|       total += indents * opts.indent_size; | ||||
|    } | ||||
| 
 | ||||
|    return total; | ||||
| } | ||||
| 
 | ||||
| void json_serialize (json_char * buf, json_value * value) | ||||
| { | ||||
|    json_serialize_ex (buf, value, default_opts); | ||||
| } | ||||
| 
 | ||||
| #define PRINT_NEWLINE() do {                          \ | ||||
|    if (opts.mode == json_serialize_mode_multiline) {  \ | ||||
|       if (opts.opts & json_serialize_opt_CRLF)        \ | ||||
|          *buf ++ = '\r';                              \ | ||||
|       *buf ++ = '\n';                                 \ | ||||
|       for(i = 0; i < indent; ++ i)                    \ | ||||
|          *buf ++ = indent_char;                       \ | ||||
|    }                                                  \ | ||||
| } while(0);                                           \ | ||||
| 
 | ||||
| #define PRINT_OPENING_BRACKET(c) do {                 \ | ||||
|    *buf ++ = (c);                                     \ | ||||
|    if (flags & f_spaces_around_brackets)              \ | ||||
|       *buf ++ = ' ';                                  \ | ||||
| } while(0);                                           \ | ||||
| 
 | ||||
| #define PRINT_CLOSING_BRACKET(c) do {                 \ | ||||
|    if (flags & f_spaces_around_brackets)              \ | ||||
|       *buf ++ = ' ';                                  \ | ||||
|    *buf ++ = (c);                                     \ | ||||
| } while(0);                                           \ | ||||
| 
 | ||||
| void json_serialize_ex (json_char * buf, json_value * value, json_serialize_opts opts) | ||||
| { | ||||
|    json_int_t integer, orig_integer; | ||||
|    json_object_entry * entry; | ||||
|    json_char * ptr, * dot; | ||||
|    int indent = 0; | ||||
|    char indent_char; | ||||
|    int i; | ||||
|    int flags; | ||||
| 
 | ||||
|    flags = get_serialize_flags (opts); | ||||
| 
 | ||||
|    indent_char = flags & f_tabs ? '\t' : ' '; | ||||
| 
 | ||||
|    while (value) | ||||
|    { | ||||
|       switch (value->type) | ||||
|       { | ||||
|          case json_array: | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == 0) | ||||
|             { | ||||
|                if (value->u.array.length == 0) | ||||
|                { | ||||
|                   *buf ++ = '['; | ||||
|                   *buf ++ = ']'; | ||||
| 
 | ||||
|                   break; | ||||
|                } | ||||
| 
 | ||||
|                PRINT_OPENING_BRACKET ('['); | ||||
| 
 | ||||
|                indent += opts.indent_size; | ||||
|                PRINT_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == value->u.array.length) | ||||
|             { | ||||
|                indent -= opts.indent_size; | ||||
|                PRINT_NEWLINE(); | ||||
|                PRINT_CLOSING_BRACKET (']'); | ||||
| 
 | ||||
|                ((json_builder_value *) value)->length_iterated = 0; | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated > 0) | ||||
|             { | ||||
|                *buf ++ = ','; | ||||
| 
 | ||||
|                if (flags & f_spaces_after_commas) | ||||
|                   *buf ++ = ' '; | ||||
| 
 | ||||
|                PRINT_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             ((json_builder_value *) value)->length_iterated++; | ||||
|             value = value->u.array.values [((json_builder_value *) value)->length_iterated - 1]; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_object: | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == 0) | ||||
|             { | ||||
|                if (value->u.object.length == 0) | ||||
|                { | ||||
|                   *buf ++ = '{'; | ||||
|                   *buf ++ = '}'; | ||||
| 
 | ||||
|                   break; | ||||
|                } | ||||
| 
 | ||||
|                PRINT_OPENING_BRACKET ('{'); | ||||
| 
 | ||||
|                indent += opts.indent_size; | ||||
|                PRINT_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated == value->u.object.length) | ||||
|             { | ||||
|                indent -= opts.indent_size; | ||||
|                PRINT_NEWLINE(); | ||||
|                PRINT_CLOSING_BRACKET ('}'); | ||||
| 
 | ||||
|                ((json_builder_value *) value)->length_iterated = 0; | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->length_iterated > 0) | ||||
|             { | ||||
|                *buf ++ = ','; | ||||
| 
 | ||||
|                if (flags & f_spaces_after_commas) | ||||
|                   *buf ++ = ' '; | ||||
| 
 | ||||
|                PRINT_NEWLINE(); | ||||
|             } | ||||
| 
 | ||||
|             entry = value->u.object.values + (((json_builder_value *) value)->length_iterated ++); | ||||
| 
 | ||||
|             *buf ++ = '\"'; | ||||
|             buf += serialize_string (buf, entry->name_length, entry->name); | ||||
|             *buf ++ = '\"'; | ||||
|             *buf ++ = ':'; | ||||
| 
 | ||||
|             if (flags & f_spaces_after_colons) | ||||
|                *buf ++ = ' '; | ||||
| 
 | ||||
|             value = entry->value; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_string: | ||||
| 
 | ||||
|             *buf ++ = '\"'; | ||||
|             buf += serialize_string (buf, value->u.string.length, value->u.string.ptr); | ||||
|             *buf ++ = '\"'; | ||||
|             break; | ||||
| 
 | ||||
|          case json_integer: | ||||
| 
 | ||||
|             integer = value->u.integer; | ||||
| 
 | ||||
|             if (integer < 0) | ||||
|             { | ||||
|                *buf ++ = '-'; | ||||
|                integer = - integer; | ||||
|             } | ||||
| 
 | ||||
|             orig_integer = integer; | ||||
| 
 | ||||
|             ++ buf; | ||||
| 
 | ||||
|             while (integer >= 10) | ||||
|             { | ||||
|                ++ buf; | ||||
|                integer /= 10; | ||||
|             } | ||||
| 
 | ||||
|             integer = orig_integer; | ||||
|             ptr = buf; | ||||
| 
 | ||||
|             do | ||||
|             { | ||||
|                *-- ptr = "0123456789"[integer % 10]; | ||||
| 
 | ||||
|             } while ((integer /= 10) > 0); | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_double: | ||||
| 
 | ||||
|             ptr = buf; | ||||
| 
 | ||||
|             buf += sprintf (buf, "%g", value->u.dbl); | ||||
| 
 | ||||
|             if ((dot = strchr (ptr, ','))) | ||||
|             { | ||||
|                *dot = '.'; | ||||
|             } | ||||
|             else if (!strchr (ptr, '.') && !strchr (ptr, 'e')) | ||||
|             { | ||||
|                *buf ++ = '.'; | ||||
|                *buf ++ = '0'; | ||||
|             } | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_boolean: | ||||
| 
 | ||||
|             if (value->u.boolean) | ||||
|             { | ||||
|                memcpy (buf, "true", 4); | ||||
|                buf += 4; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                memcpy (buf, "false", 5); | ||||
|                buf += 5; | ||||
|             } | ||||
| 
 | ||||
|             break; | ||||
| 
 | ||||
|          case json_null: | ||||
| 
 | ||||
|             memcpy (buf, "null", 4); | ||||
|             buf += 4; | ||||
|             break; | ||||
| 
 | ||||
|          default: | ||||
|             break; | ||||
|       }; | ||||
| 
 | ||||
|       value = value->parent; | ||||
|    } | ||||
| 
 | ||||
|    *buf = 0; | ||||
| } | ||||
| 
 | ||||
| void json_builder_free (json_value * value) | ||||
| { | ||||
|    json_value * cur_value; | ||||
| 
 | ||||
|    if (!value) | ||||
|       return; | ||||
| 
 | ||||
|    value->parent = 0; | ||||
| 
 | ||||
|    while (value) | ||||
|    { | ||||
|       switch (value->type) | ||||
|       { | ||||
|          case json_array: | ||||
| 
 | ||||
|             if (!value->u.array.length) | ||||
|             { | ||||
|                free (value->u.array.values); | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             value = value->u.array.values [-- value->u.array.length]; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_object: | ||||
| 
 | ||||
|             if (!value->u.object.length) | ||||
|             { | ||||
|                free (value->u.object.values); | ||||
|                break; | ||||
|             } | ||||
| 
 | ||||
|             -- value->u.object.length; | ||||
| 
 | ||||
|             if (((json_builder_value *) value)->is_builder_value) | ||||
|             { | ||||
|                /* Names are allocated separately for builder values.  In parser
 | ||||
|                 * values, they are part of the same allocation as the values array | ||||
|                 * itself. | ||||
|                 */ | ||||
|                free (value->u.object.values [value->u.object.length].name); | ||||
|             } | ||||
| 
 | ||||
|             value = value->u.object.values [value->u.object.length].value; | ||||
|             continue; | ||||
| 
 | ||||
|          case json_string: | ||||
| 
 | ||||
|             free (value->u.string.ptr); | ||||
|             break; | ||||
| 
 | ||||
|          default: | ||||
|             break; | ||||
|       }; | ||||
| 
 | ||||
|       cur_value = value; | ||||
|       value = value->parent; | ||||
|       free (cur_value); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										159
									
								
								json-builder.h
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								json-builder.h
									
									
									
									
									
								
							| @ -1,159 +0,0 @@ | ||||
| 
 | ||||
| /* vim: set et ts=3 sw=3 sts=3 ft=c:
 | ||||
|  * | ||||
|  * Copyright (C) 2014 James McLaughlin.  All rights reserved. | ||||
|  * https://github.com/udp/json-builder
 | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer in the | ||||
|  *   documentation and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _JSON_BUILDER_H | ||||
| #define _JSON_BUILDER_H | ||||
| 
 | ||||
| /* Requires json.h from json-parser
 | ||||
|  * https://github.com/udp/json-parser
 | ||||
|  */ | ||||
| #include "json.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| #endif | ||||
| 
 | ||||
| /* IMPORTANT NOTE:  If you want to use json-builder functions with values
 | ||||
|  * allocated by json-parser as part of the parsing process, you must pass | ||||
|  * json_builder_extra as the value_extra setting in json_settings when | ||||
|  * parsing.  Otherwise there will not be room for the extra state and | ||||
|  * json-builder WILL invoke undefined behaviour. | ||||
|  * | ||||
|  * Also note that unlike json-parser, json-builder does not currently support | ||||
|  * custom allocators (for no particular reason other than that it doesn't have | ||||
|  * any settings or global state.) | ||||
|  */ | ||||
| extern const size_t json_builder_extra; | ||||
| 
 | ||||
| 
 | ||||
| /*** Arrays
 | ||||
|  *** | ||||
|  * Note that all of these length arguments are just a hint to allow for | ||||
|  * pre-allocation - passing 0 is fine. | ||||
|  */ | ||||
| json_value * json_array_new (size_t length); | ||||
| json_value * json_array_push (json_value * array, json_value *); | ||||
| 
 | ||||
| 
 | ||||
| /*** Objects
 | ||||
|  ***/ | ||||
| json_value * json_object_new (size_t length); | ||||
| 
 | ||||
| json_value * json_object_push (json_value * object, | ||||
|                                const json_char * name, | ||||
|                                json_value *); | ||||
| 
 | ||||
| /* Same as json_object_push, but doesn't call strlen() for you.
 | ||||
|  */ | ||||
| json_value * json_object_push_length (json_value * object, | ||||
|                                       unsigned int name_length, const json_char * name, | ||||
|                                       json_value *); | ||||
| 
 | ||||
| /* Same as json_object_push_length, but doesn't copy the name buffer before
 | ||||
|  * storing it in the value.  Use this micro-optimisation at your own risk. | ||||
|  */ | ||||
| json_value * json_object_push_nocopy (json_value * object, | ||||
|                                       unsigned int name_length, json_char * name, | ||||
|                                       json_value *); | ||||
| 
 | ||||
| /* Merges all entries from objectB into objectA and destroys objectB.
 | ||||
|  */ | ||||
| json_value * json_object_merge (json_value * objectA, json_value * objectB); | ||||
| 
 | ||||
| /* Sort the entries of an object based on the order in a prototype object.
 | ||||
|  * Helpful when reading JSON and writing it again to preserve user order. | ||||
|  */ | ||||
| void json_object_sort (json_value * object, json_value * proto); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*** Strings
 | ||||
|  ***/ | ||||
| json_value * json_string_new (const json_char *); | ||||
| json_value * json_string_new_length (unsigned int length, const json_char *); | ||||
| json_value * json_string_new_nocopy (unsigned int length, json_char *); | ||||
| 
 | ||||
| 
 | ||||
| /*** Everything else
 | ||||
|  ***/ | ||||
| json_value * json_integer_new (json_int_t); | ||||
| json_value * json_double_new (double); | ||||
| json_value * json_boolean_new (int); | ||||
| json_value * json_null_new (void); | ||||
| 
 | ||||
| 
 | ||||
| /*** Serializing
 | ||||
|  ***/ | ||||
| #define json_serialize_mode_multiline     0 | ||||
| #define json_serialize_mode_single_line   1 | ||||
| #define json_serialize_mode_packed        2 | ||||
| 
 | ||||
| #define json_serialize_opt_CRLF                    (1 << 1) | ||||
| #define json_serialize_opt_pack_brackets           (1 << 2) | ||||
| #define json_serialize_opt_no_space_after_comma    (1 << 3) | ||||
| #define json_serialize_opt_no_space_after_colon    (1 << 4) | ||||
| #define json_serialize_opt_use_tabs                (1 << 5) | ||||
| 
 | ||||
| typedef struct json_serialize_opts | ||||
| { | ||||
|    int mode; | ||||
|    int opts; | ||||
|    int indent_size; | ||||
| 
 | ||||
| } json_serialize_opts; | ||||
| 
 | ||||
| 
 | ||||
| /* Returns a length in characters that is at least large enough to hold the
 | ||||
|  * value in its serialized form, including a null terminator. | ||||
|  */ | ||||
| size_t json_measure (json_value *); | ||||
| size_t json_measure_ex (json_value *, json_serialize_opts); | ||||
| 
 | ||||
| 
 | ||||
| /* Serializes a JSON value into the buffer given (which must already be
 | ||||
|  * allocated with a length of at least json_measure(value, opts)) | ||||
|  */ | ||||
| void json_serialize (json_char * buf, json_value *); | ||||
| void json_serialize_ex (json_char * buf, json_value *, json_serialize_opts); | ||||
| 
 | ||||
| 
 | ||||
| /*** Cleaning up
 | ||||
|  ***/ | ||||
| void json_builder_free (json_value *); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										283
									
								
								json.h
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								json.h
									
									
									
									
									
								
							| @ -1,283 +0,0 @@ | ||||
| 
 | ||||
| /* vim: set et ts=3 sw=3 sts=3 ft=c:
 | ||||
|  * | ||||
|  * Copyright (C) 2012, 2013, 2014 James McLaughlin et al.  All rights reserved. | ||||
|  * https://github.com/udp/json-parser
 | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *   notice, this list of conditions and the following disclaimer in the | ||||
|  *   documentation and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _JSON_H | ||||
| #define _JSON_H | ||||
| 
 | ||||
| #ifndef json_char | ||||
|    #define json_char char | ||||
| #endif | ||||
| 
 | ||||
| #ifndef json_int_t | ||||
|    #ifndef _MSC_VER | ||||
|       #include <inttypes.h> | ||||
|       #define json_int_t int64_t | ||||
|    #else | ||||
|       #define json_int_t __int64 | ||||
|    #endif | ||||
| #endif | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| 
 | ||||
|    #include <string.h> | ||||
| 
 | ||||
|    extern "C" | ||||
|    { | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
|    unsigned long max_memory; | ||||
|    int settings; | ||||
| 
 | ||||
|    /* Custom allocator support (leave null to use malloc/free)
 | ||||
|     */ | ||||
| 
 | ||||
|    void * (* mem_alloc) (size_t, int zero, void * user_data); | ||||
|    void (* mem_free) (void *, void * user_data); | ||||
| 
 | ||||
|    void * user_data;  /* will be passed to mem_alloc and mem_free */ | ||||
| 
 | ||||
|    size_t value_extra;  /* how much extra space to allocate for values? */ | ||||
| 
 | ||||
| } json_settings; | ||||
| 
 | ||||
| #define json_enable_comments  0x01 | ||||
| 
 | ||||
| typedef enum | ||||
| { | ||||
|    json_none, | ||||
|    json_object, | ||||
|    json_array, | ||||
|    json_integer, | ||||
|    json_double, | ||||
|    json_string, | ||||
|    json_boolean, | ||||
|    json_null | ||||
| 
 | ||||
| } json_type; | ||||
| 
 | ||||
| extern const struct _json_value json_value_none; | ||||
|         | ||||
| typedef struct _json_object_entry | ||||
| { | ||||
|     json_char * name; | ||||
|     unsigned int name_length; | ||||
|      | ||||
|     struct _json_value * value; | ||||
|      | ||||
| } json_object_entry; | ||||
| 
 | ||||
| typedef struct _json_value | ||||
| { | ||||
|    struct _json_value * parent; | ||||
| 
 | ||||
|    json_type type; | ||||
| 
 | ||||
|    union | ||||
|    { | ||||
|       int boolean; | ||||
|       json_int_t integer; | ||||
|       double dbl; | ||||
| 
 | ||||
|       struct | ||||
|       { | ||||
|          unsigned int length; | ||||
|          json_char * ptr; /* null terminated */ | ||||
| 
 | ||||
|       } string; | ||||
| 
 | ||||
|       struct | ||||
|       { | ||||
|          unsigned int length; | ||||
| 
 | ||||
|          json_object_entry * values; | ||||
| 
 | ||||
|          #if defined(__cplusplus) && __cplusplus >= 201103L | ||||
|          decltype(values) begin () const | ||||
|          {  return values; | ||||
|          } | ||||
|          decltype(values) end () const | ||||
|          {  return values + length; | ||||
|          } | ||||
|          #endif | ||||
| 
 | ||||
|       } object; | ||||
| 
 | ||||
|       struct | ||||
|       { | ||||
|          unsigned int length; | ||||
|          struct _json_value ** values; | ||||
| 
 | ||||
|          #if defined(__cplusplus) && __cplusplus >= 201103L | ||||
|          decltype(values) begin () const | ||||
|          {  return values; | ||||
|          } | ||||
|          decltype(values) end () const | ||||
|          {  return values + length; | ||||
|          } | ||||
|          #endif | ||||
| 
 | ||||
|       } array; | ||||
| 
 | ||||
|    } u; | ||||
| 
 | ||||
|    union | ||||
|    { | ||||
|       struct _json_value * next_alloc; | ||||
|       void * object_mem; | ||||
| 
 | ||||
|    } _reserved; | ||||
| 
 | ||||
|    #ifdef JSON_TRACK_SOURCE | ||||
| 
 | ||||
|       /* Location of the value in the source JSON
 | ||||
|        */ | ||||
|       unsigned int line, col; | ||||
| 
 | ||||
|    #endif | ||||
| 
 | ||||
| 
 | ||||
|    /* Some C++ operator sugar */ | ||||
| 
 | ||||
|    #ifdef __cplusplus | ||||
| 
 | ||||
|       public: | ||||
| 
 | ||||
|          inline _json_value () | ||||
|          {  memset (this, 0, sizeof (_json_value)); | ||||
|          } | ||||
| 
 | ||||
|          inline const struct _json_value &operator [] (int index) const | ||||
|          { | ||||
|             if (type != json_array || index < 0 | ||||
|                      || ((unsigned int) index) >= u.array.length) | ||||
|             { | ||||
|                return json_value_none; | ||||
|             } | ||||
| 
 | ||||
|             return *u.array.values [index]; | ||||
|          } | ||||
| 
 | ||||
|          inline const struct _json_value &operator [] (const char * index) const | ||||
|          {  | ||||
|             if (type != json_object) | ||||
|                return json_value_none; | ||||
| 
 | ||||
|             for (unsigned int i = 0; i < u.object.length; ++ i) | ||||
|                if (!strcmp (u.object.values [i].name, index)) | ||||
|                   return *u.object.values [i].value; | ||||
| 
 | ||||
|             return json_value_none; | ||||
|          } | ||||
| 
 | ||||
|          inline operator const char * () const | ||||
|          {   | ||||
|             switch (type) | ||||
|             { | ||||
|                case json_string: | ||||
|                   return u.string.ptr; | ||||
| 
 | ||||
|                default: | ||||
|                   return ""; | ||||
|             }; | ||||
|          } | ||||
| 
 | ||||
|          inline operator json_int_t () const | ||||
|          {   | ||||
|             switch (type) | ||||
|             { | ||||
|                case json_integer: | ||||
|                   return u.integer; | ||||
| 
 | ||||
|                case json_double: | ||||
|                   return (json_int_t) u.dbl; | ||||
| 
 | ||||
|                default: | ||||
|                   return 0; | ||||
|             }; | ||||
|          } | ||||
| 
 | ||||
|          inline operator bool () const | ||||
|          {   | ||||
|             if (type != json_boolean) | ||||
|                return false; | ||||
| 
 | ||||
|             return u.boolean != 0; | ||||
|          } | ||||
| 
 | ||||
|          inline operator double () const | ||||
|          {   | ||||
|             switch (type) | ||||
|             { | ||||
|                case json_integer: | ||||
|                   return (double) u.integer; | ||||
| 
 | ||||
|                case json_double: | ||||
|                   return u.dbl; | ||||
| 
 | ||||
|                default: | ||||
|                   return 0; | ||||
|             }; | ||||
|          } | ||||
| 
 | ||||
|    #endif | ||||
| 
 | ||||
| } json_value; | ||||
|         | ||||
| json_value * json_parse (const json_char * json, | ||||
|                          size_t length); | ||||
| 
 | ||||
| #define json_error_max 128 | ||||
| json_value * json_parse_ex (json_settings * settings, | ||||
|                             const json_char * json, | ||||
|                             size_t length, | ||||
|                             char * error); | ||||
| 
 | ||||
| void json_value_free (json_value *); | ||||
| 
 | ||||
| 
 | ||||
| /* Not usually necessary, unless you used a custom mem_alloc and now want to
 | ||||
|  * use a custom mem_free. | ||||
|  */ | ||||
| void json_value_free_ex (json_settings * settings, | ||||
|                          json_value *); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|    } /* extern "C" */ | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user