From 4b88795f8b40cbbc26adddfdb46c8a1c6697430e Mon Sep 17 00:00:00 2001 From: Jakob Olsson <jakob.olsson@iopsys.eu> Date: Wed, 2 Oct 2019 12:45:31 +0200 Subject: [PATCH] add full support for nested arrays --- api.c | 186 ++++++++++++++++++++++++++++++------------------ test/api_test.c | 13 +++- 2 files changed, 126 insertions(+), 73 deletions(-) diff --git a/api.c b/api.c index 39d2565..cd46a5d 100644 --- a/api.c +++ b/api.c @@ -66,32 +66,44 @@ out: return NULL; } -int get_idx(char *key) +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 -2; + return -1; - char *open_brace = strchr(key, '['); - if (open_brace) { + 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 len, idx; + int str_len; char *idx_str; - len = close_brace - open_brace; - idx_str = calloc(1, len); - strncpy(idx_str, open_brace + 1, len-1); - idx = atoi(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); - return idx; + ptr = close_brace; } } - return -2; + 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) @@ -125,9 +137,9 @@ struct json_object *dummy_val(char *val, enum json_type type) return j_val; } -int add_array(struct json_object *ptr, int idx, char *val, enum json_type type, char *key) +int add_array(struct json_object *ptr, int *idx, int len, char *val, enum json_type type, char *key) { - struct json_object *tmp; + struct json_object *tmp, *tmp1; struct json_object *j_val; j_val = dummy_val(val, type); @@ -135,44 +147,62 @@ int add_array(struct json_object *ptr, int idx, char *val, enum json_type type, return -1; json_object_object_get_ex(ptr, key, &tmp); - if (tmp && json_object_is_type(tmp, json_type_array)) { - if (idx != -1) - json_object_array_put_idx(tmp, idx, j_val); - else { - printf("%s %d\n", __func__, __LINE__); - json_object_array_add(tmp, j_val); - } - } else { + if (!tmp || !json_object_is_type(tmp, json_type_array)) { 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); } + 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; + int idx[32]; + int len; + char parsed_key[32] = {0}; - idx = get_idx(key); - printf("%s %d key=%s\n", __func__, __LINE__, key); + 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\n", __func__, __LINE__, val, json_object_get_string(j_val)); + 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 (idx == -2) { + if (len < 1) { struct json_object *tmp = ptr; if (key) @@ -180,31 +210,36 @@ int add_val(struct json_object *ptr, char *key, char *val, enum json_type type) json_object_object_foreach(j_val, key1, val1) json_object_object_add(ptr, key1, val1); - if (key) - json_object_object_add(tmp, key, ptr); + if (key) { + printf("%s %d\n", __func__, __LINE__); + json_object_object_add(tmp, parsed_key, ptr); + } } else { - add_array(ptr, idx, val, type, key); + printf("%s %d\n", __func__, __LINE__); + add_array(ptr, idx, len, val, type, parsed_key); } return 0; } - if (idx == -2 || type == json_type_array) - json_object_object_add(ptr, key, j_val); - else - add_array(ptr, idx, val, type, key); + 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 fmt_cpy[1024] = {0}; + char fmt_cpy[1024] = {0}, parsed_key[32] = {0}; char *p, *key = fmt; - int idx; + int idx[32]; + int len; if (!*src) { printf("lets allocate new object\n"); @@ -228,41 +263,54 @@ int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type /* if next key exists, parse key, let switch-case add/alter last key */ if (p) { /* TODO: pretty wonky order with get idx first to overwrite braces?*/ - idx = get_idx(key); + + 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, key, &ptr); + 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, key, ptr); + json_object_object_add(tmp, parsed_key, ptr); } - printf("key=%s\n", key); - printf("p=%s\n", p); + /* TODO: make enums for rv of get_idx */ - if (idx != -2) { - printf("%s %d\n", __func__, __LINE__); - if (ptr && json_object_get_type(ptr) == json_type_array) { - printf("%s %d\n", __func__, __LINE__); - if (idx > -1 && idx < json_object_array_length(ptr)) - ptr = json_object_array_get_idx(ptr, idx); - else { + 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) { printf("%s %d\n", __func__, __LINE__); - json_object_array_add(ptr, json_object_new_object()); - printf("ptr=%s\n", json_object_get_string(ptr)); - ptr = json_object_array_get_idx(ptr, json_object_array_length(ptr) - 1); + 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(); + 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); } - } 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("key=%s\n", key); - json_object_object_add(tmp, key, ptr); - 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); } } @@ -272,7 +320,7 @@ int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type 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, key, ptr); + 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)); } @@ -281,9 +329,7 @@ int set_by_string(char *fmt, struct json_object **src, char *val, enum json_type tmp = ptr; } - printf("%s %d key=%s\n", __func__, __LINE__, key); - - json_object_object_get_ex(ptr, key, &tar); + printf("%s %d key=%s\n", __func__, __LINE__, parsed_key); add_key: printf("%s %d\n", __func__, __LINE__); diff --git a/test/api_test.c b/test/api_test.c index 83ba97d..73bb48d 100644 --- a/test/api_test.c +++ b/test/api_test.c @@ -241,7 +241,6 @@ static void test_json_add_array_int(void **state) 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); @@ -251,6 +250,7 @@ static void test_json_add_array_int(void **state) assert_int_equal(1, json_object_equal(modify_obj, file_obj)); } + static void test_json_add_array_object(void **state) { (void) state; @@ -326,7 +326,14 @@ static void test_json_add_array_nested_array(void **state) 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].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)); @@ -362,7 +369,7 @@ int main(void) { 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), + cmocka_unit_test_setup_teardown(test_json_add_array_nested_array, setup, teardown), }; return cmocka_run_group_tests(tests, NULL, NULL); -- GitLab