From 847ab606a7c62eccf63c86e4030a667e57d5b3e8 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Thu, 15 Aug 2019 21:01:49 -0400 Subject: [PATCH] lib: make empty array/map appending/inserting functions return new object This makes the bt_value_array_append_empty_array_element(), bt_value_array_append_empty_map_element(), bt_value_map_insert_empty_array_entry(), and bt_value_map_insert_empty_map_entry() accept a new optional output parameter to return the created empty value object. The goal of appending/inserting an empty array/map value object is typically to fill it afterwards, so it makes this less painful, for example: bt_value *inner_arr_obj; status = bt_value_array_append_empty_array_element(outer_array_obj, &inner_arr_obj); assert(status == 0); status = bt_value_array_append_bool_element(inner_arr_obj, true); assert(status == 0); status = bt_value_array_append_string_element(inner_arr_obj, "id"); assert(status == 0); You can pass `NULL` as this new parameter. The returned reference is borrowed. Signed-off-by: Philippe Proulx Change-Id: I2cd3359f357a3eb1da52c0e1426ef7804a4b13aa Reviewed-on: https://review.lttng.org/c/babeltrace/+/1948 Tested-by: jenkins Reviewed-by: Francis Deslauriers Reviewed-by: Simon Marchi --- include/babeltrace2/value.h | 12 +++-- src/cli/babeltrace2-cfg-cli-args.c | 3 +- src/lib/value.c | 32 ++++++++++-- tests/lib/test_bt_values.c | 79 ++++++++++++++++++++++++++---- 4 files changed, 107 insertions(+), 19 deletions(-) diff --git a/include/babeltrace2/value.h b/include/babeltrace2/value.h index c37c090a..b7636714 100644 --- a/include/babeltrace2/value.h +++ b/include/babeltrace2/value.h @@ -105,10 +105,12 @@ extern bt_value_array_append_element_status bt_value_array_append_string_element(bt_value *array_obj, const char *val); extern bt_value_array_append_element_status -bt_value_array_append_empty_array_element(bt_value *array_obj); +bt_value_array_append_empty_array_element(bt_value *array_obj, + bt_value **element_obj); extern bt_value_array_append_element_status -bt_value_array_append_empty_map_element(bt_value *array_obj); +bt_value_array_append_empty_map_element(bt_value *array_obj, + bt_value **element_obj); typedef enum bt_value_array_set_element_by_index_status { BT_VALUE_ARRAY_SET_ELEMENT_BY_INDEX_STATUS_MEMORY_ERROR = __BT_FUNC_STATUS_MEMORY_ERROR, @@ -164,10 +166,12 @@ bt_value_map_insert_string_entry(bt_value *map_obj, const char *key, const char *val); extern bt_value_map_insert_entry_status -bt_value_map_insert_empty_array_entry(bt_value *map_obj, const char *key); +bt_value_map_insert_empty_array_entry(bt_value *map_obj, const char *key, + bt_value **entry_obj); extern bt_value_map_insert_entry_status -bt_value_map_insert_empty_map_entry(bt_value *map_obj, const char *key); +bt_value_map_insert_empty_map_entry(bt_value *map_obj, const char *key, + bt_value **entry_obj); #ifdef __cplusplus } diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 8fbe0a96..546bdbe2 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -3794,7 +3794,8 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - append_status = bt_value_array_append_empty_array_element(non_opt_params); + append_status = bt_value_array_append_empty_array_element( + non_opt_params, NULL); if (append_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) { BT_CLI_LOGE_APPEND_CAUSE_OOM(); goto error; diff --git a/src/lib/value.c b/src/lib/value.c index 42c4bfd1..77fc75b4 100644 --- a/src/lib/value.c +++ b/src/lib/value.c @@ -994,7 +994,8 @@ bt_value_array_append_string_element(struct bt_value *array_obj, } enum bt_value_array_append_element_status -bt_value_array_append_empty_array_element(struct bt_value *array_obj) +bt_value_array_append_empty_array_element(struct bt_value *array_obj, + struct bt_value **element_obj) { enum bt_value_array_append_element_status ret; struct bt_value *empty_array_obj = NULL; @@ -1002,12 +1003,18 @@ bt_value_array_append_empty_array_element(struct bt_value *array_obj) empty_array_obj = bt_value_array_create(); ret = bt_value_array_append_element(array_obj, (void *) empty_array_obj); + + if (element_obj) { + *element_obj = empty_array_obj; + } + bt_object_put_ref(empty_array_obj); return ret; } enum bt_value_array_append_element_status -bt_value_array_append_empty_map_element(struct bt_value *array_obj) +bt_value_array_append_empty_map_element(struct bt_value *array_obj, + struct bt_value **element_obj) { enum bt_value_array_append_element_status ret; struct bt_value *map_obj = NULL; @@ -1015,6 +1022,11 @@ bt_value_array_append_empty_map_element(struct bt_value *array_obj) map_obj = bt_value_map_create(); ret = bt_value_array_append_element(array_obj, (void *) map_obj); + + if (element_obj) { + *element_obj = map_obj; + } + bt_object_put_ref(map_obj); return ret; } @@ -1160,7 +1172,8 @@ enum bt_value_map_insert_entry_status bt_value_map_insert_string_entry( enum bt_value_map_insert_entry_status bt_value_map_insert_empty_array_entry( - struct bt_value *map_obj, const char *key) + struct bt_value *map_obj, const char *key, + bt_value **entry_obj) { enum bt_value_map_insert_entry_status ret; struct bt_value *array_obj = NULL; @@ -1168,12 +1181,18 @@ bt_value_map_insert_empty_array_entry( array_obj = bt_value_array_create(); ret = bt_value_map_insert_entry(map_obj, key, (void *) array_obj); + + if (entry_obj) { + *entry_obj = array_obj; + } + bt_object_put_ref(array_obj); return ret; } enum bt_value_map_insert_entry_status -bt_value_map_insert_empty_map_entry(struct bt_value *map_obj, const char *key) +bt_value_map_insert_empty_map_entry(struct bt_value *map_obj, const char *key, + bt_value **entry_obj) { enum bt_value_map_insert_entry_status ret; struct bt_value *empty_map_obj = NULL; @@ -1181,6 +1200,11 @@ bt_value_map_insert_empty_map_entry(struct bt_value *map_obj, const char *key) empty_map_obj = bt_value_map_create(); ret = bt_value_map_insert_entry(map_obj, key, (void *) empty_map_obj); + + if (entry_obj) { + *entry_obj = empty_map_obj; + } + bt_object_put_ref(empty_map_obj); return ret; } diff --git a/tests/lib/test_bt_values.c b/tests/lib/test_bt_values.c index c1700f79..97e26b97 100644 --- a/tests/lib/test_bt_values.c +++ b/tests/lib/test_bt_values.c @@ -25,7 +25,7 @@ #include #include "tap/tap.h" -#define NR_TESTS 166 +#define NR_TESTS 188 static void test_null(void) @@ -208,6 +208,7 @@ void test_array(void) bt_value *obj; const char *string_value; bt_value *array_obj; + bt_value *appended_obj; array_obj = bt_value_array_create(); ok(array_obj && bt_value_is_array(array_obj), @@ -289,12 +290,24 @@ void test_array(void) ret = bt_value_array_append_string_element(array_obj, "bt_value"); ok(!ret, "bt_value_array_append_string_element() succeeds"); - ret = bt_value_array_append_empty_array_element(array_obj); + ret = bt_value_array_append_empty_array_element(array_obj, NULL); ok(!ret, "bt_value_array_append_empty_array_element() succeeds"); - ret = bt_value_array_append_empty_map_element(array_obj); + ret = bt_value_array_append_empty_array_element(array_obj, &appended_obj); + ok(!ret, "bt_value_array_append_empty_array_element() with returned value object succeeds"); + ok(appended_obj, + "object returned by bt_value_array_append_empty_array_element() is not NULL"); + ok(bt_value_is_array(appended_obj), + "object returned by bt_value_array_append_empty_array_element() is an array value"); + ret = bt_value_array_append_empty_map_element(array_obj, NULL); ok(!ret, "bt_value_array_append_empty_map_element() succeeds"); - - ok(bt_value_array_get_length(array_obj) == 12, + ret = bt_value_array_append_empty_map_element(array_obj, &appended_obj); + ok(!ret, "bt_value_array_append_empty_map_element() with returned value object succeeds"); + ok(appended_obj, + "object returned by bt_value_array_append_empty_map_element() is not NULL"); + ok(bt_value_is_map(appended_obj), + "object returned by bt_value_array_append_empty_map_element() is an array value"); + + ok(bt_value_array_get_length(array_obj) == 14, "the bt_value_array_append_element_*() functions increment the array value object's size"); ok(!bt_value_array_is_empty(array_obj), "map value object is not empty"); @@ -335,6 +348,16 @@ void test_array(void) ok(bt_value_array_is_empty(obj), "bt_value_array_append_empty_array_element() an empty array value object"); obj = bt_value_array_borrow_element_by_index(array_obj, 11); + ok(obj && bt_value_is_array(obj), + "bt_value_array_append_empty_array_element() appends an array value object"); + ok(bt_value_array_is_empty(obj), + "bt_value_array_append_empty_array_element() an empty array value object"); + obj = bt_value_array_borrow_element_by_index(array_obj, 12); + ok(obj && bt_value_is_map(obj), + "bt_value_array_append_empty_map_element() appends a map value object"); + ok(bt_value_map_is_empty(obj), + "bt_value_array_append_empty_map_element() an empty map value object"); + obj = bt_value_array_borrow_element_by_index(array_obj, 13); ok(obj && bt_value_is_map(obj), "bt_value_array_append_empty_map_element() appends a map value object"); ok(bt_value_map_is_empty(obj), @@ -370,7 +393,9 @@ struct map_foreach_checklist { bt_bool real2; bt_bool string2; bt_bool array2; + bt_bool array3; bt_bool map2; + bt_bool map3; }; static @@ -515,6 +540,24 @@ bt_bool test_map_foreach_cb_check(const char *key, bt_value *object, "test_map_foreach_cb_check(): \"array2\" value object is empty"); checklist->array2 = BT_TRUE; } + } else if (strcmp(key, "array3") == 0) { + if (checklist->array3) { + fail("test_map_foreach_cb_check(): duplicate key \"array3\""); + } else { + ok(bt_value_is_array(object), "test_map_foreach_cb_check(): success getting \"array3\" value object"); + ok(bt_value_array_is_empty(object), + "test_map_foreach_cb_check(): \"array3\" value object is empty"); + checklist->array3 = BT_TRUE; + } + } else if (strcmp(key, "map3") == 0) { + if (checklist->map3) { + fail("test_map_foreach_cb_check(): duplicate key \"map3\""); + } else { + ok(bt_value_is_map(object), "test_map_foreach_cb_check(): success getting \"map3\" value object"); + ok(bt_value_map_is_empty(object), + "test_map_foreach_cb_check(): \"map3\" value object is empty"); + checklist->map3 = BT_TRUE; + } } else if (strcmp(key, "map2") == 0) { if (checklist->map2) { fail("test_map_foreach_cb_check(): duplicate key \"map2\""); @@ -542,6 +585,7 @@ void test_map(void) double real_value; bt_value *obj; bt_value *map_obj; + bt_value *inserted_obj; struct map_foreach_checklist checklist; map_obj = bt_value_map_create(); @@ -615,13 +659,24 @@ void test_map(void) ret = bt_value_map_insert_string_entry(map_obj, "string2", "bt_value"); ok(!ret, "bt_value_map_insert_string_entry() succeeds"); - ret = bt_value_map_insert_empty_array_entry(map_obj, - "array2"); + ret = bt_value_map_insert_empty_array_entry(map_obj, "array2", NULL); ok(!ret, "bt_value_map_insert_empty_array_entry() succeeds"); - ret = bt_value_map_insert_empty_map_entry(map_obj, "map2"); + ret = bt_value_map_insert_empty_array_entry(map_obj, "array3", &inserted_obj); + ok(!ret, "bt_value_map_insert_empty_array_entry() with returned value object succeeds"); + ok(inserted_obj, + "object returned by bt_value_map_insert_empty_array_entry() is not NULL"); + ok(bt_value_is_array(inserted_obj), + "object returned by bt_value_map_insert_empty_array_entry() is an array value"); + ret = bt_value_map_insert_empty_map_entry(map_obj, "map2", NULL); ok(!ret, "bt_value_map_insert_empty_map_entry() succeeds"); - - ok(bt_value_map_get_size(map_obj) == 11, + ret = bt_value_map_insert_empty_map_entry(map_obj, "map3", &inserted_obj); + ok(!ret, "bt_value_map_insert_empty_map_entry() with returned value object succeeds"); + ok(inserted_obj, + "object returned by bt_value_map_insert_empty_map_entry() is not NULL"); + ok(bt_value_is_map(inserted_obj), + "object returned by bt_value_map_insert_empty_map_entry() is an array value"); + + ok(bt_value_map_get_size(map_obj) == 13, "the bt_value_map_insert*() functions increment the map value object's size"); ok(!bt_value_map_has_entry(map_obj, "hello"), @@ -646,8 +701,12 @@ void test_map(void) "map value object has key \"string2\""); ok(bt_value_map_has_entry(map_obj, "array2"), "map value object has key \"array2\""); + ok(bt_value_map_has_entry(map_obj, "array3"), + "map value object has key \"array3\""); ok(bt_value_map_has_entry(map_obj, "map2"), "map value object has key \"map2\""); + ok(bt_value_map_has_entry(map_obj, "map3"), + "map value object has key \"map3\""); ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_count, &count); -- 2.34.1