• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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