Skip to content
Snippets Groups Projects
api.c 8.85 KiB
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>

#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <json-c/json.h>

#include "api.h"

/* will allocate memory! remember to free! */
char *get_file(const char *path)
{
	FILE *f;
	size_t len, nread;
	char *buffer;

	f = fopen(path, "r");
	if (!f)
		goto out;

	if (fseek(f, 0, SEEK_END))
		goto out_close;

	len = ftell(f);
	if (len < 0)
		goto out_close;

	if (fseek(f, 0, SEEK_SET))
		goto out_close;

	buffer = calloc(1, len);
	if (!buffer)
		goto out_close;

	nread = fread(buffer, sizeof(char), len, f);
	if (nread < len)
		goto out_free;

	fclose(f);
	return buffer;
out_free:
	free(buffer);
out_close:
	fclose(f);
out:
	return NULL;
}

struct json_object *path_to_obj(const char *path)
{
	struct json_object *obj;
	char *file_str;

	file_str = get_file(path);
	if (!file_str)
		goto out;

	obj = json_tokener_parse(file_str);

	free(file_str);
	return obj;
out:
	return NULL;
}

int get_idx(char *key)
{
	char *open_brace = strchr(key, '[');
	printf("open_brace=%s\n", open_brace);
	if (open_brace) {
		char *close_brace = strchr(open_brace, ']');
		if (close_brace) {
			int len = close_brace - open_brace;
			printf("len=%d\n", len);
			char *idx_str = calloc(1, len);
			strncpy(idx_str, open_brace + 1, len-1);
			printf("idx_str = %s\n", idx_str);
			int idx = atoi(idx_str);
			printf("idx = %d\n", idx);
			*open_brace = '\0';
			printf("key=%s\n", key);
			return idx;
		}
	}

	return -2;
}

int add_array(struct json_object *ptr, int idx, char *val, enum json_type type, char *key)
{
	struct json_object *tmp;
	struct json_object *j_val;
	printf("%s %d\n", __func__, __LINE__);
	switch(type) {
	case json_type_array:
		j_val = json_tokener_parse(val);
	break;
	case json_type_boolean:
		;;
	break;
	case json_type_object:
		j_val = json_tokener_parse(val);
	break;
	case json_type_string:
		j_val = json_object_new_string(val);
	break;
	case json_type_double:
		j_val = json_object_new_double(atof(val));
	break;
	case json_type_int:
		j_val = json_object_new_double(atoi(val));
	break;
	default:
		return -1;
	break;
	}
printf("%s %d\n", __func__, __LINE__);
	json_object_object_get_ex(ptr, key, &tmp);
	if (json_object_is_type(tmp, json_type_array)) {
		if (tmp && idx != -1) {
			json_object_array_put_idx(tmp, idx, j_val);
		} else if (tmp && idx == -1) {
			printf("%s %d\n", __func__, __LINE__);
			json_object_array_add(tmp, j_val);
		}
	} else {
		printf("%s %d\n", __func__, __LINE__);
		tmp = json_object_new_array();
		json_object_array_add(tmp, j_val);
		printf("%s %d type=%s, ptr_type=%s\n", __func__, __LINE__, json_type_to_name(json_object_get_type(tmp)), json_type_to_name(json_object_get_type(ptr)));
		printf("tmp=%s\n", json_object_get_string(tmp));
		printf("ptr=%s\n", json_object_get_string(ptr));
		printf("key=%s\n", key);
		json_object_object_add(ptr, key, tmp);
	}
printf("%s %d\n", __func__, __LINE__);
	return 0;
}

int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type type)
{
	struct json_object *ptr, *tmp, *tar;
	const char *delimiter = ".";
	char buffer[1024] = {0};
	char *p, *prev = fmt;
	int idx;

	if (!*src) {
		printf("lets allocate new object\n");
		*src = json_object_new_object();
	}

	printf("format = %s\n", fmt);
	printf("set val = %s\n", val);

	ptr = tmp = *src;

	strcpy(buffer, fmt);

	p = strtok(buffer,delimiter);
	while (p != NULL) {
		prev = p;
		p = strtok(NULL, delimiter);

		/* if next key exists, parse prev key, let switch-case add/alter last key */
		if (p) {
			/* TODO: pretty wonky order with get idx first to overwrite braces?*/
			idx = get_idx(prev);
			json_object_object_get_ex(tmp, prev, &ptr);
			/* if we need to step further and currently marked value isnt an object, we need to overwrite it */
			if (!json_object_is_type(ptr, json_type_object) && !json_object_is_type(ptr, json_type_array)) {
				printf("lets create new object hahah! key = %s\n", prev);
				ptr = json_object_new_object();
				json_object_object_add(tmp, prev, ptr);
			}
			printf("p=%s\n", p);

			/* TODO: if prev contains [x], get idx of x */
			printf("%s %d\n", __func__, __LINE__);
			/* TODO: make enums for rv of get_idx */
			if (idx != -2) {
				if (ptr && json_object_get_type(ptr) == json_type_array) {
					printf("%s %d\n", __func__, __LINE__);
					ptr = json_object_array_get_idx(ptr, idx);
				} else {
					ptr = json_object_new_array();
					printf("%s %d type=%s, ptr_type=%s\n", __func__, __LINE__, json_type_to_name(json_object_get_type(tmp)), json_type_to_name(json_object_get_type(ptr)));
					printf("tmp=%s\n", json_object_get_string(tmp));
					printf("ptr=%s\n", json_object_get_string(ptr));
					printf("prev=%s\n", prev);
					json_object_object_add(tmp, prev, ptr);
					//json_object_array_add(tmp, ptr);
				}
			}

			/* create prev object if it does not exist */
			if (!ptr) {
				ptr = json_object_new_object();
				printf("%s %d\n", __func__, __LINE__);
				if (json_object_get_type(tmp) == json_type_array)
					json_object_array_add(tmp, ptr);
				else if (json_object_get_type(tmp) == json_type_object)
					json_object_object_add(tmp, prev, ptr);
			}
		}

		tmp = ptr;
	}

	json_object_object_get_ex(ptr, prev, &tar);

	switch(type) {
	case json_type_object:
	{
		struct json_object *parsed_val = json_tokener_parse(val);

		if (!parsed_val) {
			fprintf(stderr, "Invalid object format\n");
			return -1;
		} else if (type != json_object_get_type(parsed_val)) {
			fprintf(stderr, "Types don't match!\n");
			return -1;
		}

		/* TODO: does this actually work? what would be the test case for this? */
		idx = get_idx(prev);
		if (idx == -2) {
			json_object_object_foreach(parsed_val, key1, val1)
				json_object_object_add(*src, key1, val1);
		} else {
			printf("%s %d\n", __func__, __LINE__);
			add_array(ptr, idx, val, type, prev);
		}
	}
	break;
	case json_type_string:
		idx = get_idx(prev);
		if (idx == -2)
			json_object_object_add(ptr, prev, json_object_new_string(val));
		else {
			printf("%s %d\n", __func__, __LINE__);
			add_array(ptr, idx, val, type, prev);
		}
	break;
	case json_type_int:
		printf("%s %d\n", __func__, __LINE__);
		idx = get_idx(prev);
		if (idx == -2)
			json_object_object_add(ptr, prev, json_object_new_int(atoi(val)));
		else {
			printf("%s %d\n", __func__, __LINE__);
			add_array(ptr, idx, val, type, prev);
		}
	break;
	case json_type_array:
	{
		struct json_object *parsed_val = json_tokener_parse(val);

		if (!parsed_val) {
			fprintf(stderr, "Invalid array format\n");
			return -1;
		} else if (type != json_object_get_type(parsed_val)) {
			fprintf(stderr, "Types don't match!\n");
			return -1;
		}

		json_object_object_add(ptr, prev, parsed_val);
	}
	break;
	case json_type_double:
		idx = get_idx(prev);
		if (idx == -2)
			json_object_object_add(ptr, prev, json_object_new_int(atof(val)));
		else {
			printf("%s %d\n", __func__, __LINE__);
			add_array(ptr, idx, val, type, prev);
		}
		
	break;
	case json_type_boolean:
	{
		bool bool_val = false;

		if (strncasecmp(val, "true", 4) || atoi(val) == 1)
			bool_val = true;


		json_object_object_add(ptr, prev, json_object_new_boolean(bool_val));
	}
	break;
	default:
		fprintf(stderr, "Not valid input type!\n");
	break;
	}

	return 0;
}

int set(char *fmt, struct json_object *src, struct json_object *val)
{
	const char *delimiter = ".";
	char buffer[1024] = {0};
	char *p;

	if (json_object_get_type(val) != json_type_object) {
		fprintf(stderr, "object must be of type object!\n");
		return -1;
	}

	src = get(fmt, src);

	strcpy(buffer, fmt);

	/* TODO: put this in some separate function */
	for (p = strtok(buffer,delimiter); p != NULL; p = strtok(NULL, delimiter)) {
		struct json_object *ptr, *tmp = src;

		json_object_object_get_ex(tmp, p, &ptr);
		if (!ptr) {
			ptr = json_object_new_object();
			json_object_object_add(tmp, p, ptr);
		}

		tmp = ptr;
	}

	json_object_object_foreach(val, key, val1)
		json_object_object_add(src, key, val1);

	return 0;
}

struct json_object *get(char *fmt, struct json_object *src)
{
	struct json_object *ptr, *tmp = src;
	const char *delimiter = ".";
	char buffer[1024] = {0};

	strcpy(buffer, fmt);

	for (char *p = strtok(buffer,delimiter); p != NULL; p = strtok(NULL, delimiter)) {
		json_object_object_get_ex(tmp, p, &ptr);
		tmp = ptr;
	}

	return ptr;
}

int main()
{
	struct json_object *obj = path_to_obj("/home/jakob/git/json-editor/test.json");
	struct json_object *ptr;

	printf("%s %d\n", __func__, __LINE__);
	struct json_object *arr = json_object_new_array();
	struct json_object *obj_arr = json_object_new_object();

	json_object_object_add(obj_arr, "test_arr", arr);
	printf("tets_arr = %s\n", json_object_get_string(obj_arr));


	printf("original obj=%s\n", json_object_get_string(obj));

	ptr = get("nested", obj);

	printf("%s\n", json_object_get_string(ptr));

	set_by_string("test.apdfgj[1].test", &obj, "gå och häng dig", json_type_string);

	printf("result: %s\n", json_object_get_string(obj));

	json_object_put(obj);
	return 0;
}