Merge branch 'fix-randtrimwrite' of https://github.com/minwooim/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
59 escapes = 0;
60 while ((input = strpbrk(input, "\\\"")) != NULL) {
61 escapes++;
62 input++;
63 }
64
a5725153 65 p = ret = malloc(strlen(str) + escapes + 1);
d366a95e
JA
66 while (*str) {
67 if (*str == '\\' || *str == '\"')
68 *p++ = '\\';
69 *p++ = *str++;
70 }
a5725153 71 *p = '\0';
d366a95e
JA
72
73 return ret;
74}
75
76/*
de8f6de9 77 * Valid JSON strings must escape '"' and '/' with a preceding '/'
d366a95e 78 */
cc372b17
SL
79static 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;
d366a95e 85 value->string = strdup_escape(str);
cc372b17
SL
86 if (!value->string) {
87 free(value);
88 value = NULL;
89 }
90 }
91 return value;
92}
93
94static 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
106static 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
cc372b17
SL
118static void json_free_pair(struct json_pair *pair);
119static void json_free_value(struct json_value *value);
f3afa57e 120
cc372b17
SL
121void 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
131static 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
141static void json_free_pair(struct json_pair *pair)
142{
143 json_free_value(pair->value);
144 free(pair->name);
145 free(pair);
146}
147
148static 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
164static 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
180static 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
eb2f29b7
BVA
194int json_object_add_value_type(struct json_object *obj, const char *name,
195 const struct json_value *arg)
cc372b17
SL
196{
197 struct json_value *value;
198 struct json_pair *pair;
cc372b17
SL
199 int ret;
200
eb2f29b7
BVA
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 }
cc372b17
SL
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
eb2f29b7
BVA
236int json_array_add_value_type(struct json_array *array,
237 const struct json_value *arg)
cc372b17
SL
238{
239 struct json_value *value;
cc372b17
SL
240 int ret;
241
eb2f29b7
BVA
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 }
cc372b17
SL
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
272static int json_value_level(struct json_value *value);
273static int json_pair_level(struct json_pair *pair);
274static int json_array_level(struct json_array *array);
275static 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
282static int json_pair_level(struct json_pair *pair)
283{
284 return json_object_level(pair->parent) + 1;
285}
286
287static int json_array_level(struct json_array *array)
288{
289 return json_value_level(array->parent);
290}
291
292static 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
a666cab8 300static void json_print_level(int level, struct buf_output *out)
cc372b17
SL
301{
302 while (level-- > 0)
a666cab8 303 log_buf(out, " ");
cc372b17
SL
304}
305
a666cab8 306static void json_print_pair(struct json_pair *pair, struct buf_output *);
a666cab8 307static void json_print_value(struct json_value *value, struct buf_output *);
038d3e5b 308
a666cab8 309void json_print_object(struct json_object *obj, struct buf_output *out)
cc372b17
SL
310{
311 int i;
312
a666cab8 313 log_buf(out, "{\n");
cc372b17
SL
314 for (i = 0; i < obj->pair_cnt; i++) {
315 if (i > 0)
a666cab8
JA
316 log_buf(out, ",\n");
317 json_print_pair(obj->pairs[i], out);
cc372b17 318 }
a666cab8
JA
319 log_buf(out, "\n");
320 json_print_level(json_object_level(obj), out);
321 log_buf(out, "}");
cc372b17
SL
322}
323
a666cab8 324static void json_print_pair(struct json_pair *pair, struct buf_output *out)
cc372b17 325{
a666cab8
JA
326 json_print_level(json_pair_level(pair), out);
327 log_buf(out, "\"%s\" : ", pair->name);
328 json_print_value(pair->value, out);
cc372b17
SL
329}
330
a666cab8 331static void json_print_array(struct json_array *array, struct buf_output *out)
cc372b17
SL
332{
333 int i;
334
a666cab8 335 log_buf(out, "[\n");
cc372b17
SL
336 for (i = 0; i < array->value_cnt; i++) {
337 if (i > 0)
a666cab8
JA
338 log_buf(out, ",\n");
339 json_print_level(json_value_level(array->values[i]), out);
340 json_print_value(array->values[i], out);
cc372b17 341 }
a666cab8
JA
342 log_buf(out, "\n");
343 json_print_level(json_array_level(array), out);
344 log_buf(out, "]");
cc372b17
SL
345}
346
a666cab8 347static void json_print_value(struct json_value *value, struct buf_output *out)
cc372b17
SL
348{
349 switch (value->type) {
2374148c
JA
350 case JSON_TYPE_STRING:
351 log_buf(out, "\"%s\"", value->string);
352 break;
cc372b17 353 case JSON_TYPE_INTEGER:
a666cab8 354 log_buf(out, "%lld", value->integer_number);
cc372b17
SL
355 break;
356 case JSON_TYPE_FLOAT:
817720e1 357 log_buf(out, "%f", value->float_number);
cc372b17
SL
358 break;
359 case JSON_TYPE_OBJECT:
a666cab8 360 json_print_object(value->object, out);
cc372b17
SL
361 break;
362 case JSON_TYPE_ARRAY:
a666cab8 363 json_print_array(value->array, out);
cc372b17
SL
364 break;
365 }
366}