From 1ae904dff2f28b890ab60f85cfb6d0cc9ea889e9 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Wed, 15 May 2024 20:46:20 +0200 Subject: [PATCH] =?UTF-8?q?Add=20support=20of=20INIT=C3=A7WITH=20for=20var?= =?UTF-8?q?iant=20in=20C11=20/=20provided=20all=20types=20of=20the=20varia?= =?UTF-8?q?nt=20are=20exclusive.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- m-variant.h | 46 ++++++++++++++++++++++++++++++++++++++++--- tests/test-mvariant.c | 10 ++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/m-variant.h b/m-variant.h index c771bfbc..09dde103 100644 --- a/m-variant.h +++ b/m-variant.h @@ -186,7 +186,17 @@ typedef struct M_F(name, _s) *M_F(name, _ptr); \ typedef const struct M_F(name, _s) *M_F(name, _srcptr); \ /* Define internal type for oplist */ \ - typedef name_t M_F(name, _ct); + typedef name_t M_F(name, _ct); \ + /* Save alias for the types of arguments */ \ + M_MAP3(M_VAR1ANT_DEFINE_GENTYPE_ELE, name, __VA_ARGS__) + +#define M_VAR1ANT_DEFINE_GENTYPE_ELE(name, num, a) \ + typedef \ + M_IF_METHOD(GENTYPE, M_VAR1ANT_GET_OPLIST a)( M_GET_GENTYPE M_VAR1ANT_GET_OPLIST a, M_VAR1ANT_GET_TYPE a) \ + M_C4(m_var1ant_, name, _gentype_, num); \ + typedef const \ + M_IF_METHOD(GENTYPE, M_VAR1ANT_GET_OPLIST a)( M_GET_GENTYPE M_VAR1ANT_GET_OPLIST a, M_VAR1ANT_GET_TYPE a) \ + M_C4(m_var1ant_, name, _const_gentype_, num); #define M_VAR1ANT_DEFINE_UNION_ELE(name, a) \ , M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) @@ -312,15 +322,22 @@ /* Define the INIT_SET of a given type function. */ #define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD(name, ...) \ - M_MAP2(M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC, name, __VA_ARGS__) + M_MAP3(M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC, name, __VA_ARGS__) -#define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC(name, a) \ +#define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC(name, num, a) \ M_INLINE void \ M_C3(name, _init_set_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my, \ M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \ my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \ M_VAR1ANT_CALL_INIT_SET(a, my -> value. M_VAR1ANT_GET_FIELD a, \ M_VAR1ANT_GET_FIELD a); \ + } \ + M_INLINE void \ + M_C4(m_var1ant_, name, _init_set_, num)(M_F(name,_ct) my, \ + M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \ + my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \ + M_VAR1ANT_CALL_INIT_SET(a, my -> value. M_VAR1ANT_GET_FIELD a, \ + M_VAR1ANT_GET_FIELD a); \ } @@ -763,6 +780,8 @@ M_INLINE void \ NAME(name), \ TYPE(M_F(name,_ct)), GENTYPE(struct M_F(name,_s)*), \ EMPTY_P(M_F(name,_empty_p)), \ + SIZE( M_NARGS(__VA_ARGS__) ), \ + INIT_WITH( API_1(M_VAR1ANT_INIT_WITH) ), \ M_IF_METHOD_ALL(HASH, __VA_ARGS__)(HASH(M_F(name, _hash)),), \ M_IF_METHOD_ALL(EQUAL, __VA_ARGS__)(EQUAL(M_F(name, _equal_p)),), \ M_IF_METHOD_ALL(GET_STR, __VA_ARGS__)(GET_STR(M_F(name, _get_str)),), \ @@ -797,6 +816,27 @@ M_INLINE void \ /********************************** INTERNAL *********************************/ +/* INIT_WITH macro using _Generic + Expand as: + _Generic ( (x), + M_C4(m_var1ant_, name, _gentype_, num) : M_C4(m_var1ant_, name, _init_set_, num)(x, M_AS_TYPE() ), + ... + ) +*/ +#define M_VAR1ANT_INIT_WITH(oplist, dest, src) \ + M_VAR1ANT_INIT_WITH_B(M_GET_NAME oplist, M_GET_SIZE oplist, dest, src) +#define M_VAR1ANT_INIT_WITH_B(name, num, dest, src) \ + _Generic( (src), \ + M_MAP2(M_VAR1ANT_INIT_WITH_FUNC, (name,dest,src), M_SEQ(1, num)) \ + struct m_var1ant_dummy_s *: abort() ) +#define M_VAR1ANT_INIT_WITH_FUNC(triplet, num) \ + M_VAR1ANT_INIT_WITH_FUNC_EXPAND(M_TRIPLE_1 triplet, M_TRIPLE_2 triplet, M_TRIPLE_3 triplet, num) +#define M_VAR1ANT_INIT_WITH_FUNC_EXPAND(name, dest, src, num) \ + M_C4(m_var1ant_, name, _gentype_, num) : M_C4(m_var1ant_, name, _init_set_, num)(dest, M_AS_TYPE(M_C4(m_var1ant_, name, _gentype_, num), src) ), \ + M_C4(m_var1ant_, name, _const_gentype_, num): M_C4(m_var1ant_, name, _init_set_, num)(dest, M_AS_TYPE(M_C4(m_var1ant_, name, _const_gentype_, num), src) ), + +/********************************** INTERNAL *********************************/ + #if M_USE_SMALL_NAME #define VARIANT_DEF2 M_VARIANT_DEF2 #define VARIANT_DEF2_AS M_VARIANT_DEF2_AS diff --git a/tests/test-mvariant.c b/tests/test-mvariant.c index 06e2a133..67040187 100644 --- a/tests/test-mvariant.c +++ b/tests/test-mvariant.c @@ -289,6 +289,16 @@ static void test_double (void) M_LET(v, Vector) { assert (vector_empty_p(v) ); } +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + M_LET( (r, (2)), rvariant2_t) { + assert( rvariant2_value_p(r)); + assert( *rvariant2_get_value(r) == 2); + } + M_LET( (r, (M_STRING_CTE("Hello"))), rvariant2_t) { + assert( rvariant2_name_p(r)); + assert( string_equal_str_p(*rvariant2_get_name(r), "Hello")); + } +#endif } int main(void)