1 2 /* vim: set et ts=3 sw=3 sts=3 ft=c: 3 * 4 * Copyright (C) 2014 James McLaughlin. All rights reserved. 5 * https://github.com/udp/json-builder 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #ifndef SG_JSON_BUILDER_H 32 #define SG_JSON_BUILDER_H 33 34 /* This code was fetched from https://github.com/json-parser/json-builder 35 * and comes with the 2 clause BSD license (shown above) which is the same 36 * license that most of the rest of this package uses. 37 * 38 * This header file is in this 'lib' directory so its interface is _not_ 39 * published with sg3_utils other header files found in the 'include' 40 * directory. Currently only this header's implementation (i.e. 41 * sg_json_builder.c) and sg_pr2serr.c are the only users of this header. */ 42 43 /* 44 * Used to require json.h from json-parser but what was needed as been 45 * included in this header. 46 * https://github.com/udp/json-parser 47 */ 48 /* #include "json.h" */ 49 50 #ifndef json_char 51 #define json_char char 52 #endif 53 54 #ifndef json_int_t 55 #undef JSON_INT_T_OVERRIDDEN 56 #if defined(_MSC_VER) 57 #define json_int_t __int64 58 #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__cplusplus) && __cplusplus >= 201103L) 59 /* C99 and C++11 */ 60 #include <stdint.h> 61 #define json_int_t int_fast64_t 62 #else 63 /* C89 */ 64 #define json_int_t long 65 #endif 66 #else 67 #define JSON_INT_T_OVERRIDDEN 1 68 #endif 69 70 #include <stddef.h> 71 72 #ifdef __cplusplus 73 74 #include <string.h> 75 76 extern "C" 77 { 78 79 #endif 80 81 typedef struct 82 { 83 unsigned long max_memory; /* should be size_t, but would modify the API */ 84 int settings; 85 86 /* Custom allocator support (leave null to use malloc/free) 87 */ 88 89 void * (* mem_alloc) (size_t, int zero, void * user_data); 90 void (* mem_free) (void *, void * user_data); 91 92 void * user_data; /* will be passed to mem_alloc and mem_free */ 93 94 size_t value_extra; /* how much extra space to allocate for values? */ 95 96 } json_settings; 97 98 #define json_enable_comments 0x01 99 100 typedef enum 101 { 102 json_none, 103 json_object, 104 json_array, 105 json_integer, 106 json_double, 107 json_string, 108 json_boolean, 109 json_null 110 111 } json_type; 112 113 extern const struct _json_value json_value_none; 114 115 typedef struct _json_object_entry 116 { 117 json_char * name; 118 unsigned int name_length; 119 120 struct _json_value * value; 121 122 } json_object_entry; 123 124 typedef struct _json_value 125 { 126 struct _json_value * parent; 127 128 json_type type; 129 130 union 131 { 132 int boolean; 133 json_int_t integer; 134 double dbl; 135 136 struct 137 { 138 unsigned int length; 139 json_char * ptr; /* null terminated */ 140 141 } string; 142 143 struct 144 { 145 unsigned int length; 146 147 json_object_entry * values; 148 149 #if defined(__cplusplus) begin_json_value::__anoncb312977030a::__anoncb3129770508150 json_object_entry * begin () const 151 { return values; 152 } end_json_value::__anoncb312977030a::__anoncb3129770508153 json_object_entry * end () const 154 { return values + length; 155 } 156 #endif 157 158 } object; 159 160 struct 161 { 162 unsigned int length; 163 struct _json_value ** values; 164 165 #if defined(__cplusplus) begin_json_value::__anoncb312977030a::__anoncb3129770608166 _json_value ** begin () const 167 { return values; 168 } end_json_value::__anoncb312977030a::__anoncb3129770608169 _json_value ** end () const 170 { return values + length; 171 } 172 #endif 173 174 } array; 175 176 } u; 177 178 union 179 { 180 struct _json_value * next_alloc; 181 void * object_mem; 182 183 } _reserved; 184 185 #ifdef JSON_TRACK_SOURCE 186 187 /* Location of the value in the source JSON 188 */ 189 unsigned int line, col; 190 191 #endif 192 193 194 /* C++ operator sugar removed */ 195 196 } json_value; 197 198 #if 0 199 #define json_error_max 128 200 json_value * json_parse_ex (json_settings * settings, 201 const json_char * json, 202 size_t length, 203 char * error); 204 205 void json_value_free (json_value *); 206 207 208 /* Not usually necessary, unless you used a custom mem_alloc and now want to 209 * use a custom mem_free. 210 */ 211 void json_value_free_ex (json_settings * settings, 212 json_value *); 213 #endif 214 215 /* <<< end of code from json-parser's json.h >>> */ 216 217 218 /* IMPORTANT NOTE: If you want to use json-builder functions with values 219 * allocated by json-parser as part of the parsing process, you must pass 220 * json_builder_extra as the value_extra setting in json_settings when 221 * parsing. Otherwise there will not be room for the extra state and 222 * json-builder WILL invoke undefined behaviour. 223 * 224 * Also note that unlike json-parser, json-builder does not currently support 225 * custom allocators (for no particular reason other than that it doesn't have 226 * any settings or global state.) 227 */ 228 extern const size_t json_builder_extra; 229 230 231 /*** Arrays 232 *** 233 * Note that all of these length arguments are just a hint to allow for 234 * pre-allocation - passing 0 is fine. 235 */ 236 json_value * json_array_new (size_t length); 237 json_value * json_array_push (json_value * array, json_value *); 238 239 240 /*** Objects 241 ***/ 242 json_value * json_object_new (size_t length); 243 244 json_value * json_object_push (json_value * object, 245 const json_char * name, 246 json_value *); 247 248 /* Same as json_object_push, but doesn't call strlen() for you. 249 */ 250 json_value * json_object_push_length (json_value * object, 251 unsigned int name_length, const json_char * name, 252 json_value *); 253 254 /* Same as json_object_push_length, but doesn't copy the name buffer before 255 * storing it in the value. Use this micro-optimisation at your own risk. 256 */ 257 json_value * json_object_push_nocopy (json_value * object, 258 unsigned int name_length, json_char * name, 259 json_value *); 260 261 /* Merges all entries from objectB into objectA and destroys objectB. 262 */ 263 json_value * json_object_merge (json_value * objectA, json_value * objectB); 264 265 /* Sort the entries of an object based on the order in a prototype object. 266 * Helpful when reading JSON and writing it again to preserve user order. 267 */ 268 void json_object_sort (json_value * object, json_value * proto); 269 270 271 272 /*** Strings 273 ***/ 274 json_value * json_string_new (const json_char *); 275 json_value * json_string_new_length (unsigned int length, const json_char *); 276 json_value * json_string_new_nocopy (unsigned int length, json_char *); 277 278 279 /*** Everything else 280 ***/ 281 json_value * json_integer_new (json_int_t); 282 json_value * json_double_new (double); 283 json_value * json_boolean_new (int); 284 json_value * json_null_new (void); 285 286 287 /*** Serializing 288 ***/ 289 #define json_serialize_mode_multiline 0 290 #define json_serialize_mode_single_line 1 291 #define json_serialize_mode_packed 2 292 293 #define json_serialize_opt_CRLF (1 << 1) 294 #define json_serialize_opt_pack_brackets (1 << 2) 295 #define json_serialize_opt_no_space_after_comma (1 << 3) 296 #define json_serialize_opt_no_space_after_colon (1 << 4) 297 #define json_serialize_opt_use_tabs (1 << 5) 298 299 typedef struct json_serialize_opts 300 { 301 int mode; 302 int opts; 303 int indent_size; 304 305 } json_serialize_opts; 306 307 308 /* Returns a length in characters that is at least large enough to hold the 309 * value in its serialized form, including a null terminator. 310 */ 311 size_t json_measure (json_value *); 312 size_t json_measure_ex (json_value *, json_serialize_opts); 313 314 315 /* Serializes a JSON value into the buffer given (which must already be 316 * allocated with a length of at least json_measure(value, opts)) 317 */ 318 void json_serialize (json_char * buf, json_value *); 319 void json_serialize_ex (json_char * buf, json_value *, json_serialize_opts); 320 321 322 /*** Cleaning up 323 ***/ 324 void json_builder_free (json_value *); 325 326 #ifdef __cplusplus 327 } 328 #endif 329 330 #endif /* SG_JSON_BUILDER_H */ 331 332 333 334