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