add serialisation macros
authorLaurent Mazet <mazet@softndesign.org>
Mon, 7 Apr 2025 21:56:39 +0000 (23:56 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Mon, 7 Apr 2025 21:56:39 +0000 (23:56 +0200)
clear_data.c
clear_data.h
makefile
parse.h
payload.c
payload.h
raw_data.c
raw_data.h

index 148a05719795562a00faab028863734a9a3d19d3..f5840bcfb61db4a8708fbed0bb8d25dafdd047e4 100644 (file)
 int parse_clear_data (char *line, CLEAR_DATA_t *out)
 {
     BEGIN_PARSE (line)
-    PARSE ("CHANNEL", out->channel_id)
-    PARSE ("BYPASS", out->bypass)
-    PARSEA ("DATA", out->data)
+    PARSE_INT ("CHANNEL", out->channel_id)
+    PARSE_INT ("BYPASS", out->bypass)
+    PARSE_ARRAY ("DATA", out->data)
     END_PARSE ()
 }
 
 int format_clear_data (CLEAR_DATA_t *in, char *buffer, int maxlen)
 {
     BEGIN_FORMAT (buffer, maxlen);
-    FORMAT ("CHANNEL", out->channel_id)
-    FORMAT ("BYPASS", out->bypass)
-    FORMATA ("DATA", out->data)
+    FORMAT_INT ("CHANNEL", out->channel_id)
+    FORMAT_INT ("BYPASS", out->bypass)
+    FORMAT_ARRAY ("DATA", out->data)
     END_FORMAT ()
 }
 
+int serial_clear_data (CLEAR_DATA_t *in, uint8_t *buffer, int maxlen)
+{
+    BEGIN_SERIAL (buffer, maxlen);
+    SERIAL_INT (out->channel_id)
+    SERIAL_INT (out->bypass)
+    SERIAL_ARRAY (out->data)
+    END_SERIAL ()
+}
+
 /* vim: set ts=4 sw=4 si et: */
index 795e9ec762e6458b8dc50146b523a13650bafeb5..ba1ae18b7b0ec56002056d7730d0a752b494d979 100644 (file)
@@ -54,6 +54,17 @@ int parse_clear_data (char *line, CLEAR_DATA_t *out);
 */
 int format_clear_data (CLEAR_DATA_t *in, char *buffer, int maxlen);
 
+/**
+   @ingroup MESSAGES
+
+   Serial clear data type fields into a network stream
+
+   @param in input structure
+   @param buffer network stream
+   @param maxlen buffer limit
+*/
+int serial_clear_data (CLEAR_DATA_t *in, uint8_t *buffer, int maxlen);
+
 __END_DECLS
 
 #endif /* __CLEAR_DATA_H__ */
index a15e1088ba6046fddca53f35d7e78e5839404dc9..02cc6b1eb9b22f61cfd76cb12c8e0075ed2d6633 100644 (file)
--- a/makefile
+++ b/makefile
@@ -13,7 +13,8 @@ OFLAGS  = -O4 -Os
 #OFLAGS += -malign-double
 CFLAGS += -W -Wall -Wextra -g
 #CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
-CFLAGS += -std=c11 -D_XOPEN_SOURCE=500
+#CFLAGS += -std=c11 -D_XOPEN_SOURCE=500
+CFLAGS += -D_XOPEN_SOURCE=500
 CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS)
 LDFLAGS += -g $(LDOPTS) $(OPTIONS)
 
diff --git a/parse.h b/parse.h
index e01570cdfc518f8af9d633df4f3c664923c28ab7..a351a022fd14b6c73e574f518b3b339c790690d6 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -15,6 +15,7 @@
 #ifndef __PARSE_H__
 #define __PARSE_H__
 
+#include <arpa/inet.h>
 #include <stdint.h>
 #include <string.h>
 #include <sys/cdefs.h>
@@ -85,25 +86,37 @@ __BEGIN_DECLS
 /**
    @ingroup MESSAGES
 
-   Parsing macro
+   Parsing macro for integer field
 
    @param name field name
    @param buf preallocated storage
 */
-#define PARSE(name, buf)                           \
-        else if (strcmp (var, name) == 0) {        \
-            _Generic ((buf),                       \
-                uint8_t: buf = parse_int (val),    \
-                int8_t: buf = parse_int (val),     \
-                uint16_t: buf = parse_int (val),   \
-                int16_t: buf = parse_int (val),    \
-                uint32_t: buf = parse_int (val),   \
-                int32_t: buf = parse_int (val),    \
-                float: buf = parse_double (val),   \
-                double: buf = parse_double (val)); \
+#define PARSE_INT(name, buf)                \
+        else if (strcmp (var, name) == 0) { \
+            buf = parse_int (val);          \
+        }
+/**
+   @ingroup MESSAGES
+
+   Parsing macro for floating point field
+
+   @param name field name
+   @param buf preallocated storage
+*/
+#define PARSE_DOUBLE(name, buf)             \
+        else if (strcmp (var, name) == 0) { \
+            buf = parse_double (val);       \
         }
 
-#define PARSEA(name, buf)                                     \
+/**
+   @ingroup MESSAGES
+
+   Parsing macro for array field
+
+   @param name field name
+   @param buf preallocated storage
+*/
+#define PARSE_ARRAY(name, buf)                                \
         else if (strcmp (var, name) == 0) {                   \
             buf##_len = parse_array (val, buf, sizeof (buf)); \
         }
@@ -139,26 +152,40 @@ __BEGIN_DECLS
 /**
    @ingroup MESSAGES
 
-   Format a field
+   Format an integer field
+
+   @param name field name
+   @param field data from structure
+*/
+#define FORMAT_INT(name, field)                                              \
+    len += snprintf (_buffer, _maxlen - len, "%d", field);                   \
+    if (len == _maxlen) {                                                    \
+        VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+    }
+
+/**
+   @ingroup MESSAGES
+
+   Format a floating point field
 
    @param name field name
    @param field data from structure
 */
-#define FORMAT(name, field)                                                  \
-    _Generic (field,                                                         \
-        uint8_t: len += snprintf (_buffer, _maxlen - len, "%d", field),      \
-        int8_t: len += snprintf (_buffer, _maxlen - len, "%d", field),       \
-        uint16_t: len += snprintf (_buffer, _maxlen - len, "%d", field),     \
-        int16_t: len += snprintf (_buffer, _maxlen - len, "%d", field),      \
-        uint32_t: len += snprintf (_buffer, _maxlen - len, "%d", field),     \
-        int32_t: len += snprintf (_buffer, _maxlen - len, "%d", field),      \
-        float: len += snprintf (_buffer, _maxlen - len, "%g", field),        \
-        double: len += snprintf (_buffer, _maxlen - len, "%g", field));      \
+#define FORMAT_DOUBLE(name, field)                                           \
+    len += snprintf (_buffer, _maxlen - len, "%g", field);                   \
     if (len == _maxlen) {                                                    \
         VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
     }
 
-#define FORMATA(name, field)                                                 \
+/**
+   @ingroup MESSAGES
+
+   Format an array field
+
+   @param name field name
+   @param field data from structure
+*/
+#define FORMAT_ARRAY(name, field)                                            \
     len += snprint_array (_buffer, _maxlen - len, field, field##_len);       \
     if (len == _maxlen) {                                                    \
         VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
@@ -172,6 +199,111 @@ __BEGIN_DECLS
 #define END_FORMAT()         \
     return (len >= _maxlen);
 
+/**
+   @ingroup MESSAGES
+
+   Initialize serialisation section
+
+   @param buffer output buffer
+   @maxlen buffer limit
+*/
+#define BEGIN_SERIAL(buffer, maxlen) \
+    uint8_t *_buffer = (buffer);     \
+    int _maxlen = (maxlen);          \
+    int len = 0;
+
+/**
+   @ingroup MESSAGES
+
+   Serialyze an integer field
+
+   @param name field name
+   @param field data from structure
+*/
+#define SERIAL_INT(field)                                                        \
+    switch (sizeof (field)) {                                                    \
+    case 1:                                                                      \
+        if (len < _maxlen) {                                                     \
+            _buffer[len++] = field;                                              \
+        } else  {                                                                \
+            VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+            len = _maxlen;                                                       \
+        }                                                                        \
+        break;                                                                   \
+    case 2:                                                                      \
+        if (len + 1 < _maxlen) {                                                 \
+            *((uint16_t *)(_buffer + len)) = htons ((uint16_t)field);            \
+            len += 2;                                                            \
+        } else  {                                                                \
+            VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+            len = _maxlen;                                                       \
+        }                                                                        \
+        break;                                                                   \
+    case 4:                                                                      \
+        if (len + 3 < _maxlen) {                                                 \
+            *((uint32_t *)(_buffer + len)) = htons ((uint32_t)field);            \
+            len += 4;                                                            \
+        } else  {                                                                \
+            VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+            len = _maxlen;                                                       \
+        }                                                                        \
+        break;                                                                   \
+    }
+
+/**
+   @ingroup MESSAGES
+
+   Serialyze a floating point field
+
+   @param name field name
+   @param field data from structure
+*/
+#define SERIAL_DOUBLE(field)                                                     \
+    switch (sizeof (field)) {                                                    \
+    case 4:                                                                      \
+        if (len + 3 < _maxlen) {                                                 \
+            *((float *)(_buffer + len)) = field;                                 \
+        } else  {                                                                \
+            VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+            len = _maxlen;                                                       \
+        }                                                                        \
+        break;                                                                   \
+    case 8:                                                                      \
+        if (len + 7 < _maxlen) {                                                 \
+            *((double *)(_buffer + len)) = field;                                \
+        } else  {                                                                \
+            VERBOSE (morep, WARNING, PRINTF ("field '%s' too large\n", #field)); \
+            len = _maxlen;                                                       \
+        }                                                                        \
+        break;                                                                   \
+    }
+
+/**
+   @ingroup MESSAGES
+
+   Serialyze an array field
+
+   @param name field name
+   @param field data from structure
+*/
+#define SERIAL_ARRAY(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));  \
+    }
+
+/**
+   @ingroup MESSAGES
+
+   End of serialisation section
+*/
+#define END_SERIAL()         \
+    return (len >= _maxlen);
+
 /* private function (do not use outside) */
 
 int parse_int (char *val);
index 4a6d69002859b911fc86f9f6cb01a42b0ad2af81..88ad718abc544685c22003d6f2763c31f2f056dc 100644 (file)
--- a/payload.c
+++ b/payload.c
 int parse_payload (char *line, PAYLOAD_t *out)
 {
     BEGIN_PARSE (line)
-    PARSE ("MSG", out->msgtype)
-    PARSEA ("PAYLOAD", out->data)
+    PARSE_INT ("MSG", out->msgtype)
+    PARSE_ARRAY ("PAYLOAD", out->data)
     END_PARSE ()
 }
 
 int format_payload (PAYLOAD_t *in, char *buffer, int maxlen)
 {
     BEGIN_FORMAT (buffer, maxlen)
-    FORMAT ("MSG", in->msgtype)
-    FORMATA ("PAYLOAD", in->data)
+    FORMAT_INT ("MSG", in->msgtype)
+    FORMAT_ARRAY ("PAYLOAD", in->data)
     END_FORMAT ()
 }
 
+int serial_payload (PAYLOAD_t *in, uint8_t *buffer, int maxlen)
+{
+    BEGIN_SERIAL (buffer, maxlen)
+    SERIAL_INT (in->msgtype)
+    SERIAL_ARRAY (in->data)
+    END_SERIAL ()
+}
+
 /* vim: set ts=4 sw=4 si et: */
index b53a329aba3dc3f95ddcdcba80173936c2c85bf0..f21cecd72cf17c6a387f0df35191915eb002ff95 100644 (file)
--- a/payload.h
+++ b/payload.h
@@ -52,6 +52,17 @@ int parse_payload (char *line, PAYLOAD_t *out);
 */
 int format_payload (PAYLOAD_t *in, char *buffer, int maxlen);
 
+/**
+   @ingroup MESSAGES
+
+   Serialize payload into a network stream
+
+   @param in input structure
+   @param buffer network stream
+   @param maxlen buffer limit
+*/
+int serial_payload (PAYLOAD_t *in, uint8_t *buffer, int maxlen);
+
 __END_DECLS
 
 #endif /* __PAYLOAD_H__ */
index 00cc787d607f178eb5447e278af4d167f899d416..b9aa2582a07169515473170ee11c51d408f80fab 100644 (file)
 int parse_raw_data (char *line, RAW_DATA_t *out)
 {
     BEGIN_PARSE (line)
-    PARSEA ("DATA", out->data)
-    PARSEA ("PAYLOAD", out->data)
+    PARSE_ARRAY ("DATA", out->data)
     END_PARSE ()
 }
 
 int format_raw_data (RAW_DATA_t *in, char *buffer, int maxlen)
 {
     BEGIN_FORMAT (buffer, maxlen)
-    FORMATA ("DATA", in->data)
+    FORMAT_ARRAY ("DATA", in->data)
     END_FORMAT ()
 }
 
+int serial_raw_data (RAW_DATA_t *in, uint8_t *buffer, int maxlen)
+{
+    BEGIN_SERIAL (buffer, maxlen)
+    SERIAL_ARRAY (in->data)
+    END_SERIAL ()
+}
+
 /* vim: set ts=4 sw=4 si et: */
index e4dc47690e3489109efb0fae2999e888576fc654..2fdca220ef7375b864d434d37ffa924b083f1064 100644 (file)
@@ -51,6 +51,17 @@ int parse_raw_data (char *line, RAW_DATA_t *out);
 */
 int format_raw_data (RAW_DATA_t *in, char *buffer, int maxlen);
 
+/**
+   @ingroup MESSAGES
+
+   Serial raw data type fields into a network stream
+
+   @param in input structure
+   @param buffer output network stream
+   @param maxlen buffer limit
+*/
+int serial_raw_data (RAW_DATA_t *in, uint8_t *buffer, int maxlen);
+
 __END_DECLS
 
 #endif /* __RAW_DATA_H__ */