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