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