Add M_ENUM_OPLIST

This commit is contained in:
Patrick Pelissier committed 2020-06-24 21:13:13 +02:00
1 parent fd3cb50249
commit 68788a6fb8
2 files changed
+114 -2

No files matched your search

+111 -2
View File
@@ -2389,18 +2389,21 @@ m_core_hash (const void *str, size_t length)
#define M_MEMCMP2_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0], b[0]), memcmp(&(a[0]), &(b[0]), sizeof (a[0])))
#define M_HASH_A1_DEFAULT(a) (m_core_hash((const void*) &(a[0]), sizeof (a[0])) )
/* Default oplist for plain structure */
#define M_POD_OPLIST \
(INIT(M_MEMSET_DEFAULT), INIT_SET(M_MEMCPY_DEFAULT), SET(M_MEMCPY_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_MEMCMP1_DEFAULT), CMP(M_MEMCMP2_DEFAULT), \
HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT))
/* Default oplist for a structure defined with an array of size 1 */
#define M_A1_OPLIST \
(INIT(M_MEMSET_A1_DEFAULT), INIT_SET(M_MEMCPY_A1_DEFAULT), SET(M_MEMCPY_A1_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_MEMCMP1_A1_DEFAULT), CMP(M_MEMCMP2_A1_DEFAULT), \
HASH(M_HASH_A1_DEFAULT))
/* Oplist for a type that does nothing and shall not be instanciated */
#define M_EMPTY_OPLIST \
(INIT(M_EMPTY_DEFAULT), INIT_SET(M_EMPTY_DEFAULT), \
@@ -2411,6 +2414,7 @@ m_core_hash (const void *str, size_t length)
OUT_SERIAL(M_EMPTY_DEFAULT), IN_SERIAL(M_TRUE_DEFAULT), \
PARSE_STR(M_TRUE_DEFAULT))
/* Default oplist for C standard types (int & float).
Implement generic out_str/in_str/parse_str/get_str function if using C11.
Add FILE I/O if stdio.h has been included
@@ -2418,7 +2422,7 @@ m_core_hash (const void *str, size_t length)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
# if M_USE_STDIO
/* FILE support */
/* C11 + FILE support */
# define M_DEFAULT_OPLIST \
(INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
@@ -2430,7 +2434,7 @@ m_core_hash (const void *str, size_t length)
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
/* No FILE support */
/* C11 + No FILE support */
# define M_DEFAULT_OPLIST \
(INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
@@ -2442,6 +2446,7 @@ m_core_hash (const void *str, size_t length)
PARSE_STR(M_PARSE_DEFAULT_TYPE M_IPTR), M_GET_STR_METHOD_FOR_DEFAULT_TYPE)
# endif
#else
/* C99 */
# define M_DEFAULT_OPLIST \
(INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
@@ -2451,6 +2456,7 @@ m_core_hash (const void *str, size_t length)
HASH(M_HASH_DEFAULT), SWAP(M_SWAP_DEFAULT) )
#endif
/* Specialized oplist for a boolean.
* M_DEFAULT_OPLIST is nearly ok, except for ADD/SUB/MUL/DIV
* that generates warnings with boolean.
@@ -2459,6 +2465,91 @@ m_core_hash (const void *str, size_t length)
M_OPEXTEND(M_DEFAULT_OPLIST, ADD(M_OR_DEFAULT), MUL(M_AND_DEFAULT), \
SUB(0), DIV(0))
/* Specialized oplist for an enum.
* M_DEFAULT_OPLIST is nearly ok, except if build in C++ mode.
* Also I/O and arithmetics are removed
* OPLIST doesn't store an oplist but an additional parameter
*/
#if M_USE_STDIO
/* FILE support */
#define M_ENUM_OPLIST(type, init) \
(INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \
SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \
HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \
TYPE(type), OPLIST(init), \
IN_STR(API_1(M_ENUM_FSCAN)), OUT_STR(M_ENUM_FPRINT), \
IN_SERIAL(API_1(M_ENUM_IN_SERIAL)), OUT_SERIAL(M_ENUM_OUT_SERIAL), \
PARSE_STR(API_1(M_ENUM_PARSE)), M_GET_STR_METHOD_FOR_ENUM_TYPE \
)
#else
/* No File support */
#define M_ENUM_OPLIST(type, init) \
(INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \
SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \
HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \
TYPE(type), OPLIST(init), \
IN_SERIAL(API_1(M_ENUM_IN_SERIAL)), OUT_SERIAL(M_ENUM_OUT_SERIAL), \
PARSE_STR(API_1(M_ENUM_PARSE)), M_GET_STR_METHOD_FOR_ENUM_TYPE \
)
#endif /* M_USE_STDIO */
/* It will be overloaded if m-string.h is included */
#define M_GET_STR_METHOD_FOR_ENUM_TYPE
/* Initialize an enum to its init value */
#define M_ENUM_INIT(oplist, var) \
((var) = M_GET_OPLIST oplist )
/* Define helper functions for enum oplist */
/* Input/Output an enumerate.
It is stored as a long long integer for best compatibility. */
#if M_USE_STDIO
static inline long long
m_core_fscan_enum (FILE *f)
{
long long ret;
int s = m_core_fscanf(f, "%lld", &ret) == 1;
/* HACK: Push back the return code in FILE stream,
so that it can be popped later with a fgetc */
ungetc(s, f);
return ret;
}
#define M_ENUM_FPRINT(f, var) fprintf( (f), "%lld", (long long) (var))
#define M_ENUM_FSCAN(oplist, var, f) \
( var = (M_GET_TYPE oplist) (true ? m_core_fscan_enum(f) : 0), fgetc(f))
#endif /* M_USE_STDIO */
/* HACK: Parse two times to convert and then compute
if the conversion succeeds for PARSE */
static inline long long
m_core_parse1_enum (const char str[])
{
return strtoll(str, NULL, 10);
}
static inline bool
m_core_parse2_enum (const char str[], const char **endptr)
{
char *end;
strtoll(str, &end, 10);
if (endptr != NULL) *endptr = end;
return end != str;
}
#define M_ENUM_OUT_SERIAL(serial, var) \
((serial)->m_interface->write_integer(serial, (long long) (var), sizeof (var)))
#define M_ENUM_IN_SERIAL(oplist, var, serial) \
( var = (M_GET_TYPE oplist)(true ? m_core_in_serial_enum(serial) : 0), (serial)->tmp.r)
#define M_ENUM_GET_STR(str, var, append) \
((append ? string_cat_printf : string_printf) (str, "%lld", (long long) (var) ))
#define M_ENUM_PARSE(oplist, var, str, endptr) \
( var = (M_GET_TYPE oplist) (true ? m_core_parse1_enum(str) : 0), m_core_parse2_enum(str, endptr))
/* Default oplist for standard types of pointers.
*/
#define M_PTR_OPLIST \
@@ -2467,6 +2558,7 @@ m_core_hash (const void *str, size_t length)
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \
SWAP(M_SWAP_DEFAULT) )
/* Default oplist for complex objects with "classic" names for methods.
*/
#define M_CLASSIC_OPLIST(name) ( \
@@ -2476,6 +2568,7 @@ m_core_hash (const void *str, size_t length)
CLEAR(M_C(name, _clear)), \
TYPE(M_C(name, _t)) )
/* OPLIST for 'const char *' string (with NO memory allocation).
TODO: M_CSTR_HASH is buggy as the alignment condition of the string
doesn't match the one of m_core_hash.
@@ -2489,6 +2582,7 @@ m_core_hash (const void *str, size_t length)
CMP(strcmp), TYPE(const char *), \
OUT_STR(M_CSTR_OUT_STR) )
/* From an oplist (...) return ... */
#define M_OPFLAT(...) __VA_ARGS__
@@ -2998,12 +3092,14 @@ inline m_serial_return_code_t operator&(m_serial_return_code_t a, m_serial_retur
* an integer
* a size
* a pointer to something.
* a serial return code
*/
typedef union m_serial_ll_u {
bool b;
int i;
size_t s;
void *p;
m_serial_return_code_t r;
} m_serial_ll_t;
/* Object to handle the construction of a serial write/read of an object
@@ -3016,12 +3112,14 @@ typedef struct m_serial_local_s {
/* Object to handle the generic serial read of an object:
* - interface is the pointer to the constant interface object that has all callbacks
* - tmp is temporary variable used localy by the non recursive serializer
* - data is user defined data to use by the serialization object as it wants
* NOTE: interface cannot be used as a field name as some system headers define it
* as a macro.
* */
typedef struct m_serial_read_s {
const struct m_serial_read_interface_s *m_interface;
m_serial_ll_t tmp;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_read_t[1];
@@ -3048,10 +3146,12 @@ typedef struct m_serial_read_interface_s {
/* Object to handle the generic serial write of an object:
* - interface is the pointer to the constant interface object that has all callbacks
* - tmp is temporary variable used localy by the non recursive serializer
* - data is user defined data to use by the serialization object as it wants
* */
typedef struct m_serial_write_s {
const struct m_serial_write_interface_s *m_interface;
m_serial_ll_t tmp;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_write_t[1];
@@ -3154,6 +3254,15 @@ M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_float, float, read_float, long dou
M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_double, double, read_float, long double)
M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_ldouble, long double, read_float, long double)
/* Helper function for M_ENUM_IN_SERIAL */
static long long
m_core_in_serial_enum(m_serial_read_t serial)
{
long long i;
serial->tmp.r = serial->m_interface->read_integer(serial, &i, sizeof (long long));
return i;
}
/* Encapsulation of strlen to avoid warnings in M_OUT_SERIAL_DEFAULT_ARG
* because of expanded code will call strlen with NULL (which is illegal)
* However, the branch where it is called is unreachable, so the warning
+3
View File
@@ -1745,6 +1745,9 @@ namespace m_string {
#endif
/* Internal Macro: Provide GET_STR method to enum type */
#undef M_GET_STR_METHOD_FOR_ENUM_TYPE
#define M_GET_STR_METHOD_FOR_ENUM_TYPE GET_STR(M_ENUM_GET_STR)
/***********************************************************************/
/* */