diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 4be5efe5b..d135bed8d 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -19,6 +19,17 @@ #include #include +typedef struct { + void (*deleter)(void *data, void *context); + void *context; +} _z_delete_context; + +_z_delete_context _z_delete_context_null(void); +_Bool _z_delete_context_is_null(const _z_delete_context *c); +_z_delete_context _z_delete_context_create(void (*deleter)(void *context, void *data), void *context); +_z_delete_context _z_delete_context_default(void); +void _z_delete_context_delete(_z_delete_context *c, void *data); + /*-------- Slice --------*/ /** * An array of bytes. @@ -26,12 +37,12 @@ * Members: * size_t len: The length of the bytes array. * uint8_t *start: A pointer to the bytes array. - * _Bool _is_alloc: Indicates if memory has been allocated by this module + * _z_delete_context delete_context - context used to delete the data. */ typedef struct { size_t len; const uint8_t *start; - _Bool _is_alloc; + _z_delete_context _delete_context; } _z_slice_t; _z_slice_t _z_slice_empty(void); @@ -39,6 +50,7 @@ inline static _Bool _z_slice_check(const _z_slice_t *slice) { return slice->star int8_t _z_slice_init(_z_slice_t *bs, size_t capacity); _z_slice_t _z_slice_make(size_t capacity); _z_slice_t _z_slice_wrap(const uint8_t *bs, size_t len); +_z_slice_t _z_slice_wrap_custom_deleter(const uint8_t *p, size_t len, _z_delete_context dc); _z_slice_t _z_slice_wrap_copy(const uint8_t *bs, size_t len); _z_slice_t _z_slice_steal(_z_slice_t *b); int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); @@ -49,5 +61,6 @@ _Bool _z_slice_is_empty(const _z_slice_t *bs); _Bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right); void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); +_Bool _z_slice_is_alloced(const _z_slice_t *s); #endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/src/collections/slice.c b/src/collections/slice.c index 1a059a8cb..32c63e63c 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -21,8 +21,31 @@ #include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/result.h" +void _z_default_deleter(void *data, void *context) { + _ZP_UNUSED(context); + z_free(data); +} + +_z_delete_context _z_delete_context_null(void) { return _z_delete_context_create(NULL, NULL); } + +_Bool _z_delete_context_is_null(const _z_delete_context *c) { return c->deleter == NULL; } + +_z_delete_context _z_delete_context_create(void (*deleter)(void *data, void *context), void *context) { + return (_z_delete_context){.deleter = deleter, .context = context}; +} + +_z_delete_context _z_delete_context_default(void) { return _z_delete_context_create(_z_default_deleter, NULL); } + +void _z_delete_context_delete(_z_delete_context *c, void *data) { + if (!_z_delete_context_is_null(c)) { + c->deleter(data, c->context); + } +} + /*-------- Slice --------*/ -_z_slice_t _z_slice_empty(void) { return (_z_slice_t){.start = NULL, .len = 0, ._is_alloc = false}; } +_z_slice_t _z_slice_empty(void) { + return (_z_slice_t){.start = NULL, .len = 0, ._delete_context = _z_delete_context_null()}; +} int8_t _z_slice_init(_z_slice_t *bs, size_t capacity) { int8_t ret = _Z_RES_OK; @@ -30,10 +53,10 @@ int8_t _z_slice_init(_z_slice_t *bs, size_t capacity) { bs->start = capacity == 0 ? NULL : (uint8_t *)z_malloc(capacity); if (bs->start != NULL) { bs->len = capacity; - bs->_is_alloc = true; + bs->_delete_context = _z_delete_context_default(); } else { bs->len = 0; - bs->_is_alloc = false; + bs->_delete_context = _z_delete_context_null(); } if (bs->len != capacity) { @@ -49,14 +72,18 @@ _z_slice_t _z_slice_make(size_t capacity) { return bs; } -_z_slice_t _z_slice_wrap(const uint8_t *p, size_t len) { +_z_slice_t _z_slice_wrap_custom_deleter(const uint8_t *p, size_t len, _z_delete_context dc) { _z_slice_t bs; bs.start = p; bs.len = len; - bs._is_alloc = false; + bs._delete_context = dc; return bs; } +_z_slice_t _z_slice_wrap(const uint8_t *p, size_t len) { + return _z_slice_wrap_custom_deleter(p, len, _z_delete_context_null()); +} + _z_slice_t _z_slice_wrap_copy(const uint8_t *p, size_t len) { _z_slice_t bs = _z_slice_wrap(p, len); return _z_slice_duplicate(&bs); @@ -65,12 +92,12 @@ _z_slice_t _z_slice_wrap_copy(const uint8_t *p, size_t len) { void _z_slice_reset(_z_slice_t *bs) { bs->start = NULL; bs->len = 0; - bs->_is_alloc = false; + bs->_delete_context = _z_delete_context_null(); } void _z_slice_clear(_z_slice_t *bs) { - if ((bs->_is_alloc == true) && (bs->start != NULL)) { - z_free((uint8_t *)bs->start); + if ((bs->start != NULL)) { + _z_delete_context_delete(&bs->_delete_context, (void *)bs->start); } _z_slice_reset(bs); } @@ -98,7 +125,7 @@ int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src) { void _z_slice_move(_z_slice_t *dst, _z_slice_t *src) { dst->start = src->start; dst->len = src->len; - dst->_is_alloc = src->_is_alloc; + dst->_delete_context = src->_delete_context; _z_slice_reset(src); } @@ -119,3 +146,5 @@ _z_slice_t _z_slice_steal(_z_slice_t *b) { _Bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right) { return left->len == right->len && memcmp(left->start, right->start, left->len) == 0; } + +_Bool _z_slice_is_alloced(const _z_slice_t *s) { return !_z_delete_context_is_null(&s->_delete_context); } diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 8a9cbc406..7e1ae3158 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -280,7 +280,7 @@ int8_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_ int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { _z_slice_t s; _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); - if (s._is_alloc) { + if (_z_slice_is_alloced(&s)) { return _z_bytes_from_slice(bs, s); } else { return _z_bytes_from_buf(bs, s.start, s.len); diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index aade731ec..ed7296005 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -306,7 +306,7 @@ int8_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { } case _Z_MSG_EXT_ENC_ZBUF | 0x03: { // Attachment _z_slice_t s; - if (extension->_body._zbuf._val._is_alloc) { + if (_z_slice_is_alloced(&extension->_body._zbuf._val)) { s = _z_slice_steal(&extension->_body._zbuf._val); } else { _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); @@ -447,7 +447,7 @@ int8_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { } case _Z_MSG_EXT_ENC_ZBUF | 0x05: { // Attachment _z_slice_t s; - if (extension->_body._zbuf._val._is_alloc) { + if (_z_slice_is_alloced(&extension->_body._zbuf._val)) { s = _z_slice_steal(&extension->_body._zbuf._val); } else { _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); @@ -637,7 +637,8 @@ int8_t _z_hello_encode(_z_wbuf_t *wbf, uint8_t header, const _z_s_msg_hello_t *m cbyte |= _z_whatami_to_uint8(msg->_whatami); cbyte |= (uint8_t)(((zidlen - 1) & 0x0F) << 4); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)) - _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, &(_z_slice_t){.start = msg->_zid.id, .len = zidlen, ._is_alloc = false})); + _z_slice_t s = _z_slice_wrap(msg->_zid.id, zidlen); + _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, &s)); if (_Z_HAS_FLAG(header, _Z_FLAG_T_HELLO_L) == true) { _Z_RETURN_IF_ERR(_z_locators_encode(wbf, &msg->_locators)) diff --git a/tests/z_data_struct_test.c b/tests/z_data_struct_test.c index 461ee92ca..d17d67892 100644 --- a/tests/z_data_struct_test.c +++ b/tests/z_data_struct_test.c @@ -48,8 +48,7 @@ void entry_list_test(void) { _z_transport_peer_entry_list_free(&root); } -int main(void) { - entry_list_test(); +void str_vec_list_intmap_test(void) { char *s = (char *)malloc(64); size_t len = 128; @@ -140,6 +139,38 @@ int main(void) { _z_str_intmap_clear(&map); assert(_z_str_intmap_is_empty(&map) == true); +} + +void _z_slice_custom_deleter(void *data, void *context) { + _ZP_UNUSED(data); + size_t *cnt = (size_t *)context; + (*cnt)++; +} + +void z_slice_custom_delete_test(void) { + size_t counter = 0; + uint8_t data[5] = {1, 2, 3, 4, 5}; + _z_delete_context dc = (_z_delete_context){.deleter = _z_slice_custom_deleter, .context = &counter}; + _z_slice_t s1 = _z_slice_wrap_custom_deleter(data, 5, dc); + _z_slice_t s2 = _z_slice_wrap_custom_deleter(data, 5, dc); + _z_slice_t s3 = _z_slice_wrap_copy(data, 5); + _z_slice_t s4 = _z_slice_wrap(data, 5); + assert(_z_slice_is_alloced(&s1)); + assert(_z_slice_is_alloced(&s2)); + assert(_z_slice_is_alloced(&s3)); + assert(!_z_slice_is_alloced(&s4)); + + _z_slice_clear(&s1); + _z_slice_clear(&s2); + _z_slice_clear(&s3); + _z_slice_clear(&s4); + assert(counter == 2); +} + +int main(void) { + entry_list_test(); + str_vec_list_intmap_test(); + z_slice_custom_delete_test(); return 0; } diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 30a55aae3..8eaa7b643 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -171,18 +171,15 @@ _z_wbuf_t gen_wbuf(size_t len) { } _z_slice_t gen_slice(size_t len) { - _z_slice_t arr; - arr._is_alloc = true; - arr.len = len; - arr.start = NULL; - if (len == 0) return arr; + if (len == 0) { + return _z_slice_empty(); + } - arr.start = (uint8_t *)z_malloc(sizeof(uint8_t) * len); + uint8_t *p = (uint8_t *)z_malloc(sizeof(uint8_t) * len); for (_z_zint_t i = 0; i < len; i++) { - ((uint8_t *)arr.start)[i] = gen_uint8() & 0x7f; // 0b01111111 + ((uint8_t *)p)[i] = gen_uint8() & 0x7f; // 0b01111111 } - - return arr; + return _z_slice_wrap_custom_deleter(p, len, _z_delete_context_default()); } _z_bytes_t gen_payload(size_t len) { diff --git a/zenohpico.pc b/zenohpico.pc index b48d8e2c0..4e9ff5bd2 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20240720dev +Version: 1.0.20240729dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico