Newer
Older
#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! */
static 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;
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 *json_object_file_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 json_object_obj_to_file(struct json_object *obj, const char *path)
{
FILE *out;
int rv = -1;
if (!obj) {
fprintf(stderr, "%s error: No object provided!\n", __func__);
goto out;
}
if (!path) {
fprintf(stderr, "%s error: No file path provided!\n", __func__);
goto out;
}
data = json_object_get_string(obj);
if (!data) {
fprintf(stderr, "%s error: Converting object to string!\n", __func__);
goto out;
}
out = fopen (path, "ab+");
if (out != NULL) {
if (fputs (data, out) != EOF)
goto out_fclose;
rv = 0;
}
out_fclose:
fclose (out);
out:
return rv;
}
static int get_idx(char *key, int *idx, char *out)
char *open_brace;
int len = 0;
char buffer[64] = {0};
char *ptr;
strncpy(buffer, key, sizeof(buffer) - 1);
ptr = (char *)buffer;
while((open_brace = strchr(ptr, '['))) {
char *close_brace = strchr(open_brace, ']');
str_len = close_brace - open_brace;
idx_str = calloc(1, str_len);
strncpy(idx_str, open_brace + 1, str_len-1);
idx[len++] = atoi(idx_str);
static struct json_object *dummy_val(char *val, enum json_type type)
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_int(atoi(val));
return j_val;
}
/**
* If key to be added is indexed, makes sure specified key is an array and selects appropriate index.
* Should the key not be an array, it will be converted to an array and appropriate indexes will be prepared.
*
*/
static int iterate_array(struct json_object *src, int *idx, int len, struct json_object *j_val, enum json_type type, char *key)
if (!j_val)
return -1;
/* select key, if it does not exist or is not an array, create one */
json_object_object_get_ex(src, key, &val);
if (!val || !json_object_is_type(val, json_type_array)) {
val = json_object_new_array();
json_object_object_add(src, key, val);
/* iterate every index that was appended to the key */
struct json_object *j_idx;
/* select specified idx from currently selected array */
j_idx = json_object_array_get_idx(val, idx[i]);
/* if we are not at final idx, make sure next entry is an array */
if (!j_idx || !json_object_is_type(j_idx, json_type_array)) {
j_idx = json_object_new_array();
json_object_array_put_idx(val, idx[i], j_idx);
val = j_idx;
}
/* at final index, place passed object at specified idx */
else {
json_object_array_put_idx(val, idx[i], j_val);
static void copy_object_into_object(struct json_object *src, struct json_object *dst)
{
json_object_object_foreach(src, key, val)
json_object_object_add(dst, key, json_object_get(val));
json_object_put(src);
}
/**
* Add a value key pair to src object
*
*/
static int add_val(struct json_object *src, char *key, char *val, enum json_type type)
int idx[32];
int len;
char parsed_key[32] = {0};
j_val = dummy_val(val, type);
if (!j_val || !json_object_is_type(j_val, type)) {
fprintf(stderr, "Invalid input value, parsed value and input type does not match!\n");
/* if input object is of type object we need to iterate the object and copy {key:value} into specified key */
/* if a key is provided, place input under that key, else place in root */
if (key) {
struct json_object *tmp;
tmp = json_object_new_object();
if (!tmp)
return -1;
copy_object_into_object(j_val, tmp);
json_object_object_add(src, parsed_key, tmp);
} else
copy_object_into_object(j_val, src);
} else
iterate_array(src, idx, len, j_val, type, parsed_key);
/* object type is not an object, attach to provided key */
if (len < 1 || type == json_type_array)
json_object_object_add(src, parsed_key, j_val);
iterate_array(src, idx, len, j_val, type, parsed_key);
int json_object_set_by_string(struct json_object **src, char *fmt, char *val, enum json_type type)
{
return json_object_set_by_string_delimiter(src, fmt, val, type, ".");
}
/**
* Generate object according to javascript style format
*
*/
int json_object_set_by_string_delimiter(struct json_object **src, char *fmt, char *val, enum json_type type, const char *delimiter)
struct json_object *ptr, *outer_obj, *j_idx;
char fmt_cpy[1024] = {0}, parsed_key[32] = {0};
if (!*src) {
printf("lets allocate new object\n");
*src = json_object_new_object();
}
if (!fmt)
goto add_key;
strcpy(fmt_cpy, fmt);
p = strtok(fmt_cpy,delimiter);
while (p != NULL) {
p = strtok(NULL, delimiter);
/* if next key exists, parse key, let switch-case add/alter last key */
memset(idx, 0, sizeof(idx));
len = get_idx(key, idx, parsed_key);
/* as next key exists (p), we muts create an object here if it is currently not an object */
json_object_object_get_ex(outer_obj, parsed_key, &ptr);
if (!json_object_is_type(ptr, json_type_object) && !json_object_is_type(ptr, json_type_array)) {
/* we know its an object because it is not the last key */
json_object_object_add(outer_obj, parsed_key, ptr);
/* if the key is indexed, we need step into the array */
for (int i = 0; i < len; i++) {
/* make sure ptr is an array, step into specified index */
if (ptr && json_object_get_type(ptr) == json_type_array) {
if (idx[i] > -1 && idx[i] < json_object_array_length(ptr)) {
j_idx = json_object_array_get_idx(ptr, idx[i]);
if (!json_object_is_type(j_idx, json_type_object)) {
struct json_object *obj = json_object_new_object();
if (!obj)
return -1;
json_object_array_put_idx(ptr, idx[i], obj);
j_idx = json_object_array_get_idx(ptr, idx[i]);
ptr = j_idx;
}
else {
if (i == len - 1)
json_object_array_add(ptr, json_object_new_object());
else if (i < len -1)
json_object_array_add(ptr, json_object_new_array());
ptr = json_object_array_get_idx(ptr, json_object_array_length(ptr) - 1);
}
} else {
ptr = json_object_new_array();
json_object_object_add(outer_obj, parsed_key, ptr);
if (i == len - 1) {
json_object_array_add(ptr, json_object_new_object());
ptr = json_object_array_get_idx(ptr, json_object_array_length(ptr) - 1);
}
}
/* if this point is reached and ptr is not set, a key is specified which does not exist - create it */
if (!ptr) {
ptr = json_object_new_object();
if (json_object_get_type(outer_obj) == json_type_array)
json_object_array_add(outer_obj, ptr);
else if (json_object_get_type(outer_obj) == json_type_object)
json_object_object_add(outer_obj, parsed_key, ptr);
}
}
return 0;
}
int json_object_set(struct json_object *src, char *fmt, struct json_object *val)
{
return json_object_set_delimiter(src, fmt, val, ".");
}
int json_object_set_delimiter(struct json_object *src, char *fmt, struct json_object *val, const char *delimiter)
char *p;
if (json_object_get_type(val) != json_type_object) {
fprintf(stderr, "object must be of type object!\n");
return -1;
}
src = json_object_get_by_string(src, fmt);
for (p = strtok(fmt_cpy,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, j_val)
json_object_object_add(src, key, j_val);
return 0;
}
struct json_object *json_object_get_by_string(struct json_object *src, char *fmt)
{
return json_object_get_by_string_delimiter(src, fmt, ".");
}
struct json_object *json_object_get_by_string_delimiter(struct json_object *src, char *fmt, const char *delimiter)
{
struct json_object *ptr, *tmp = src;
for (char *key = strtok(fmt_cpy,delimiter); key != NULL; key = strtok(NULL, delimiter)) {
int len = 0;
len = get_idx(key, idx, parsed_key);
json_object_object_get_ex(tmp, parsed_key, &ptr);
for (int i = 0; i < len; i++) {
if (!json_object_is_type(ptr, json_type_array))
return NULL;
int index = (idx[i] == -1 ? json_object_array_length(ptr) -1 : idx[i]);
ptr = json_object_array_get_idx(ptr, index);
}
tmp = ptr;
}
return ptr;
}