From 91cc083b3d7c6634f44fe91a028b3583e0968e24 Mon Sep 17 00:00:00 2001 From: Jakob Olsson <jakob.olsson@iopsys.eu> Date: Fri, 4 Oct 2019 09:27:34 +0200 Subject: [PATCH] add deleter function --- src/json-editor.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++ src/json-editor.h | 2 + test/api_test.c | 94 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) diff --git a/src/json-editor.c b/src/json-editor.c index 6fc28aa..d104b2c 100644 --- a/src/json-editor.c +++ b/src/json-editor.c @@ -284,6 +284,55 @@ out: return 0; } +/** + * 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, "."); @@ -452,3 +501,59 @@ struct json_object *json_object_get_by_string_delimiter(struct json_object *src, return ptr; } + +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; +} diff --git a/src/json-editor.h b/src/json-editor.h index bc9f3af..35b030e 100644 --- a/src/json-editor.h +++ b/src/json-editor.h @@ -16,3 +16,5 @@ int json_object_set(struct json_object *src, char *fmt, struct json_object *val) int json_object_set_delimiter(struct json_object *src, char *fmt, struct json_object *val, const char *delimiter); struct json_object *json_object_get_by_string(struct json_object *src, char *fmt); struct json_object *json_object_get_by_string_delimiter(struct json_object *src, char *fmt, const char *delimiter); +int json_object_del_by_string(struct json_object *src, char *fmt); +int json_object_del_by_string_delimiter(struct json_object *src, char *fmt, const char *delimiter); \ No newline at end of file diff --git a/test/api_test.c b/test/api_test.c index 227202e..7c541b6 100644 --- a/test/api_test.c +++ b/test/api_test.c @@ -633,6 +633,96 @@ static void test_json_set_wrong_type_int_to_string(void **state) assert_int_not_equal(1, json_object_equal(e->modify_obj, e->file_obj)); } +static void test_json_del_int(void **state) +{ + struct test_env *e = (struct test_env *) *state; + + printf("before delete: %s\n", json_object_get_string(e->modify_obj)); + + json_object_del_by_string(e->modify_obj, "integer"); + + printf("after delete: %s\n", json_object_get_string(e->modify_obj)); + + assert_non_null(e->file_obj); + assert_non_null(e->modify_obj); + assert_null(json_object_get_by_string(e->modify_obj, "integer")); + assert_int_not_equal(1, json_object_equal(e->file_obj, e->modify_obj)); +} + +static void test_json_del_nested_string(void **state) +{ + struct test_env *e = (struct test_env *) *state; + + printf("before delete: %s\n", json_object_get_string(e->modify_obj)); + + json_object_del_by_string(e->modify_obj, "nested.api"); + + printf("after delete: %s\n", json_object_get_string(e->modify_obj)); + + assert_non_null(e->file_obj); + assert_non_null(e->modify_obj); + assert_null(json_object_get_by_string(e->modify_obj, "nested.api")); + assert_int_not_equal(1, json_object_equal(e->file_obj, e->modify_obj)); +} + +static void test_json_del_array_int(void **state) +{ + struct test_env *e = (struct test_env *) *state; + int len_before, len_after; + struct json_object *array; + + array = json_object_get_by_string(e->modify_obj, "simple_array"); + + assert_non_null(array); + assert_int_equal(1, json_object_is_type(array, json_type_array)); + + len_before = json_object_array_length(array); + + printf("before delete: %s\n", json_object_get_string(e->modify_obj)); + + json_object_del_by_string(e->modify_obj, "simple_array[2]"); + array = json_object_get_by_string(e->modify_obj, "simple_array"); + assert_non_null(array); + + len_after = json_object_array_length(array); + + printf("after delete: %s\n", json_object_get_string(e->modify_obj)); + + assert_int_equal(len_before, len_after + 1); + assert_non_null(e->file_obj); + assert_non_null(e->modify_obj); + assert_int_not_equal(1, json_object_equal(e->file_obj, e->modify_obj)); +} + +static void test_json_del_nested_array_int(void **state) +{ + struct test_env *e = (struct test_env *) *state; + int len_before, len_after; + struct json_object *array; + + array = json_object_get_by_string(e->modify_obj, "array[1]"); + + assert_non_null(array); + assert_int_equal(1, json_object_is_type(array, json_type_array)); + + len_before = json_object_array_length(array); + + printf("before delete: %s\n", json_object_get_string(e->modify_obj)); + + json_object_del_by_string(e->modify_obj, "array[1][2]"); + array = json_object_get_by_string(e->modify_obj, "array[1]"); + assert_non_null(array); + + len_after = json_object_array_length(array); + + printf("after delete: %s\n", json_object_get_string(e->modify_obj)); + + assert_int_equal(len_before, len_after + 1); + assert_non_null(e->file_obj); + assert_non_null(e->modify_obj); + assert_int_not_equal(1, json_object_equal(e->file_obj, e->modify_obj)); +} + static int setup (void** state) { struct test_env *e = (struct test_env *) *state; @@ -697,6 +787,10 @@ int main(void) { cmocka_unit_test_setup_teardown(test_json_set_array_invalid_format, setup, teardown), cmocka_unit_test_setup_teardown(test_json_set_wrong_type_string_to_int, setup, teardown), cmocka_unit_test_setup_teardown(test_json_set_wrong_type_int_to_string, setup, teardown), + cmocka_unit_test_setup_teardown(test_json_del_int, setup, teardown), + cmocka_unit_test_setup_teardown(test_json_del_nested_string, setup, teardown), + cmocka_unit_test_setup_teardown(test_json_del_array_int, setup, teardown), + cmocka_unit_test_setup_teardown(test_json_del_nested_array_int, setup, teardown), }; return cmocka_run_group_tests(tests, group_setup, group_teardown); -- GitLab