• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
json_create_object(void)9 struct json_object *json_create_object(void)
10 {
11 	return calloc(1, sizeof(struct json_object));
12 }
13 
json_create_array(void)14 struct json_array *json_create_array(void)
15 {
16 	return calloc(1, sizeof(struct json_array));
17 }
18 
json_create_pair(const char * name,struct json_value * value)19 static 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 
json_create_value_int(long long number)32 static struct json_value *json_create_value_int(long long number)
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 
json_create_value_float(double number)43 static struct json_value *json_create_value_float(double 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 
strdup_escape(const char * str)54 static char *strdup_escape(const char *str)
55 {
56 	const char *input = str;
57 	char *p, *ret;
58 	int escapes;
59 
60 	if (!strlen(str))
61 		return NULL;
62 
63 	escapes = 0;
64 	while ((input = strpbrk(input, "\\\"")) != NULL) {
65 		escapes++;
66 		input++;
67 	}
68 
69 	p = ret = malloc(strlen(str) + escapes + 1);
70 	while (*str) {
71 		if (*str == '\\' || *str == '\"')
72 			*p++ = '\\';
73 		*p++ = *str++;
74 	}
75 	*p = '\0';
76 
77 	return ret;
78 }
79 
80 /*
81  * Valid JSON strings must escape '"' and '/' with a preceding '/'
82  */
json_create_value_string(const char * str)83 static 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;
89 		value->string = strdup_escape(str);
90 		if (!value->string) {
91 			free(value);
92 			value = NULL;
93 		}
94 	}
95 	return value;
96 }
97 
json_create_value_object(struct json_object * obj)98 static 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 
json_create_value_array(struct json_array * array)110 static 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 
122 static void json_free_pair(struct json_pair *pair);
123 static void json_free_value(struct json_value *value);
124 
json_free_object(struct json_object * obj)125 void 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 
json_free_array(struct json_array * array)135 static 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 
json_free_pair(struct json_pair * pair)145 static void json_free_pair(struct json_pair *pair)
146 {
147 	json_free_value(pair->value);
148 	free(pair->name);
149 	free(pair);
150 }
151 
json_free_value(struct json_value * value)152 static 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 
json_array_add_value(struct json_array * array,struct json_value * value)168 static 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 
json_object_add_pair(struct json_object * obj,struct json_pair * pair)184 static 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 
json_object_add_value_type(struct json_object * obj,const char * name,int type,...)198 int 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)
209 		value = json_create_value_int(va_arg(args, long long));
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 
234 static void json_print_array(struct json_array *array, struct buf_output *);
json_array_add_value_type(struct json_array * array,int type,...)235 int 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)
245 		value = json_create_value_int(va_arg(args, long long));
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 
265 static int json_value_level(struct json_value *value);
266 static int json_pair_level(struct json_pair *pair);
267 static int json_array_level(struct json_array *array);
json_object_level(struct json_object * object)268 static 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 
json_pair_level(struct json_pair * pair)275 static int json_pair_level(struct json_pair *pair)
276 {
277 	return json_object_level(pair->parent) + 1;
278 }
279 
json_array_level(struct json_array * array)280 static int json_array_level(struct json_array *array)
281 {
282 	return json_value_level(array->parent);
283 }
284 
json_value_level(struct json_value * value)285 static 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 
json_print_level(int level,struct buf_output * out)293 static void json_print_level(int level, struct buf_output *out)
294 {
295 	while (level-- > 0)
296 		log_buf(out, "  ");
297 }
298 
299 static void json_print_pair(struct json_pair *pair, struct buf_output *);
300 static void json_print_array(struct json_array *array, struct buf_output *);
301 static void json_print_value(struct json_value *value, struct buf_output *);
json_print_object(struct json_object * obj,struct buf_output * out)302 void json_print_object(struct json_object *obj, struct buf_output *out)
303 {
304 	int i;
305 
306 	log_buf(out, "{\n");
307 	for (i = 0; i < obj->pair_cnt; i++) {
308 		if (i > 0)
309 			log_buf(out, ",\n");
310 		json_print_pair(obj->pairs[i], out);
311 	}
312 	log_buf(out, "\n");
313 	json_print_level(json_object_level(obj), out);
314 	log_buf(out, "}");
315 }
316 
json_print_pair(struct json_pair * pair,struct buf_output * out)317 static void json_print_pair(struct json_pair *pair, struct buf_output *out)
318 {
319 	json_print_level(json_pair_level(pair), out);
320 	log_buf(out, "\"%s\" : ", pair->name);
321 	json_print_value(pair->value, out);
322 }
323 
json_print_array(struct json_array * array,struct buf_output * out)324 static void json_print_array(struct json_array *array, struct buf_output *out)
325 {
326 	int i;
327 
328 	log_buf(out, "[\n");
329 	for (i = 0; i < array->value_cnt; i++) {
330 		if (i > 0)
331 			log_buf(out, ",\n");
332 		json_print_level(json_value_level(array->values[i]), out);
333 		json_print_value(array->values[i], out);
334 	}
335 	log_buf(out, "\n");
336 	json_print_level(json_array_level(array), out);
337 	log_buf(out, "]");
338 }
339 
json_print_value(struct json_value * value,struct buf_output * out)340 static void json_print_value(struct json_value *value, struct buf_output *out)
341 {
342 	switch (value->type) {
343 	case JSON_TYPE_STRING:
344 		log_buf(out, "\"%s\"", value->string);
345 		break;
346 	case JSON_TYPE_INTEGER:
347 		log_buf(out, "%lld", value->integer_number);
348 		break;
349 	case JSON_TYPE_FLOAT:
350 		log_buf(out, "%f", value->float_number);
351 		break;
352 	case JSON_TYPE_OBJECT:
353 		json_print_object(value->object, out);
354 		break;
355 	case JSON_TYPE_ARRAY:
356 		json_print_array(value->array, out);
357 		break;
358 	}
359 }
360