• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* vim: set et ts=3 sw=3 sts=3 ft=c:
3  *
4  * Copyright (C) 2014 James McLaughlin.  All rights reserved.
5  * https://github.com/udp/json-builder
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in the
16  *   documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #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