Home | History | Annotate | Download | only in fio
      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 
      9 struct json_object *json_create_object(void)
     10 {
     11 	return calloc(1, sizeof(struct json_object));
     12 }
     13 
     14 struct json_array *json_create_array(void)
     15 {
     16 	return calloc(1, sizeof(struct json_array));
     17 }
     18 
     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 
     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 
     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 
     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  */
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 *);
    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);
    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 
    275 static int json_pair_level(struct json_pair *pair)
    276 {
    277 	return json_object_level(pair->parent) + 1;
    278 }
    279 
    280 static int json_array_level(struct json_array *array)
    281 {
    282 	return json_value_level(array->parent);
    283 }
    284 
    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 
    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 *);
    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 
    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 
    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 
    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