Blame util/json.c

Packit Service b7b338
#include <stdlib.h>
Packit Service b7b338
#include <string.h>
Packit Service b7b338
#include <stdio.h>
Packit Service b7b338
#include <errno.h>
Packit Service b7b338
#include <stdarg.h>
Packit Service b7b338
#include "json.h"
Packit Service b7b338
Packit Service b7b338
static inline void fail_and_notify(void)
Packit Service b7b338
{
Packit Service b7b338
	fprintf(stderr, "Allocation of memory for json object failed, aborting.\n");
Packit Service b7b338
	abort();
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
struct json_object *json_create_object(void)
Packit Service b7b338
{
Packit Service b7b338
	void *test = calloc(1, sizeof(struct json_object));
Packit Service b7b338
	if (!test)
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
	return test;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
struct json_array *json_create_array(void)
Packit Service b7b338
{
Packit Service b7b338
	void *test = calloc(1, sizeof(struct json_array));
Packit Service b7b338
	if (!test)
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
	return test;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_pair *json_create_pair(const char *name, struct json_value *value)
Packit Service b7b338
{
Packit Service b7b338
	struct json_pair *pair = malloc(sizeof(struct json_pair));
Packit Service b7b338
	if (pair) {
Packit Service b7b338
		pair->name = strdup(name);
Packit Service b7b338
		pair->value = value;
Packit Service b7b338
Packit Service b7b338
		value->parent_type = JSON_PARENT_TYPE_PAIR;
Packit Service b7b338
		value->parent_pair = pair;
Packit Service b7b338
	} else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return pair;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_value *json_create_value_int(long long number)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_INTEGER;
Packit Service b7b338
		value->integer_number = number;
Packit Service b7b338
	} else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_value *json_create_value_uint(unsigned long long number)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_UINT;
Packit Service b7b338
		value->uint_number = number;
Packit Service b7b338
	} else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_value *json_create_value_float(long double number)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_FLOAT;
Packit Service b7b338
		value->float_number = number;
Packit Service b7b338
	}  else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static char *strdup_escape(const char *str)
Packit Service b7b338
{
Packit Service b7b338
	const char *input = str;
Packit Service b7b338
	char *p, *ret;
Packit Service b7b338
	int escapes;
Packit Service b7b338
Packit Service b7b338
	if (!strlen(str))
Packit Service b7b338
		return NULL;
Packit Service b7b338
Packit Service b7b338
	escapes = 0;
Packit Service b7b338
	while ((input = strpbrk(input, "\\\"")) != NULL) {
Packit Service b7b338
		escapes++;
Packit Service b7b338
		input++;
Packit Service b7b338
	}
Packit Service b7b338
Packit Service b7b338
	p = ret = malloc(strlen(str) + escapes + 1);
Packit Service b7b338
	if (!ret)
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	while (*str) {
Packit Service b7b338
		if (*str == '\\' || *str == '\"')
Packit Service b7b338
			*p++ = '\\';
Packit Service b7b338
		*p++ = *str++;
Packit Service b7b338
	}
Packit Service b7b338
	*p = '\0';
Packit Service b7b338
Packit Service b7b338
	return ret;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
/*
Packit Service b7b338
 * Valid JSON strings must escape '"' and '/' with a preceding '/'
Packit Service b7b338
 */
Packit Service b7b338
static struct json_value *json_create_value_string(const char *str)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_STRING;
Packit Service b7b338
		value->string = strdup_escape(str ? str : "(null)");
Packit Service b7b338
		if (!value->string) {
Packit Service b7b338
			free(value);
Packit Service b7b338
			value = NULL;
Packit Service b7b338
			return value;
Packit Service b7b338
		}
Packit Service b7b338
	}
Packit Service b7b338
	if (!value)
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_value *json_create_value_object(struct json_object *obj)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_OBJECT;
Packit Service b7b338
		value->object = obj;
Packit Service b7b338
		obj->parent = value;
Packit Service b7b338
	} else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static struct json_value *json_create_value_array(struct json_array *array)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value = malloc(sizeof(struct json_value));
Packit Service b7b338
Packit Service b7b338
	if (value) {
Packit Service b7b338
		value->type = JSON_TYPE_ARRAY;
Packit Service b7b338
		value->array = array;
Packit Service b7b338
		array->parent = value;
Packit Service b7b338
	} else
Packit Service b7b338
		fail_and_notify();
Packit Service b7b338
Packit Service b7b338
	return value;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_free_pair(struct json_pair *pair);
Packit Service b7b338
static void json_free_value(struct json_value *value);
Packit Service b7b338
Packit Service b7b338
void json_free_object(struct json_object *obj)
Packit Service b7b338
{
Packit Service b7b338
	int i;
Packit Service b7b338
Packit Service b7b338
	for (i = 0; i < obj->pair_cnt; i++)
Packit Service b7b338
		json_free_pair(obj->pairs[i]);
Packit Service b7b338
	free(obj->pairs);
Packit Service b7b338
	free(obj);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
void json_free_array(struct json_array *array)
Packit Service b7b338
{
Packit Service b7b338
	int i;
Packit Service b7b338
Packit Service b7b338
	for (i = 0; i < array->value_cnt; i++)
Packit Service b7b338
		json_free_value(array->values[i]);
Packit Service b7b338
	free(array->values);
Packit Service b7b338
	free(array);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_free_pair(struct json_pair *pair)
Packit Service b7b338
{
Packit Service b7b338
	json_free_value(pair->value);
Packit Service b7b338
	free(pair->name);
Packit Service b7b338
	free(pair);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_free_value(struct json_value *value)
Packit Service b7b338
{
Packit Service b7b338
	switch (value->type) {
Packit Service b7b338
	case JSON_TYPE_STRING:
Packit Service b7b338
		free(value->string);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_OBJECT:
Packit Service b7b338
		json_free_object(value->object);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_ARRAY:
Packit Service b7b338
		json_free_array(value->array);
Packit Service b7b338
		break;
Packit Service b7b338
	}
Packit Service b7b338
	free(value);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_array_add_value(struct json_array *array, struct json_value *value)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value **values = realloc(array->values,
Packit Service b7b338
		sizeof(struct json_value *) * (array->value_cnt + 1));
Packit Service b7b338
Packit Service b7b338
	if (!values)
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
	values[array->value_cnt] = value;
Packit Service b7b338
	array->value_cnt++;
Packit Service b7b338
	array->values = values;
Packit Service b7b338
Packit Service b7b338
	value->parent_type = JSON_PARENT_TYPE_ARRAY;
Packit Service b7b338
	value->parent_array = array;
Packit Service b7b338
	return 0;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_object_add_pair(struct json_object *obj, struct json_pair *pair)
Packit Service b7b338
{
Packit Service b7b338
	struct json_pair **pairs = realloc(obj->pairs,
Packit Service b7b338
		sizeof(struct json_pair *) * (obj->pair_cnt + 1));
Packit Service b7b338
	if (!pairs)
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
	pairs[obj->pair_cnt] = pair;
Packit Service b7b338
	obj->pair_cnt++;
Packit Service b7b338
	obj->pairs = pairs;
Packit Service b7b338
Packit Service b7b338
	pair->parent = obj;
Packit Service b7b338
	return 0;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
int json_object_add_value_type(struct json_object *obj, const char *name, int type, ...)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value;
Packit Service b7b338
	struct json_pair *pair;
Packit Service b7b338
	va_list args;
Packit Service b7b338
	int ret;
Packit Service b7b338
Packit Service b7b338
	va_start(args, type);
Packit Service b7b338
	if (type == JSON_TYPE_STRING)
Packit Service b7b338
		value = json_create_value_string(va_arg(args, char *));
Packit Service b7b338
	else if (type == JSON_TYPE_INTEGER)
Packit Service b7b338
		value = json_create_value_int(va_arg(args, long long));
Packit Service b7b338
	else if (type == JSON_TYPE_UINT)
Packit Service b7b338
		value = json_create_value_uint(va_arg(args, unsigned long long));
Packit Service b7b338
	else if (type == JSON_TYPE_FLOAT)
Packit Service b7b338
		value = json_create_value_float(va_arg(args, long double));
Packit Service b7b338
	else if (type == JSON_TYPE_OBJECT)
Packit Service b7b338
		value = json_create_value_object(va_arg(args, struct json_object *));
Packit Service b7b338
	else
Packit Service b7b338
		value = json_create_value_array(va_arg(args, struct json_array *));
Packit Service b7b338
	va_end(args);
Packit Service b7b338
Packit Service b7b338
	if (!value)
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
Packit Service b7b338
	pair = json_create_pair(name, value);
Packit Service b7b338
	if (!pair) {
Packit Service b7b338
		json_free_value(value);
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
	}
Packit Service b7b338
	ret = json_object_add_pair(obj, pair);
Packit Service b7b338
	if (ret) {
Packit Service b7b338
		json_free_pair(pair);
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
	}
Packit Service b7b338
	return 0;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_array(struct json_array *array, void *);
Packit Service b7b338
int json_array_add_value_type(struct json_array *array, int type, ...)
Packit Service b7b338
{
Packit Service b7b338
	struct json_value *value;
Packit Service b7b338
	va_list args;
Packit Service b7b338
	int ret;
Packit Service b7b338
Packit Service b7b338
	va_start(args, type);
Packit Service b7b338
	if (type == JSON_TYPE_STRING)
Packit Service b7b338
		value = json_create_value_string(va_arg(args, char *));
Packit Service b7b338
	else if (type == JSON_TYPE_INTEGER)
Packit Service b7b338
		value = json_create_value_int(va_arg(args, long long));
Packit Service b7b338
	else if (type == JSON_TYPE_UINT)
Packit Service b7b338
		value = json_create_value_uint(va_arg(args, unsigned long long));
Packit Service b7b338
	else if (type == JSON_TYPE_FLOAT)
Packit Service b7b338
		value = json_create_value_float(va_arg(args, double));
Packit Service b7b338
	else if (type == JSON_TYPE_OBJECT)
Packit Service b7b338
		value = json_create_value_object(va_arg(args, struct json_object *));
Packit Service b7b338
	else
Packit Service b7b338
		value = json_create_value_array(va_arg(args, struct json_array *));
Packit Service b7b338
	va_end(args);
Packit Service b7b338
Packit Service b7b338
	if (!value)
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
Packit Service b7b338
	ret = json_array_add_value(array, value);
Packit Service b7b338
	if (ret) {
Packit Service b7b338
		json_free_value(value);
Packit Service b7b338
		return ENOMEM;
Packit Service b7b338
	}
Packit Service b7b338
	return 0;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_value_level(struct json_value *value);
Packit Service b7b338
static int json_pair_level(struct json_pair *pair);
Packit Service b7b338
static int json_array_level(struct json_array *array);
Packit Service b7b338
static int json_object_level(struct json_object *object)
Packit Service b7b338
{
Packit Service b7b338
	if (object->parent == NULL)
Packit Service b7b338
		return 0;
Packit Service b7b338
	return json_value_level(object->parent);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_pair_level(struct json_pair *pair)
Packit Service b7b338
{
Packit Service b7b338
	return json_object_level(pair->parent) + 1;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_array_level(struct json_array *array)
Packit Service b7b338
{
Packit Service b7b338
	return json_value_level(array->parent);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static int json_value_level(struct json_value *value)
Packit Service b7b338
{
Packit Service b7b338
	if (value->parent_type == JSON_PARENT_TYPE_PAIR)
Packit Service b7b338
		return json_pair_level(value->parent_pair);
Packit Service b7b338
	else
Packit Service b7b338
		return json_array_level(value->parent_array) + 1;
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_level(int level, void *out)
Packit Service b7b338
{
Packit Service b7b338
	while (level-- > 0)
Packit Service b7b338
		printf("  ");
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_pair(struct json_pair *pair, void *);
Packit Service b7b338
static void json_print_array(struct json_array *array, void *);
Packit Service b7b338
static void json_print_value(struct json_value *value, void *);
Packit Service b7b338
void json_print_object(struct json_object *obj, void *out)
Packit Service b7b338
{
Packit Service b7b338
	int i;
Packit Service b7b338
Packit Service b7b338
	printf("{\n");
Packit Service b7b338
	for (i = 0; i < obj->pair_cnt; i++) {
Packit Service b7b338
		if (i > 0)
Packit Service b7b338
			printf(",\n");
Packit Service b7b338
		json_print_pair(obj->pairs[i], out);
Packit Service b7b338
	}
Packit Service b7b338
	printf("\n");
Packit Service b7b338
	json_print_level(json_object_level(obj), out);
Packit Service b7b338
	printf("}");
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_pair(struct json_pair *pair, void *out)
Packit Service b7b338
{
Packit Service b7b338
	json_print_level(json_pair_level(pair), out);
Packit Service b7b338
	printf("\"%s\" : ", pair->name);
Packit Service b7b338
	json_print_value(pair->value, out);
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_array(struct json_array *array, void *out)
Packit Service b7b338
{
Packit Service b7b338
	int i;
Packit Service b7b338
Packit Service b7b338
	printf("[\n");
Packit Service b7b338
	for (i = 0; i < array->value_cnt; i++) {
Packit Service b7b338
		if (i > 0)
Packit Service b7b338
			printf(",\n");
Packit Service b7b338
		json_print_level(json_value_level(array->values[i]), out);
Packit Service b7b338
		json_print_value(array->values[i], out);
Packit Service b7b338
	}
Packit Service b7b338
	printf("\n");
Packit Service b7b338
	json_print_level(json_array_level(array), out);
Packit Service b7b338
	printf("]");
Packit Service b7b338
}
Packit Service b7b338
Packit Service b7b338
static void json_print_value(struct json_value *value, void *out)
Packit Service b7b338
{
Packit Service b7b338
	switch (value->type) {
Packit Service b7b338
	case JSON_TYPE_STRING:
Packit Service b7b338
		printf( "\"%s\"", value->string);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_INTEGER:
Packit Service b7b338
		printf( "%lld", value->integer_number);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_UINT:
Packit Service b7b338
		printf( "%llu", value->uint_number);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_FLOAT:
Packit Service b7b338
		printf( "%.0Lf", value->float_number);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_OBJECT:
Packit Service b7b338
		json_print_object(value->object, out);
Packit Service b7b338
		break;
Packit Service b7b338
	case JSON_TYPE_ARRAY:
Packit Service b7b338
		json_print_array(value->array, out);
Packit Service b7b338
		break;
Packit Service b7b338
	}
Packit Service b7b338
}