Make M*LIB stricter for INIT_MOVE operator:

* either the default INIT_MOVE operator works ('=')
* either an INIT_MOVE method is defined
* or it is disabled.
As a consequence, fix usage of testobj_t and mpz_t in the repository

The emulation layer of INIT_MOVE using INIT_SET+CLEAR is removed:
it wasn't working correctly with the local memory context
(INIT_MOVE doesn't need any local memory context to work,
 whereas INIT_SET/CLEAR does)
Remove macro M_DO_INIT_MOVE as it is now useless and uses M_CALL_INIT_MOVE.

The INIT_MOVE default method no longer sets the old 'src' to '0':
it was useless (it doesn't catch any error) and complicates compiler parsing.

Fix POD & A1 & CSTR & classic oplists definition (missing INIT_MOVE operators).
This commit is contained in:
Patrick Pelissier committed 2025-05-07 21:02:24 +02:00
1 parent 3a39ce5a4a
commit d548117538
19 files changed
+126 -157

No files matched your search

+16 -9
View File
@@ -356,7 +356,7 @@ Here is another example with a complete type (with proper initialization & clear
#include <stdio.h> #include <stdio.h>
#include <gmp.h> #include <gmp.h>
#include "m-array.h" #include "m-array.h"
ARRAY_DEF(array_mpz, mpz_t, (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear)) ) ARRAY_DEF(array_mpz, mpz_t, (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT)) )
int main(void) { int main(void) {
array_mpz_t array ; /* array_mpz_t has been define above */ array_mpz_t array ; /* array_mpz_t has been define above */
array_mpz_init(array); /* All type needs to be initialized */ array_mpz_init(array); /* All type needs to be initialized */
@@ -401,7 +401,7 @@ We can also write the same example shorter:
// Register the oplist of a mpz_t. // Register the oplist of a mpz_t.
#define M_OPL_mpz_t() (INIT(mpz_init), INIT_SET(mpz_init_set), \ #define M_OPL_mpz_t() (INIT(mpz_init), INIT_SET(mpz_init_set), \
SET(mpz_set), CLEAR(mpz_clear)) SET(mpz_set), CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT))
// Define an instance of an array of mpz_t (both type and function) // Define an instance of an array of mpz_t (both type and function)
ARRAY_DEF(array_mpz, mpz_t) ARRAY_DEF(array_mpz, mpz_t)
// Register the oplist of the created instance of array of mpz_t // Register the oplist of the created instance of array of mpz_t
@@ -786,7 +786,7 @@ void mpz_clear(mpz_t z); // Destructor of the object z
A basic oplist will be: A basic oplist will be:
```C ```C
(INIT(mpz_init),SET(mpz_set),INIT_SET(mpz_init_set),CLEAR(mpz_clear),TYPE(mpz_t)) (INIT(mpz_init),SET(mpz_set),INIT_SET(mpz_init_set),CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT),TYPE(mpz_t))
``` ```
Much more complete oplist can be built for this type however, enabling much more powerful generation: Much more complete oplist can be built for this type however, enabling much more powerful generation:
@@ -803,7 +803,7 @@ Example:
```C ```C
#define M_OPL_mpz_t() (INIT(mpz_init),SET(mpz_set), \ #define M_OPL_mpz_t() (INIT(mpz_init),SET(mpz_set), \
INIT_SET(mpz_init_set),CLEAR(mpz_clear),TYPE(mpz_t)) INIT_SET(mpz_init_set),CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT),TYPE(mpz_t))
``` ```
This can simplify a lot `OPLIST` usage and it is recommended. This can simplify a lot `OPLIST` usage and it is recommended.
@@ -841,7 +841,7 @@ The API Adaptation to use shall be embedded in the `OPLIST` definition.
For example: For example:
```C ```C
(INIT(API_0(mpz_init)), SET(API_0(mpz_set)), INIT_SET(API_0(mpz_init_set)), CLEAR(API_0(mpz_clear))) (INIT(API_0(mpz_init)), SET(API_0(mpz_set)), INIT_SET(API_0(mpz_init_set)), CLEAR(API_0(mpz_clear)), INIT_MOVE(M_COPY_A1_DEFAULT))
``` ```
The default adaptation is API_0 (i.e. no adaptation between operator interface and method interface). The default adaptation is API_0 (i.e. no adaptation between operator interface and method interface).
@@ -1174,6 +1174,11 @@ perl -i -e 's/;/;\n/g' test-file.i
cc -std=c99 -c -Wall test-file.i cc -std=c99 -c -Wall test-file.i
``` ```
If you get the error "assignment to expression with array type", it means that the library
tries using the default '=' operator to set an object which is not compatible:
give the right method to the needed operator (usually `INIT_MOVE` or `INIT_SET`) in its oplist
or use the proper oplist of the type.
If there is a warning reported by the compiler in the generated code, If there is a warning reported by the compiler in the generated code,
then there is definitely an **error** you should fix (except if it reports then there is definitely an **error** you should fix (except if it reports
shadowed variables), in particular cast evolving pointers. shadowed variables), in particular cast evolving pointers.
@@ -1311,6 +1316,8 @@ and you shall use a typedef as an intermediary named type for such types.
The output parameters are listed fist, then the input/output parameters and finally the input parameters. The output parameters are listed fist, then the input/output parameters and finally the input parameters.
The oplist shall also provide the `INIT_MOVE` operator if the default instance (aka '=' operator) is not working for this type (for example for array of size 1, in which case the method `M_COPY_A1_DEFAULT` is likely to work), or disable the operator.
This generic interface is specified as follow: This generic interface is specified as follow:
##### `void name_init(name_t container)` ##### `void name_init(name_t container)`
@@ -1773,7 +1780,7 @@ Example:
#define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x) #define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x)
LIST_DEF(list_mpz, mpz_t, \ LIST_DEF(list_mpz, mpz_t, \
(INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \ (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \
CLEAR(mpz_clear), OUT_STR(MPZ_OUT_STR))) CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT), OUT_STR(MPZ_OUT_STR)))
int main(void) { int main(void) {
list_mpz_t a; list_mpz_t a;
@@ -1973,7 +1980,7 @@ Example:
#define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x) #define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x)
LIST_DUAL_PUSH_DEF(list_mpz, mpz_t, \ LIST_DUAL_PUSH_DEF(list_mpz, mpz_t, \
(INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \ (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \
CLEAR(mpz_clear), OUT_STR(MPZ_OUT_STR))) CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT), OUT_STR(MPZ_OUT_STR)))
int main(void) { int main(void) {
list_mpz_t a; list_mpz_t a;
@@ -2132,7 +2139,7 @@ Example:
#define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x) #define MPZ_OUT_STR(stream, x) mpz_out_str(stream, 0, x)
ARRAY_DEF(array_mpz, mpz_t, \ ARRAY_DEF(array_mpz, mpz_t, \
(INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \ (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), \
CLEAR(mpz_clear), OUT_STR(MPZ_OUT_STR))) CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT), OUT_STR(MPZ_OUT_STR)))
int main(void) { int main(void) {
array_mpz_t a; array_mpz_t a;
@@ -2339,7 +2346,7 @@ Example:
#include "m-deque.h" #include "m-deque.h"
DEQUE_DEF(deque_mpz, mpz_t, \ DEQUE_DEF(deque_mpz, mpz_t, \
(INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear))) (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear), INIT_MOVE(M_COPY_A1_DEFAULT)))
int main(void) { int main(void) {
deque_mpz_t a; deque_mpz_t a;
+2
View File
@@ -99,3 +99,5 @@ V0.8.0 : * The prototypes of REALLOC / FREE operators are incompatible:
* m-buffer push / pop no longer return a bool (it was undocumented) * m-buffer push / pop no longer return a bool (it was undocumented)
* Remove MEMPOOL support from list & R/B tree * Remove MEMPOOL support from list & R/B tree
* m-mempool: Header is obsolete (and no longer useful at all as lists & RB Tree no longer can use it. To remove?). Use new M_USE_POOL interface to pass local pool context. * m-mempool: Header is obsolete (and no longer useful at all as lists & RB Tree no longer can use it. To remove?). Use new M_USE_POOL interface to pass local pool context.
* M*LIB becomes stricter for INIT_MOVE: Emulation layer using CLEAR+INIT_SET when missing INIT_MOVE operator has been removed: either default INIT_MOVE operator (operator '=') is working, or a methode is provided for INIT_MOVE or it is disabled.
(It's because supporting emulation layer with new memory context parameter was complicated)
+3 -3
View File
@@ -1,7 +1,7 @@
*Long term issues* *Long term issues*
========================================================== ==========================================================
* TODO #34 : Pass old size arguments to memory allocator :ENHANCEMENT: * DONE #34 : Pass old size arguments to memory allocator :ENHANCEMENT:
** State ** State
@@ -53,7 +53,7 @@ function due to the copy of the object one per one. Each copied sub object
may throw an exception, so we always need to have the container in a correct may throw an exception, so we always need to have the container in a correct
state so that it can be cleanup. state so that it can be cleanup.
* TODO #32 : User specialization fields in the container :ENHANCEMENT: * DONE #32 : User specialization fields in the container :ENHANCEMENT:
** State ** State
Some methods of a contained object may need to have some options that Some methods of a contained object may need to have some options that
@@ -452,7 +452,7 @@ as DPRIORITY_QUEUE_DEF ?
NOTE: Needs for such container? NOTE: Needs for such container?
On hold until a user needs it. On hold until a user needs it.
* TODO #23 : Strict MOVE semantic to clarify :ENHANCEMENT: * DONE #23 : Strict MOVE semantic to clarify :ENHANCEMENT:
** State ** State
+3 -1
View File
@@ -35,6 +35,7 @@ mpz_fast_hash(const mpz_t z)
#define M_OPL_mpz_t() \ #define M_OPL_mpz_t() \
(INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear), \ (INIT(mpz_init), INIT_SET(mpz_init_set), SET(mpz_set), CLEAR(mpz_clear), \
INIT_WITH(API_1(M_INIT_WITH_THROUGH_EMPLACE_TYPE)), \ INIT_WITH(API_1(M_INIT_WITH_THROUGH_EMPLACE_TYPE)), \
INIT_MOVE(M_COPY_A1_DEFAULT) \
EQUAL( API( mpz_cmp, EQ(0), ARG1, ARG2)), \ EQUAL( API( mpz_cmp, EQ(0), ARG1, ARG2)), \
CMP(mpz_cmp), \ CMP(mpz_cmp), \
HASH(mpz_fast_hash), \ HASH(mpz_fast_hash), \
@@ -77,7 +78,8 @@ mpfr_fast_hash (const mpfr_t f)
/* Define the OPLIST of a mpfr_t and register it globally */ /* Define the OPLIST of a mpfr_t and register it globally */
#define M_OPL_mpfr_t() \ #define M_OPL_mpfr_t() \
(INIT(mpfr_init), INIT_SET(API(mpfr_init_set, VOID, ARG1, ARG2, MPFR_RNDN)), SET(API(mpfr_set, VOID, ARG1, ARG2, MPFR_RNDN)), CLEAR(mpfr_clear), \ (INIT(mpfr_init), INIT_SET(API(mpfr_init_set, VOID, ARG1, ARG2, MPFR_RNDN)), SET(API(mpfr_set, VOID, ARG1, ARG2, MPFR_RNDN)), CLEAR(mpfr_clear), \
INIT_WITH(API_1(M_INIT_WITH_THROUGH_EMPLACE_TYPE)), \ INIT_WITH(API_1(M_INIT_WITH_THROUGH_EMPLACE_TYPE)), \
INIT_MOVE(M_COPY_A1_DEFAULT) \
EQUAL( API( mpfr_cmp, EQ(0), ARG1, ARG2)), \ EQUAL( API( mpfr_cmp, EQ(0), ARG1, ARG2)), \
CMP(mpfr_cmp), \ CMP(mpfr_cmp), \
HASH(mpfr_fast_hash), \ HASH(mpfr_fast_hash), \
+7 -22
View File
@@ -173,7 +173,6 @@
#define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \ #define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \
M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \ M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \ M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
/* TODO: Check if type has not disabled INIT_MOVE */ \
M_ARRA4_DEF_CORE(name, type, oplist, array_t, it_t) \ M_ARRA4_DEF_CORE(name, type, oplist, array_t, it_t) \
M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \ M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \
M_EMPLACE_QUEUE_DEF(name, array_t, _emplace_back, oplist, M_ARRA4_EMPLACE_DEF) M_EMPLACE_QUEUE_DEF(name, array_t, _emplace_back, oplist, M_ARRA4_EMPLACE_DEF)
@@ -365,16 +364,14 @@
} \ } \
, /* No INIT */ ) \ , /* No INIT */ ) \
\ \
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \
M_P(void, name, _push_move, array_t v, type *x) \ M_P(void, name, _push_move, array_t v, type *x) \
{ \ { \
M_ASSERT (x != NULL); \ M_ASSERT (x != NULL); \
type *data = M_F(name, _push_raw) M_R(v); \ type *data = M_F(name, _push_raw) M_R(v); \
if (M_UNLIKELY (data == NULL) ) \ if (M_UNLIKELY (data == NULL) ) \
return; \ return; \
M_DO_INIT_MOVE (oplist, *data, *x); \ M_CALL_INIT_MOVE (oplist, *data, *x); \
} \ } \
, /* INIT_SET | INIT_MOVE */ ) \
\ \
M_IF_METHOD(INIT_SET, oplist)( \ M_IF_METHOD(INIT_SET, oplist)( \
M_P(void, name, _push_at, array_t v, size_t key, type const x) \ M_P(void, name, _push_at, array_t v, size_t key, type const x) \
@@ -490,7 +487,6 @@
} \ } \
, /* No INIT */) \ , /* No INIT */) \
\ \
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
M_P(void, name, _pop_back, type *dest, array_t v) \ M_P(void, name, _pop_back, type *dest, array_t v) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
@@ -505,11 +501,7 @@
} \ } \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
, /* SET | INIT_MOVE */ ) \
\ \
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \
/* FIXME: type has to be trivially movable (imposed by array) ! */ \
/* FIXME: Really allocation or allocation free? */ \
M_INLINE void \ M_INLINE void \
M_F(name, _pop_move)(type *dest, array_t v) \ M_F(name, _pop_move)(type *dest, array_t v) \
{ \ { \
@@ -518,11 +510,9 @@
M_ASSERT_INDEX(0, v->size); \ M_ASSERT_INDEX(0, v->size); \
M_ASSERT (dest != NULL); \ M_ASSERT (dest != NULL); \
v->size--; \ v->size--; \
/* FIXME: M_DO_INIT_MOVE may use INIT_SET so allocator !*/ \ M_CALL_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \
M_DO_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
, /* INIT_SET | INIT_MOVE */ ) \
\ \
/* TODO: Factorize all INIT dependent methods within the same IF*/ \ /* TODO: Factorize all INIT dependent methods within the same IF*/ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
@@ -556,14 +546,12 @@
return v->alloc; \ return v->alloc; \
} \ } \
\ \
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
M_P(void, name, _pop_at, type *dest, array_t v, size_t i) \ M_P(void, name, _pop_at, type *dest, array_t v, size_t i) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \ M_ASSERT_POOL(); \
M_ASSERT (v->size > 0 && v->ptr != NULL); \ M_ASSERT (v->size > 0 && v->ptr != NULL); \
M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(i, v->size); \
/* FIXME: type is trivially movable */ \
if (dest) \ if (dest) \
M_DO_MOVE (oplist, *dest, v->ptr[i]); \ M_DO_MOVE (oplist, *dest, v->ptr[i]); \
else \ else \
@@ -580,7 +568,6 @@
M_F(name, _pop_at) M_R(NULL, a, i); \ M_F(name, _pop_at) M_R(NULL, a, i); \
return true; \ return true; \
} \ } \
, /* SET | INIT_MOVE */ ) \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_P(void, name, _insert_v, array_t v, size_t i, size_t num) \ M_P(void, name, _insert_v, array_t v, size_t i, size_t num) \
@@ -644,7 +631,6 @@
M_ARRA4_CONTRACT(v2); \ M_ARRA4_CONTRACT(v2); \
} \ } \
\ \
M_IF_AT_LEAST_METHOD(INIT_SET,INIT_MOVE,oplist) ( \
M_INLINE void \ M_INLINE void \
M_F(name, _swap_at)(array_t v, size_t i, size_t j) \ M_F(name, _swap_at)(array_t v, size_t i, size_t j) \
{ \ { \
@@ -653,12 +639,11 @@
M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(i, v->size); \
M_ASSERT_INDEX(j, v->size); \ M_ASSERT_INDEX(j, v->size); \
type tmp; \ type tmp; \
M_DO_INIT_MOVE(oplist, tmp, v->ptr[i]); \ M_CALL_INIT_MOVE(oplist, tmp, v->ptr[i]); \
M_DO_INIT_MOVE(oplist, v->ptr[i], v->ptr[j]); \ M_CALL_INIT_MOVE(oplist, v->ptr[i], v->ptr[j]); \
M_DO_INIT_MOVE(oplist, v->ptr[j], tmp); \ M_CALL_INIT_MOVE(oplist, v->ptr[j], tmp); \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
, /* INIT_SET | INIT_MOVE */ ) \
\ \
M_INLINE type * \ M_INLINE type * \
M_F(name, _get)(const array_t v, size_t i) \ M_F(name, _get)(const array_t v, size_t i) \
@@ -849,7 +834,7 @@
k += n1+n2; \ k += n1+n2; \
for (;;) { \ for (;;) { \
if (M_CALL_CMP(oplist, *el1, *el2) <= 0) { \ if (M_CALL_CMP(oplist, *el1, *el2) <= 0) { \
M_DO_INIT_MOVE(oplist, *dest, *el1); \ M_CALL_INIT_MOVE(oplist, *dest, *el1); \
dest++; \ dest++; \
el1++; \ el1++; \
if (M_UNLIKELY(-- n1 == 0)) { \ if (M_UNLIKELY(-- n1 == 0)) { \
@@ -860,7 +845,7 @@
break; \ break; \
} \ } \
} else { \ } else { \
M_DO_INIT_MOVE(oplist, *dest, *el2); \ M_CALL_INIT_MOVE(oplist, *dest, *el2); \
dest++; \ dest++; \
el2++; \ el2++; \
if (M_UNLIKELY(-- n2 == 0)) { \ if (M_UNLIKELY(-- n2 == 0)) { \
+6 -6
View File
@@ -541,7 +541,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *data, v->data[v->idx_cons].x); \ M_CALL_SET(oplist, *data, v->data[v->idx_cons].x); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_cons].x); \ M_CALL_INIT_MOVE (oplist, *data, v->data[v->idx_cons].x); \
} \ } \
v->idx_cons = (v->idx_cons == M_BUFF3R_SIZE(m_size)-1) ? 0 : (v->idx_cons + 1); \ v->idx_cons = (v->idx_cons == M_BUFF3R_SIZE(m_size)-1) ? 0 : (v->idx_cons + 1); \
} else { \ } else { \
@@ -550,7 +550,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *data, v->data[v->idx_prod].x); \ M_CALL_SET(oplist, *data, v->data[v->idx_prod].x); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *data, v->data[v->idx_prod].x); \ M_CALL_INIT_MOVE (oplist, *data, v->data[v->idx_prod].x); \
} \ } \
} \ } \
\ \
@@ -767,7 +767,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *ptr, table->Tab[i].x); \ M_CALL_SET(oplist, *ptr, table->Tab[i].x); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \ M_CALL_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \
} \ } \
atomic_store_explicit(&table->Tab[i].seq, 2*iC + 1, memory_order_release); \ atomic_store_explicit(&table->Tab[i].seq, 2*iC + 1, memory_order_release); \
M_QU3UE_MPMC_CONTRACT(table); \ M_QU3UE_MPMC_CONTRACT(table); \
@@ -971,7 +971,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_DO_MOVE(oplist, table->Tab[i].x, *x); \ M_DO_MOVE(oplist, table->Tab[i].x, *x); \
} else { \ } else { \
M_DO_INIT_MOVE(oplist, table->Tab[i].x, *x); \ M_CALL_INIT_MOVE(oplist, table->Tab[i].x, *x); \
} \ } \
atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \ atomic_store_explicit(&table->prodIdx, w+1, memory_order_release); \
M_QU3UE_SPSC_CONTRACT(table); \ M_QU3UE_SPSC_CONTRACT(table); \
@@ -993,7 +993,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, *ptr , table->Tab[i].x); \ M_CALL_SET(oplist, *ptr , table->Tab[i].x); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \ M_CALL_INIT_MOVE (oplist, *ptr, table->Tab[i].x); \
} \ } \
atomic_store_explicit(&table->consoIdx, r+1, memory_order_release); \ atomic_store_explicit(&table->consoIdx, r+1, memory_order_release); \
M_QU3UE_SPSC_CONTRACT(table); \ M_QU3UE_SPSC_CONTRACT(table); \
@@ -1044,7 +1044,7 @@ M_N(void, name, _init, buffer_t v, size_t size) \
if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \ if (!M_BUFF3R_POLICY_P((policy), M_BUFFER_PUSH_INIT_POP_MOVE)) { \
M_CALL_SET(oplist, ptr[k], table->Tab[i].x); \ M_CALL_SET(oplist, ptr[k], table->Tab[i].x); \
} else { \ } else { \
M_DO_INIT_MOVE (oplist, ptr[k], table->Tab[i].x); \ M_CALL_INIT_MOVE (oplist, ptr[k], table->Tab[i].x); \
} \ } \
} \ } \
atomic_store_explicit(&table->consoIdx, r+max, memory_order_release); \ atomic_store_explicit(&table->consoIdx, r+max, memory_order_release); \
+43 -56
View File
@@ -3545,7 +3545,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
/* Get the given method */ /* Get the given method */
#define M_GET_INIT(...) M_GET_METHOD(INIT, M_INIT_DEFAULT, __VA_ARGS__) #define M_GET_INIT(...) M_GET_METHOD(INIT, M_INIT_DEFAULT, __VA_ARGS__)
#define M_GET_INIT_SET(...) M_GET_METHOD(INIT_SET, M_SET_DEFAULT, __VA_ARGS__) #define M_GET_INIT_SET(...) M_GET_METHOD(INIT_SET, M_SET_DEFAULT, __VA_ARGS__)
#define M_GET_INIT_MOVE(...) M_GET_METHOD(INIT_MOVE, M_NO_DEF_INIT_MOVE, __VA_ARGS__) #define M_GET_INIT_MOVE(...) M_GET_METHOD(INIT_MOVE, M_SET_DEFAULT, __VA_ARGS__)
#define M_GET_INIT_WITH(...) M_GET_METHOD(INIT_WITH, M_NO_DEF_INIT_WITH, __VA_ARGS__) #define M_GET_INIT_WITH(...) M_GET_METHOD(INIT_WITH, M_NO_DEF_INIT_WITH, __VA_ARGS__)
#define M_GET_SET(...) M_GET_METHOD(SET, M_SET_DEFAULT, __VA_ARGS__) #define M_GET_SET(...) M_GET_METHOD(SET, M_SET_DEFAULT, __VA_ARGS__)
#define M_GET_MOVE(...) M_GET_METHOD(MOVE, M_NO_DEF_MOVE, __VA_ARGS__) #define M_GET_MOVE(...) M_GET_METHOD(MOVE, M_NO_DEF_MOVE, __VA_ARGS__)
@@ -3869,12 +3869,6 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
"The " #operator " operator has no method associated in the given OPLIST."),\ "The " #operator " operator has no method associated in the given OPLIST."),\
(return_type) 0) (return_type) 0)
// TODO: Use default INIT_MOVE which assume trivially movable type
// by getting throught API_2 the oplist and the size of the type
// If no type defined and no INIT_MOVE defined, just use sizeof (dst)
// Most types are trivially movable. Can remove macro M_DO_INIT_MOVE to use M_CALL_INIT_MOVE
// If disabled in oplist, M_CALL_INIT_MOVE will generate an error.
#define M_NO_DEF_INIT_MOVE(...) M_NO_DEFAULT(INIT_MOVE, void)
#define M_NO_DEF_INIT_WITH(...) M_NO_DEFAULT(INIT_WITH, void) #define M_NO_DEF_INIT_WITH(...) M_NO_DEFAULT(INIT_WITH, void)
#define M_NO_DEF_MOVE(...) M_NO_DEFAULT(MOVE, void) #define M_NO_DEF_MOVE(...) M_NO_DEFAULT(MOVE, void)
#define M_NO_DEF_SWAP(...) M_NO_DEFAULT(SWAP, void) #define M_NO_DEF_SWAP(...) M_NO_DEFAULT(SWAP, void)
@@ -4063,9 +4057,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
/* NOTE: Theses operators are NOT compatible with the '[1]' tricks /* NOTE: Theses operators are NOT compatible with the '[1]' tricks
if the variable is defined as a parameter of a function if the variable is defined as a parameter of a function
(sizeof (a) is not portable). */ (sizeof (a) is not portable). */
#define M_MOVE_DEFAULT(a,b) (M_CHECK_SAME(a, b), M_MEMCPY_DEFAULT(a, b), memset(&(b), 0, sizeof (a))) #define M_RESET_DEFAULT(a) (memset(&(a), 0, sizeof (a)))
#define M_MEMCPY_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcpy(&(a), &(b), sizeof (a)))
#define M_MEMSET_DEFAULT(a) (memset(&(a), 0, sizeof (a)))
#define M_MEMCMP1_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a)) == 0) #define M_MEMCMP1_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a)) == 0)
#define M_MEMCMP2_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a))) #define M_MEMCMP2_DEFAULT(a,b) (M_CHECK_SAME(a, b), memcmp(&(a), &(b), sizeof (a)))
#define M_SWAP_DEFAULT(el1, el2) do { \ #define M_SWAP_DEFAULT(el1, el2) do { \
@@ -4076,28 +4068,35 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
memcpy(&(el2), &_tmp, sizeof (el1)); \ memcpy(&(el2), &_tmp, sizeof (el1)); \
} while (0) } while (0)
/* Default oplist for plain structure */
#define M_POD_OPLIST \
(INIT(M_RESET_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
EQUAL(M_MEMCMP1_DEFAULT), CMP(M_MEMCMP2_DEFAULT), HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \
INIT_MOVE(M_SET_DEFAULT) )
/* NOTE: Theses operators are to be used with the '[1]' tricks /* NOTE: Theses operators are to be used with the '[1]' tricks
if the variable is defined as a parameter of a function if the variable is defined as a parameter of a function
(sizeof (a) is not portable). */ (sizeof (a) is not portable). */
#define M_MOVE_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0], b[0]), M_MEMCPY_A1_DEFAULT(a, b), M_MEMSET_A1_DEFAULT(b)) #define M_COPY_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0], b[0]), memcpy(&(a[0]), &(b[0]), sizeof (a[0])))
#define M_MEMCPY_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0], b[0]), memcpy(&(a[0]), &(b[0]), sizeof (a[0]))) #define M_RESET_A1_DEFAULT(a) (memset(&(a[0]), 0, sizeof (a[0])))
#define M_MEMSET_A1_DEFAULT(a) (memset(&(a[0]), 0, sizeof (a[0])))
#define M_MEMCMP1_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0],b[0]), memcmp(&(a[0]), &(b[0]), sizeof (a[0])) == 0) #define M_MEMCMP1_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0],b[0]), memcmp(&(a[0]), &(b[0]), sizeof (a[0])) == 0)
#define M_MEMCMP2_A1_DEFAULT(a,b) (M_CHECK_SAME(a[0], b[0]), memcmp(&(a[0]), &(b[0]), sizeof (a[0]))) #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])) ) #define M_HASH_A1_DEFAULT(a) (m_core_hash((const void*) &(a[0]), sizeof (a[0])) )
#define M_SWAP_A1_DEFAULT(a, b) do { \
char _tmp[sizeof (a[0])]; \
M_CHECK_SAME(a[0], b[0]); \
memcpy(&_tmp, &(a[0]), sizeof (a[0])); \
memcpy(&(a[0]), &(b[0]), sizeof (a[0])); \
memcpy(&(b[0]), &_tmp, sizeof (a[0])); \
} while (0)
/* Default oplist for plain structure */ /* Default oplist for a structure defined with an array of size 1.
#define M_POD_OPLIST \ MOVE operator is not defined since the object may need to release some data */
(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 \ #define M_A1_OPLIST \
(INIT(M_MEMSET_A1_DEFAULT), INIT_SET(M_MEMCPY_A1_DEFAULT), SET(M_MEMCPY_A1_DEFAULT), \ (INIT(M_RESET_A1_DEFAULT), INIT_SET(M_COPY_A1_DEFAULT), SET(M_COPY_A1_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_MEMCMP1_A1_DEFAULT), CMP(M_MEMCMP2_A1_DEFAULT), \ EQUAL(M_MEMCMP1_A1_DEFAULT), CMP(M_MEMCMP2_A1_DEFAULT), HASH(M_HASH_A1_DEFAULT), SWAP(M_SWAP_A1_DEFAULT), \
HASH(M_HASH_A1_DEFAULT)) INIT_MOVE(M_COPY_A1_DEFAULT) )
/* Oplist for a type that does nothing and shall not be instanciated */ /* Oplist for a type that does nothing and shall not be instanciated */
@@ -4122,7 +4121,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
# define M_BASIC_OPLIST \ # define M_BASIC_OPLIST \
(INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \ (INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \ CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) , \
RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \ RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \
ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \ ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \
MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \ MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \
@@ -4135,7 +4134,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
# define M_BASIC_OPLIST \ # define M_BASIC_OPLIST \
(INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \ (INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \ CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) , \
RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \ RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \
ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \ ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \
MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \ MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \
@@ -4148,7 +4147,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
# define M_BASIC_OPLIST \ # define M_BASIC_OPLIST \
(INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \ (INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \ CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_BASIC), CMP(M_CMP_BASIC), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) , \
RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \ RESET(M_INIT_BASIC), PROPERTIES( (NOCLEAR(1)) ), \
ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \ ADD(M_ADD_DEFAULT), SUB(M_SUB_DEFAULT), \
MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \ MUL(M_MUL_DEFAULT), DIV(M_DIV_DEFAULT), \
@@ -4179,7 +4178,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
(INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \ (INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \
SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \ SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \ EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) , \
HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \ HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \
TYPE(type), OPLIST(init), \ TYPE(type), OPLIST(init), \
IN_STR(API_1(M_ENUM_FSCAN)), OUT_STR(M_ENUM_FPRINT), \ IN_STR(API_1(M_ENUM_FSCAN)), OUT_STR(M_ENUM_FPRINT), \
@@ -4192,7 +4191,7 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
(INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \ (INIT(API_1(M_ENUM_INIT)), INIT_SET(M_SET_DEFAULT), \
SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \ SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \ EQUAL(M_EQUAL_DEFAULT), CMP(M_CMP_DEFAULT), \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) , \
HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \ HASH(M_HASH_POD_DEFAULT), SWAP(M_SWAP_DEFAULT), \
TYPE(type), OPLIST(init), \ TYPE(type), OPLIST(init), \
IN_SERIAL(API_1(M_ENUM_IN_SERIAL)), OUT_SERIAL(M_ENUM_OUT_SERIAL), \ IN_SERIAL(API_1(M_ENUM_IN_SERIAL)), OUT_SERIAL(M_ENUM_OUT_SERIAL), \
@@ -4255,32 +4254,29 @@ m_core_parse2_enum (const char str[], const char **endptr)
/* Default oplist for standard types of pointers. /* Default oplist for standard types of pointers.
*/ */
#define M_PTR_OPLIST \ #define M_PTR_OPLIST \
(INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), \ (INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
CLEAR(M_NOTHING_DEFAULT), EQUAL(M_EQUAL_DEFAULT), \ EQUAL(M_EQUAL_DEFAULT), SWAP(M_SWAP_DEFAULT) \
INIT_MOVE(M_MOVE_DEFAULT), MOVE(M_MOVE_DEFAULT) , \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT) )
SWAP(M_SWAP_DEFAULT) )
/* Default oplist for complex objects with "classic" names for methods. /* Default oplist for complex objects (using [1] trick) with "classic" names for methods.
*/ */
#define M_CLASSIC_OPLIST(name) ( \ #define M_CLASSIC_OPLIST(name) ( \
INIT(M_F(name, _init)), \ INIT(M_F(name, _init)), INIT_SET(M_F(name, _init_set)), SET(M_F(name, _set)), CLEAR(M_F(name, _clear)), \
INIT_SET(M_F(name, _init_set)), \ INIT_MOVE(M_COPY_A1_DEFAULT), TYPE(M_F(name, _t)) )
SET(M_F(name, _set)), \
CLEAR(M_F(name, _clear)), \
TYPE(M_F(name, _t)) )
/* OPLIST for 'const char *' string (with NO memory allocation). /* Default oplist for 'const char *' string (with NO memory allocation).
*/ */
#define M_CSTR_EQUAL(a,b) (strcmp((a),(b)) == 0) #define M_CSTR_EQUAL(a,b) (strcmp((a),(b)) == 0)
#define M_CSTR_OUT_STR(file, str) fprintf(file, "%s", str) #define M_CSTR_OUT_STR(file, str) fprintf(file, "%s", str)
#define M_CSTR_OPLIST (INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), \ #define M_CSTR_OPLIST \
SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \ (INIT(M_INIT_DEFAULT), INIT_SET(M_SET_DEFAULT), SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT), \
HASH(m_core_cstr_hash), EQUAL(M_CSTR_EQUAL), \ HASH(m_core_cstr_hash), EQUAL(M_CSTR_EQUAL), CMP(strcmp), SWAP(M_SWAP_DEFAULT), \
CMP(strcmp), TYPE(const char *), \ INIT_MOVE(M_SET_DEFAULT), MOVE(M_SET_DEFAULT), TYPE(const char *), \
OUT_STR(M_CSTR_OUT_STR) ) OUT_STR(M_CSTR_OUT_STR) )
/****************************************************************************/
/* From an oplist (...) return ... (Like M_ID but for OPLIST) */ /* From an oplist (...) return ... (Like M_ID but for OPLIST) */
#define M_OPFLAT(...) __VA_ARGS__ #define M_OPFLAT(...) __VA_ARGS__
@@ -4365,15 +4361,6 @@ m_core_parse2_enum (const char str[], const char **endptr)
so that the first argument becomes a pointer to the destination (OBSOLETE MACRO) */ so that the first argument becomes a pointer to the destination (OBSOLETE MACRO) */
#define M_IPTR(...) ( & __VA_ARGS__ ) #define M_IPTR(...) ( & __VA_ARGS__ )
/* Perform an INIT_MOVE if present, or emulate it using INIT_SET/CLEAR */
/* FIXME: Use INIT_MOVE if present or assume trivially movable otherwise? */
/* A non trivially movable type shall provide an INIT_MOVE method or disable it */
#define M_DO_INIT_MOVE(oplist, dest, src) do { \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_INIT_SET(oplist, (dest), (src)) ; \
M_CALL_CLEAR(oplist, (src) )); \
} while (0)
/* Perform a MOVE if present, or emulate it using CLEAR/INIT_MOVE /* Perform a MOVE if present, or emulate it using CLEAR/INIT_MOVE
if possible, or with SET/CLEAR otherwise */ if possible, or with SET/CLEAR otherwise */
#define M_DO_MOVE(oplist, dest, src) do { \ #define M_DO_MOVE(oplist, dest, src) do { \
@@ -4756,8 +4743,8 @@ m_core_parse2_enum (const char str[], const char **endptr)
so it reverses the final order. so it reverses the final order.
*/ */
#define M_INIT_VAI(oplist, dest, ...) \ #define M_INIT_VAI(oplist, dest, ...) \
(void)(M_CALL_INIT(oplist, dest) , \ (void)(M_CALL_INIT(oplist, dest) , \
M_MAP2_C(M_INIT_VAI_FUNC, (dest, oplist) , __VA_ARGS__) \ M_MAP2_C(M_INIT_VAI_FUNC, (dest, oplist) , __VA_ARGS__) \
M_IF_METHOD(REVERSE, oplist)(M_DEFERRED_COMMA M_CALL_REVERSE(oplist, dest), ) \ M_IF_METHOD(REVERSE, oplist)(M_DEFERRED_COMMA M_CALL_REVERSE(oplist, dest), ) \
) )
#define M_INIT_VAI_FUNC(d, a) \ #define M_INIT_VAI_FUNC(d, a) \
+2 -2
View File
@@ -309,7 +309,7 @@
{ \ { \
M_ASSERT (x != NULL); \ M_ASSERT (x != NULL); \
type *p = M_F(name, _push_back_raw)M_R(d); \ type *p = M_F(name, _push_back_raw)M_R(d); \
M_DO_INIT_MOVE (oplist, *p, *x); \ M_CALL_INIT_MOVE (oplist, *p, *x); \
} \ } \
\ \
M_P(type *, name, _push_front_raw, deque_t d) \ M_P(type *, name, _push_front_raw, deque_t d) \
@@ -358,7 +358,7 @@
{ \ { \
M_ASSERT (x != NULL); \ M_ASSERT (x != NULL); \
type *p = M_F(name, _push_front_raw)M_R(d); \ type *p = M_F(name, _push_front_raw)M_R(d); \
M_DO_INIT_MOVE (oplist, *p, *x); \ M_CALL_INIT_MOVE (oplist, *p, *x); \
} \ } \
\ \
M_P(void, name, _pop_back, type *ptr, deque_t d) \ M_P(void, name, _pop_back, type *ptr, deque_t d) \
+12 -12
View File
@@ -1421,8 +1421,8 @@ enum m_d1ct_oa_element_e {
\ \
/* NOTE: We don't want a real oplist for this sub type */ \ /* NOTE: We don't want a real oplist for this sub type */ \
M_ARRAY_DEF(M_F(name, _array_pair), M_F(name, _pair_ct), \ M_ARRAY_DEF(M_F(name, _array_pair), M_F(name, _pair_ct), \
(INIT(M_NOTHING_DEFAULT), SET(M_MEMCPY_DEFAULT), \ (INIT(M_NOTHING_DEFAULT), SET(M_SET_DEFAULT), \
INIT_SET(M_MEMCPY_DEFAULT), CLEAR(M_NOTHING_DEFAULT))) \ INIT_SET(M_SET_DEFAULT), CLEAR(M_NOTHING_DEFAULT))) \
\ \
typedef struct M_F(name,_s) { \ typedef struct M_F(name,_s) { \
size_t mask, count, count_delete; \ size_t mask, count, count_delete; \
@@ -1576,12 +1576,12 @@ enum m_d1ct_oa_element_e {
if (p != i) { \ if (p != i) { \
if (M_LIKELY (M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) \ if (M_LIKELY (M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) \
|| M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_DELETED))) { \ || M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_DELETED))) { \
M_DO_INIT_MOVE(key_oplist, data[p].key, data[i].key); \ M_CALL_INIT_MOVE(key_oplist, data[p].key, data[i].key); \
M_DO_INIT_MOVE(value_oplist, data[p].value, data[i].value); \ M_CALL_INIT_MOVE(value_oplist, data[p].value, data[i].value); \
} else { \ } else { \
M_F(name, _pair_ct) *ptr = M_F(name, _array_pair_push_raw)M_R(tmp); \ M_F(name, _pair_ct) *ptr = M_F(name, _array_pair_push_raw)M_R(tmp); \
M_DO_INIT_MOVE(key_oplist, ptr->key, data[i].key); \ M_CALL_INIT_MOVE(key_oplist, ptr->key, data[i].key); \
M_DO_INIT_MOVE(value_oplist, ptr->value, data[i].value); \ M_CALL_INIT_MOVE(value_oplist, ptr->value, data[i].value); \
} \ } \
M_CALL_OOR_SET(key_oplist, data[i].key, M_D1CT_OA_EMPTY); \ M_CALL_OOR_SET(key_oplist, data[i].key, M_D1CT_OA_EMPTY); \
} \ } \
@@ -1750,12 +1750,12 @@ enum m_d1ct_oa_element_e {
if (p != i) { \ if (p != i) { \
if (M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) \ if (M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) \
|| M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_DELETED)) { \ || M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_DELETED)) { \
M_DO_INIT_MOVE(key_oplist, data[p].key, data[i].key); \ M_CALL_INIT_MOVE(key_oplist, data[p].key, data[i].key); \
M_DO_INIT_MOVE(value_oplist, data[p].value, data[i].value); \ M_CALL_INIT_MOVE(value_oplist, data[p].value, data[i].value); \
} else { \ } else { \
M_F(name, _pair_ct) *ptr = M_F(name, _array_pair_push_raw)M_R(tmp); \ M_F(name, _pair_ct) *ptr = M_F(name, _array_pair_push_raw)M_R(tmp); \
M_DO_INIT_MOVE(key_oplist, ptr->key, data[i].key); \ M_CALL_INIT_MOVE(key_oplist, ptr->key, data[i].key); \
M_DO_INIT_MOVE(value_oplist, ptr->value, data[i].value); \ M_CALL_INIT_MOVE(value_oplist, ptr->value, data[i].value); \
} \ } \
M_CALL_OOR_SET(key_oplist, data[i].key, M_D1CT_OA_EMPTY); \ M_CALL_OOR_SET(key_oplist, data[i].key, M_D1CT_OA_EMPTY); \
} \ } \
@@ -1773,8 +1773,8 @@ enum m_d1ct_oa_element_e {
M_ASSERT (s <= h->mask); \ M_ASSERT (s <= h->mask); \
} while (!M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) ); \ } while (!M_CALL_OOR_EQUAL(key_oplist, data[p].key, M_D1CT_OA_EMPTY) ); \
} \ } \
M_DO_INIT_MOVE(key_oplist, data[p].key, data[i].key); \ M_CALL_INIT_MOVE(key_oplist, data[p].key, data[i].key); \
M_DO_INIT_MOVE(value_oplist, data[p].value, data[i].value); \ M_CALL_INIT_MOVE(value_oplist, data[p].value, data[i].value); \
} \ } \
} \ } \
/* Pass 3: scan moved entries and move them back */ \ /* Pass 3: scan moved entries and move them back */ \
+5 -5
View File
@@ -307,14 +307,14 @@
type *data = M_F(name, _push_raw)M_R(v); \ type *data = M_F(name, _push_raw)M_R(v); \
if (M_UNLIKELY (data == NULL)) \ if (M_UNLIKELY (data == NULL)) \
return; \ return; \
M_DO_INIT_MOVE (oplist, *data, *x); \ M_CALL_INIT_MOVE (oplist, *data, *x); \
} \ } \
\ \
M_P(void, name, _pop_move, type *data, list_t v) \ M_P(void, name, _pop_move, type *data, list_t v) \
{ \ { \
M_L1ST_CONTRACT(v); \ M_L1ST_CONTRACT(v); \
M_ASSERT(*v != NULL && data != NULL); \ M_ASSERT(*v != NULL && data != NULL); \
M_DO_INIT_MOVE (oplist, *data, (*v)->data); \ M_CALL_INIT_MOVE (oplist, *data, (*v)->data); \
struct M_F(name, _s) *tofree = *v; \ struct M_F(name, _s) *tofree = *v; \
*v = (*v)->next; \ *v = (*v)->next; \
M_CALL_DEL(oplist, tofree); \ M_CALL_DEL(oplist, tofree); \
@@ -1057,7 +1057,7 @@
type *data = M_F(name, _push_back_raw)M_R(v); \ type *data = M_F(name, _push_back_raw)M_R(v); \
if (M_UNLIKELY (data == NULL)) \ if (M_UNLIKELY (data == NULL)) \
return; \ return; \
M_DO_INIT_MOVE (oplist, *data, *x); \ M_CALL_INIT_MOVE (oplist, *data, *x); \
} \ } \
\ \
M_P(void, name, _push_move, list_t v, type *x) \ M_P(void, name, _push_move, list_t v, type *x) \
@@ -1091,7 +1091,7 @@
M_ASSERT (v->back != NULL); \ M_ASSERT (v->back != NULL); \
M_ASSERT (data != NULL); \ M_ASSERT (data != NULL); \
struct M_F(name, _s) *tofree = v->back; \ struct M_F(name, _s) *tofree = v->back; \
M_DO_INIT_MOVE (oplist, *data, tofree->data); \ M_CALL_INIT_MOVE (oplist, *data, tofree->data); \
v->back = tofree->next; \ v->back = tofree->next; \
M_CALL_DEL(oplist, tofree); \ M_CALL_DEL(oplist, tofree); \
/* Update front too if the list became empty */ \ /* Update front too if the list became empty */ \
@@ -1149,7 +1149,7 @@
type *data = M_F(name, _push_front_raw)(v); \ type *data = M_F(name, _push_front_raw)(v); \
if (M_UNLIKELY (data == NULL)) \ if (M_UNLIKELY (data == NULL)) \
return; \ return; \
M_DO_INIT_MOVE (oplist, *data, *x); \ M_CALL_INIT_MOVE (oplist, *data, *x); \
} \ } \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
+1
View File
@@ -2357,6 +2357,7 @@ namespace m_lib {
INIT_SET(M_F(name,_init_set)), \ INIT_SET(M_F(name,_init_set)), \
SET(M_F(name,_set)), \ SET(M_F(name,_set)), \
CLEAR(M_F(name,_clear)), \ CLEAR(M_F(name,_clear)), \
INIT_MOVE(M_COPY_A1_DEFAULT), \
NAME(name), \ NAME(name), \
INIT_WITH( API_1(M_BOUNDED_STR1NG_INIT_WITH)), \ INIT_WITH( API_1(M_BOUNDED_STR1NG_INIT_WITH)), \
HASH(M_F(name,_hash)), \ HASH(M_F(name,_hash)), \
+5 -5
View File
@@ -476,7 +476,7 @@ typedef int32_t m_tr33_index_t;
\ \
M_P(it_t, name, _move_up, it_t pos, type *data) { \ M_P(it_t, name, _move_up, it_t pos, type *data) { \
it_t it = M_F(name, _insert_up_raw)M_R(pos); \ it_t it = M_F(name, _insert_up_raw)M_R(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \ M_CALL_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
M_TR33_IT_CONTRACT(it, true); \ M_TR33_IT_CONTRACT(it, true); \
return it; \ return it; \
} \ } \
@@ -510,7 +510,7 @@ typedef int32_t m_tr33_index_t;
\ \
M_P(it_t, name, _move_down, it_t pos, type *data) { \ M_P(it_t, name, _move_down, it_t pos, type *data) { \
it_t it = M_F(name, _insert_down_raw)M_R(pos); \ it_t it = M_F(name, _insert_down_raw)M_R(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \ M_CALL_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
M_TR33_IT_CONTRACT(it, true); \ M_TR33_IT_CONTRACT(it, true); \
return it; \ return it; \
} \ } \
@@ -544,7 +544,7 @@ typedef int32_t m_tr33_index_t;
\ \
M_P(it_t, name, _move_child, it_t pos, type *data) { \ M_P(it_t, name, _move_child, it_t pos, type *data) { \
it_t it = M_F(name, _insert_child_raw)M_R(pos); \ it_t it = M_F(name, _insert_child_raw)M_R(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \ M_CALL_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
M_TR33_IT_CONTRACT(it, true); \ M_TR33_IT_CONTRACT(it, true); \
return it; \ return it; \
} \ } \
@@ -581,7 +581,7 @@ typedef int32_t m_tr33_index_t;
\ \
M_P(it_t, name, _move_left, it_t pos, type *data) { \ M_P(it_t, name, _move_left, it_t pos, type *data) { \
it_t it = M_F(name, _insert_left_raw)M_R(pos); \ it_t it = M_F(name, _insert_left_raw)M_R(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \ M_CALL_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
M_TR33_IT_CONTRACT(it, true); \ M_TR33_IT_CONTRACT(it, true); \
return it; \ return it; \
} \ } \
@@ -612,7 +612,7 @@ typedef int32_t m_tr33_index_t;
\ \
M_P(it_t, name, _move_right, it_t pos, type *data) { \ M_P(it_t, name, _move_right, it_t pos, type *data) { \
it_t it = M_F(name, _insert_right_raw)M_R(pos); \ it_t it = M_F(name, _insert_right_raw)M_R(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \ M_CALL_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
M_TR33_IT_CONTRACT(it, true); \ M_TR33_IT_CONTRACT(it, true); \
return it; \ return it; \
} \ } \
+3 -3
View File
@@ -33,9 +33,9 @@ END_COVERAGE
#define ARRAY_UINT_OPLIST ARRAY_OPLIST(array_uint) #define ARRAY_UINT_OPLIST ARRAY_OPLIST(array_uint)
// Array with the minimum number of methods. // Array with the minimum number of methods.
ARRAY_DEF(array_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear))) ARRAY_DEF(array_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT) ))
ARRAY_DEF(array_min2_z, testobj_t, (INIT(testobj_init), CLEAR(testobj_clear))) ARRAY_DEF(array_min2_z, testobj_t, (INIT(testobj_init), CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT) ) )
ARRAY_DEF(array_min3_z, testobj_t, (CLEAR(testobj_clear))) ARRAY_DEF(array_min3_z, testobj_t, (CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT)))
ARRAY_DEF(array_ulong, uint64_t) ARRAY_DEF(array_ulong, uint64_t)
ARRAY_DEF(array_string, string_t) ARRAY_DEF(array_string, string_t)
+10 -23
View File
@@ -746,65 +746,54 @@ typedef struct { int b,c; } ts;
static void f_ti(ti x) static void f_ti(ti x)
{ {
ti y; ti y;
M_MOVE_A1_DEFAULT(y,x); M_COPY_A1_DEFAULT(y,x);
assert(y[0] == 9); assert(y[0] == 9);
assert(x[0] == 0);
} }
static void f_ts(ts x) static void f_ts(ts x)
{ {
ts y; ts y;
M_MOVE_DEFAULT(y,x); M_SET_DEFAULT(y,x);
assert(y.b == 2); assert(y.b == 2);
assert(y.c == 3); assert(y.c == 3);
assert(x.b == 0);
assert(x.c == 0);
} }
static void f_ts2(ts *x) static void f_ts2(ts *x)
{ {
ts y; ts y;
M_MOVE_DEFAULT(y,*x); M_SET_DEFAULT(y,*x);
assert(y.b == 2); assert(y.b == 2);
assert(y.c == 3); assert(y.c == 3);
assert(x->b == 0);
assert(x->c == 0);
} }
static void test_move_default(void) static void test_move_default(void)
{ {
int o, p; int o, p;
o = 9; o = 9;
M_MOVE_DEFAULT(p, o); M_SET_DEFAULT(p, o);
assert(p == 9); assert(p == 9);
assert(o == 0);
double u, k; double u, k;
k = -1.0; k = -1.0;
u = 9.5; u = 9.5;
M_MOVE_DEFAULT(k, u); M_SET_DEFAULT(k, u);
assert(k == 9.5); assert(k == 9.5);
assert(u == 0.0); // NOTE: memset(0) sets an IEEE-754 number to 0.0
int *ptr = &o, *m; int *ptr = &o, *m;
M_MOVE_DEFAULT(m, ptr); M_SET_DEFAULT(m, ptr);
assert( ptr == NULL); (void)m;
assert( m == &o);
ti x, y; ti x, y;
x[0] = 9; x[0] = 9;
M_MOVE_A1_DEFAULT(y, x); M_COPY_A1_DEFAULT(y, x);
assert(y[0] == 9); assert(y[0] == 9);
assert(x[0] == 0);
x[0] = 9; x[0] = 9;
f_ti(x); f_ti(x);
assert(x[0] == 0);
ts y2, x2 = { 2, 3}; ts y2, x2 = { 2, 3};
M_MOVE_DEFAULT(y2, x2); M_SET_DEFAULT(y2, x2);
assert(y2.b == 2 && y2.c == 3); assert(y2.b == 2 && y2.c == 3);
assert(x2.b == 0 && x2.c == 0);
x2.b = 2; x2.c = 3; x2.b = 2; x2.c = 3;
f_ts(x2); f_ts(x2);
@@ -812,8 +801,6 @@ static void test_move_default(void)
assert(x2.c == 3); assert(x2.c == 3);
f_ts2(&x2); f_ts2(&x2);
assert(x2.b == 0);
assert(x2.c == 0);
} }
static void test_builtin(void) static void test_builtin(void)
+1 -1
View File
@@ -35,7 +35,7 @@ END_COVERAGE
DEQUE_DEF(deque_mpz, testobj_t, TESTOBJ_OPLIST) DEQUE_DEF(deque_mpz, testobj_t, TESTOBJ_OPLIST)
// Deque with the minimum number of methods. // Deque with the minimum number of methods.
DEQUE_DEF(deque_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear))) DEQUE_DEF(deque_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT) ))
// Dequeue of an enumerate // Dequeue of an enumerate
typedef enum { typedef enum {
+2 -2
View File
@@ -35,8 +35,8 @@ LIST_DUAL_PUSH_DEF(list2_mpz, testobj_t, TESTOBJ_OPLIST)
#define LIST2_DOUBLE_OPLIST LIST_OPLIST(list2_double) #define LIST2_DOUBLE_OPLIST LIST_OPLIST(list2_double)
// Array with the minimum number of methods. // Array with the minimum number of methods.
LIST_DEF(list_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear))) LIST_DEF(list_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT) ))
LIST_DUAL_PUSH_DEF(list2_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear))) LIST_DUAL_PUSH_DEF(list2_min_z, testobj_t, (INIT_SET(testobj_init_set), SET(testobj_set), CLEAR(testobj_clear), INIT_MOVE(M_COPY_A1_DEFAULT)))
LIST_DEF(list_string, string_t) LIST_DEF(list_string, string_t)
#define M_OPL_list_string_t() LIST_OPLIST(list_string, STRING_OPLIST) #define M_OPL_list_string_t() LIST_OPLIST(list_string, STRING_OPLIST)
-5
View File
@@ -295,31 +295,26 @@ static void test_basic(void)
tree_move_up(it2, &data); tree_move_up(it2, &data);
tree_get_str(s, t, false); tree_get_str(s, t, false);
assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{2,[{1,[{5}]}]}]}]}]")); assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{2,[{1,[{5}]}]}]}]}]"));
assert(data == 0);
data = 11; data = 11;
tree_move_left(it2, &data); tree_move_left(it2, &data);
tree_get_str(s, t, false); tree_get_str(s, t, false);
assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{1,[{5}]}]}]}]}]")); assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{1,[{5}]}]}]}]}]"));
assert(data == 0);
data = 12; data = 12;
tree_move_right(it2, &data); tree_move_right(it2, &data);
tree_get_str(s, t, false); tree_get_str(s, t, false);
assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{1,[{5}]}]},{12}]}]}]")); assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{1,[{5}]}]},{12}]}]}]"));
assert(data == 0);
data = 13; data = 13;
tree_move_child(it2, &data); tree_move_child(it2, &data);
tree_get_str(s, t, false); tree_get_str(s, t, false);
assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{13},{1,[{5}]}]},{12}]}]}]")); assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{13},{1,[{5}]}]},{12}]}]}]"));
assert(data == 0);
data = 14; data = 14;
tree_move_down(it2, &data); tree_move_down(it2, &data);
tree_get_str(s, t, false); tree_get_str(s, t, false);
assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{14,[{13},{1,[{5}]}]}]},{12}]}]}]")); assert(string_equal_str_p(s, "[{0,[{-1,[{3}]},{10,[{11},{2,[{14,[{13},{1,[{5}]}]}]},{12}]}]}]"));
assert(data == 0);
tree_it_set(&it, root); tree_it_set(&it, root);
assert(tree_it_equal_p(it, root)); assert(tree_it_equal_p(it, root));
+1
View File
@@ -236,6 +236,7 @@ static inline size_t test_obj_except__hash(const test_obj_except__t z)
INIT_SET(test_obj_except__init_set), \ INIT_SET(test_obj_except__init_set), \
SET(test_obj_except__set), \ SET(test_obj_except__set), \
CLEAR(test_obj_except__clear), \ CLEAR(test_obj_except__clear), \
INIT_MOVE(M_COPY_A1_DEFAULT), \
TYPE(test_obj_except__t), \ TYPE(test_obj_except__t), \
ADD(test_obj_except__add), \ ADD(test_obj_except__add), \
OUT_STR(test_obj_except__out_str), \ OUT_STR(test_obj_except__out_str), \
+4 -2
View File
@@ -227,11 +227,12 @@ static inline void testobj_str(string_t str, const testobj_t z, bool append)
// This enables testing good macro expansion in OPLIST usage // This enables testing good macro expansion in OPLIST usage
#define testobj_clear_indirect(op, x) testobj_clear(x) #define testobj_clear_indirect(op, x) testobj_clear(x)
#define TESTOBJ_OPLIST \ #define TESTOBJ_OPLIST \
(INIT(testobj_init), \ (INIT(testobj_init), \
INIT_SET(testobj_init_set), \ INIT_SET(testobj_init_set), \
SET(testobj_set), \ SET(testobj_set), \
CLEAR(API_1(testobj_clear_indirect)), \ CLEAR(API_1(testobj_clear_indirect)), \
INIT_MOVE(M_COPY_A1_DEFAULT), \
TYPE(testobj_t), \ TYPE(testobj_t), \
OUT_STR(testobj_out_str), \ OUT_STR(testobj_out_str), \
IN_STR(testobj_in_str), \ IN_STR(testobj_in_str), \
@@ -242,11 +243,12 @@ static inline void testobj_str(string_t str, const testobj_t z, bool append)
EMPLACE_TYPE( LIST( (_ui, testobj_init_set_ui, unsigned int), (_str, testobj_init_set_str, const char *), ( /*empty*/, testobj_init_set, testobj_t) ) ) \ EMPLACE_TYPE( LIST( (_ui, testobj_init_set_ui, unsigned int), (_str, testobj_init_set_str, const char *), ( /*empty*/, testobj_init_set, testobj_t) ) ) \
) )
#define TESTOBJ_CMP_OPLIST \ #define TESTOBJ_CMP_OPLIST \
(INIT(testobj_init), \ (INIT(testobj_init), \
INIT_SET(testobj_init_set), \ INIT_SET(testobj_init_set), \
SET(testobj_set), \ SET(testobj_set), \
CLEAR(testobj_clear), \ CLEAR(testobj_clear), \
INIT_MOVE(M_COPY_A1_DEFAULT), \
TYPE(testobj_t), \ TYPE(testobj_t), \
OUT_STR(testobj_out_str), \ OUT_STR(testobj_out_str), \
IN_STR(testobj_in_str), \ IN_STR(testobj_in_str), \