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