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