From 13d0d0c83dc7286bae275958be60d98c9296b543 Mon Sep 17 00:00:00 2001 From: Mazet Laurent Date: Tue, 8 Apr 2025 03:05:57 +0200 Subject: [PATCH] add deserialization --- clear_data.h | 15 ++++++ parse.h | 137 ++++++++++++++++++++++++++++++++++++++++++++++----- raw_data.c | 9 +++- raw_data.h | 19 ++++++- 4 files changed, 164 insertions(+), 16 deletions(-) diff --git a/clear_data.h b/clear_data.h index ba1ae18..29da2f9 100644 --- a/clear_data.h +++ b/clear_data.h @@ -40,6 +40,7 @@ typedef struct { @param line string to analyse @param out output structure + @return 0 on success */ int parse_clear_data (char *line, CLEAR_DATA_t *out); @@ -51,6 +52,7 @@ int parse_clear_data (char *line, CLEAR_DATA_t *out); @param in input structure @param buffer output string @param maxlen buffer limit + @return 0 on success */ int format_clear_data (CLEAR_DATA_t *in, char *buffer, int maxlen); @@ -62,9 +64,22 @@ int format_clear_data (CLEAR_DATA_t *in, char *buffer, int maxlen); @param in input structure @param buffer network stream @param maxlen buffer limit + @return buffer length */ int serial_clear_data (CLEAR_DATA_t *in, uint8_t *buffer, int maxlen); +/** + @ingroup MESSAGES + + Deserial clear data type fields from a network stream + + @param buffer network stream + @param maxlen buffer limit + @param out output structure + @return 0 on success +*/ +int deserial_clear_data (uint8_t *buffer, int maxlen, CLEAR_DATA_t *out); + __END_DECLS #endif /* __CLEAR_DATA_H__ */ diff --git a/parse.h b/parse.h index a351a02..53c6a32 100644 --- a/parse.h +++ b/parse.h @@ -220,13 +220,13 @@ __BEGIN_DECLS @param name field name @param field data from structure */ -#define SERIAL_INT(field) \ +#define SERIAL_INT(name, field) \ switch (sizeof (field)) { \ case 1: \ if (len < _maxlen) { \ _buffer[len++] = field; \ } else { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ len = _maxlen; \ } \ break; \ @@ -235,16 +235,16 @@ __BEGIN_DECLS *((uint16_t *)(_buffer + len)) = htons ((uint16_t)field); \ len += 2; \ } else { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ len = _maxlen; \ } \ break; \ case 4: \ if (len + 3 < _maxlen) { \ - *((uint32_t *)(_buffer + len)) = htons ((uint32_t)field); \ + *((uint32_t *)(_buffer + len)) = htonl ((uint32_t)field); \ len += 4; \ } else { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ len = _maxlen; \ } \ break; \ @@ -258,21 +258,23 @@ __BEGIN_DECLS @param name field name @param field data from structure */ -#define SERIAL_DOUBLE(field) \ +#define SERIAL_DOUBLE(name, field) \ switch (sizeof (field)) { \ case 4: \ - if (len + 3 < _maxlen) {  \ + if (len + 3 < _maxlen) { \ *((float *)(_buffer + len)) = field; \ + len += 4; \ } else { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ len = _maxlen; \ } \ break; \ case 8: \ - if (len + 7 < _maxlen) {  \ + if (len + 7 < _maxlen) { \ *((double *)(_buffer + len)) = field; \ + len += 8; \ } else { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ len = _maxlen; \ } \ break; \ @@ -286,14 +288,14 @@ __BEGIN_DECLS @param name field name @param field data from structure */ -#define SERIAL_ARRAY(field) \ +#define SERIAL_ARRAY(name, field) \ { \ int _l = (field##_len < _maxlen - len) ? field##_len : _maxlen - len; \ memcpy (_buffer + len, field, _l); \ len += _l; \ } \ if (len == _maxlen) { \ - VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \ + VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", name)); \ } /** @@ -302,7 +304,116 @@ __BEGIN_DECLS End of serialisation section */ #define END_SERIAL() \ - return (len >= _maxlen); + return len; + +/** + @ingroup MESSAGES + + Initialize deserialisation section + + @param buffer input buffer + @param len buffer length +*/ +#define BEGIN_DESERIAL(buffer, len) \ + uint8_t *_buffer = (buffer); \ + uint8_t *end = _buffer + (len); \ + uint8_t *ptr = _buffer; + +/** + @ingroup MESSAGES + + Deserialyze to an integer field + + @param name field name + @param field data from structure +*/ +#define DESERIAL_INT(name, field) \ + switch (sizeof (field)) { \ + case 1: \ + if (ptr < end) { \ + field = *ptr++; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + ptr = end + 1; \ + } \ + break; \ + case 2: \ + if (ptr + 1 < end) { \ + field = ntohs (*((uint16_t *)ptr)); \ + ptr -= 2; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + ptr = end + 1; \ + } \ + break; \ + case 4: \ + if (ptr + 3 < end) { \ + field = ntohl (*((uint32_t *)ptr)); \ + ptr -= 4; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + ptr = end + 1; \ + } \ + break; \ + } + +/** + @ingroup MESSAGES + + Deserialyze to a floating point field + + @param name field name + @param field data from structure +*/ +#define DESERIAL_DOUBLE(name, field) \ + switch (sizeof (field)) { \ + case 4: \ + if (ptr + 3 < end) { \ + field = *(float *)ptr; \ + ptr -= 4; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + ptr = end + 1; \ + } \ + break; \ + case 8: \ + if (ptr + 7 < end) { \ + field = *(double *)ptr; \ + ptr -= 8; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + ptr = end + 1; \ + } \ + break; \ + } + +/** + @ingroup MESSAGES + + Deserialyze to an array field + + @param name field name + @param field data from structure +*/ +#define DESERIAL_ARRAY(name, field) \ + if (field##_len == 0) { \ + memcpy (field, ptr, end - ptr); \ + field##_len = end - ptr; \ + ptr = end; \ + } else if (field##_len < end - ptr) { \ + memcpy (field, ptr, field##_len); \ + ptr += field##_len; \ + } else { \ + VERBOSE (morep, WARNING, PRINTF ("no data for field '%s'\n", name)); \ + } + +/** + @ingroup MESSAGES + + End of deserialisation section +*/ +#define END_DESERIAL() \ + return (ptr > end); /* private function (do not use outside) */ diff --git a/raw_data.c b/raw_data.c index b9aa258..b9c6ec2 100644 --- a/raw_data.c +++ b/raw_data.c @@ -35,8 +35,15 @@ int format_raw_data (RAW_DATA_t *in, char *buffer, int maxlen) int serial_raw_data (RAW_DATA_t *in, uint8_t *buffer, int maxlen) { BEGIN_SERIAL (buffer, maxlen) - SERIAL_ARRAY (in->data) + SERIAL_ARRAY ("DATA", in->data) END_SERIAL () } +int deserial_raw_data (uint8_t *buffer, int maxlen, RAW_DATA_t *out) +{ + BEGIN_DESERIAL (buffer, maxlen) + DESERIAL_ARRAY ("DATA", out->data) + END_DESERIAL () +} + /* vim: set ts=4 sw=4 si et: */ diff --git a/raw_data.h b/raw_data.h index 2fdca22..1153888 100644 --- a/raw_data.h +++ b/raw_data.h @@ -37,6 +37,7 @@ typedef struct { @param line string to analyse @param out output structure + @return 0 on success */ int parse_raw_data (char *line, RAW_DATA_t *out); @@ -48,20 +49,34 @@ int parse_raw_data (char *line, RAW_DATA_t *out); @param in input structure @param buffer output string @param maxlen buffer limit + @return 0 on success */ int format_raw_data (RAW_DATA_t *in, char *buffer, int maxlen); /** @ingroup MESSAGES - Serial raw data type fields into a network stream + Serialize raw data type fields into a network stream @param in input structure - @param buffer output network stream + @param buffer network stream @param maxlen buffer limit + @return buffer length */ int serial_raw_data (RAW_DATA_t *in, uint8_t *buffer, int maxlen); +/** + @ingroup MESSAGES + + Deserial raw data type fields from a network stream + + @param buffer network stream + @param maxlen buffer limit + @param out output structure + @return 0 on success +*/ +int deserial_raw_data (uint8_t *buffer, int maxlen, RAW_DATA_t *out); + __END_DECLS #endif /* __RAW_DATA_H__ */ -- 2.30.2