diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 93b0116a8..4d5cbeb3f 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -274,6 +274,15 @@ void z_config_new(z_owned_config_t *config); */ int8_t z_config_default(z_owned_config_t *config); +/** + * Clones a zenoh configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + * src: Pointer to the :c:type:`z_loaned_config_t` to clone. + */ +void z_config_clone(z_owned_config_t *config, const z_loaned_config_t *src); + /** * Builds a new, zenoh-allocated, client configuration. * diff --git a/include/zenoh-pico/collections/intmap.h b/include/zenoh-pico/collections/intmap.h index caa54e035..c3c853670 100644 --- a/include/zenoh-pico/collections/intmap.h +++ b/include/zenoh-pico/collections/intmap.h @@ -61,6 +61,9 @@ size_t _z_int_void_map_capacity(const _z_int_void_map_t *map); size_t _z_int_void_map_len(const _z_int_void_map_t *map); _Bool _z_int_void_map_is_empty(const _z_int_void_map_t *map); +int8_t _z_int_void_map_copy(_z_int_void_map_t *dst, const _z_int_void_map_t *src, z_element_clone_f f_c); +_z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_clone_f f_c, z_element_free_f f_f); + void _z_int_void_map_clear(_z_int_void_map_t *map, z_element_free_f f); void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); @@ -74,6 +77,13 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); *e = NULL; \ } \ } \ + static inline void *name##_intmap_entry_elem_clone(const void *e) { \ + const name##_intmap_entry_t *src = (name##_intmap_entry_t *)e; \ + name##_intmap_entry_t *dst = (name##_intmap_entry_t *)z_malloc(sizeof(name##_intmap_entry_t)); \ + dst->_key = src->_key; \ + dst->_val = name##_elem_clone(src->_val); \ + return dst; \ + } \ typedef _z_int_void_map_t name##_intmap_t; \ static inline void name##_intmap_init(name##_intmap_t *m) { \ _z_int_void_map_init(m, _Z_DEFAULT_INT_MAP_CAPACITY); \ @@ -87,6 +97,9 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); static inline type *name##_intmap_get(const name##_intmap_t *m, size_t k) { \ return (type *)_z_int_void_map_get(m, k); \ } \ + static inline name##_intmap_t name##_intmap_clone(const name##_intmap_t *m) { \ + return _z_int_void_map_clone(m, name##_intmap_entry_elem_clone, name##_intmap_entry_elem_free); \ + } \ static inline void name##_intmap_remove(name##_intmap_t *m, size_t k) { \ _z_int_void_map_remove(m, k, name##_intmap_entry_elem_free); \ } \ diff --git a/include/zenoh-pico/utils/config.h b/include/zenoh-pico/utils/config.h index 6c587370d..0a538e7d0 100644 --- a/include/zenoh-pico/utils/config.h +++ b/include/zenoh-pico/utils/config.h @@ -70,6 +70,17 @@ char *_z_config_get(const _z_config_t *ps, uint8_t key); */ #define _z_config_len _z_str_intmap_len +/** + * Clone a config. + * + * Parameters: + * m: A pointer to the config to clone. + * + * Returns: + * The clone of the config. + */ +#define _z_config_clone _z_str_intmap_clone + /** * Get the length of the given properties map. * diff --git a/src/api/api.c b/src/api/api.c index 3b9aae0ea..105ff350a 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -174,6 +174,8 @@ void z_config_new(z_owned_config_t *config) { config->_val = _z_config_empty(); int8_t z_config_default(z_owned_config_t *config) { return _z_config_default(&config->_val); } +void z_config_clone(z_owned_config_t *config, const z_loaned_config_t *src) { config->_val = _z_config_clone(src); } + int8_t z_config_client(z_owned_config_t *config, const char *locator) { return _z_config_client(&config->_val, locator); } diff --git a/src/collections/intmap.c b/src/collections/intmap.c index 5abeab4f7..5e78dee3e 100644 --- a/src/collections/intmap.c +++ b/src/collections/intmap.c @@ -14,6 +14,7 @@ #include "zenoh-pico/collections/intmap.h" +#include #include #include @@ -49,6 +50,39 @@ size_t _z_int_void_map_len(const _z_int_void_map_t *map) { return len; } +int8_t _z_int_void_map_copy(_z_int_void_map_t *dst, const _z_int_void_map_t *src, z_element_clone_f f_c) { + assert((dst != NULL) && (src != NULL) && (dst->_capacity == src->_capacity)); + for (size_t idx = 0; idx < src->_capacity; idx++) { + const _z_list_t *src_list = src->_vals[idx]; + if (src_list == NULL) { + continue; + } + // Allocate entry + dst->_vals[idx] = _z_list_clone(src_list, f_c); + if (dst->_vals[idx] == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + } + return _Z_RES_OK; +} + +_z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_clone_f f_c, z_element_free_f f_f) { + _z_int_void_map_t dst = {._capacity = src->_capacity, ._vals = NULL}; + // Lazily allocate and initialize to NULL all the pointers + size_t len = dst._capacity * sizeof(_z_list_t *); + dst._vals = (_z_list_t **)z_malloc(len); + if (dst._vals == NULL) { + return dst; + } + (void)memset(dst._vals, 0, len); + // Copy elements + if (_z_int_void_map_copy(&dst, src, f_c) != _Z_RES_OK) { + // Free the map + _z_int_void_map_clear(&dst, f_f); + } + return dst; +} + _Bool _z_int_void_map_is_empty(const _z_int_void_map_t *map) { return _z_int_void_map_len(map) == (size_t)0; } void _z_int_void_map_remove(_z_int_void_map_t *map, size_t k, z_element_free_f f) {