Skip to content
Snippets Groups Projects
Commit 88dda86b authored by Jakob Olsson's avatar Jakob Olsson
Browse files

Merge branch 'array-manipulation' into devel

parents 09b28bee 4b88795f
Branches
No related tags found
No related merge requests found
......@@ -66,126 +66,274 @@ out:
return NULL;
}
int get_idx(char *key, int *idx, char *out)
{
char *open_brace;
int len = 0;
char buffer[64] = {0};
char *ptr;
printf("%s %d key=%s\n", __func__, __LINE__, key);
if(!key)
return -1;
strncpy(buffer, key, sizeof(buffer) - 1);
ptr = (char *)buffer;
printf("%s %d ptr=%s\n", __func__, __LINE__, ptr);
while((open_brace = strchr(ptr, '['))) {
char *close_brace = strchr(open_brace, ']');
if (close_brace) {
int str_len;
char *idx_str;
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);
*open_brace = '\0';
free(idx_str);
ptr = close_brace;
}
}
strncpy(out, buffer, 31);
printf("%s %d, out=%s, buffer=%s", __func__, __LINE__, out, buffer);
return len;
}
struct json_object *dummy_val(char *val, enum json_type type)
{
struct json_object *j_val;
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));
break;
default:
return NULL;
break;
}
return j_val;
}
int add_array(struct json_object *ptr, int *idx, int len, char *val, enum json_type type, char *key)
{
struct json_object *tmp, *tmp1;
struct json_object *j_val;
j_val = dummy_val(val, type);
if (!j_val)
return -1;
json_object_object_get_ex(ptr, key, &tmp);
if (!tmp || !json_object_is_type(tmp, json_type_array)) {
tmp = json_object_new_array();
json_object_object_add(ptr, key, tmp);
}
for (int i = 0; i < len; i++) {
struct json_object *tmp1;
tmp1 = json_object_array_get_idx(tmp, idx[i]);
printf("%s %d ptr = %s, tmp = %s\n", __func__, __LINE__, json_object_get_string(ptr), json_object_get_string(tmp));
if (i < len -1) {
if (!tmp1 || !json_object_is_type(tmp1, json_type_array)) {
tmp1 = json_object_new_array();
if (idx[i] > -1)
json_object_array_put_idx(tmp, idx[i], tmp1);
else
json_object_array_add(tmp, tmp1);
}
tmp = tmp1;
} else {
printf("%s %d ptr = %s, tmp = %s, tmp1=%s\n", __func__, __LINE__, json_object_get_string(ptr), json_object_get_string(tmp), json_object_get_string(tmp1));
if (idx[i] > -1)
json_object_array_put_idx(tmp, idx[i], j_val);
else
json_object_array_add(tmp, j_val);
}
}
printf("%s %d ptr = %s, tmp = %s\n", __func__, __LINE__, json_object_get_string(ptr), json_object_get_string(tmp));
return 0;
}
int add_val(struct json_object *ptr, char *key, char *val, enum json_type type)
{
struct json_object *j_val;
int idx[32];
int len;
char parsed_key[32] = {0};
len = get_idx(key, idx, parsed_key);
printf("%s %d parsed_key=%s\n", __func__, __LINE__, parsed_key);
j_val = dummy_val(val, type);
if (!j_val || !json_object_is_type(j_val, type)) {
fprintf(stderr, "Invalid input value!\n");
return -1;
}
printf("%s %d val=%s, j_val=%s, ptr=%s\n", __func__, __LINE__, val, json_object_get_string(j_val), json_object_get_string(ptr));
if (json_type_object == type) {
printf("%s %d\n", __func__, __LINE__);
/* TODO: does this actually work? what would be the test case for this? */
if (len < 1) {
struct json_object *tmp = ptr;
if (key)
ptr = json_object_new_object();
json_object_object_foreach(j_val, key1, val1)
json_object_object_add(ptr, key1, val1);
if (key) {
printf("%s %d\n", __func__, __LINE__);
json_object_object_add(tmp, parsed_key, ptr);
}
} else {
printf("%s %d\n", __func__, __LINE__);
add_array(ptr, idx, len, val, type, parsed_key);
}
return 0;
}
if (len < 1 || type == json_type_array)
json_object_object_add(ptr, parsed_key, j_val);
else {
add_array(ptr, idx, len, val, type, parsed_key);
}
return 0;
}
int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type type)
{
struct json_object *ptr, *tmp, *tar;
struct json_object *ptr, *tmp;
const char *delimiter = ".";
char buffer[1024] = {0};
char *p, *prev = fmt;
char fmt_cpy[1024] = {0}, parsed_key[32] = {0};
char *p, *key = fmt;
int idx[32];
int len;
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;
if (!fmt)
goto add_key;
strcpy(buffer, fmt);
strcpy(fmt_cpy, fmt);
p = strtok(fmt_cpy,delimiter);
p = strtok(buffer,delimiter);
while (p != NULL) {
prev = p;
key = p;
p = strtok(NULL, delimiter);
/* if next key exists, parse prev key, let switch-case add/alter last key */
/* if next key exists, parse key, let switch-case add/alter last key */
if (p) {
json_object_object_get_ex(tmp, prev, &ptr);
printf("p=%s\n", p);
/* TODO: if prev contains [x], get idx of x */
char *open_brace = strchr(prev, '[');
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("prev=%s\n", prev);
/* TODO: pretty wonky order with get idx first to overwrite braces?*/
memset(idx, 0, sizeof(idx));
len = get_idx(key, idx, parsed_key);
printf("parsed_key=%s\n", parsed_key);
printf("len=%d\n", len);
/* if we need to step further and currently marked value isnt an object, we need to overwrite it */
json_object_object_get_ex(tmp, parsed_key, &ptr);
if (!json_object_is_type(ptr, json_type_object) && !json_object_is_type(ptr, json_type_array)) {
ptr = json_object_new_object();
json_object_object_add(tmp, parsed_key, ptr);
}
/* TODO: make enums for rv of get_idx */
if (len > 0) {
for (int i = 0; i < len; i++) {
printf("%s %d, ptr = %s\n", __func__, __LINE__, json_object_get_string(ptr));
if (ptr && json_object_get_type(ptr) == json_type_array) {
ptr = json_object_array_get_idx(ptr, idx);
printf("%s %d\n", __func__, __LINE__);
if (idx[i] > -1 && idx[i] < json_object_array_length(ptr))
ptr = json_object_array_get_idx(ptr, idx[i]);
else {
printf("%s %d\n", __func__, __LINE__);
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());
printf("ptr=%s\n", json_object_get_string(ptr));
ptr = json_object_array_get_idx(ptr, json_object_array_length(ptr) - 1);
printf("ptr=%s\n", json_object_get_string(ptr));
}
} else {
ptr = json_object_new_array();
json_object_object_add(tmp, prev, ptr);
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(tmp, 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);
}
//json_object_array_add(tmp, ptr);
}
}
}
/* create prev object if it does not exist */
/* create key object if it does not exist */
if (!ptr) {
ptr = json_object_new_object();
json_object_object_add(tmp, prev, ptr);
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, parsed_key, ptr);
printf("%s %d: ptr=%s\n", __func__, __LINE__, json_object_get_string(ptr));
printf("%s %d: tmp=%s\n", __func__, __LINE__, json_object_get_string(tmp));
}
}
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;
}
json_object_object_foreach(parsed_val, key1, val1)
json_object_object_add(*src, key1, val1);
}
break;
case json_type_string:
json_object_object_add(ptr, prev, json_object_new_string(val));
break;
case json_type_int:
json_object_object_add(ptr, prev, json_object_new_int(atoi(val)));
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:
json_object_object_add(ptr, prev, json_object_new_int(atof(val)));
break;
case json_type_boolean:
{
bool bool_val = false;
if (strncasecmp(val, "true", 4) || atoi(val) == 1)
bool_val = true;
printf("%s %d key=%s\n", __func__, __LINE__, parsed_key);
json_object_object_add(ptr, prev, json_object_new_boolean(bool_val));
}
break;
default:
fprintf(stderr, "Not valid input type!\n");
break;
}
add_key:
printf("%s %d\n", __func__, __LINE__);
add_val(ptr, key, val, type);
return 0;
}
......@@ -193,7 +341,7 @@ int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type
int set(char *fmt, struct json_object *src, struct json_object *val)
{
const char *delimiter = ".";
char buffer[1024] = {0};
char fmt_cpy[1024] = {0};
char *p;
if (json_object_get_type(val) != json_type_object) {
......@@ -203,10 +351,10 @@ int set(char *fmt, struct json_object *src, struct json_object *val)
src = get(fmt, src);
strcpy(buffer, fmt);
strcpy(fmt_cpy, fmt);
/* TODO: put this in some separate function */
for (p = strtok(buffer,delimiter); p != NULL; p = strtok(NULL, delimiter)) {
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);
......@@ -228,11 +376,11 @@ struct json_object *get(char *fmt, struct json_object *src)
{
struct json_object *ptr, *tmp = src;
const char *delimiter = ".";
char buffer[1024] = {0};
char fmt_cpy[1024] = {0};
strcpy(buffer, fmt);
strcpy(fmt_cpy, fmt);
for (char *p = strtok(buffer,delimiter); p != NULL; p = strtok(NULL, delimiter)) {
for (char *p = strtok(fmt_cpy,delimiter); p != NULL; p = strtok(NULL, delimiter)) {
json_object_object_get_ex(tmp, p, &ptr);
tmp = ptr;
}
......@@ -242,18 +390,26 @@ struct json_object *get(char *fmt, struct json_object *src)
int main()
{
struct json_object *obj = path_to_obj("/home/jakob/git/json-editor-api/test.json");
struct json_object *obj = path_to_obj("/home/jakob/git/json-editor/test.json");
struct json_object *ptr;
printf("%s %d obj=%s\n", __func__, __LINE__, json_object_get_string(obj));
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("nested.api[1].test", &obj, "1", json_type_string);
set_by_string("test.asd[-1].test.tested", &obj, "{\"api_test\":\"hej\"}", json_type_object);
printf("%s\n", json_object_get_string(obj));
printf("result: %s\n", json_object_get_string(obj));
json_object_put(obj);
return 0;
......
......@@ -43,18 +43,21 @@ static void test_build_from_scratch(void **state)
struct json_object *file = path_to_obj("/home/jakob/git/json-editor-api/test.json");
struct json_object *jobj = NULL;
set_by_string("", &jobj, "{ \"test\":\"success\", \"nested\": { \"api\":\"test2\"} }", json_type_object);
set_by_string(NULL, &jobj, "{ \"test\":\"success\", \"nested\": { \"api\":\"test2\"} }", json_type_object);
assert_int_equal(1, json_object_equal(file, jobj));
printf("file_obj=%s\n", json_object_get_string(file));
printf("modify_obj=%s\n", json_object_get_string(jobj));
assert_int_equal(1, json_object_equal(file, jobj));
}
static void test_json_add_object(void **state)
{
(void) state;
//struct json_object *obj = json_object_new_object();
json_object_object_add(file_obj, "test2", json_object_new_string("success"));
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "test2", json_object_new_string("success"));
json_object_object_add(file_obj, "string", obj);
//json_object_object_add(file_obj, "string", json_object_new_string("1"));
set_by_string("string", &modify_obj, "{\"test2\":\"success\"}", json_type_object);
......@@ -138,7 +141,7 @@ static void test_json_add_multi_obj(void **state)
json_object_object_add(file_obj, "string", json_object_new_string("1"));
json_object_object_add(file_obj, "integer", json_object_new_int(1));
set_by_string("", &modify_obj, "{ \"nested0\": {\"nested1\": {\"integer\": 1}}, \"ints\": [1, 2, 3], \"string\":\"1\", \"integer\": 1}", json_type_object);
set_by_string(NULL, &modify_obj, "{ \"nested0\": {\"nested1\": {\"integer\": 1}}, \"ints\": [1, 2, 3], \"string\":\"1\", \"integer\": 1}", json_type_object);
printf("file_obj=%s\n", json_object_get_string(file_obj));
printf("modify_obj=%s\n", json_object_get_string(modify_obj));
......@@ -226,6 +229,118 @@ static void test_json_add_int_nested(void **state)
assert_int_equal(1, json_object_equal(modify_obj, file_obj));
}
static void test_json_add_array_int(void **state)
{
(void) state;
struct json_object *arr = json_object_new_array();
struct json_object *obj = json_object_new_object();
json_object_array_add(arr, json_object_new_int(1));
json_object_object_add(file_obj, "array", arr);
json_object_object_add(obj, "array", json_object_get(arr));
json_object_object_add(file_obj, "inner", obj);
set_by_string("array[-1]", &modify_obj, "1", json_type_int);
set_by_string("inner.array[-1]", &modify_obj, "1", json_type_int);
printf("file_obj=%s\n", json_object_get_string(file_obj));
printf("modify_obj=%s\n", json_object_get_string(modify_obj));
assert_int_equal(1, json_object_equal(modify_obj, file_obj));
}
static void test_json_add_array_object(void **state)
{
(void) state;
struct json_object *arr = json_object_new_array();
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "integer", json_object_new_int(1));
json_object_object_add(obj, "string", json_object_new_string("test"));
json_object_array_add(arr, obj);
json_object_array_add(arr, json_object_get(obj)); // array will now hold two references to the same object (will double free otherwise)
json_object_object_add(file_obj, "array", arr);
set_by_string("array[-1].integer", &modify_obj, "1", json_type_int);
set_by_string("array[0].string", &modify_obj, "test", json_type_string);
set_by_string("array[-1]", &modify_obj, "{\"integer\": 1, \"string\":\"test\"}", json_type_object);
printf("file_obj=%s\n", json_object_get_string(file_obj));
printf("modify_obj=%s\n", json_object_get_string(modify_obj));
assert_int_equal(1, json_object_equal(modify_obj, file_obj));
}
static void test_json_add_array_nested_object(void **state)
{
(void) state;
struct json_object *arr = json_object_new_array();
struct json_object *obj = json_object_new_object();
struct json_object *nested = json_object_new_object();
struct json_object *nested1 = json_object_new_object();
json_object_object_add(nested, "integer", json_object_new_int(1));
json_object_object_add(nested1, "nested1", nested);
json_object_object_add(obj, "nested", nested1);
json_object_array_add(arr, obj);
json_object_array_add(arr, json_object_get(obj));
json_object_array_add(arr, json_object_get(obj));
json_object_array_add(arr, json_object_get(obj));
json_object_array_add(arr, json_object_get(obj));
json_object_object_add(file_obj, "array", arr);
set_by_string(NULL, &modify_obj, "{\"array\": [{\"nested\": {\"nested1\": {\"integer\": 1}}}]}", json_type_object);
set_by_string("array[5].nested.nested1.integer", &modify_obj, "1", json_type_int);
set_by_string("array[-1].nested.nested1", &modify_obj, "{\"integer\": 1}", json_type_object);
set_by_string("array[-1].nested", &modify_obj, "{\"nested1\": {\"integer\": 1}}", json_type_object);
set_by_string("array[-1]", &modify_obj, "{\"nested\": {\"nested1\": {\"integer\": 1}}}", json_type_object);
printf("file_obj=%s\n", json_object_get_string(file_obj));
printf("modify_obj=%s\n", json_object_get_string(modify_obj));
assert_int_equal(1, json_object_equal(modify_obj, file_obj));
}
static void test_json_add_array_nested_array(void **state)
{
(void) state;
struct json_object *arr = json_object_new_array();
struct json_object *nested_arr = json_object_new_array();
struct json_object *nested1_arr = json_object_new_array();
json_object_array_add(nested_arr, json_object_new_int(1));
json_object_array_add(nested_arr, json_object_new_int(2));
json_object_array_add(nested_arr, json_object_new_int(3));
json_object_array_add(nested1_arr, json_object_new_int(5));
json_object_array_add(nested1_arr, json_object_new_int(6));
json_object_array_add(nested1_arr, json_object_new_int(7));
json_object_array_add(arr, nested_arr);
json_object_array_add(arr, nested1_arr);
json_object_object_add(file_obj, "array", arr);
//set_by_string("array[0][0].test", &modify_obj, "1", json_type_int);
set_by_string("array[0][0]", &modify_obj, "1", json_type_int);
set_by_string("array[0][1]", &modify_obj, "2", json_type_int);
set_by_string("array[0][2]", &modify_obj, "3", json_type_int);
set_by_string("array[1][-1]", &modify_obj, "5", json_type_int);
set_by_string("array[1][-1]", &modify_obj, "6", json_type_int);
set_by_string("array[1][-1]", &modify_obj, "7", json_type_int);
printf("file_obj=%s\n", json_object_get_string(file_obj));
printf("modify_obj=%s\n", json_object_get_string(modify_obj));
assert_int_equal(1, json_object_equal(modify_obj, file_obj));
}
static int setup (void** state) {
file_obj = path_to_obj("/home/jakob/git/json-editor-api/test.json");
modify_obj = path_to_obj("/home/jakob/git/json-editor-api/test.json");
......@@ -251,6 +366,10 @@ int main(void) {
cmocka_unit_test_setup_teardown(test_json_add_multi_types, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_add_multi_obj, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_overwrite_string, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_add_array_int, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_add_array_object, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_add_array_nested_object, setup, teardown),
cmocka_unit_test_setup_teardown(test_json_add_array_nested_array, setup, teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment