From 8ee6c9d91b9e1adf51b47beaf5866d416514b6f2 Mon Sep 17 00:00:00 2001 From: Jean-Roland Date: Tue, 11 Jun 2024 17:23:41 +0200 Subject: [PATCH] feat: add bytes encode/decode functions --- include/zenoh-pico/api/primitives.h | 294 ++++++++++++++++++++++++- include/zenoh-pico/collections/slice.h | 6 + src/api/api.c | 170 +++++++++++++- src/collections/slice.c | 69 ++++++ 4 files changed, 529 insertions(+), 10 deletions(-) diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index a301f93cf..6194ec2c0 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -462,6 +462,138 @@ const uint8_t *z_bytes_data(const z_loaned_bytes_t *bytes); */ size_t z_bytes_len(const z_loaned_bytes_t *bytes); +/** + * Decodes data into a `int8_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int8_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_int8(const z_loaned_bytes_t *bytes, int8_t *dst); + +/** + * Decodes data into a `int16_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int16_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_int16(const z_loaned_bytes_t *bytes, int16_t *dst); + +/** + * Decodes data into a `int32_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int32_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_int32(const z_loaned_bytes_t *bytes, int32_t *dst); + +/** + * Decodes data into a `int64_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int64_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_int64(const z_loaned_bytes_t *bytes, int64_t *dst); + +/** + * Decodes data into a `uint8_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint8_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_uint8(const z_loaned_bytes_t *bytes, uint8_t *dst); + +/** + * Decodes data into a `uint16_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint16_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_uint16(const z_loaned_bytes_t *bytes, uint16_t *dst); + +/** + * Decodes data into a `uint32_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint32_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_uint32(const z_loaned_bytes_t *bytes, uint32_t *dst); + +/** + * Decodes data into a `uint64_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint64_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_uint64(const z_loaned_bytes_t *bytes, uint64_t *dst); + +/** + * Decodes data into a `float` floating number. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`float` to contain the decoded float. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_float(const z_loaned_bytes_t *bytes, float *dst); + +/** + * Decodes data into a `double` floating number. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`double` to contain the decoded float. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_double(const z_loaned_bytes_t *bytes, double *dst); + +/** + * Decodes data into a :c:type:`z_owned_slice_t` + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * str: Pointer to an uninitialized :c:type:`z_owned_slice_t` to contain the decoded slice. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_decode_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst); + /** * Decodes data into a :c:type:`z_owned_string_t` * @@ -475,16 +607,172 @@ size_t z_bytes_len(const z_loaned_bytes_t *bytes); int8_t z_bytes_decode_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *str); /** - * Encodes a string into a :c:type:`z_owned_bytes_t` + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int8_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_int8(z_owned_bytes_t *bytes, int8_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int16_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_int16(z_owned_bytes_t *bytes, int16_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int32_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_int32(z_owned_bytes_t *bytes, int32_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int64_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_int64(z_owned_bytes_t *bytes, int64_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint8_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_uint8(z_owned_bytes_t *bytes, uint8_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint16_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_uint16(z_owned_bytes_t *bytes, uint16_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint32_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_uint32(z_owned_bytes_t *bytes, uint32_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint64_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_uint64(z_owned_bytes_t *bytes, uint64_t val); + +/** + * Encodes a floating number into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `float` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_float(z_owned_bytes_t *bytes, float val); + +/** + * Encodes a floating number into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `double` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_double(z_owned_bytes_t *bytes, double val); + +/** + * Encodes a slice into a :c:type:`z_owned_bytes_t` by aliasing + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded slice. + * str: Pointer to the slice to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_slice(z_owned_bytes_t *bytes, const uint8_t *data, size_t len); + +/** + * Encodes a slice into a :c:type:`z_owned_bytes_t` by copying + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded slice. + * str: Pointer to the slice to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_slice_copy(z_owned_bytes_t *bytes, const uint8_t *data, size_t len); + +/** + * Encodes a string into a :c:type:`z_owned_bytes_t` by aliasing + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * str: Pointer to the string to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_encode_from_string(z_owned_bytes_t *bytes, const z_loaned_string_t *str); + +/** + * Encodes a string into a :c:type:`z_owned_bytes_t` by copying * * Parameters: - * buffer: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. * str: Pointer to the string to encode. * * Return: * ``0`` if encode successful, ``negative value`` otherwise. */ -int8_t z_bytes_encode_from_string(z_owned_bytes_t *buffer, const z_loaned_string_t *str); +int8_t z_bytes_encode_from_string_copy(z_owned_bytes_t *bytes, const char *s); /** * Checks validity of a timestamp diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 14bdc6a26..c61a5089c 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -68,5 +68,11 @@ _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src); void _z_bytes_clear(_z_bytes_t *bytes); void _z_bytes_free(_z_bytes_t **bs); +uint64_t _z_bytes_to_int(const _z_bytes_t *bs); +float _z_bytes_to_float(const _z_bytes_t *bs); +double _z_bytes_to_double(const _z_bytes_t *bs); +_z_bytes_t _z_bytes_from_int(uint64_t val); +_z_bytes_t _z_bytes_from_float(float val); +_z_bytes_t _z_bytes_from_double(double val); #endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/src/api/api.c b/src/api/api.c index a8a85342a..71d0a1578 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -268,6 +268,68 @@ const uint8_t *z_bytes_data(const z_loaned_bytes_t *bytes) { return bytes->_slic size_t z_bytes_len(const z_loaned_bytes_t *bytes) { return bytes->_slice.len; } +int8_t z_bytes_decode_into_int8(const z_loaned_bytes_t *bytes, int8_t *dst) { + *dst = (int8_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_int16(const z_loaned_bytes_t *bytes, int16_t *dst) { + *dst = (int16_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_int32(const z_loaned_bytes_t *bytes, int32_t *dst) { + *dst = (int32_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_int64(const z_loaned_bytes_t *bytes, int64_t *dst) { + *dst = (int64_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_uint8(const z_loaned_bytes_t *bytes, uint8_t *dst) { + *dst = (uint8_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_uint16(const z_loaned_bytes_t *bytes, uint16_t *dst) { + *dst = (uint16_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_uint32(const z_loaned_bytes_t *bytes, uint32_t *dst) { + *dst = (uint32_t)_z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_uint64(const z_loaned_bytes_t *bytes, uint64_t *dst) { + *dst = _z_bytes_to_int(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_float(const z_loaned_bytes_t *bytes, float *dst) { + *dst = _z_bytes_to_float(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_double(const z_loaned_bytes_t *bytes, double *dst) { + *dst = _z_bytes_to_double(bytes); + return _Z_RES_OK; +} + +int8_t z_bytes_decode_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst) { + // Init owned slice + z_slice_null(dst); + dst->_val = (_z_slice_t *)z_malloc(sizeof(_z_slice_t)); + if (dst->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Convert bytes to slice + *dst->_val = bytes->_slice; + return _Z_RES_OK; +} + int8_t z_bytes_decode_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *s) { // Init owned string z_string_null(s); @@ -275,24 +337,118 @@ int8_t z_bytes_decode_into_string(const z_loaned_bytes_t *bytes, z_owned_string_ if (s->_val == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - // Convert slice to string + // Convert bytes to string *s->_val = _z_string_from_bytes(&bytes->_slice); return _Z_RES_OK; } -int8_t z_bytes_encode_from_string(z_owned_bytes_t *buffer, const z_loaned_string_t *s) { +int8_t z_bytes_encode_from_int8(z_owned_bytes_t *bytes, int8_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_int16(z_owned_bytes_t *bytes, int16_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_int32(z_owned_bytes_t *bytes, int32_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_int64(z_owned_bytes_t *bytes, int64_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_uint8(z_owned_bytes_t *bytes, uint8_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_uint16(z_owned_bytes_t *bytes, uint16_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_uint32(z_owned_bytes_t *bytes, uint32_t val) { + return z_bytes_encode_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_encode_from_uint64(z_owned_bytes_t *bytes, uint64_t val) { + // 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; + } + // Encode data + *bytes->_val = _z_bytes_from_int(val); + if (!_z_bytes_check(*bytes->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} + +int8_t z_bytes_encode_from_float(z_owned_bytes_t *bytes, float val) { + // 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; + } + // Encode data + *bytes->_val = _z_bytes_from_float(val); + if (!_z_bytes_check(*bytes->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} + +int8_t z_bytes_encode_from_double(z_owned_bytes_t *bytes, double val) { + // 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; + } + // Encode data + *bytes->_val = _z_bytes_from_double(val); + if (!_z_bytes_check(*bytes->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} + +int8_t z_bytes_encode_from_slice(z_owned_bytes_t *bytes, const uint8_t *data, size_t 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; + } + // Encode data + bytes->_val->_slice = _z_slice_wrap((uint8_t *)data, len); + return _Z_RES_OK; +} + +int8_t z_bytes_encode_from_slice_copy(z_owned_bytes_t *bytes, const uint8_t *data, size_t len) { + // FIXME: TODO + return _Z_RES_OK; +} + +int8_t z_bytes_encode_from_string(z_owned_bytes_t *bytes, const z_loaned_string_t *s) { + // FIXME: switch to char * arg // Init owned bytes - z_bytes_null(buffer); - buffer->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (buffer->_val == NULL) { + 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; } // Encode data - buffer->_val->_slice = _z_slice_wrap((uint8_t *)s->val, s->len); + bytes->_val->_slice = _z_slice_wrap((uint8_t *)s->val, s->len); return _Z_RES_OK; } -// TODO: Other encode/decode functions +int8_t z_bytes_encode_from_string_copy(z_owned_bytes_t *bytes, const char *s) { + // FIXME: TODO + return _Z_RES_OK; +} _Bool z_timestamp_check(z_timestamp_t ts) { return _z_timestamp_check(&ts); } diff --git a/src/collections/slice.c b/src/collections/slice.c index 57fea24c0..3583f4619 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -147,4 +147,73 @@ void _z_bytes_free(_z_bytes_t **bs) { z_free(ptr); *bs = NULL; } +} + +uint64_t _z_bytes_to_int(const _z_bytes_t *bs) { + uint64_t ret = 0; + for (size_t i = 0; i < bs->_slice.len; i++) { + ret |= (uint64_t)(bs->_slice.start[i] << (8 * i)); + } + return ret; +} + +float _z_bytes_to_float(const _z_bytes_t *bs) { + uint32_t temp = (uint32_t)_z_bytes_to_int(bs); + float val = 0; + memcpy(&val, &temp, sizeof(val)); + return val; +} + +double _z_bytes_to_double(const _z_bytes_t *bs) { + uint64_t temp = _z_bytes_to_int(bs); + double val = 0; + memcpy(&val, &temp, sizeof(val)); + return val; +} + +static size_t _z_bytes_int_len(uint64_t val) { + if ((val & (uint64_t)0xff00000000000000) != 0) { + return 8; + } else if ((val & (uint64_t)0x00ff000000000000) != 0) { + return 7; + } else if ((val & (uint64_t)0x0000ff0000000000) != 0) { + return 6; + } else if ((val & (uint64_t)0x000000ff00000000) != 0) { + return 5; + } else if ((val & (uint64_t)0x00000000ff000000) != 0) { + return 4; + } else if ((val & (uint64_t)0x0000000000ff0000) != 0) { + return 3; + } else if ((val & (uint64_t)0x000000000000ff00) != 0) { + return 2; + } else { + return 1; + } +} + +_z_bytes_t _z_bytes_from_int(uint64_t val) { + _z_bytes_t ret = _z_bytes_null(); + // Init bytes array + size_t len = _z_bytes_int_len(val); + if (_z_slice_init(&ret._slice, len) != _Z_RES_OK) { + return ret; + } + // Encode int + for (size_t i = 0; i < len; i++) { + ((uint8_t *)ret._slice.start)[i] = (uint8_t)(val >> (8 * i)); + } +} + +_z_bytes_t _z_bytes_from_float(float val) { + // Convert float to uint32_t + uint32_t temp; + memcpy(&temp, &val, sizeof(temp)); + return _z_bytes_from_int((uint64_t)temp); +} + +_z_bytes_t _z_bytes_from_double(double val) { + // Convert float to uint64_t + uint64_t temp; + memcpy(&temp, &val, sizeof(temp)); + return _z_bytes_from_int(temp); } \ No newline at end of file