diff --git a/CMakeLists.txt b/CMakeLists.txt index dd644085f..2c7af19fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,6 +177,7 @@ endif() if(CMAKE_BUILD_TYPE MATCHES "DEBUG") if(UNIX) + # FIXME: seems to not apply to library files, Issue #422 add_compile_options(-c -Wall -Wextra -Werror -Wshadow -Wpedantic -Wunused -Wstrict-prototypes -pipe -g -O0) # add_compile_options(-Wconversion) # add_link_options(-fsanitize=address) diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index de9aa2bd5..bdf754c92 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -584,6 +584,21 @@ int8_t z_bytes_decode_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t */ int8_t z_bytes_decode_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *str); +/** + * Decodes data into a pair of :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * first: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the first element. + * second: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the second element. + * curr_idx: Pointer to the current decoding index. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t zp_bytes_decode_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, + size_t *curr_idx); + /** * Encodes a signed integer into a :c:type:`z_owned_bytes_t` * @@ -752,6 +767,36 @@ int8_t z_bytes_encode_from_string(z_owned_bytes_t *bytes, const char *s); */ int8_t z_bytes_encode_from_string_copy(z_owned_bytes_t *bytes, const char *s); +/** + * Constructs payload from an iterator to `z_owned_bytes_t`. + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded payload. + * iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. + * context: Arbitrary context that will be passed to iterator_body. + * total_len: The length of all the items to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t zp_bytes_encode_from_iter(z_owned_bytes_t *bytes, + _Bool (*iterator_body)(z_owned_bytes_t *data, void *context, size_t *curr_idx), + void *context, size_t total_len); + +/** + * Append a pair of `z_owned_bytes` objects which are consumed in the process. + * + * Parameters: + * bytes: An pre-initialized :c:type:`z_owned_bytes_t` to contain the encoded pair. + * first: Pointer to the first `z_owned_bytes` to encode. + * second: Pointer to the second `z_owned_bytes` to encode. + * curr_idx: Pointer to the current encoding index value. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t zp_bytes_encode_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, + size_t *curr_idx); + /** * Checks validity of a timestamp * diff --git a/src/api/api.c b/src/api/api.c index 7ab6ce292..9bea1c9d8 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -337,6 +337,49 @@ int8_t z_bytes_decode_into_string(const z_loaned_bytes_t *bytes, z_owned_string_ return _Z_RES_OK; } +int8_t zp_bytes_decode_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, + size_t *curr_idx) { + // Check bound size + if (*curr_idx >= bytes->_slice.len) { + return _Z_ERR_GENERIC; + } + // Init pair of owned bytes + z_bytes_null(first); + z_bytes_null(second); + first->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); + second->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); + if ((first->_val == NULL) || (second->_val == NULL)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Extract first item size + size_t first_len = 0; + // FIXME: size endianness, Issue #420 + memcpy(&first_len, &bytes->_slice.start[*curr_idx], sizeof(uint32_t)); + *curr_idx += sizeof(uint32_t); + // Allocate first item bytes + *first->_val = _z_bytes_make(first_len); + if (!_z_bytes_check(*first->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Extract first item data + memcpy((uint8_t *)first->_val->_slice.start, &bytes->_slice.start[*curr_idx], first_len); + *curr_idx += first_len; + + // Extract second item size + size_t second_len = 0; + memcpy(&second_len, &bytes->_slice.start[*curr_idx], sizeof(uint32_t)); + *curr_idx += sizeof(uint32_t); + // Allocate second item bytes + *second->_val = _z_bytes_make(second_len); + if (!_z_bytes_check(*second->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Extract second item data + memcpy((uint8_t *)second->_val->_slice.start, &bytes->_slice.start[*curr_idx], second_len); + *curr_idx += second_len; + return _Z_RES_OK; +} + int8_t z_bytes_encode_from_int8(z_owned_bytes_t *bytes, int8_t val) { return z_bytes_encode_from_uint8(bytes, (uint8_t)val); } @@ -503,6 +546,48 @@ int8_t z_bytes_encode_from_string_copy(z_owned_bytes_t *bytes, const char *s) { return _Z_RES_OK; } +int8_t zp_bytes_encode_from_iter(z_owned_bytes_t *bytes, + _Bool (*iterator_body)(z_owned_bytes_t *data, void *context, size_t *curr_idx), + void *context, size_t total_len) { + // Init owned bytes + z_bytes_null(bytes); + bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); + if (bytes->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Allocate bytes + *bytes->_val = _z_bytes_make(total_len); + if (!_z_bytes_check(*bytes->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + size_t curr_idx = 0; + while (iterator_body(bytes, context, &curr_idx)) + ; + return _Z_RES_OK; +} + +int8_t zp_bytes_encode_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, + size_t *curr_idx) { + // Calculate pair size + size_t first_len = z_slice_len(&first->_val->_slice); + size_t second_len = z_slice_len(&second->_val->_slice); + size_t len = 2 * sizeof(uint32_t) + first_len + second_len; + // Copy data + // FIXME: size endianness, Issue #420 + memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], &first_len, sizeof(uint32_t)); + *curr_idx += sizeof(uint32_t); + memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], z_slice_data(&first->_val->_slice), first_len); + *curr_idx += first_len; + memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], &second_len, sizeof(uint32_t)); + *curr_idx += sizeof(uint32_t); + memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], z_slice_data(&second->_val->_slice), second_len); + *curr_idx += second_len; + // Clean up + z_bytes_drop(first); + z_bytes_drop(second); + return _Z_RES_OK; +} + _Bool z_timestamp_check(z_timestamp_t ts) { return _z_timestamp_check(&ts); } z_query_target_t z_query_target_default(void) { return Z_QUERY_TARGET_DEFAULT; } @@ -985,9 +1070,9 @@ int8_t z_publisher_put(const z_loaned_publisher_t *pub, const uint8_t *payload, // Trigger local subscriptions _z_trigger_local_subscriptions(&pub->_zn.in->val, pub->_key, payload, len, _Z_N_QOS_DEFAULT, _z_bytes_from_owned_bytes(opt.attachment)); - // Clean-up z_encoding_drop(opt.encoding); + z_bytes_drop(opt.attachment); return ret; } diff --git a/src/collections/slice.c b/src/collections/slice.c index e9e24dbc2..59668747e 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -162,6 +162,7 @@ uint8_t _z_bytes_to_uint8(const _z_bytes_t *bs) { return val; } +// FIXME: int16+ endianness, Issue #420 uint16_t _z_bytes_to_uint16(const _z_bytes_t *bs) { uint16_t val = 0; memcpy(&val, bs->_slice.start, sizeof(val));