]> mj.ucw.cz Git - libucw.git/blob - ucw-json/format.c
JSON: Rudimentary formatting
[libucw.git] / ucw-json / format.c
1 /*
2  *      UCW JSON Library -- Formatter
3  *
4  *      (c) 2015 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/fastbuf.h>
12 #include <ucw/gary.h>
13 #include <ucw/ff-unicode.h>
14 #include <ucw/unicode.h>
15 #include <ucw-json/json.h>
16
17 #include <stdio.h>
18
19 void json_set_output(struct json_context *js, struct fastbuf *fb)
20 {
21   js->out_fb = fb;
22 }
23
24 static void write_string(struct fastbuf *fb, const char *p)
25 {
26   bputc(fb, '"');
27   for (;;)
28     {
29       uint u;
30       p = utf8_32_get(p, &u);
31       if (!u)
32         break;
33       if (u == '"' || u == '\\')
34         {
35           bputc(fb, '\\');
36           bputc(fb, u);
37         }
38       else if (u < 0x20)
39         {
40           // We avoid "\f" nor "\b" and use "\uXXXX" instead
41           switch (u)
42             {
43             case 0x09: bputs(fb, "\\t"); break;
44             case 0x0a: bputs(fb, "\\n"); break;
45             case 0x0d: bputs(fb, "\\r"); break;
46             default:
47               bprintf(fb, "\\u%04x", u);
48             }
49         }
50       else
51         bputc(fb, u);
52     }
53   bputc(fb, '"');
54 }
55
56 void json_write_value(struct json_context *js, struct json_node *n)
57 {
58   struct fastbuf *fb = js->out_fb;
59
60   switch (n->type)
61     {
62     case JSON_NULL:
63       bputs(fb, "null");
64       break;
65     case JSON_BOOLEAN:
66       bputs(fb, (n->boolean ? "true" : "false"));
67       break;
68     case JSON_NUMBER:
69       // FIXME: Formatting of floats
70       bprintf(fb, "%f", n->number);
71       break;
72     case JSON_STRING:
73       write_string(fb, n->string);
74       break;
75     case JSON_ARRAY:
76       {
77         // FIXME: Indent
78         bputs(fb, "[ ");
79         for (size_t i=0; i < GARY_SIZE(n->elements); i++)
80           {
81             if (i)
82               bputs(fb, ", ");
83             json_write_value(js, n->elements[i]);
84           }
85         bputc(fb, ']');
86         break;
87       }
88     case JSON_OBJECT:
89       {
90         bputs(fb, "{ ");
91         // FIXME: Indent
92         for (size_t i=0; i < GARY_SIZE(n->pairs); i++)
93           {
94             if (i)
95               bputs(fb, ", ");
96             struct json_pair *p = &n->pairs[i];
97             write_string(fb, p->key);
98             bputs(fb, ": ");
99             json_write_value(js, p->value);
100           }
101         bputc(fb, '}');
102         break;
103       }
104     default:
105       ASSERT(0);
106     }
107 }
108
109 void json_write(struct json_context *js, struct fastbuf *fb, struct json_node *n)
110 {
111   json_set_output(js, fb);
112   json_write_value(js, n);
113   bputc(fb, '\n');
114 }