6375b3c2faac225d5980d727fac2a0558b53da7d
[fio.git] / json.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <stdarg.h>
5 #include "json.h"
6 #include "log.h"
7
8 struct json_object *json_create_object(void)
9 {
10         return calloc(1, sizeof(struct json_object));
11 }
12
13 struct json_array *json_create_array(void)
14 {
15         return calloc(1, sizeof(struct json_array));
16 }
17
18 static struct json_pair *json_create_pair(const char *name, struct json_value *value)
19 {
20         struct json_pair *pair = malloc(sizeof(struct json_pair));
21         if (pair) {
22                 pair->name = strdup(name);
23                 pair->value = value;
24
25                 value->parent_type = JSON_PARENT_TYPE_PAIR;
26                 value->parent_pair = pair;
27         }
28         return pair;
29 }
30
31 static struct json_value *json_create_value_int(long long number)
32 {
33         struct json_value *value = malloc(sizeof(struct json_value));
34
35         if (value) {
36                 value->type = JSON_TYPE_INTEGER;
37                 value->integer_number = number;
38         }
39         return value;
40 }
41
42 static struct json_value *json_create_value_float(double number)
43 {
44         struct json_value *value = malloc(sizeof(struct json_value));
45
46         if (value) {
47                 value->type = JSON_TYPE_FLOAT;
48                 value->float_number = number;
49         }
50         return value;
51 }
52
53 static char *strdup_escape(const char *str)
54 {
55         const char *input = str;
56         char *p, *ret;
57         int escapes;
58
59         escapes = 0;
60         while ((input = strpbrk(input, "\\\"")) != NULL) {
61                 escapes++;
62                 input++;
63         }
64
65         p = ret = malloc(strlen(str) + escapes + 1);
66         while (*str) {
67                 if (*str == '\\' || *str == '\"')
68                         *p++ = '\\';
69                 *p++ = *str++;
70         }
71         *p = '\0';
72
73         return ret;
74 }
75
76 /*
77  * Valid JSON strings must escape '"' and '/' with a preceding '/'
78  */
79 static struct json_value *json_create_value_string(const char *str)
80 {
81         struct json_value *value = malloc(sizeof(struct json_value));
82
83         if (value) {
84                 value->type = JSON_TYPE_STRING;
85                 value->string = strdup_escape(str);
86                 if (!value->string) {
87                         free(value);
88                         value = NULL;
89                 }
90         }
91         return value;
92 }
93
94 static struct json_value *json_create_value_object(struct json_object *obj)
95 {
96         struct json_value *value = malloc(sizeof(struct json_value));
97
98         if (value) {
99                 value->type = JSON_TYPE_OBJECT;
100                 value->object = obj;
101                 obj->parent = value;
102         }
103         return value;
104 }
105
106 static struct json_value *json_create_value_array(struct json_array *array)
107 {
108         struct json_value *value = malloc(sizeof(struct json_value));
109
110         if (value) {
111                 value->type = JSON_TYPE_ARRAY;
112                 value->array = array;
113                 array->parent = value;
114         }
115         return value;
116 }
117
118 static void json_free_pair(struct json_pair *pair);
119 static void json_free_value(struct json_value *value);
120
121 void json_free_object(struct json_object *obj)
122 {
123         int i;
124
125         for (i = 0; i < obj->pair_cnt; i++)
126                 json_free_pair(obj->pairs[i]);
127         free(obj->pairs);
128         free(obj);
129 }
130
131 static void json_free_array(struct json_array *array)
132 {
133         int i;
134
135         for (i = 0; i < array->value_cnt; i++)
136                 json_free_value(array->values[i]);
137         free(array->values);
138         free(array);
139 }
140
141 static void json_free_pair(struct json_pair *pair)
142 {
143         json_free_value(pair->value);
144         free(pair->name);
145         free(pair);
146 }
147
148 static void json_free_value(struct json_value *value)
149 {
150         switch (value->type) {
151         case JSON_TYPE_STRING:
152                 free(value->string);
153                 break;
154         case JSON_TYPE_OBJECT:
155                 json_free_object(value->object);
156                 break;
157         case JSON_TYPE_ARRAY:
158                 json_free_array(value->array);
159                 break;
160         }
161         free(value);
162 }
163
164 static int json_array_add_value(struct json_array *array, struct json_value *value)
165 {
166         struct json_value **values = realloc(array->values,
167                 sizeof(struct json_value *) * (array->value_cnt + 1));
168
169         if (!values)
170                 return ENOMEM;
171         values[array->value_cnt] = value;
172         array->value_cnt++;
173         array->values = values;
174
175         value->parent_type = JSON_PARENT_TYPE_ARRAY;
176         value->parent_array = array;
177         return 0;
178 }
179
180 static int json_object_add_pair(struct json_object *obj, struct json_pair *pair)
181 {
182         struct json_pair **pairs = realloc(obj->pairs,
183                 sizeof(struct json_pair *) * (obj->pair_cnt + 1));
184         if (!pairs)
185                 return ENOMEM;
186         pairs[obj->pair_cnt] = pair;
187         obj->pair_cnt++;
188         obj->pairs = pairs;
189
190         pair->parent = obj;
191         return 0;
192 }
193
194 int json_object_add_value_type(struct json_object *obj, const char *name,
195                                const struct json_value *arg)
196 {
197         struct json_value *value;
198         struct json_pair *pair;
199         int ret;
200
201         switch (arg->type) {
202         case JSON_TYPE_STRING:
203                 value = json_create_value_string(arg->string);
204                 break;
205         case JSON_TYPE_INTEGER:
206                 value = json_create_value_int(arg->integer_number);
207                 break;
208         case JSON_TYPE_FLOAT:
209                 value = json_create_value_float(arg->float_number);
210                 break;
211         case JSON_TYPE_OBJECT:
212                 value = json_create_value_object(arg->object);
213                 break;
214         default:
215         case JSON_TYPE_ARRAY:
216                 value = json_create_value_array(arg->array);
217                 break;
218         }
219
220         if (!value)
221                 return ENOMEM;
222
223         pair = json_create_pair(name, value);
224         if (!pair) {
225                 json_free_value(value);
226                 return ENOMEM;
227         }
228         ret = json_object_add_pair(obj, pair);
229         if (ret) {
230                 json_free_pair(pair);
231                 return ENOMEM;
232         }
233         return 0;
234 }
235
236 int json_array_add_value_type(struct json_array *array,
237                               const struct json_value *arg)
238 {
239         struct json_value *value;
240         int ret;
241
242         switch (arg->type) {
243         case JSON_TYPE_STRING:
244                 value = json_create_value_string(arg->string);
245                 break;
246         case JSON_TYPE_INTEGER:
247                 value = json_create_value_int(arg->integer_number);
248                 break;
249         case JSON_TYPE_FLOAT:
250                 value = json_create_value_float(arg->float_number);
251                 break;
252         case JSON_TYPE_OBJECT:
253                 value = json_create_value_object(arg->object);
254                 break;
255         default:
256         case JSON_TYPE_ARRAY:
257                 value = json_create_value_array(arg->array);
258                 break;
259         }
260
261         if (!value)
262                 return ENOMEM;
263
264         ret = json_array_add_value(array, value);
265         if (ret) {
266                 json_free_value(value);
267                 return ENOMEM;
268         }
269         return 0;
270 }
271
272 static int json_value_level(struct json_value *value);
273 static int json_pair_level(struct json_pair *pair);
274 static int json_array_level(struct json_array *array);
275 static int json_object_level(struct json_object *object)
276 {
277         if (object->parent == NULL)
278                 return 0;
279         return json_value_level(object->parent);
280 }
281
282 static int json_pair_level(struct json_pair *pair)
283 {
284         return json_object_level(pair->parent) + 1;
285 }
286
287 static int json_array_level(struct json_array *array)
288 {
289         return json_value_level(array->parent);
290 }
291
292 static int json_value_level(struct json_value *value)
293 {
294         if (value->parent_type == JSON_PARENT_TYPE_PAIR)
295                 return json_pair_level(value->parent_pair);
296         else
297                 return json_array_level(value->parent_array) + 1;
298 }
299
300 static void json_print_level(int level, struct buf_output *out)
301 {
302         while (level-- > 0)
303                 log_buf(out, "  ");
304 }
305
306 static void json_print_pair(struct json_pair *pair, struct buf_output *);
307 static void json_print_value(struct json_value *value, struct buf_output *);
308
309 void json_print_object(struct json_object *obj, struct buf_output *out)
310 {
311         int i;
312
313         log_buf(out, "{\n");
314         for (i = 0; i < obj->pair_cnt; i++) {
315                 if (i > 0)
316                         log_buf(out, ",\n");
317                 json_print_pair(obj->pairs[i], out);
318         }
319         log_buf(out, "\n");
320         json_print_level(json_object_level(obj), out);
321         log_buf(out, "}");
322 }
323
324 static void json_print_pair(struct json_pair *pair, struct buf_output *out)
325 {
326         json_print_level(json_pair_level(pair), out);
327         log_buf(out, "\"%s\" : ", pair->name);
328         json_print_value(pair->value, out);
329 }
330
331 static void json_print_array(struct json_array *array, struct buf_output *out)
332 {
333         int i;
334
335         log_buf(out, "[\n");
336         for (i = 0; i < array->value_cnt; i++) {
337                 if (i > 0)
338                         log_buf(out, ",\n");
339                 json_print_level(json_value_level(array->values[i]), out);
340                 json_print_value(array->values[i], out);
341         }
342         log_buf(out, "\n");
343         json_print_level(json_array_level(array), out);
344         log_buf(out, "]");
345 }
346
347 static void json_print_value(struct json_value *value, struct buf_output *out)
348 {
349         switch (value->type) {
350         case JSON_TYPE_STRING:
351                 log_buf(out, "\"%s\"", value->string);
352                 break;
353         case JSON_TYPE_INTEGER:
354                 log_buf(out, "%lld", value->integer_number);
355                 break;
356         case JSON_TYPE_FLOAT:
357                 log_buf(out, "%f", value->float_number);
358                 break;
359         case JSON_TYPE_OBJECT:
360                 json_print_object(value->object, out);
361                 break;
362         case JSON_TYPE_ARRAY:
363                 json_print_array(value->array, out);
364                 break;
365         }
366 }