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