Newer
Older
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <json-c/json.h>
/* will allocate memory! remember to free! */
static char *get_file(const char *path)
{
FILE *f;
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, 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) {
copy_object_into_object(j_val, j_new);
json_object_object_add(src, parsed_key, j_new);
} else
copy_object_into_object(j_val, src);
} else
iterate_array(src, idx, len, j_val, 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, parsed_key);
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/**
* del a value key pair to src object
*
*/
static int del_val(struct json_object *src, char *key)
{
struct json_object *val;
int idx[32];
int len, rv = -1;
char parsed_key[32] = {0};
len = get_idx(key, idx, parsed_key);
json_object_object_get_ex(src, parsed_key, &val);
if (len < 1 || !val || !json_object_is_type(val, json_type_array)) {
json_object_object_del(src, parsed_key);
rv = 0;
} else {
/* iterate every index that was appended to the key */
for (int i = 0; i < len; i++) {
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 (i < len -1) {
if (!j_idx || !json_object_is_type(j_idx, json_type_array)) {
fprintf(stderr, "%s error: type is not array!\n", __func__);
goto out;
}
val = j_idx;
}
/* at final index, delete at specified idx */
else {
if (idx[i] > -1)
json_object_array_del_idx(val, idx[i], 1);
else
json_object_array_del_idx(val, json_object_array_length(val) - 1, 1);
rv = 0;
}
}
}
out:
return rv;
}
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};
*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)) {
if (!ptr) {
ptr = json_object_new_object();
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)
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(outer_obj, 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);
}
}
return ptr;
}
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
int json_object_del_by_string(struct json_object *src, char *fmt)
{
return json_object_del_by_string_delimiter(src, fmt, ".");
}
int json_object_del_by_string_delimiter(struct json_object *src, char *fmt, const char *delimiter)
{
struct json_object *ptr, *outer_obj, *j_idx;
char fmt_cpy[1024] = {0}, parsed_key[32] = {0};
char *p, *key = fmt;
int idx[32];
int len;
if (!src) {
fprintf(stderr, "%s error: No object\n", __func__);
return -1;
}
if (!fmt) {
fprintf(stderr, "%s error: Invalid format\n", __func__);
return -1;
}
ptr = outer_obj = src;
strcpy(fmt_cpy, fmt);
p = strtok(fmt_cpy,delimiter);
while (p != NULL) {
key = p;
p = strtok(NULL, delimiter);
if (p) {
int len = 0;
len = get_idx(key, idx, parsed_key);
json_object_object_get_ex(outer_obj, parsed_key, &ptr);
for (int i = 0; i < len; i++) {
if (!json_object_is_type(ptr, json_type_array))
return -1;
int index = (idx[i] == -1 ? json_object_array_length(ptr) -1 : idx[i]);
ptr = json_object_array_get_idx(ptr, index);
}
}
outer_obj = ptr;
}
del_val(ptr, key);
return 0;
}