xref: /aosp_15_r20/external/sg3_utils/lib/sg_json_builder.c (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 #include "sg_json_builder.h"
32*44704f69SBart Van Assche 
33*44704f69SBart Van Assche #include <string.h>
34*44704f69SBart Van Assche #include <assert.h>
35*44704f69SBart Van Assche #include <stdlib.h>
36*44704f69SBart Van Assche #include <stdio.h>
37*44704f69SBart Van Assche 
38*44704f69SBart Van Assche /* This code was fetched from https://github.com/json-parser/json-builder
39*44704f69SBart Van Assche  * and comes with the 2 clause BSD license (shown above) which is the same
40*44704f69SBart Van Assche  * license that most of the rest of this package uses. */
41*44704f69SBart Van Assche 
42*44704f69SBart Van Assche #ifdef _MSC_VER
43*44704f69SBart Van Assche     #define snprintf _snprintf
44*44704f69SBart Van Assche #endif
45*44704f69SBart Van Assche 
46*44704f69SBart Van Assche static const json_serialize_opts default_opts =
47*44704f69SBart Van Assche {
48*44704f69SBart Van Assche    json_serialize_mode_single_line,
49*44704f69SBart Van Assche    0,
50*44704f69SBart Van Assche    3  /* indent_size */
51*44704f69SBart Van Assche };
52*44704f69SBart Van Assche 
53*44704f69SBart Van Assche typedef struct json_builder_value
54*44704f69SBart Van Assche {
55*44704f69SBart Van Assche    json_value value;
56*44704f69SBart Van Assche 
57*44704f69SBart Van Assche    int is_builder_value;
58*44704f69SBart Van Assche 
59*44704f69SBart Van Assche    size_t additional_length_allocated;
60*44704f69SBart Van Assche    size_t length_iterated;
61*44704f69SBart Van Assche 
62*44704f69SBart Van Assche } json_builder_value;
63*44704f69SBart Van Assche 
builderize(json_value * value)64*44704f69SBart Van Assche static int builderize (json_value * value)
65*44704f69SBart Van Assche {
66*44704f69SBart Van Assche    if (((json_builder_value *) value)->is_builder_value)
67*44704f69SBart Van Assche       return 1;
68*44704f69SBart Van Assche 
69*44704f69SBart Van Assche    if (value->type == json_object)
70*44704f69SBart Van Assche    {
71*44704f69SBart Van Assche       unsigned int i;
72*44704f69SBart Van Assche 
73*44704f69SBart Van Assche       /* Values straight out of the parser have the names of object entries
74*44704f69SBart Van Assche        * allocated in the same allocation as the values array itself.  This is
75*44704f69SBart Van Assche        * not desirable when manipulating values because the names would be easy
76*44704f69SBart Van Assche        * to clobber.
77*44704f69SBart Van Assche        */
78*44704f69SBart Van Assche       for (i = 0; i < value->u.object.length; ++ i)
79*44704f69SBart Van Assche       {
80*44704f69SBart Van Assche          json_char * name_copy;
81*44704f69SBart Van Assche          json_object_entry * entry = &value->u.object.values [i];
82*44704f69SBart Van Assche 
83*44704f69SBart Van Assche          if (! (name_copy = (json_char *) malloc ((entry->name_length + 1) * sizeof (json_char))))
84*44704f69SBart Van Assche             return 0;
85*44704f69SBart Van Assche 
86*44704f69SBart Van Assche          memcpy (name_copy, entry->name, entry->name_length + 1);
87*44704f69SBart Van Assche          entry->name = name_copy;
88*44704f69SBart Van Assche       }
89*44704f69SBart Van Assche    }
90*44704f69SBart Van Assche 
91*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
92*44704f69SBart Van Assche 
93*44704f69SBart Van Assche    return 1;
94*44704f69SBart Van Assche }
95*44704f69SBart Van Assche 
96*44704f69SBart Van Assche const size_t json_builder_extra = sizeof(json_builder_value) - sizeof(json_value);
97*44704f69SBart Van Assche 
98*44704f69SBart Van Assche /* These flags are set up from the opts before serializing to make the
99*44704f69SBart Van Assche  * serializer conditions simpler.
100*44704f69SBart Van Assche  */
101*44704f69SBart Van Assche const int f_spaces_around_brackets = (1 << 0);
102*44704f69SBart Van Assche const int f_spaces_after_commas    = (1 << 1);
103*44704f69SBart Van Assche const int f_spaces_after_colons    = (1 << 2);
104*44704f69SBart Van Assche const int f_tabs                   = (1 << 3);
105*44704f69SBart Van Assche 
get_serialize_flags(json_serialize_opts opts)106*44704f69SBart Van Assche static int get_serialize_flags (json_serialize_opts opts)
107*44704f69SBart Van Assche {
108*44704f69SBart Van Assche    int flags = 0;
109*44704f69SBart Van Assche 
110*44704f69SBart Van Assche    if (opts.mode == json_serialize_mode_packed)
111*44704f69SBart Van Assche       return 0;
112*44704f69SBart Van Assche 
113*44704f69SBart Van Assche    if (opts.mode == json_serialize_mode_multiline)
114*44704f69SBart Van Assche    {
115*44704f69SBart Van Assche       if (opts.opts & json_serialize_opt_use_tabs)
116*44704f69SBart Van Assche          flags |= f_tabs;
117*44704f69SBart Van Assche    }
118*44704f69SBart Van Assche    else
119*44704f69SBart Van Assche    {
120*44704f69SBart Van Assche       if (! (opts.opts & json_serialize_opt_pack_brackets))
121*44704f69SBart Van Assche          flags |= f_spaces_around_brackets;
122*44704f69SBart Van Assche 
123*44704f69SBart Van Assche       if (! (opts.opts & json_serialize_opt_no_space_after_comma))
124*44704f69SBart Van Assche          flags |= f_spaces_after_commas;
125*44704f69SBart Van Assche    }
126*44704f69SBart Van Assche 
127*44704f69SBart Van Assche    if (! (opts.opts & json_serialize_opt_no_space_after_colon))
128*44704f69SBart Van Assche       flags |= f_spaces_after_colons;
129*44704f69SBart Van Assche 
130*44704f69SBart Van Assche    return flags;
131*44704f69SBart Van Assche }
132*44704f69SBart Van Assche 
json_array_new(size_t length)133*44704f69SBart Van Assche json_value * json_array_new (size_t length)
134*44704f69SBart Van Assche {
135*44704f69SBart Van Assche     json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
136*44704f69SBart Van Assche 
137*44704f69SBart Van Assche     if (!value)
138*44704f69SBart Van Assche        return NULL;
139*44704f69SBart Van Assche 
140*44704f69SBart Van Assche     ((json_builder_value *) value)->is_builder_value = 1;
141*44704f69SBart Van Assche 
142*44704f69SBart Van Assche     value->type = json_array;
143*44704f69SBart Van Assche 
144*44704f69SBart Van Assche     if (! (value->u.array.values = (json_value **) malloc (length * sizeof (json_value *))))
145*44704f69SBart Van Assche     {
146*44704f69SBart Van Assche        free (value);
147*44704f69SBart Van Assche        return NULL;
148*44704f69SBart Van Assche     }
149*44704f69SBart Van Assche 
150*44704f69SBart Van Assche     ((json_builder_value *) value)->additional_length_allocated = length;
151*44704f69SBart Van Assche 
152*44704f69SBart Van Assche     return value;
153*44704f69SBart Van Assche }
154*44704f69SBart Van Assche 
json_array_push(json_value * array,json_value * value)155*44704f69SBart Van Assche json_value * json_array_push (json_value * array, json_value * value)
156*44704f69SBart Van Assche {
157*44704f69SBart Van Assche    assert (array->type == json_array);
158*44704f69SBart Van Assche 
159*44704f69SBart Van Assche    if (!builderize (array) || !builderize (value))
160*44704f69SBart Van Assche       return NULL;
161*44704f69SBart Van Assche 
162*44704f69SBart Van Assche    if (((json_builder_value *) array)->additional_length_allocated > 0)
163*44704f69SBart Van Assche    {
164*44704f69SBart Van Assche       -- ((json_builder_value *) array)->additional_length_allocated;
165*44704f69SBart Van Assche    }
166*44704f69SBart Van Assche    else
167*44704f69SBart Van Assche    {
168*44704f69SBart Van Assche       json_value ** values_new = (json_value **) realloc
169*44704f69SBart Van Assche             (array->u.array.values, sizeof (json_value *) * (array->u.array.length + 1));
170*44704f69SBart Van Assche 
171*44704f69SBart Van Assche       if (!values_new)
172*44704f69SBart Van Assche          return NULL;
173*44704f69SBart Van Assche 
174*44704f69SBart Van Assche       array->u.array.values = values_new;
175*44704f69SBart Van Assche    }
176*44704f69SBart Van Assche 
177*44704f69SBart Van Assche    array->u.array.values [array->u.array.length] = value;
178*44704f69SBart Van Assche    ++ array->u.array.length;
179*44704f69SBart Van Assche 
180*44704f69SBart Van Assche    value->parent = array;
181*44704f69SBart Van Assche 
182*44704f69SBart Van Assche    return value;
183*44704f69SBart Van Assche }
184*44704f69SBart Van Assche 
json_object_new(size_t length)185*44704f69SBart Van Assche json_value * json_object_new (size_t length)
186*44704f69SBart Van Assche {
187*44704f69SBart Van Assche     json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
188*44704f69SBart Van Assche 
189*44704f69SBart Van Assche     if (!value)
190*44704f69SBart Van Assche        return NULL;
191*44704f69SBart Van Assche 
192*44704f69SBart Van Assche     ((json_builder_value *) value)->is_builder_value = 1;
193*44704f69SBart Van Assche 
194*44704f69SBart Van Assche     value->type = json_object;
195*44704f69SBart Van Assche 
196*44704f69SBart Van Assche     if (! (value->u.object.values = (json_object_entry *) calloc
197*44704f69SBart Van Assche            (length, sizeof (*value->u.object.values))))
198*44704f69SBart Van Assche     {
199*44704f69SBart Van Assche        free (value);
200*44704f69SBart Van Assche        return NULL;
201*44704f69SBart Van Assche     }
202*44704f69SBart Van Assche 
203*44704f69SBart Van Assche     ((json_builder_value *) value)->additional_length_allocated = length;
204*44704f69SBart Van Assche 
205*44704f69SBart Van Assche     return value;
206*44704f69SBart Van Assche }
207*44704f69SBart Van Assche 
json_object_push(json_value * object,const json_char * name,json_value * value)208*44704f69SBart Van Assche json_value * json_object_push (json_value * object,
209*44704f69SBart Van Assche                                const json_char * name,
210*44704f69SBart Van Assche                                json_value * value)
211*44704f69SBart Van Assche {
212*44704f69SBart Van Assche    return json_object_push_length (object, strlen (name), name, value);
213*44704f69SBart Van Assche }
214*44704f69SBart Van Assche 
json_object_push_length(json_value * object,unsigned int name_length,const json_char * name,json_value * value)215*44704f69SBart Van Assche json_value * json_object_push_length (json_value * object,
216*44704f69SBart Van Assche                                       unsigned int name_length, const json_char * name,
217*44704f69SBart Van Assche                                       json_value * value)
218*44704f69SBart Van Assche {
219*44704f69SBart Van Assche    json_char * name_copy;
220*44704f69SBart Van Assche 
221*44704f69SBart Van Assche    assert (object->type == json_object);
222*44704f69SBart Van Assche 
223*44704f69SBart Van Assche    if (! (name_copy = (json_char *) malloc ((name_length + 1) * sizeof (json_char))))
224*44704f69SBart Van Assche       return NULL;
225*44704f69SBart Van Assche 
226*44704f69SBart Van Assche    memcpy (name_copy, name, name_length * sizeof (json_char));
227*44704f69SBart Van Assche    name_copy [name_length] = 0;
228*44704f69SBart Van Assche 
229*44704f69SBart Van Assche    if (!json_object_push_nocopy (object, name_length, name_copy, value))
230*44704f69SBart Van Assche    {
231*44704f69SBart Van Assche       free (name_copy);
232*44704f69SBart Van Assche       return NULL;
233*44704f69SBart Van Assche    }
234*44704f69SBart Van Assche 
235*44704f69SBart Van Assche    return value;
236*44704f69SBart Van Assche }
237*44704f69SBart Van Assche 
json_object_push_nocopy(json_value * object,unsigned int name_length,json_char * name,json_value * value)238*44704f69SBart Van Assche json_value * json_object_push_nocopy (json_value * object,
239*44704f69SBart Van Assche                                       unsigned int name_length, json_char * name,
240*44704f69SBart Van Assche                                       json_value * value)
241*44704f69SBart Van Assche {
242*44704f69SBart Van Assche    json_object_entry * entry;
243*44704f69SBart Van Assche 
244*44704f69SBart Van Assche    assert (object->type == json_object);
245*44704f69SBart Van Assche 
246*44704f69SBart Van Assche    if (!builderize (object) || !builderize (value))
247*44704f69SBart Van Assche       return NULL;
248*44704f69SBart Van Assche 
249*44704f69SBart Van Assche    if (((json_builder_value *) object)->additional_length_allocated > 0)
250*44704f69SBart Van Assche    {
251*44704f69SBart Van Assche       -- ((json_builder_value *) object)->additional_length_allocated;
252*44704f69SBart Van Assche    }
253*44704f69SBart Van Assche    else
254*44704f69SBart Van Assche    {
255*44704f69SBart Van Assche       json_object_entry * values_new = (json_object_entry *)
256*44704f69SBart Van Assche             realloc (object->u.object.values, sizeof (*object->u.object.values)
257*44704f69SBart Van Assche                             * (object->u.object.length + 1));
258*44704f69SBart Van Assche 
259*44704f69SBart Van Assche       if (!values_new)
260*44704f69SBart Van Assche          return NULL;
261*44704f69SBart Van Assche 
262*44704f69SBart Van Assche       object->u.object.values = values_new;
263*44704f69SBart Van Assche    }
264*44704f69SBart Van Assche 
265*44704f69SBart Van Assche    entry = object->u.object.values + object->u.object.length;
266*44704f69SBart Van Assche 
267*44704f69SBart Van Assche    entry->name_length = name_length;
268*44704f69SBart Van Assche    entry->name = name;
269*44704f69SBart Van Assche    entry->value = value;
270*44704f69SBart Van Assche 
271*44704f69SBart Van Assche    ++ object->u.object.length;
272*44704f69SBart Van Assche 
273*44704f69SBart Van Assche    value->parent = object;
274*44704f69SBart Van Assche 
275*44704f69SBart Van Assche    return value;
276*44704f69SBart Van Assche }
277*44704f69SBart Van Assche 
json_string_new(const json_char * buf)278*44704f69SBart Van Assche json_value * json_string_new (const json_char * buf)
279*44704f69SBart Van Assche {
280*44704f69SBart Van Assche    return json_string_new_length (strlen (buf), buf);
281*44704f69SBart Van Assche }
282*44704f69SBart Van Assche 
json_string_new_length(unsigned int length,const json_char * buf)283*44704f69SBart Van Assche json_value * json_string_new_length (unsigned int length, const json_char * buf)
284*44704f69SBart Van Assche {
285*44704f69SBart Van Assche    json_value * value;
286*44704f69SBart Van Assche    json_char * copy = (json_char *) malloc ((length + 1) * sizeof (json_char));
287*44704f69SBart Van Assche 
288*44704f69SBart Van Assche    if (!copy)
289*44704f69SBart Van Assche       return NULL;
290*44704f69SBart Van Assche 
291*44704f69SBart Van Assche    memcpy (copy, buf, length * sizeof (json_char));
292*44704f69SBart Van Assche    copy [length] = 0;
293*44704f69SBart Van Assche 
294*44704f69SBart Van Assche    if (! (value = json_string_new_nocopy (length, copy)))
295*44704f69SBart Van Assche    {
296*44704f69SBart Van Assche       free (copy);
297*44704f69SBart Van Assche       return NULL;
298*44704f69SBart Van Assche    }
299*44704f69SBart Van Assche 
300*44704f69SBart Van Assche    return value;
301*44704f69SBart Van Assche }
302*44704f69SBart Van Assche 
json_string_new_nocopy(unsigned int length,json_char * buf)303*44704f69SBart Van Assche json_value * json_string_new_nocopy (unsigned int length, json_char * buf)
304*44704f69SBart Van Assche {
305*44704f69SBart Van Assche    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
306*44704f69SBart Van Assche 
307*44704f69SBart Van Assche    if (!value)
308*44704f69SBart Van Assche       return NULL;
309*44704f69SBart Van Assche 
310*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
311*44704f69SBart Van Assche 
312*44704f69SBart Van Assche    value->type = json_string;
313*44704f69SBart Van Assche    value->u.string.length = length;
314*44704f69SBart Van Assche    value->u.string.ptr = buf;
315*44704f69SBart Van Assche 
316*44704f69SBart Van Assche    return value;
317*44704f69SBart Van Assche }
318*44704f69SBart Van Assche 
json_integer_new(json_int_t integer)319*44704f69SBart Van Assche json_value * json_integer_new (json_int_t integer)
320*44704f69SBart Van Assche {
321*44704f69SBart Van Assche    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
322*44704f69SBart Van Assche 
323*44704f69SBart Van Assche    if (!value)
324*44704f69SBart Van Assche       return NULL;
325*44704f69SBart Van Assche 
326*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
327*44704f69SBart Van Assche 
328*44704f69SBart Van Assche    value->type = json_integer;
329*44704f69SBart Van Assche    value->u.integer = integer;
330*44704f69SBart Van Assche 
331*44704f69SBart Van Assche    return value;
332*44704f69SBart Van Assche }
333*44704f69SBart Van Assche 
json_double_new(double dbl)334*44704f69SBart Van Assche json_value * json_double_new (double dbl)
335*44704f69SBart Van Assche {
336*44704f69SBart Van Assche    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
337*44704f69SBart Van Assche 
338*44704f69SBart Van Assche    if (!value)
339*44704f69SBart Van Assche       return NULL;
340*44704f69SBart Van Assche 
341*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
342*44704f69SBart Van Assche 
343*44704f69SBart Van Assche    value->type = json_double;
344*44704f69SBart Van Assche    value->u.dbl = dbl;
345*44704f69SBart Van Assche 
346*44704f69SBart Van Assche    return value;
347*44704f69SBart Van Assche }
348*44704f69SBart Van Assche 
json_boolean_new(int b)349*44704f69SBart Van Assche json_value * json_boolean_new (int b)
350*44704f69SBart Van Assche {
351*44704f69SBart Van Assche    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
352*44704f69SBart Van Assche 
353*44704f69SBart Van Assche    if (!value)
354*44704f69SBart Van Assche       return NULL;
355*44704f69SBart Van Assche 
356*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
357*44704f69SBart Van Assche 
358*44704f69SBart Van Assche    value->type = json_boolean;
359*44704f69SBart Van Assche    value->u.boolean = b;
360*44704f69SBart Van Assche 
361*44704f69SBart Van Assche    return value;
362*44704f69SBart Van Assche }
363*44704f69SBart Van Assche 
json_null_new(void)364*44704f69SBart Van Assche json_value * json_null_new (void)
365*44704f69SBart Van Assche {
366*44704f69SBart Van Assche    json_value * value = (json_value *) calloc (1, sizeof (json_builder_value));
367*44704f69SBart Van Assche 
368*44704f69SBart Van Assche    if (!value)
369*44704f69SBart Van Assche       return NULL;
370*44704f69SBart Van Assche 
371*44704f69SBart Van Assche    ((json_builder_value *) value)->is_builder_value = 1;
372*44704f69SBart Van Assche 
373*44704f69SBart Van Assche    value->type = json_null;
374*44704f69SBart Van Assche 
375*44704f69SBart Van Assche    return value;
376*44704f69SBart Van Assche }
377*44704f69SBart Van Assche 
json_object_sort(json_value * object,json_value * proto)378*44704f69SBart Van Assche void json_object_sort (json_value * object, json_value * proto)
379*44704f69SBart Van Assche {
380*44704f69SBart Van Assche    unsigned int i, out_index = 0;
381*44704f69SBart Van Assche 
382*44704f69SBart Van Assche    if (!builderize (object))
383*44704f69SBart Van Assche       return;  /* TODO error */
384*44704f69SBart Van Assche 
385*44704f69SBart Van Assche    assert (object->type == json_object);
386*44704f69SBart Van Assche    assert (proto->type == json_object);
387*44704f69SBart Van Assche 
388*44704f69SBart Van Assche    for (i = 0; i < proto->u.object.length; ++ i)
389*44704f69SBart Van Assche    {
390*44704f69SBart Van Assche       unsigned int j;
391*44704f69SBart Van Assche       json_object_entry proto_entry = proto->u.object.values [i];
392*44704f69SBart Van Assche 
393*44704f69SBart Van Assche       for (j = 0; j < object->u.object.length; ++ j)
394*44704f69SBart Van Assche       {
395*44704f69SBart Van Assche          json_object_entry entry = object->u.object.values [j];
396*44704f69SBart Van Assche 
397*44704f69SBart Van Assche          if (entry.name_length != proto_entry.name_length)
398*44704f69SBart Van Assche             continue;
399*44704f69SBart Van Assche 
400*44704f69SBart Van Assche          if (memcmp (entry.name, proto_entry.name, entry.name_length) != 0)
401*44704f69SBart Van Assche             continue;
402*44704f69SBart Van Assche 
403*44704f69SBart Van Assche          object->u.object.values [j] = object->u.object.values [out_index];
404*44704f69SBart Van Assche          object->u.object.values [out_index] = entry;
405*44704f69SBart Van Assche 
406*44704f69SBart Van Assche          ++ out_index;
407*44704f69SBart Van Assche       }
408*44704f69SBart Van Assche    }
409*44704f69SBart Van Assche }
410*44704f69SBart Van Assche 
json_object_merge(json_value * objectA,json_value * objectB)411*44704f69SBart Van Assche json_value * json_object_merge (json_value * objectA, json_value * objectB)
412*44704f69SBart Van Assche {
413*44704f69SBart Van Assche    unsigned int i;
414*44704f69SBart Van Assche 
415*44704f69SBart Van Assche    assert (objectA->type == json_object);
416*44704f69SBart Van Assche    assert (objectB->type == json_object);
417*44704f69SBart Van Assche    assert (objectA != objectB);
418*44704f69SBart Van Assche 
419*44704f69SBart Van Assche    if (!builderize (objectA) || !builderize (objectB))
420*44704f69SBart Van Assche       return NULL;
421*44704f69SBart Van Assche 
422*44704f69SBart Van Assche    if (objectB->u.object.length <=
423*44704f69SBart Van Assche         ((json_builder_value *) objectA)->additional_length_allocated)
424*44704f69SBart Van Assche    {
425*44704f69SBart Van Assche       ((json_builder_value *) objectA)->additional_length_allocated
426*44704f69SBart Van Assche           -= objectB->u.object.length;
427*44704f69SBart Van Assche    }
428*44704f69SBart Van Assche    else
429*44704f69SBart Van Assche    {
430*44704f69SBart Van Assche       json_object_entry * values_new;
431*44704f69SBart Van Assche 
432*44704f69SBart Van Assche       unsigned int alloc =
433*44704f69SBart Van Assche           objectA->u.object.length
434*44704f69SBart Van Assche               + ((json_builder_value *) objectA)->additional_length_allocated
435*44704f69SBart Van Assche               + objectB->u.object.length;
436*44704f69SBart Van Assche 
437*44704f69SBart Van Assche       if (! (values_new = (json_object_entry *)
438*44704f69SBart Van Assche             realloc (objectA->u.object.values, sizeof (json_object_entry) * alloc)))
439*44704f69SBart Van Assche       {
440*44704f69SBart Van Assche           return NULL;
441*44704f69SBart Van Assche       }
442*44704f69SBart Van Assche 
443*44704f69SBart Van Assche       objectA->u.object.values = values_new;
444*44704f69SBart Van Assche    }
445*44704f69SBart Van Assche 
446*44704f69SBart Van Assche    for (i = 0; i < objectB->u.object.length; ++ i)
447*44704f69SBart Van Assche    {
448*44704f69SBart Van Assche       json_object_entry * entry = &objectA->u.object.values[objectA->u.object.length + i];
449*44704f69SBart Van Assche 
450*44704f69SBart Van Assche       *entry = objectB->u.object.values[i];
451*44704f69SBart Van Assche       entry->value->parent = objectA;
452*44704f69SBart Van Assche    }
453*44704f69SBart Van Assche 
454*44704f69SBart Van Assche    objectA->u.object.length += objectB->u.object.length;
455*44704f69SBart Van Assche 
456*44704f69SBart Van Assche    free (objectB->u.object.values);
457*44704f69SBart Van Assche    free (objectB);
458*44704f69SBart Van Assche 
459*44704f69SBart Van Assche    return objectA;
460*44704f69SBart Van Assche }
461*44704f69SBart Van Assche 
measure_string(unsigned int length,const json_char * str)462*44704f69SBart Van Assche static size_t measure_string (unsigned int length,
463*44704f69SBart Van Assche                               const json_char * str)
464*44704f69SBart Van Assche {
465*44704f69SBart Van Assche    unsigned int i;
466*44704f69SBart Van Assche    size_t measured_length = 0;
467*44704f69SBart Van Assche 
468*44704f69SBart Van Assche    for(i = 0; i < length; ++ i)
469*44704f69SBart Van Assche    {
470*44704f69SBart Van Assche       json_char c = str [i];
471*44704f69SBart Van Assche 
472*44704f69SBart Van Assche       switch (c)
473*44704f69SBart Van Assche       {
474*44704f69SBart Van Assche       case '"':
475*44704f69SBart Van Assche       case '\\':
476*44704f69SBart Van Assche       case '\b':
477*44704f69SBart Van Assche       case '\f':
478*44704f69SBart Van Assche       case '\n':
479*44704f69SBart Van Assche       case '\r':
480*44704f69SBart Van Assche       case '\t':
481*44704f69SBart Van Assche 
482*44704f69SBart Van Assche          measured_length += 2;
483*44704f69SBart Van Assche          break;
484*44704f69SBart Van Assche 
485*44704f69SBart Van Assche       default:
486*44704f69SBart Van Assche 
487*44704f69SBart Van Assche          ++ measured_length;
488*44704f69SBart Van Assche          break;
489*44704f69SBart Van Assche       };
490*44704f69SBart Van Assche    };
491*44704f69SBart Van Assche 
492*44704f69SBart Van Assche    return measured_length;
493*44704f69SBart Van Assche }
494*44704f69SBart Van Assche 
495*44704f69SBart Van Assche #define PRINT_ESCAPED(c) do {  \
496*44704f69SBart Van Assche    *buf ++ = '\\';             \
497*44704f69SBart Van Assche    *buf ++ = (c);              \
498*44704f69SBart Van Assche } while(0);                    \
499*44704f69SBart Van Assche 
serialize_string(json_char * buf,unsigned int length,const json_char * str)500*44704f69SBart Van Assche static size_t serialize_string (json_char * buf,
501*44704f69SBart Van Assche                                 unsigned int length,
502*44704f69SBart Van Assche                                 const json_char * str)
503*44704f69SBart Van Assche {
504*44704f69SBart Van Assche    json_char * orig_buf = buf;
505*44704f69SBart Van Assche    unsigned int i;
506*44704f69SBart Van Assche 
507*44704f69SBart Van Assche    for(i = 0; i < length; ++ i)
508*44704f69SBart Van Assche    {
509*44704f69SBart Van Assche       json_char c = str [i];
510*44704f69SBart Van Assche 
511*44704f69SBart Van Assche       switch (c)
512*44704f69SBart Van Assche       {
513*44704f69SBart Van Assche       case '"':   PRINT_ESCAPED ('\"');  continue;
514*44704f69SBart Van Assche       case '\\':  PRINT_ESCAPED ('\\');  continue;
515*44704f69SBart Van Assche       case '\b':  PRINT_ESCAPED ('b');   continue;
516*44704f69SBart Van Assche       case '\f':  PRINT_ESCAPED ('f');   continue;
517*44704f69SBart Van Assche       case '\n':  PRINT_ESCAPED ('n');   continue;
518*44704f69SBart Van Assche       case '\r':  PRINT_ESCAPED ('r');   continue;
519*44704f69SBart Van Assche       case '\t':  PRINT_ESCAPED ('t');   continue;
520*44704f69SBart Van Assche 
521*44704f69SBart Van Assche       default:
522*44704f69SBart Van Assche 
523*44704f69SBart Van Assche          *buf ++ = c;
524*44704f69SBart Van Assche          break;
525*44704f69SBart Van Assche       };
526*44704f69SBart Van Assche    };
527*44704f69SBart Van Assche 
528*44704f69SBart Van Assche    return buf - orig_buf;
529*44704f69SBart Van Assche }
530*44704f69SBart Van Assche 
json_measure(json_value * value)531*44704f69SBart Van Assche size_t json_measure (json_value * value)
532*44704f69SBart Van Assche {
533*44704f69SBart Van Assche    return json_measure_ex (value, default_opts);
534*44704f69SBart Van Assche }
535*44704f69SBart Van Assche 
536*44704f69SBart Van Assche #define MEASURE_NEWLINE() do {                     \
537*44704f69SBart Van Assche    ++ newlines;                                    \
538*44704f69SBart Van Assche    indents += depth;                               \
539*44704f69SBart Van Assche } while(0);                                        \
540*44704f69SBart Van Assche 
json_measure_ex(json_value * value,json_serialize_opts opts)541*44704f69SBart Van Assche size_t json_measure_ex (json_value * value, json_serialize_opts opts)
542*44704f69SBart Van Assche {
543*44704f69SBart Van Assche    size_t total = 1;  /* null terminator */
544*44704f69SBart Van Assche    size_t newlines = 0;
545*44704f69SBart Van Assche    size_t depth = 0;
546*44704f69SBart Van Assche    size_t indents = 0;
547*44704f69SBart Van Assche    int flags;
548*44704f69SBart Van Assche    int bracket_size, comma_size, colon_size;
549*44704f69SBart Van Assche 
550*44704f69SBart Van Assche    flags = get_serialize_flags (opts);
551*44704f69SBart Van Assche 
552*44704f69SBart Van Assche    /* to reduce branching
553*44704f69SBart Van Assche     */
554*44704f69SBart Van Assche    bracket_size = flags & f_spaces_around_brackets ? 2 : 1;
555*44704f69SBart Van Assche    comma_size = flags & f_spaces_after_commas ? 2 : 1;
556*44704f69SBart Van Assche    colon_size = flags & f_spaces_after_colons ? 2 : 1;
557*44704f69SBart Van Assche 
558*44704f69SBart Van Assche    while (value)
559*44704f69SBart Van Assche    {
560*44704f69SBart Van Assche       json_int_t integer;
561*44704f69SBart Van Assche       json_object_entry * entry;
562*44704f69SBart Van Assche 
563*44704f69SBart Van Assche       switch (value->type)
564*44704f69SBart Van Assche       {
565*44704f69SBart Van Assche          case json_array:
566*44704f69SBart Van Assche 
567*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == 0)
568*44704f69SBart Van Assche             {
569*44704f69SBart Van Assche                if (value->u.array.length == 0)
570*44704f69SBart Van Assche                {
571*44704f69SBart Van Assche                   total += 2;  /* `[]` */
572*44704f69SBart Van Assche                   break;
573*44704f69SBart Van Assche                }
574*44704f69SBart Van Assche 
575*44704f69SBart Van Assche                total += bracket_size;  /* `[` */
576*44704f69SBart Van Assche 
577*44704f69SBart Van Assche                ++ depth;
578*44704f69SBart Van Assche                MEASURE_NEWLINE(); /* \n after [ */
579*44704f69SBart Van Assche             }
580*44704f69SBart Van Assche 
581*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == value->u.array.length)
582*44704f69SBart Van Assche             {
583*44704f69SBart Van Assche                -- depth;
584*44704f69SBart Van Assche                MEASURE_NEWLINE();
585*44704f69SBart Van Assche                total += bracket_size;  /* `]` */
586*44704f69SBart Van Assche 
587*44704f69SBart Van Assche                ((json_builder_value *) value)->length_iterated = 0;
588*44704f69SBart Van Assche                break;
589*44704f69SBart Van Assche             }
590*44704f69SBart Van Assche 
591*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated > 0)
592*44704f69SBart Van Assche             {
593*44704f69SBart Van Assche                total += comma_size;  /* `, ` */
594*44704f69SBart Van Assche 
595*44704f69SBart Van Assche                MEASURE_NEWLINE();
596*44704f69SBart Van Assche             }
597*44704f69SBart Van Assche 
598*44704f69SBart Van Assche             ((json_builder_value *) value)->length_iterated++;
599*44704f69SBart Van Assche             value = value->u.array.values [((json_builder_value *) value)->length_iterated - 1];
600*44704f69SBart Van Assche             continue;
601*44704f69SBart Van Assche 
602*44704f69SBart Van Assche          case json_object:
603*44704f69SBart Van Assche 
604*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == 0)
605*44704f69SBart Van Assche             {
606*44704f69SBart Van Assche                if (value->u.object.length == 0)
607*44704f69SBart Van Assche                {
608*44704f69SBart Van Assche                   total += 2;  /* `{}` */
609*44704f69SBart Van Assche                   break;
610*44704f69SBart Van Assche                }
611*44704f69SBart Van Assche 
612*44704f69SBart Van Assche                total += bracket_size;  /* `{` */
613*44704f69SBart Van Assche 
614*44704f69SBart Van Assche                ++ depth;
615*44704f69SBart Van Assche                MEASURE_NEWLINE(); /* \n after { */
616*44704f69SBart Van Assche             }
617*44704f69SBart Van Assche 
618*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == value->u.object.length)
619*44704f69SBart Van Assche             {
620*44704f69SBart Van Assche                -- depth;
621*44704f69SBart Van Assche                MEASURE_NEWLINE();
622*44704f69SBart Van Assche                total += bracket_size;  /* `}` */
623*44704f69SBart Van Assche 
624*44704f69SBart Van Assche                ((json_builder_value *) value)->length_iterated = 0;
625*44704f69SBart Van Assche                break;
626*44704f69SBart Van Assche             }
627*44704f69SBart Van Assche 
628*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated > 0)
629*44704f69SBart Van Assche             {
630*44704f69SBart Van Assche                total += comma_size;  /* `, ` */
631*44704f69SBart Van Assche                MEASURE_NEWLINE();
632*44704f69SBart Van Assche             }
633*44704f69SBart Van Assche 
634*44704f69SBart Van Assche             entry = value->u.object.values + (((json_builder_value *) value)->length_iterated ++);
635*44704f69SBart Van Assche 
636*44704f69SBart Van Assche             total += 2 + colon_size;  /* `"": ` */
637*44704f69SBart Van Assche             total += measure_string (entry->name_length, entry->name);
638*44704f69SBart Van Assche 
639*44704f69SBart Van Assche             value = entry->value;
640*44704f69SBart Van Assche             continue;
641*44704f69SBart Van Assche 
642*44704f69SBart Van Assche          case json_string:
643*44704f69SBart Van Assche 
644*44704f69SBart Van Assche             total += 2;  /* `""` */
645*44704f69SBart Van Assche             total += measure_string (value->u.string.length, value->u.string.ptr);
646*44704f69SBart Van Assche             break;
647*44704f69SBart Van Assche 
648*44704f69SBart Van Assche          case json_integer:
649*44704f69SBart Van Assche 
650*44704f69SBart Van Assche             integer = value->u.integer;
651*44704f69SBart Van Assche 
652*44704f69SBart Van Assche             if (integer < 0)
653*44704f69SBart Van Assche             {
654*44704f69SBart Van Assche                total += 1;  /* `-` */
655*44704f69SBart Van Assche                integer = - integer;
656*44704f69SBart Van Assche             }
657*44704f69SBart Van Assche 
658*44704f69SBart Van Assche             ++ total;  /* first digit */
659*44704f69SBart Van Assche 
660*44704f69SBart Van Assche             while (integer >= 10)
661*44704f69SBart Van Assche             {
662*44704f69SBart Van Assche                ++ total;  /* another digit */
663*44704f69SBart Van Assche                integer /= 10;
664*44704f69SBart Van Assche             }
665*44704f69SBart Van Assche 
666*44704f69SBart Van Assche             break;
667*44704f69SBart Van Assche 
668*44704f69SBart Van Assche          case json_double:
669*44704f69SBart Van Assche 
670*44704f69SBart Van Assche             total += snprintf (NULL, 0, "%g", value->u.dbl);
671*44704f69SBart Van Assche 
672*44704f69SBart Van Assche             /* Because sometimes we need to add ".0" if sprintf does not do it
673*44704f69SBart Van Assche              * for us. Downside is that we allocate more bytes than strictly
674*44704f69SBart Van Assche              * needed for serialization.
675*44704f69SBart Van Assche              */
676*44704f69SBart Van Assche             total += 2;
677*44704f69SBart Van Assche 
678*44704f69SBart Van Assche             break;
679*44704f69SBart Van Assche 
680*44704f69SBart Van Assche          case json_boolean:
681*44704f69SBart Van Assche 
682*44704f69SBart Van Assche             total += value->u.boolean ?
683*44704f69SBart Van Assche                4:  /* `true` */
684*44704f69SBart Van Assche                5;  /* `false` */
685*44704f69SBart Van Assche 
686*44704f69SBart Van Assche             break;
687*44704f69SBart Van Assche 
688*44704f69SBart Van Assche          case json_null:
689*44704f69SBart Van Assche 
690*44704f69SBart Van Assche             total += 4;  /* `null` */
691*44704f69SBart Van Assche             break;
692*44704f69SBart Van Assche 
693*44704f69SBart Van Assche          default:
694*44704f69SBart Van Assche             break;
695*44704f69SBart Van Assche       };
696*44704f69SBart Van Assche 
697*44704f69SBart Van Assche       value = value->parent;
698*44704f69SBart Van Assche    }
699*44704f69SBart Van Assche 
700*44704f69SBart Van Assche    if (opts.mode == json_serialize_mode_multiline)
701*44704f69SBart Van Assche    {
702*44704f69SBart Van Assche       total += newlines * (((opts.opts & json_serialize_opt_CRLF) ? 2 : 1) + opts.indent_size);
703*44704f69SBart Van Assche       total += indents * opts.indent_size;
704*44704f69SBart Van Assche    }
705*44704f69SBart Van Assche 
706*44704f69SBart Van Assche    return total;
707*44704f69SBart Van Assche }
708*44704f69SBart Van Assche 
json_serialize(json_char * buf,json_value * value)709*44704f69SBart Van Assche void json_serialize (json_char * buf, json_value * value)
710*44704f69SBart Van Assche {
711*44704f69SBart Van Assche    json_serialize_ex (buf, value, default_opts);
712*44704f69SBart Van Assche }
713*44704f69SBart Van Assche 
714*44704f69SBart Van Assche #define PRINT_NEWLINE() do {                          \
715*44704f69SBart Van Assche    if (opts.mode == json_serialize_mode_multiline) {  \
716*44704f69SBart Van Assche       if (opts.opts & json_serialize_opt_CRLF)        \
717*44704f69SBart Van Assche          *buf ++ = '\r';                              \
718*44704f69SBart Van Assche       *buf ++ = '\n';                                 \
719*44704f69SBart Van Assche       for(i = 0; i < indent; ++ i)                    \
720*44704f69SBart Van Assche          *buf ++ = indent_char;                       \
721*44704f69SBart Van Assche    }                                                  \
722*44704f69SBart Van Assche } while(0);                                           \
723*44704f69SBart Van Assche 
724*44704f69SBart Van Assche #define PRINT_OPENING_BRACKET(c) do {                 \
725*44704f69SBart Van Assche    *buf ++ = (c);                                     \
726*44704f69SBart Van Assche    if (flags & f_spaces_around_brackets)              \
727*44704f69SBart Van Assche       *buf ++ = ' ';                                  \
728*44704f69SBart Van Assche } while(0);                                           \
729*44704f69SBart Van Assche 
730*44704f69SBart Van Assche #define PRINT_CLOSING_BRACKET(c) do {                 \
731*44704f69SBart Van Assche    if (flags & f_spaces_around_brackets)              \
732*44704f69SBart Van Assche       *buf ++ = ' ';                                  \
733*44704f69SBart Van Assche    *buf ++ = (c);                                     \
734*44704f69SBart Van Assche } while(0);                                           \
735*44704f69SBart Van Assche 
json_serialize_ex(json_char * buf,json_value * value,json_serialize_opts opts)736*44704f69SBart Van Assche void json_serialize_ex (json_char * buf, json_value * value, json_serialize_opts opts)
737*44704f69SBart Van Assche {
738*44704f69SBart Van Assche    json_int_t integer, orig_integer;
739*44704f69SBart Van Assche    json_object_entry * entry;
740*44704f69SBart Van Assche    json_char * ptr, * dot;
741*44704f69SBart Van Assche    int indent = 0;
742*44704f69SBart Van Assche    char indent_char;
743*44704f69SBart Van Assche    int i;
744*44704f69SBart Van Assche    int flags;
745*44704f69SBart Van Assche 
746*44704f69SBart Van Assche    flags = get_serialize_flags (opts);
747*44704f69SBart Van Assche 
748*44704f69SBart Van Assche    indent_char = flags & f_tabs ? '\t' : ' ';
749*44704f69SBart Van Assche 
750*44704f69SBart Van Assche    while (value)
751*44704f69SBart Van Assche    {
752*44704f69SBart Van Assche       switch (value->type)
753*44704f69SBart Van Assche       {
754*44704f69SBart Van Assche          case json_array:
755*44704f69SBart Van Assche 
756*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == 0)
757*44704f69SBart Van Assche             {
758*44704f69SBart Van Assche                if (value->u.array.length == 0)
759*44704f69SBart Van Assche                {
760*44704f69SBart Van Assche                   *buf ++ = '[';
761*44704f69SBart Van Assche                   *buf ++ = ']';
762*44704f69SBart Van Assche 
763*44704f69SBart Van Assche                   break;
764*44704f69SBart Van Assche                }
765*44704f69SBart Van Assche 
766*44704f69SBart Van Assche                PRINT_OPENING_BRACKET ('[');
767*44704f69SBart Van Assche 
768*44704f69SBart Van Assche                indent += opts.indent_size;
769*44704f69SBart Van Assche                PRINT_NEWLINE();
770*44704f69SBart Van Assche             }
771*44704f69SBart Van Assche 
772*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == value->u.array.length)
773*44704f69SBart Van Assche             {
774*44704f69SBart Van Assche                indent -= opts.indent_size;
775*44704f69SBart Van Assche                PRINT_NEWLINE();
776*44704f69SBart Van Assche                PRINT_CLOSING_BRACKET (']');
777*44704f69SBart Van Assche 
778*44704f69SBart Van Assche                ((json_builder_value *) value)->length_iterated = 0;
779*44704f69SBart Van Assche                break;
780*44704f69SBart Van Assche             }
781*44704f69SBart Van Assche 
782*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated > 0)
783*44704f69SBart Van Assche             {
784*44704f69SBart Van Assche                *buf ++ = ',';
785*44704f69SBart Van Assche 
786*44704f69SBart Van Assche                if (flags & f_spaces_after_commas)
787*44704f69SBart Van Assche                   *buf ++ = ' ';
788*44704f69SBart Van Assche 
789*44704f69SBart Van Assche                PRINT_NEWLINE();
790*44704f69SBart Van Assche             }
791*44704f69SBart Van Assche 
792*44704f69SBart Van Assche             ((json_builder_value *) value)->length_iterated++;
793*44704f69SBart Van Assche             value = value->u.array.values [((json_builder_value *) value)->length_iterated - 1];
794*44704f69SBart Van Assche             continue;
795*44704f69SBart Van Assche 
796*44704f69SBart Van Assche          case json_object:
797*44704f69SBart Van Assche 
798*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == 0)
799*44704f69SBart Van Assche             {
800*44704f69SBart Van Assche                if (value->u.object.length == 0)
801*44704f69SBart Van Assche                {
802*44704f69SBart Van Assche                   *buf ++ = '{';
803*44704f69SBart Van Assche                   *buf ++ = '}';
804*44704f69SBart Van Assche 
805*44704f69SBart Van Assche                   break;
806*44704f69SBart Van Assche                }
807*44704f69SBart Van Assche 
808*44704f69SBart Van Assche                PRINT_OPENING_BRACKET ('{');
809*44704f69SBart Van Assche 
810*44704f69SBart Van Assche                indent += opts.indent_size;
811*44704f69SBart Van Assche                PRINT_NEWLINE();
812*44704f69SBart Van Assche             }
813*44704f69SBart Van Assche 
814*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated == value->u.object.length)
815*44704f69SBart Van Assche             {
816*44704f69SBart Van Assche                indent -= opts.indent_size;
817*44704f69SBart Van Assche                PRINT_NEWLINE();
818*44704f69SBart Van Assche                PRINT_CLOSING_BRACKET ('}');
819*44704f69SBart Van Assche 
820*44704f69SBart Van Assche                ((json_builder_value *) value)->length_iterated = 0;
821*44704f69SBart Van Assche                break;
822*44704f69SBart Van Assche             }
823*44704f69SBart Van Assche 
824*44704f69SBart Van Assche             if (((json_builder_value *) value)->length_iterated > 0)
825*44704f69SBart Van Assche             {
826*44704f69SBart Van Assche                *buf ++ = ',';
827*44704f69SBart Van Assche 
828*44704f69SBart Van Assche                if (flags & f_spaces_after_commas)
829*44704f69SBart Van Assche                   *buf ++ = ' ';
830*44704f69SBart Van Assche 
831*44704f69SBart Van Assche                PRINT_NEWLINE();
832*44704f69SBart Van Assche             }
833*44704f69SBart Van Assche 
834*44704f69SBart Van Assche             entry = value->u.object.values + (((json_builder_value *) value)->length_iterated ++);
835*44704f69SBart Van Assche 
836*44704f69SBart Van Assche             *buf ++ = '\"';
837*44704f69SBart Van Assche             buf += serialize_string (buf, entry->name_length, entry->name);
838*44704f69SBart Van Assche             *buf ++ = '\"';
839*44704f69SBart Van Assche             *buf ++ = ':';
840*44704f69SBart Van Assche 
841*44704f69SBart Van Assche             if (flags & f_spaces_after_colons)
842*44704f69SBart Van Assche                *buf ++ = ' ';
843*44704f69SBart Van Assche 
844*44704f69SBart Van Assche             value = entry->value;
845*44704f69SBart Van Assche             continue;
846*44704f69SBart Van Assche 
847*44704f69SBart Van Assche          case json_string:
848*44704f69SBart Van Assche 
849*44704f69SBart Van Assche             *buf ++ = '\"';
850*44704f69SBart Van Assche             buf += serialize_string (buf, value->u.string.length, value->u.string.ptr);
851*44704f69SBart Van Assche             *buf ++ = '\"';
852*44704f69SBart Van Assche             break;
853*44704f69SBart Van Assche 
854*44704f69SBart Van Assche          case json_integer:
855*44704f69SBart Van Assche 
856*44704f69SBart Van Assche             integer = value->u.integer;
857*44704f69SBart Van Assche 
858*44704f69SBart Van Assche             if (integer < 0)
859*44704f69SBart Van Assche             {
860*44704f69SBart Van Assche                *buf ++ = '-';
861*44704f69SBart Van Assche                integer = - integer;
862*44704f69SBart Van Assche             }
863*44704f69SBart Van Assche 
864*44704f69SBart Van Assche             orig_integer = integer;
865*44704f69SBart Van Assche 
866*44704f69SBart Van Assche             ++ buf;
867*44704f69SBart Van Assche 
868*44704f69SBart Van Assche             while (integer >= 10)
869*44704f69SBart Van Assche             {
870*44704f69SBart Van Assche                ++ buf;
871*44704f69SBart Van Assche                integer /= 10;
872*44704f69SBart Van Assche             }
873*44704f69SBart Van Assche 
874*44704f69SBart Van Assche             integer = orig_integer;
875*44704f69SBart Van Assche             ptr = buf;
876*44704f69SBart Van Assche 
877*44704f69SBart Van Assche             do
878*44704f69SBart Van Assche             {
879*44704f69SBart Van Assche                *-- ptr = "0123456789"[integer % 10];
880*44704f69SBart Van Assche 
881*44704f69SBart Van Assche             } while ((integer /= 10) > 0);
882*44704f69SBart Van Assche 
883*44704f69SBart Van Assche             break;
884*44704f69SBart Van Assche 
885*44704f69SBart Van Assche          case json_double:
886*44704f69SBart Van Assche 
887*44704f69SBart Van Assche             ptr = buf;
888*44704f69SBart Van Assche 
889*44704f69SBart Van Assche             buf += sprintf (buf, "%g", value->u.dbl);
890*44704f69SBart Van Assche 
891*44704f69SBart Van Assche             if ((dot = strchr (ptr, ',')))
892*44704f69SBart Van Assche             {
893*44704f69SBart Van Assche                *dot = '.';
894*44704f69SBart Van Assche             }
895*44704f69SBart Van Assche             else if (!strchr (ptr, '.') && !strchr (ptr, 'e'))
896*44704f69SBart Van Assche             {
897*44704f69SBart Van Assche                *buf ++ = '.';
898*44704f69SBart Van Assche                *buf ++ = '0';
899*44704f69SBart Van Assche             }
900*44704f69SBart Van Assche 
901*44704f69SBart Van Assche             break;
902*44704f69SBart Van Assche 
903*44704f69SBart Van Assche          case json_boolean:
904*44704f69SBart Van Assche 
905*44704f69SBart Van Assche             if (value->u.boolean)
906*44704f69SBart Van Assche             {
907*44704f69SBart Van Assche                memcpy (buf, "true", 4);
908*44704f69SBart Van Assche                buf += 4;
909*44704f69SBart Van Assche             }
910*44704f69SBart Van Assche             else
911*44704f69SBart Van Assche             {
912*44704f69SBart Van Assche                memcpy (buf, "false", 5);
913*44704f69SBart Van Assche                buf += 5;
914*44704f69SBart Van Assche             }
915*44704f69SBart Van Assche 
916*44704f69SBart Van Assche             break;
917*44704f69SBart Van Assche 
918*44704f69SBart Van Assche          case json_null:
919*44704f69SBart Van Assche 
920*44704f69SBart Van Assche             memcpy (buf, "null", 4);
921*44704f69SBart Van Assche             buf += 4;
922*44704f69SBart Van Assche             break;
923*44704f69SBart Van Assche 
924*44704f69SBart Van Assche          default:
925*44704f69SBart Van Assche             break;
926*44704f69SBart Van Assche       };
927*44704f69SBart Van Assche 
928*44704f69SBart Van Assche       value = value->parent;
929*44704f69SBart Van Assche    }
930*44704f69SBart Van Assche 
931*44704f69SBart Van Assche    *buf = 0;
932*44704f69SBart Van Assche }
933*44704f69SBart Van Assche 
json_builder_free(json_value * value)934*44704f69SBart Van Assche void json_builder_free (json_value * value)
935*44704f69SBart Van Assche {
936*44704f69SBart Van Assche    json_value * cur_value;
937*44704f69SBart Van Assche 
938*44704f69SBart Van Assche    if (!value)
939*44704f69SBart Van Assche       return;
940*44704f69SBart Van Assche 
941*44704f69SBart Van Assche    value->parent = 0;
942*44704f69SBart Van Assche 
943*44704f69SBart Van Assche    while (value)
944*44704f69SBart Van Assche    {
945*44704f69SBart Van Assche       switch (value->type)
946*44704f69SBart Van Assche       {
947*44704f69SBart Van Assche          case json_array:
948*44704f69SBart Van Assche 
949*44704f69SBart Van Assche             if (!value->u.array.length)
950*44704f69SBart Van Assche             {
951*44704f69SBart Van Assche                free (value->u.array.values);
952*44704f69SBart Van Assche                break;
953*44704f69SBart Van Assche             }
954*44704f69SBart Van Assche 
955*44704f69SBart Van Assche             value = value->u.array.values [-- value->u.array.length];
956*44704f69SBart Van Assche             continue;
957*44704f69SBart Van Assche 
958*44704f69SBart Van Assche          case json_object:
959*44704f69SBart Van Assche 
960*44704f69SBart Van Assche             if (!value->u.object.length)
961*44704f69SBart Van Assche             {
962*44704f69SBart Van Assche                free (value->u.object.values);
963*44704f69SBart Van Assche                break;
964*44704f69SBart Van Assche             }
965*44704f69SBart Van Assche 
966*44704f69SBart Van Assche             -- value->u.object.length;
967*44704f69SBart Van Assche 
968*44704f69SBart Van Assche             if (((json_builder_value *) value)->is_builder_value)
969*44704f69SBart Van Assche             {
970*44704f69SBart Van Assche                /* Names are allocated separately for builder values.  In parser
971*44704f69SBart Van Assche                 * values, they are part of the same allocation as the values array
972*44704f69SBart Van Assche                 * itself.
973*44704f69SBart Van Assche                 */
974*44704f69SBart Van Assche                free (value->u.object.values [value->u.object.length].name);
975*44704f69SBart Van Assche             }
976*44704f69SBart Van Assche 
977*44704f69SBart Van Assche             value = value->u.object.values [value->u.object.length].value;
978*44704f69SBart Van Assche             continue;
979*44704f69SBart Van Assche 
980*44704f69SBart Van Assche          case json_string:
981*44704f69SBart Van Assche 
982*44704f69SBart Van Assche             free (value->u.string.ptr);
983*44704f69SBart Van Assche             break;
984*44704f69SBart Van Assche 
985*44704f69SBart Van Assche          default:
986*44704f69SBart Van Assche             break;
987*44704f69SBart Van Assche       };
988*44704f69SBart Van Assche 
989*44704f69SBart Van Assche       cur_value = value;
990*44704f69SBart Van Assche       value = value->parent;
991*44704f69SBart Van Assche       free (cur_value);
992*44704f69SBart Van Assche    }
993*44704f69SBart Van Assche }
994*44704f69SBart Van Assche 
995*44704f69SBart Van Assche 
996*44704f69SBart Van Assche 
997*44704f69SBart Van Assche 
998*44704f69SBart Van Assche 
999*44704f69SBart Van Assche 
1000