From b38a926f3c414b1d3e996bdcac5ebe4d40a2b61b Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Tue, 28 Feb 2017 22:42:20 +0100 Subject: [PATCH] Adding OUT_STR & GET_STR operators for variants --- m-core.h | 3 +++ m-variant.h | 53 +++++++++++++++++++++++++++++++++++++++---- tests/test-mvariant.c | 3 +++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/m-core.h b/m-core.h index 94a5fb22..15b27c19 100644 --- a/m-core.h +++ b/m-core.h @@ -195,6 +195,9 @@ /* Return 1 if comma inside the argument list, 0 otherwise */ #define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless) +/* Return the string representation of the evaluated x */ +#define M_AS_STR(x) #x + /* Return 1 if the argument is 'empty', 0 otherwise. Handle: EMPTY_P(), EMPTY_P(x), EMPTY_P(()) and EMPTY_P(,) and EMPTY_P(f) with #define f() 2,3 */ #define M_EMPTYI_DETECT(...) 0, 1, diff --git a/m-variant.h b/m-variant.h index 94e976d9..5f8ade65 100644 --- a/m-variant.h +++ b/m-variant.h @@ -226,11 +226,50 @@ break; -#define VARIANTI_DEFINE_MOVE(name, ...) \ - static inline void M_C(name, _move)(M_C(name,_t) el, M_C(name,_t) org) { \ - M_C(name, _clear)(el); \ - M_C(name, _init_move)(el , org); \ - } +#define VARIANTI_DEFINE_MOVE(name, ...) \ + static inline void M_C(name, _move)(M_C(name,_t) el, M_C(name,_t) org) { \ + M_C(name, _clear)(el); \ + M_C(name, _init_move)(el , org); \ + } + +#define VARIANTI_DEFINE_GET_STR(name, ...) \ + static inline void M_C(name, _get_str)(string_t str, \ + M_C(name,_t) const el, \ + bool append) { \ + assert (str != NULL && el != NULL); \ + void (*func)(string_t, const char *); \ + func = append ? string_cat_str : string_set_str; \ + switch (el->type) { \ + case M_C(name, _EMPTY): func(str, "@EMPTY@"); break; \ + M_MAP2(VARIANTI_DEFINE_GET_STR_FUNC , name, __VA_ARGS__) \ + default: assert(false); break; \ + } \ + string_push_back (str, '@'); \ + } +#define VARIANTI_DEFINE_GET_STR_FUNC(name, a) \ + case M_C3(name, _, VARIANTI_GET_FIELD a): \ + func(str, "@" M_AS_STR(VARIANTI_GET_FIELD a) "@"); \ + VARIANTI_GET_STR a (str, el -> value . VARIANTI_GET_FIELD a, true); \ + break; + + +#define VARIANTI_DEFINE_OUT_STR(name, ...) \ + static inline void M_C(name, _out_str)(FILE *f, \ + M_C(name,_t) const el) { \ + assert (f != NULL && el != NULL); \ + switch (el->type) { \ + case M_C(name, _EMPTY): fprintf(f, "@EMPTY@"); break; \ + M_MAP2(VARIANTI_DEFINE_OUT_STR_FUNC , name, __VA_ARGS__) \ + default: assert(false); break; \ + } \ + fputc ('@', f); \ + } +#define VARIANTI_DEFINE_OUT_STR_FUNC(name, a) \ + case M_C3(name, _, VARIANTI_GET_FIELD a): \ + fprintf(f, "@" M_AS_STR(VARIANTI_GET_FIELD a) "@"); \ + VARIANTI_GET_OUT_STR a (f, el -> value . VARIANTI_GET_FIELD a); \ + break; + #define VARIANTI_OPLIST(name, ...) \ @@ -282,6 +321,10 @@ (VARIANTI_DEFINE_HASH(name, __VA_ARGS__),) \ M_IF(VARIANTI_ALL_EQUAL(__VA_ARGS__)) \ (VARIANTI_DEFINE_EQUAL(name, __VA_ARGS__),) \ + M_IF(VARIANTI_ALL_GET_STR(__VA_ARGS__)) \ + (VARIANTI_DEFINE_GET_STR(name, __VA_ARGS__),) \ + M_IF(VARIANTI_ALL_OUT_STR(__VA_ARGS__)) \ + (VARIANTI_DEFINE_OUT_STR(name, __VA_ARGS__),) \ M_IF(VARIANTI_ALL_INIT_MOVE(__VA_ARGS__)) \ (VARIANTI_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \ M_IF(VARIANTI_ALL_INIT_MOVE(__VA_ARGS__)) \ diff --git a/tests/test-mvariant.c b/tests/test-mvariant.c index 4c0ce808..ba072daf 100644 --- a/tests/test-mvariant.c +++ b/tests/test-mvariant.c @@ -123,6 +123,9 @@ test_triple(void) triple_clear(t); } +VARIANT_DEF2(single, + (s, string_t, STRING_OPLIST)) + int main(void) { test_pair();