diff options
author | lonkaars <loek@pipeframe.xyz> | 2022-12-12 13:57:33 +0100 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2022-12-12 13:57:33 +0100 |
commit | 61dd8a5ee66734dfd53ee9be725c9e71fd8d5414 (patch) | |
tree | da896421d93baa3a80a7c6ebb3a16fc25138516f /shared | |
parent | 8c21a929d06ed108b0e64f3892d036cd4cd67e51 (diff) |
implement DYN_MEMBER_SIZEOF macro correctly and implement cd_cmd_response_sizeof
Diffstat (limited to 'shared')
-rw-r--r-- | shared/bin.c | 8 | ||||
-rw-r--r-- | shared/bin.h | 16 | ||||
-rw-r--r-- | shared/protocol-tests/ping-response.bin | bin | 0 -> 10 bytes | |||
-rw-r--r-- | shared/protocol.c | 32 |
4 files changed, 51 insertions, 5 deletions
diff --git a/shared/bin.c b/shared/bin.c index fdceb30..875d013 100644 --- a/shared/bin.c +++ b/shared/bin.c @@ -65,6 +65,14 @@ uint16_t cd_bin_hton16(uint16_t h16) { uint32_t cd_bin_ntoh32(uint32_t n32) { return cd_bin_hton32(n32); } uint16_t cd_bin_ntoh16(uint16_t n16) { return cd_bin_hton16(n16); } +uint32_t cd_bin_ntohd(uint8_t* n, size_t s) { return cd_bin_htond(n, s); } + +uint32_t cd_bin_htond(uint8_t* h, size_t s) { + if (s == sizeof(uint8_t)) return *h; + else if (s == sizeof(uint16_t)) return cd_bin_hton16(*(uint16_t*) h); + else if (s == sizeof(uint32_t)) return cd_bin_hton32(*(uint32_t*) h); + else return 0; +} cd_s_bin *cd_bin_s_alloc(uint16_t bytes, uint8_t *data) { cd_s_bin *temp = malloc(sizeof(cd_s_bin) + sizeof(uint8_t) * bytes); diff --git a/shared/bin.h b/shared/bin.h index 35d2bc4..0e16ec0 100644 --- a/shared/bin.h +++ b/shared/bin.h @@ -10,6 +10,7 @@ */ #include <stdint.h> +#include <malloc.h> #ifdef __cplusplus extern "C" { @@ -50,6 +51,21 @@ uint32_t cd_bin_ntoh32(uint32_t n32); /** @brief convert 16-bit value from network (big-endian) to host endian */ uint16_t cd_bin_ntoh16(uint16_t n16); +/** + * @brief convert (8*s)-bit value from network (big-endian) to host endian + * (dynamic size) + * + * @param n pointer to number + * @param s size of number in bytes + * + * @return 32-bit integer regardless of `s` + * + * this function is exclusively used by the CD_DYN_MEMBER_SIZEOF macro in + * shared/protocol.c + */ +uint32_t cd_bin_ntohd(uint8_t* n, size_t s); +uint32_t cd_bin_htond(uint8_t* h, size_t s); + /** @brief replace 32-bit value from host endian to network (big-endian) */ void cd_bin_repl_hton32(uint32_t *h32); /** @brief replace 16-bit value from host endian to network (big-endian) */ diff --git a/shared/protocol-tests/ping-response.bin b/shared/protocol-tests/ping-response.bin Binary files differnew file mode 100644 index 0000000..6067349 --- /dev/null +++ b/shared/protocol-tests/ping-response.bin diff --git a/shared/protocol.c b/shared/protocol.c index 474398a..1d66f17 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -1,3 +1,5 @@ +#include <stddef.h> + #include "protocol.h" #ifdef __cplusplus @@ -16,13 +18,33 @@ size_t cd_cmd_sizeof(uint8_t data[CD_SERIAL_READ_BUFFER_SIZE], uint8_t data_leng return length; } -#define CD_DYN_MEMBER_SIZEOF(struct_t, length_byte, trailing_type) \ - sizeof(struct_t) + \ - (data->bytes > length_byte ? (sizeof(trailing_type) * data->data[length_byte]) : 0) +/** + * @brief macro to calculate size of message based on struct with member to + * indicate length of dynamic (last) field + * + * @param data cd_s_bin pointer to currently received data + * @param struct_t message struct + * @param length_field struct field with dynamic length + * + * @return size_t with calculated size + * + * equivalent c code: + * + * size_t size = sizeof(struct_t); + * size_t dyn_member_offset = offsetof(struct_t, length_field); + * size_t dyn_member_size = sizeof(((struct_t*)0)->length_field); + * if (data->bytes >= (dyn_member_offset + dyn_member_size)) + * size += cd_bin_ntohd(&data->data[dyn_member_offset], dyn_member_size); + * return size; + */ +#define CD_DYN_MEMBER_SIZEOF(data, struct_t, length_field) \ + sizeof(struct_t) + ( \ + (data->bytes >= (offsetof(struct_t, length_field) + sizeof(((struct_t*)0)->length_field))) ? \ + (cd_bin_ntohd(&data->data[offsetof(struct_t, length_field)], sizeof(((struct_t*)0)->length_field))) :\ + 0); size_t cd_cmd_response_sizeof(cd_s_bin* data) { - (void) data; // unused variable TODO: implement this - return 0; + return CD_DYN_MEMBER_SIZEOF(data, cd_s_cmd_response, response_size); } #ifdef __cplusplus |