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