Skip to content

Commit

Permalink
add custom deleter support for slice (#562)
Browse files Browse the repository at this point in the history
* add custom deleter support for slice

* typo fix

* .pc
  • Loading branch information
DenisBiryukov91 authored Jul 29, 2024
1 parent de6e9e0 commit a07ee80
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 27 deletions.
17 changes: 15 additions & 2 deletions include/zenoh-pico/collections/slice.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,38 @@
#include <stddef.h>
#include <stdint.h>

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.
*
* 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);
inline static _Bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; }
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);
Expand All @@ -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 */
47 changes: 38 additions & 9 deletions src/collections/slice.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,42 @@
#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;

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) {
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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); }
2 changes: 1 addition & 1 deletion src/protocol/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions src/protocol/codec/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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))
Expand Down
35 changes: 33 additions & 2 deletions tests/z_data_struct_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
15 changes: 6 additions & 9 deletions tests/z_msgcodec_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion zenohpico.pc
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit a07ee80

Please sign in to comment.