ioengine: allow several external ioengines
[fio.git] / json.c
CommitLineData
cc372b17
SL
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
9struct 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
17struct 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
25static 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
38static 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
49static 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
60static struct json_value *json_create_value_string(const char *str)
61{
62 struct json_value *value = malloc(sizeof(struct json_value));
63
64 if (value) {
65 value->type = JSON_TYPE_STRING;
66 value->string = strdup(str);
67 if (!value->string) {
68 free(value);
69 value = NULL;
70 }
71 }
72 return value;
73}
74
75static struct json_value *json_create_value_object(struct json_object *obj)
76{
77 struct json_value *value = malloc(sizeof(struct json_value));
78
79 if (value) {
80 value->type = JSON_TYPE_OBJECT;
81 value->object = obj;
82 obj->parent = value;
83 }
84 return value;
85}
86
87static struct json_value *json_create_value_array(struct json_array *array)
88{
89 struct json_value *value = malloc(sizeof(struct json_value));
90
91 if (value) {
92 value->type = JSON_TYPE_ARRAY;
93 value->array = array;
94 array->parent = value;
95 }
96 return value;
97}
98
cc372b17
SL
99static void json_free_pair(struct json_pair *pair);
100static void json_free_value(struct json_value *value);
f3afa57e 101
cc372b17
SL
102void json_free_object(struct json_object *obj)
103{
104 int i;
105
106 for (i = 0; i < obj->pair_cnt; i++)
107 json_free_pair(obj->pairs[i]);
108 free(obj->pairs);
109 free(obj);
110}
111
112static void json_free_array(struct json_array *array)
113{
114 int i;
115
116 for (i = 0; i < array->value_cnt; i++)
117 json_free_value(array->values[i]);
118 free(array->values);
119 free(array);
120}
121
122static void json_free_pair(struct json_pair *pair)
123{
124 json_free_value(pair->value);
125 free(pair->name);
126 free(pair);
127}
128
129static void json_free_value(struct json_value *value)
130{
131 switch (value->type) {
132 case JSON_TYPE_STRING:
133 free(value->string);
134 break;
135 case JSON_TYPE_OBJECT:
136 json_free_object(value->object);
137 break;
138 case JSON_TYPE_ARRAY:
139 json_free_array(value->array);
140 break;
141 }
142 free(value);
143}
144
145static int json_array_add_value(struct json_array *array, struct json_value *value)
146{
147 struct json_value **values = realloc(array->values,
148 sizeof(struct json_value *) * (array->value_cnt + 1));
149
150 if (!values)
151 return ENOMEM;
152 values[array->value_cnt] = value;
153 array->value_cnt++;
154 array->values = values;
155
156 value->parent_type = JSON_PARENT_TYPE_ARRAY;
157 value->parent_array = array;
158 return 0;
159}
160
161static int json_object_add_pair(struct json_object *obj, struct json_pair *pair)
162{
163 struct json_pair **pairs = realloc(obj->pairs,
164 sizeof(struct json_pair *) * (obj->pair_cnt + 1));
165 if (!pairs)
166 return ENOMEM;
167 pairs[obj->pair_cnt] = pair;
168 obj->pair_cnt++;
169 obj->pairs = pairs;
170
171 pair->parent = obj;
172 return 0;
173}
174
175int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...)
176{
177 struct json_value *value;
178 struct json_pair *pair;
179 va_list args;
180 int ret;
181
182 va_start(args, type);
183 if (type == JSON_TYPE_STRING)
184 value = json_create_value_string(va_arg(args, char *));
185 else if (type == JSON_TYPE_INTEGER)
186 value = json_create_value_int(va_arg(args, long));
187 else if (type == JSON_TYPE_FLOAT)
188 value = json_create_value_float(va_arg(args, double));
189 else if (type == JSON_TYPE_OBJECT)
190 value = json_create_value_object(va_arg(args, struct json_object *));
191 else
192 value = json_create_value_array(va_arg(args, struct json_array *));
193 va_end(args);
194
195 if (!value)
196 return ENOMEM;
197
198 pair = json_create_pair(name, value);
199 if (!pair) {
200 json_free_value(value);
201 return ENOMEM;
202 }
203 ret = json_object_add_pair(obj, pair);
204 if (ret) {
205 json_free_pair(pair);
206 return ENOMEM;
207 }
208 return 0;
209}
210
211static void json_print_array(struct json_array *array);
212int json_array_add_value_type(struct json_array *array, int type, ...)
213{
214 struct json_value *value;
215 va_list args;
216 int ret;
217
218 va_start(args, type);
219 if (type == JSON_TYPE_STRING)
220 value = json_create_value_string(va_arg(args, char *));
221 else if (type == JSON_TYPE_INTEGER)
222 value = json_create_value_int(va_arg(args, long));
223 else if (type == JSON_TYPE_FLOAT)
224 value = json_create_value_float(va_arg(args, double));
225 else if (type == JSON_TYPE_OBJECT)
226 value = json_create_value_object(va_arg(args, struct json_object *));
227 else
228 value = json_create_value_array(va_arg(args, struct json_array *));
229 va_end(args);
230
231 if (!value)
232 return ENOMEM;
233
234 ret = json_array_add_value(array, value);
235 if (ret) {
236 json_free_value(value);
237 return ENOMEM;
238 }
239 return 0;
240}
241
242static int json_value_level(struct json_value *value);
243static int json_pair_level(struct json_pair *pair);
244static int json_array_level(struct json_array *array);
245static int json_object_level(struct json_object *object)
246{
247 if (object->parent == NULL)
248 return 0;
249 return json_value_level(object->parent);
250}
251
252static int json_pair_level(struct json_pair *pair)
253{
254 return json_object_level(pair->parent) + 1;
255}
256
257static int json_array_level(struct json_array *array)
258{
259 return json_value_level(array->parent);
260}
261
262static int json_value_level(struct json_value *value)
263{
264 if (value->parent_type == JSON_PARENT_TYPE_PAIR)
265 return json_pair_level(value->parent_pair);
266 else
267 return json_array_level(value->parent_array) + 1;
268}
269
270static void json_print_level(int level)
271{
272 while (level-- > 0)
273 log_info(" ");
274}
275
276static void json_print_pair(struct json_pair *pair);
277static void json_print_array(struct json_array *array);
278static void json_print_value(struct json_value *value);
279void json_print_object(struct json_object *obj)
280{
281 int i;
282
283 log_info("{\n");
284 for (i = 0; i < obj->pair_cnt; i++) {
285 if (i > 0)
286 log_info(",\n");
287 json_print_pair(obj->pairs[i]);
288 }
289 log_info("\n");
290 json_print_level(json_object_level(obj));
291 log_info("}");
292}
293
294static void json_print_pair(struct json_pair *pair)
295{
296 json_print_level(json_pair_level(pair));
297 log_info("\"%s\" : ", pair->name);
298 json_print_value(pair->value);
299}
300
301static void json_print_array(struct json_array *array)
302{
303 int i;
304
305 log_info("[\n");
306 for (i = 0; i < array->value_cnt; i++) {
307 if (i > 0)
308 log_info(",\n");
309 json_print_level(json_value_level(array->values[i]));
310 json_print_value(array->values[i]);
311 }
312 log_info("\n");
313 json_print_level(json_array_level(array));
314 log_info("]");
315}
316
317static void json_print_value(struct json_value *value)
318{
319 switch (value->type) {
320 case JSON_TYPE_STRING:
321 log_info("\"%s\"", value->string);
322 break;
323 case JSON_TYPE_INTEGER:
324 log_info("%ld", value->integer_number);
325 break;
326 case JSON_TYPE_FLOAT:
327 log_info("%.2f", value->float_number);
328 break;
329 case JSON_TYPE_OBJECT:
330 json_print_object(value->object);
331 break;
332 case JSON_TYPE_ARRAY:
333 json_print_array(value->array);
334 break;
335 }
336}