From 5222fabf02bf978b7dcb54083825916a8bd6d11d Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Wed, 8 May 2019 11:11:53 +0200 Subject: [PATCH] Add tuple support for serial --- m-core.h | 44 ++++++++++++++++++---------------- m-tuple.h | 58 +++++++++++++++++++++++++++++++++++++++++++++ tests/test-mtuple.c | 4 ++++ 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/m-core.h b/m-core.h index ea9b32cf..2eb93680 100644 --- a/m-core.h +++ b/m-core.h @@ -2188,6 +2188,7 @@ m_core_hash (const void *str, size_t length) INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ HASH(M_HASH_DEFAULT), SWAP(M_SWAP_DEFAULT) , \ IN_STR(M_FSCAN_ARG M_IPTR), OUT_STR(M_FPRINT_ARG), \ + IN_SERIAL(M_IN_SERIAL_DEFAULT_ARG M_IPTR), OUT_SERIAL(M_OUT_SERIAL_DEFAULT_ARG), \ PARSE_STR(M_PARSE_DEFAULT_TYPE M_IPTR), M_GET_STR_METHOD_FOR_DEFAULT_TYPE) # else /* FILE support */ @@ -2196,6 +2197,7 @@ m_core_hash (const void *str, size_t length) CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \ INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ HASH(M_HASH_DEFAULT), SWAP(M_SWAP_DEFAULT) , \ + IN_SERIAL(M_IN_SERIAL_DEFAULT_ARG M_IPTR), OUT_SERIAL(M_OUT_SERIAL_DEFAULT_ARG), \ PARSE_STR(M_PARSE_DEFAULT_TYPE M_IPTR), M_GET_STR_METHOD_FOR_DEFAULT_TYPE) # endif #else @@ -2564,7 +2566,7 @@ m_backoff_clear(m_backoff_t backoff) * - Fail parsing */ typedef enum m_serial_return_code_e { - M_SERIAL_OK_DONE, M_SERIAL_OK_CONTINUE, M_SERIAL_FAIL + M_SERIAL_OK_DONE = 0, M_SERIAL_OK_CONTINUE = 1, M_SERIAL_FAIL = 2 } m_serial_return_code_t; /* Maximum data size of a serializator structure @@ -2627,30 +2629,30 @@ typedef struct m_serial_write_interface_s { } m_serial_write_interface_t; /* Convert a C default variale (bool, integer, float) to a Serialized data */ -#define M_OUT_SERIAL_DEFAULT_ARG(serial, xptr) \ - _Generic(((void)0,*xptr), \ - bool: (serial)->interface->write_boolean(serial, *M_AS_TYPE(bool *, xptr)), \ - char: (serial)->interface->write_integer(serial, *M_AS_TYPE(char*,xptr)), \ - signed char: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed char*,xptr)), \ - unsigned char: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned char*,xptr)), \ - signed short: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed short*,xptr)), \ - unsigned short: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned short*,xptr)), \ - signed int: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed int*,xptr)), \ - unsigned int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned int*,xptr)), \ - long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(long*,xptr)), \ - unsigned long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned long*,xptr)), \ - long long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(long long*,xptr)), \ - unsigned long long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned long long*,xptr)), \ - float: (serial)->interface->write_float(serial, *M_AS_TYPE(float*,xptr)), \ - double: (serial)->interface->write_float(serial, *M_AS_TYPE(double*,xptr)), \ - long double: (serial)->interface->write_float(serial, *M_AS_TYPE(long double*,xptr)), \ - const char *: (serial)->interface->write_string(serial, *M_AS_TYPE(const char **,xptr)), \ - char *: (serial)->interface->write_string(serial, *M_AS_TYPE(char **,xptr)), \ +#define M_OUT_SERIAL_DEFAULT_ARG(serial, x) \ + _Generic(((void)0,x), \ + bool: (serial)->interface->write_boolean(serial, *M_AS_TYPE(bool *, &(x))), \ + char: (serial)->interface->write_integer(serial, *M_AS_TYPE(char*,&(x))), \ + signed char: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed char*,&(x))), \ + unsigned char: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned char*,&(x))), \ + signed short: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed short*,&(x))), \ + unsigned short: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned short*,&(x))), \ + signed int: (serial)->interface->write_integer(serial, *M_AS_TYPE(signed int*,&(x))), \ + unsigned int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned int*,&(x))), \ + long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(long*,&(x))), \ + unsigned long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned long*,&(x))), \ + long long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(long long*,&(x))), \ + unsigned long long int: (serial)->interface->write_integer(serial, *M_AS_TYPE(unsigned long long*,&(x))), \ + float: (serial)->interface->write_float(serial, *M_AS_TYPE(float*,&(x))), \ + double: (serial)->interface->write_float(serial, *M_AS_TYPE(double*,&(x))), \ + long double: (serial)->interface->write_float(serial, *M_AS_TYPE(long double*,&(x))), \ + const char *: (serial)->interface->write_string(serial, *M_AS_TYPE(const char **,&(x))), \ + char *: (serial)->interface->write_string(serial, *M_AS_TYPE(char **,&(x))), \ const void *: M_SERIAL_FAIL /* unsupported */, \ void *: M_SERIAL_FAIL /* unsupported */) /* Convert a Serialized data to a C default variale (bool, integer, float) */ -#define M_IN_SERIAL_DEFAULT_ARG(serial, xptr) \ +#define M_IN_SERIAL_DEFAULT_ARG(xptr, serial) \ _Generic(((void)0,*xptr), \ bool: (serial)->interface->read_boolean(serial, M_AS_TYPE(bool *, xptr)), \ char: m_core_in_serial_char(serial, M_AS_TYPE(char*,xptr)), \ diff --git a/m-tuple.h b/m-tuple.h index 86929326..26a5851b 100644 --- a/m-tuple.h +++ b/m-tuple.h @@ -110,6 +110,10 @@ namespace m_tuple { (TUPLE_DEFINE_IN_STR(name, __VA_ARGS__),) \ TUPLEI_IF_ALL(PARSE_STR, __VA_ARGS__) \ (TUPLE_DEFINE_PARSE_STR(name, __VA_ARGS__),) \ + TUPLEI_IF_ALL(OUT_SERIAL, __VA_ARGS__) \ + (TUPLE_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \ + TUPLEI_IF_ALL(IN_SERIAL, __VA_ARGS__) \ + (TUPLE_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \ TUPLEI_IF_ALL(INIT_MOVE, __VA_ARGS__) \ (TUPLE_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \ TUPLEI_IF_ALL(MOVE, __VA_ARGS__) \ @@ -140,6 +144,8 @@ namespace m_tuple { #define TUPLE_GET_STR(f,t,o) M_GET_GET_STR o #define TUPLE_GET_OUT_STR(f,t,o) M_GET_OUT_STR o #define TUPLE_GET_IN_STR(f,t,o) M_GET_IN_STR o +#define TUPLE_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o +#define TUPLE_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o #define TUPLE_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o #define TUPLE_GET_SWAP(f,t,o) M_GET_SWAP o #define TUPLE_GET_CLEAN(f,t,o) M_GET_CLEAN o @@ -157,6 +163,8 @@ namespace m_tuple { #define TUPLE_CALL_OUT_STR(t, ...) M_APPLY_API(TUPLE_GET_OUT_STR t, TUPLE_GET_OPLIST t, __VA_ARGS__) #define TUPLE_CALL_IN_STR(t, ...) M_APPLY_API(TUPLE_GET_IN_STR t, TUPLE_GET_OPLIST t, __VA_ARGS__) #define TUPLE_CALL_PARSE_STR(t, ...) M_APPLY_API(TUPLE_GET_PARSE_STR t, TUPLE_GET_OPLIST t, __VA_ARGS__) +#define TUPLE_CALL_OUT_SERIAL(t, ...) M_APPLY_API(TUPLE_GET_OUT_SERIAL t, TUPLE_GET_OPLIST t, __VA_ARGS__) +#define TUPLE_CALL_IN_SERIAL(t, ...) M_APPLY_API(TUPLE_GET_IN_SERIAL t, TUPLE_GET_OPLIST t, __VA_ARGS__) #define TUPLE_CALL_SWAP(t, ...) M_APPLY_API(TUPLE_GET_SWAP t, TUPLE_GET_OPLIST t, __VA_ARGS__) #define TUPLE_CALL_CLEAN(t, ...) M_APPLY_API(TUPLE_GET_CLEAN t, TUPLE_GET_OPLIST t, __VA_ARGS__) @@ -399,6 +407,56 @@ namespace m_tuple { if (TUPLE_CALL_PARSE_STR(a, el -> TUPLE_GET_FIELD a, str, &str) == false) \ goto exit ; \ +#define TUPLE_STRINGIFY_NAME(a) \ + M_APPLY(M_AS_STR, TUPLE_GET_FIELD a) + +#define TUPLE_DEFINE_OUT_SERIAL(name, ...) \ + static inline m_serial_return_code_t \ + M_C(name, _out_serial)(m_serial_write_t f, \ + M_C(name,_t) const el) { \ + assert (f != NULL && el != NULL); \ + int index = 0; \ + const int field_max = M_NARGS(__VA_ARGS__); \ + static const char *const field_name[] = \ + { M_MAP(TUPLE_STRINGIFY_NAME, __VA_ARGS__) }; \ + m_serial_return_code_t ret; \ + ret = f->interface->write_tuple_start(f); \ + M_MAP(TUPLE_DEFINE_OUT_SERIAL_FUNC , __VA_ARGS__) \ + assert( index == field_max); \ + ret |= f->interace->write_tuple_end(f); \ + return ret & M_SERIAL_FAIL; \ + } +#define TUPLE_DEFINE_OUT_SERIAL_FUNC(a) \ + f->serial->write_tuple_id(f, field_name, field_max, index); \ + TUPLE_CALL_OUT_SERIAL(a, f, el -> TUPLE_GET_FIELD a); \ + index++; \ + +#define TUPLE_DEFINE_IN_SERIAL(name, ...) \ + static inline m_serial_return_code_t \ + M_C(name, _in_serial)(M_C(name,_t) el, m_serial_read_t f) { \ + assert (f != NULL && el != NULL); \ + int index = 0; \ + const int field_max = M_NARGS(__VA_ARGS__); \ + static const char *const field_name[] = \ + { M_MAP(TUPLE_STRINGIFY_NAME, __VA_ARGS__) }; \ + m_serial_return_code_t ret; \ + ret = f->interface->read_tuple_start(f); \ + while (ret != M_SERIAL_OK_CONTINUE) { \ + ret = f->interface->read_tuple_id(f, field_name, field_max, &index); \ + if (ret == M_SERIAL_OK_CONTINUE) { \ + switch (1+index) { \ + M_MAP(TUPLE_DEFINE_IN_SERIAL_FUNC , __VA_ARGS__) \ + default: assert(0); \ + } \ + } \ + } \ + return ret; \ + } +#define TUPLE_DEFINE_IN_SERIAL_FUNC(a) \ + case M_C4(name, _, TUPLE_GET_FIELD a, _value): \ + ret = TUPLE_CALL_IN_SERIAL(a, el -> TUPLE_GET_FIELD a, f); \ + break; \ + #define TUPLE_DEFINE_INIT_MOVE(name, ...) \ static inline void M_C(name, _init_move)(M_C(name,_t) el, M_C(name,_t) org) { \ diff --git a/tests/test-mtuple.c b/tests/test-mtuple.c index f9d72f56..a6059070 100644 --- a/tests/test-mtuple.c +++ b/tests/test-mtuple.c @@ -60,6 +60,10 @@ TUPLE_DEF2(pair2_str, (str, string_t), (value, unsigned long)) +TUPLE_DEF2(int_float, + (vala, int), + (valb, float)) + // Recursive tuple definition. TUPLE_DEF2(rtuple, (ituple, pair_str_t),