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