iolog: Added option read_iolog_chunked. Used to avoid reading large iologs at once.
[fio.git] / json.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <stdarg.h>
5 #include "json.h"
6 #include "log.h"
7
8 struct json_object *json_create_object(void)
9 {
10         return calloc(1, sizeof(struct json_object));
11 }
12
13 struct json_array *json_create_array(void)
14 {
15         return calloc(1, sizeof(struct json_array));
16 }
17
18 static 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
31 static struct json_value *json_create_value_int(long long number)
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
42 static struct json_value *json_create_value_float(double number)
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
53 static char *strdup_escape(const char *str)
54 {
55         const char *input = str;
56         char *p, *ret;
57         int escapes;
58
59         if (!strlen(str))
60                 return NULL;
61
62         escapes = 0;
63         while ((input = strpbrk(input, "\\\"")) != NULL) {
64                 escapes++;
65                 input++;
66         }
67
68         p = ret = malloc(strlen(str) + escapes + 1);
69         while (*str) {
70                 if (*str == '\\' || *str == '\"')
71                         *p++ = '\\';
72                 *p++ = *str++;
73         }
74         *p = '\0';
75
76         return ret;
77 }
78
79 /*
80  * Valid JSON strings must escape '"' and '/' with a preceding '/'
81  */
82 static 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;
88                 value->string = strdup_escape(str);
89                 if (!value->string) {
90                         free(value);
91                         value = NULL;
92                 }
93         }
94         return value;
95 }
96
97 static 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
109 static 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
121 static void json_free_pair(struct json_pair *pair);
122 static void json_free_value(struct json_value *value);
123
124 void 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
134 static 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
144 static void json_free_pair(struct json_pair *pair)
145 {
146         json_free_value(pair->value);
147         free(pair->name);
148         free(pair);
149 }
150
151 static 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
167 static 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
183 static 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
197 int 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)
208                 value = json_create_value_int(va_arg(args, long long));
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
233 static void json_print_array(struct json_array *array, struct buf_output *);
234 int 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)
244                 value = json_create_value_int(va_arg(args, long long));
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
264 static int json_value_level(struct json_value *value);
265 static int json_pair_level(struct json_pair *pair);
266 static int json_array_level(struct json_array *array);
267 static 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
274 static int json_pair_level(struct json_pair *pair)
275 {
276         return json_object_level(pair->parent) + 1;
277 }
278
279 static int json_array_level(struct json_array *array)
280 {
281         return json_value_level(array->parent);
282 }
283
284 static 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
292 static void json_print_level(int level, struct buf_output *out)
293 {
294         while (level-- > 0)
295                 log_buf(out, "  ");
296 }
297
298 static void json_print_pair(struct json_pair *pair, struct buf_output *);
299 static void json_print_array(struct json_array *array, struct buf_output *);
300 static void json_print_value(struct json_value *value, struct buf_output *);
301 void json_print_object(struct json_object *obj, struct buf_output *out)
302 {
303         int i;
304
305         log_buf(out, "{\n");
306         for (i = 0; i < obj->pair_cnt; i++) {
307                 if (i > 0)
308                         log_buf(out, ",\n");
309                 json_print_pair(obj->pairs[i], out);
310         }
311         log_buf(out, "\n");
312         json_print_level(json_object_level(obj), out);
313         log_buf(out, "}");
314 }
315
316 static void json_print_pair(struct json_pair *pair, struct buf_output *out)
317 {
318         json_print_level(json_pair_level(pair), out);
319         log_buf(out, "\"%s\" : ", pair->name);
320         json_print_value(pair->value, out);
321 }
322
323 static void json_print_array(struct json_array *array, struct buf_output *out)
324 {
325         int i;
326
327         log_buf(out, "[\n");
328         for (i = 0; i < array->value_cnt; i++) {
329                 if (i > 0)
330                         log_buf(out, ",\n");
331                 json_print_level(json_value_level(array->values[i]), out);
332                 json_print_value(array->values[i], out);
333         }
334         log_buf(out, "\n");
335         json_print_level(json_array_level(array), out);
336         log_buf(out, "]");
337 }
338
339 static void json_print_value(struct json_value *value, struct buf_output *out)
340 {
341         switch (value->type) {
342         case JSON_TYPE_STRING:
343                 log_buf(out, "\"%s\"", value->string);
344                 break;
345         case JSON_TYPE_INTEGER:
346                 log_buf(out, "%lld", value->integer_number);
347                 break;
348         case JSON_TYPE_FLOAT:
349                 log_buf(out, "%f", value->float_number);
350                 break;
351         case JSON_TYPE_OBJECT:
352                 json_print_object(value->object, out);
353                 break;
354         case JSON_TYPE_ARRAY:
355                 json_print_array(value->array, out);
356                 break;
357         }
358 }