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