From 770750d3f959953ed4da34e0f9e44912ce387faf Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Fri, 26 Feb 2016 01:27:47 -0500 Subject: [PATCH] values: add bt_value_map_extend() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- include/babeltrace/values.h | 63 +++++++++++++++++++++++++++++++ lib/values.c | 75 +++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/include/babeltrace/values.h b/include/babeltrace/values.h index 78fa4e5d..d5ffef0b 100644 --- a/include/babeltrace/values.h +++ b/include/babeltrace/values.h @@ -1422,6 +1422,69 @@ On success, \p key is copied. extern enum bt_value_status bt_value_map_insert_empty_map( struct bt_value *map_obj, const char *key); +/** +@brief Creates a copy of the base map value object \p base_map_obj + superficially extended with the entries of the extension map + value object \p extension_map_obj. + +This function creates a superficial extension of \p base_map_obj with +\p extension_map_obj by adding new entries to it and replacing the +ones that share the keys in the extension object. The extension is +\em superficial because it does not merge internal array and map +value objects. + +For example, consider the following \p base_map_obj (JSON representation): + +@code{.unparsed} +{ + "hello": 23, + "code": -17, + "em": false, + "return": [5, 6, null] +} +@endcode + +and the following \p extension_map_obj (JSON representation): + +@code{.unparsed} +{ + "comma": ",", + "code": 22, + "return": 17.88 +} +@endcode + +The extended object is (JSON representation): + +@code{.unparsed} +{ + "hello": 23, + "code": 22, + "em": false, + "return": 17.88, + "comma": "," +} +@endcode + +@param[in] base_map_obj Base map value object with initial + entries. +@param[in] extension_map_obj Extension map value object containing + the entries to add to or replace in + \p base_map_obj. +@returns Created extended map value object, or + \c NULL on error. + +@prenotnull{base_map_obj} +@prenotnull{extension_map_obj} +@pre \p base_map_obj is a map value object. +@pre \p extension_map_obj is a map value object. +@postrefcountsame{base_map_obj} +@postrefcountsame{extension_map_obj} +@postsuccessrefcountret1 +*/ +extern struct bt_value *bt_value_map_extend(struct bt_value *base_map_obj, + struct bt_value *extension_map_obj); + /** @} */ /** @} */ diff --git a/lib/values.c b/lib/values.c index bd217bf6..cea4b10b 100644 --- a/lib/values.c +++ b/lib/values.c @@ -1168,6 +1168,81 @@ end: return ret; } +struct extend_map_element_data { + struct bt_value *extended_obj; + bool got_error; +}; + +static +bool extend_map_element(const char *key, + struct bt_value *extension_obj_elem, void *data) +{ + bool ret = true; + + struct extend_map_element_data *extend_data = data; + + /* Copy object which is to replace the current one */ + struct bt_value *extension_obj_elem_copy = + bt_value_copy(extension_obj_elem); + + /* Replace in extended object */ + if (bt_value_map_insert(extend_data->extended_obj, key, + extension_obj_elem_copy)) { + goto error; + } + + goto end; + +error: + ret = false; + extend_data->got_error = true; + +end: + BT_PUT(extension_obj_elem_copy); + + return ret; +} + +struct bt_value *bt_value_map_extend(struct bt_value *base_map_obj, + struct bt_value *extension_obj) +{ + struct bt_value *extended_obj = NULL; + struct extend_map_element_data extend_data = { 0 }; + + if (!bt_value_is_map(base_map_obj) || !bt_value_is_map(extension_obj)) { + goto error; + } + + /* Create copy of base map object to start with */ + extended_obj = bt_value_copy(base_map_obj); + if (!extended_obj) { + goto error; + } + + /* + * For each key in the extension map object, replace this key + * in the copied map object. + */ + extend_data.extended_obj = extended_obj; + + if (bt_value_map_foreach(extension_obj, extend_map_element, + &extend_data)) { + goto error; + } + + if (extend_data.got_error) { + goto error; + } + + goto end; + +error: + BT_PUT(extended_obj); + +end: + return extended_obj; +} + struct bt_value *bt_value_copy(const struct bt_value *object) { struct bt_value *copy_obj = NULL; -- 2.34.1