xref: /aosp_15_r20/external/sg3_utils/lib/sg_json_builder.h (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
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