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