mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
added cmsis_core, furi, mlib and nanobake implemented basic app structure from furi implemented basic placeholder apps
785 lines
45 KiB
C++
785 lines
45 KiB
C++
/*
|
|
* M*LIB - TUPLE module
|
|
*
|
|
* Copyright (c) 2017-2023, Patrick Pelissier
|
|
* All rights reserved.
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* + Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* + Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#ifndef MSTARLIB_TUPLE_H
|
|
#define MSTARLIB_TUPLE_H
|
|
|
|
#include "m-core.h"
|
|
|
|
/* Define the tuple type and functions.
|
|
USAGE:
|
|
TUPLE_DEF2(name, [(field1, type1[, oplist1]), (field2, type2[, oplist2]), ...] ) */
|
|
#define M_TUPLE_DEF2(name, ...) \
|
|
M_TUPLE_DEF2_AS(name, M_F(name,_t), __VA_ARGS__)
|
|
|
|
|
|
/* Define the tuple type and functions
|
|
as the given name.
|
|
USAGE:
|
|
TUPLE_DEF2_AS(name, name_t, [(field1, type1[, oplist1]), (field2, type2[, oplist2]), ...] ) */
|
|
#define M_TUPLE_DEF2_AS(name, name_t, ...) \
|
|
M_BEGIN_PROTECTED_CODE \
|
|
M_TUPL3_DEF2_P1( (name, name_t M_TUPL3_INJECT_GLOBAL(__VA_ARGS__)) ) \
|
|
M_END_PROTECTED_CODE
|
|
|
|
|
|
/* Define the oplist of a tuple.
|
|
USAGE: TUPLE_OPLIST(name[, oplist of the first type, ...]) */
|
|
#define M_TUPLE_OPLIST(...) \
|
|
M_IF_NARGS_EQ1(__VA_ARGS__) \
|
|
(M_TUPL3_OPLIST_P1((__VA_ARGS__, M_BASIC_OPLIST )), \
|
|
M_TUPL3_OPLIST_P1((__VA_ARGS__ )))
|
|
|
|
|
|
/* Return an array suitable for the WIP _cmp_order function.
|
|
As compound literals are not supported in C++,
|
|
provide a separate definition for C++ using initializer_list
|
|
(shall be constexpr, but only supported in C++14).
|
|
*/
|
|
#ifndef __cplusplus
|
|
#define M_TUPLE_ORDER(name, ...) \
|
|
( (const int[]) {M_MAP2_C(M_TUPL3_ORDER_CONVERT, name, __VA_ARGS__), 0})
|
|
#else
|
|
#include <initializer_list>
|
|
namespace m_lib {
|
|
template <unsigned int N>
|
|
struct m_tupl3_integer_va {
|
|
int data[N];
|
|
/*constexpr*/ inline m_tupl3_integer_va(std::initializer_list<int> init){
|
|
int j = 0;
|
|
for(auto i:init) {
|
|
data[j++] = i;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
#define M_TUPLE_ORDER(name, ...) \
|
|
(m_lib::m_tupl3_integer_va<M_NARGS(__VA_ARGS__,0)>({M_MAP2_C(M_TUPL3_ORDER_CONVERT, name, __VA_ARGS__), 0}).data)
|
|
#endif
|
|
|
|
|
|
/*****************************************************************************/
|
|
/********************************** INTERNAL *********************************/
|
|
/*****************************************************************************/
|
|
|
|
/* Contract of a tuple. Nothing notable */
|
|
#define M_TUPL3_CONTRACT(tup) do { \
|
|
M_ASSERT(tup != NULL); \
|
|
} while (0)
|
|
|
|
/* Inject the oplist within the list of arguments */
|
|
#define M_TUPL3_INJECT_GLOBAL(...) \
|
|
M_MAP(M_TUPL3_INJECT_OPLIST_A, __VA_ARGS__)
|
|
|
|
/* Transform (x, type) into (x, type, oplist) if there is global registered oplist
|
|
or (x, type, M_BASIC_OPLIST) if there is no global one,
|
|
or keep (x, type, oplist) if oplist was already present */
|
|
#define M_TUPL3_INJECT_OPLIST_A( duo_or_trio ) \
|
|
M_TUPL3_INJECT_OPLIST_B duo_or_trio
|
|
|
|
#define M_TUPL3_INJECT_OPLIST_B( f, ... ) \
|
|
M_DEFERRED_COMMA \
|
|
M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) )
|
|
|
|
// Deferred evaluation
|
|
#define M_TUPL3_DEF2_P1(...) M_ID( M_TUPL3_DEF2_P2 __VA_ARGS__ )
|
|
|
|
// Test if all third argument of all arguments is an oplist
|
|
#define M_TUPL3_IF_ALL_OPLIST(...) \
|
|
M_IF(M_REDUCE(M_TUPL3_IS_OPLIST_P, M_AND, __VA_ARGS__))
|
|
|
|
// Test if the third argument of (name, type, oplist) is an oplist
|
|
#define M_TUPL3_IS_OPLIST_P(a) \
|
|
M_OPLIST_P(M_RET_ARG3 a)
|
|
|
|
/* Validate the oplist before going further */
|
|
#define M_TUPL3_DEF2_P2(name, name_t, ...) \
|
|
M_TUPL3_IF_ALL_OPLIST(__VA_ARGS__)(M_TUPL3_DEF2_P3, M_TUPL3_DEF2_FAILURE)(name, name_t, __VA_ARGS__)
|
|
|
|
/* Stop processing with a compilation failure */
|
|
#define M_TUPL3_DEF2_FAILURE(name, name_t, ...) \
|
|
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(TUPLE_DEF2): at least one of the given argument is not a valid oplist: " #__VA_ARGS__)
|
|
|
|
/* Define the tuple */
|
|
#define M_TUPL3_DEF2_P3(name, name_t, ...) \
|
|
M_TUPL3_DEFINE_TYPE(name, name_t, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_ENUM(name, __VA_ARGS__) \
|
|
M_TUPL3_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
|
|
M_TUPL3_IF_ALL(INIT, __VA_ARGS__)(M_TUPL3_DEFINE_INIT(name, __VA_ARGS__),) \
|
|
M_TUPL3_DEFINE_INIT_SET(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_INIT_SET2(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_SET(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_SET2(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_CLEAR(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_GETTER_FIELD(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_SETTER_FIELD(name, __VA_ARGS__) \
|
|
M_TUPL3_DEFINE_EMPLACE_FIELD(name, __VA_ARGS__) \
|
|
M_TUPL3_IF_ONE(CMP, __VA_ARGS__)(M_TUPL3_DEFINE_CMP(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(CMP, __VA_ARGS__)(M_TUPL3_DEFINE_CMP_ORDER(name, __VA_ARGS__),) \
|
|
M_TUPL3_DEFINE_CMP_FIELD(name, __VA_ARGS__) \
|
|
M_TUPL3_IF_ONE(HASH, __VA_ARGS__)(M_TUPL3_DEFINE_HASH(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ONE(EQUAL, __VA_ARGS__)(M_TUPL3_DEFINE_EQUAL(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(GET_STR, __VA_ARGS__)(M_TUPL3_DEFINE_GET_STR(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(OUT_STR, __VA_ARGS__)(M_TUPL3_DEFINE_OUT_STR(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(IN_STR, __VA_ARGS__)(M_TUPL3_DEFINE_IN_STR(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(PARSE_STR, __VA_ARGS__)(M_TUPL3_DEFINE_PARSE_STR(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(OUT_SERIAL, __VA_ARGS__)(M_TUPL3_DEFINE_OUT_SERIAL(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(IN_SERIAL, __VA_ARGS__)(M_TUPL3_DEFINE_IN_SERIAL(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(INIT_MOVE, __VA_ARGS__)(M_TUPL3_DEFINE_INIT_MOVE(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(MOVE, __VA_ARGS__)(M_TUPL3_DEFINE_MOVE(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(SWAP, __VA_ARGS__)(M_TUPL3_DEFINE_SWAP(name, __VA_ARGS__),) \
|
|
M_TUPL3_IF_ALL(RESET, __VA_ARGS__)(M_TUPL3_DEFINE_RESET(name, __VA_ARGS__),)
|
|
|
|
/* Provide order for _cmp_order */
|
|
#define M_TUPL3_ORDER_CONVERT(name, x) M_F(name, M_C(M_TUPL3_ORDER_CONVERT_, x))
|
|
#define M_TUPL3_ORDER_CONVERT_ASC(x) M_C3(_,x,_value)
|
|
#define M_TUPL3_ORDER_CONVERT_DSC(x) M_C3(_,x,_value)*-1
|
|
|
|
/* Get the field name, the type, the oplist or the methods
|
|
based on the tuple (field, type, oplist) */
|
|
#define M_TUPL3_GET_FIELD(f,t,o) f
|
|
#define M_TUPL3_GET_TYPE(f,t,o) t
|
|
#define M_TUPL3_GET_OPLIST(f,t,o) o
|
|
#define M_TUPL3_GET_INIT(f,t,o) M_GET_INIT o
|
|
#define M_TUPL3_GET_INIT_SET(f,t,o) M_GET_INIT_SET o
|
|
#define M_TUPL3_GET_INIT_MOVE(f,t,o) M_GET_INIT_MOVE o
|
|
#define M_TUPL3_GET_MOVE(f,t,o) M_GET_MOVE o
|
|
#define M_TUPL3_GET_SET(f,t,o) M_GET_SET o
|
|
#define M_TUPL3_GET_CLEAR(f,t,o) M_GET_CLEAR o
|
|
#define M_TUPL3_GET_CMP(f,t,o) M_GET_CMP o
|
|
#define M_TUPL3_GET_HASH(f,t,o) M_GET_HASH o
|
|
#define M_TUPL3_GET_EQUAL(f,t,o) M_GET_EQUAL o
|
|
#define M_TUPL3_GET_STR(f,t,o) M_GET_GET_STR o
|
|
#define M_TUPL3_GET_OUT_STR(f,t,o) M_GET_OUT_STR o
|
|
#define M_TUPL3_GET_IN_STR(f,t,o) M_GET_IN_STR o
|
|
#define M_TUPL3_GET_OUT_SERIAL(f,t,o) M_GET_OUT_SERIAL o
|
|
#define M_TUPL3_GET_IN_SERIAL(f,t,o) M_GET_IN_SERIAL o
|
|
#define M_TUPL3_GET_PARSE_STR(f,t,o) M_GET_PARSE_STR o
|
|
#define M_TUPL3_GET_SWAP(f,t,o) M_GET_SWAP o
|
|
#define M_TUPL3_GET_RESET(f,t,o) M_GET_RESET o
|
|
|
|
/* Call the method associated to the given operator for the given parameter
|
|
of the tuple t=(name, type, oplist) */
|
|
#define M_TUPL3_CALL_INIT(t, ...) M_APPLY_API(M_TUPL3_GET_INIT t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_INIT_SET(t, ...) M_APPLY_API(M_TUPL3_GET_INIT_SET t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_INIT_MOVE(t, ...) M_APPLY_API(M_TUPL3_GET_INIT_MOVE t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_MOVE(t, ...) M_APPLY_API(M_TUPL3_GET_MOVE t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_SET(t, ...) M_APPLY_API(M_TUPL3_GET_SET t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_CLEAR(t, ...) M_APPLY_API(M_TUPL3_GET_CLEAR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_CMP(t, ...) M_APPLY_API(M_TUPL3_GET_CMP t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_HASH(t, ...) M_APPLY_API(M_TUPL3_GET_HASH t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_EQUAL(t, ...) M_APPLY_API(M_TUPL3_GET_EQUAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_GET_STR(t, ...) M_APPLY_API(M_TUPL3_GET_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_OUT_STR(t, ...) M_APPLY_API(M_TUPL3_GET_OUT_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_IN_STR(t, ...) M_APPLY_API(M_TUPL3_GET_IN_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_PARSE_STR(t, ...) M_APPLY_API(M_TUPL3_GET_PARSE_STR t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_OUT_SERIAL(t, ...) M_APPLY_API(M_TUPL3_GET_OUT_SERIAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_IN_SERIAL(t, ...) M_APPLY_API(M_TUPL3_GET_IN_SERIAL t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_SWAP(t, ...) M_APPLY_API(M_TUPL3_GET_SWAP t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
#define M_TUPL3_CALL_RESET(t, ...) M_APPLY_API(M_TUPL3_GET_RESET t, M_TUPL3_GET_OPLIST t, __VA_ARGS__)
|
|
|
|
|
|
/* Define the type of a tuple */
|
|
#define M_TUPL3_DEFINE_TYPE(name, name_t, ...) \
|
|
typedef struct M_F(name, _s) { \
|
|
M_MAP(M_TUPL3_DEFINE_RECUR_TYPE_ELE , __VA_ARGS__) \
|
|
} name_t[1]; \
|
|
\
|
|
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); \
|
|
/* Save constant as the number of arguments (internal) */ \
|
|
typedef enum { \
|
|
M_C3(m_tupl3_, name, _num_args) = M_NARGS(__VA_ARGS__) \
|
|
} M_C3(m_tupl3_, name, _num_args_ct); \
|
|
/* Save alias for the types of arguments */ \
|
|
M_MAP3(M_TUPL3_DEFINE_TYPE_ELE, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_DEFINE_TYPE_ELE(name, num, a) \
|
|
typedef M_TUPL3_GET_TYPE a M_C4(name, _type_, num, _ct);
|
|
|
|
#define M_TUPL3_DEFINE_RECUR_TYPE_ELE(a) \
|
|
M_TUPL3_GET_TYPE a M_TUPL3_GET_FIELD a ;
|
|
|
|
/* Define the basic enumerate, identifying a parameter */
|
|
#define M_TUPL3_DEFINE_ENUM(name, ...) \
|
|
typedef enum { \
|
|
M_F(name, _first_one_val), \
|
|
M_MAP2_C(M_TUPL3_DEFINE_ENUM_ELE , name, __VA_ARGS__) \
|
|
} M_F(name,_field_e);
|
|
|
|
#define M_TUPL3_DEFINE_ENUM_ELE(name, a) \
|
|
M_C4(name, _, M_TUPL3_GET_FIELD a, _value)
|
|
|
|
/* Control that all given oplists of all parameters are really oplists */
|
|
#define M_TUPL3_CONTROL_ALL_OPLIST(name, ...) \
|
|
M_MAP2(M_TUPL3_CONTROL_OPLIST, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_CONTROL_OPLIST(name, a) \
|
|
M_CHECK_COMPATIBLE_OPLIST(name, M_TUPL3_GET_FIELD a, \
|
|
M_TUPL3_GET_TYPE a, M_TUPL3_GET_OPLIST a)
|
|
|
|
/* Define the INIT method calling the INIT method for all params */
|
|
#define M_TUPL3_DEFINE_INIT(name, ...) \
|
|
M_INLINE void M_F(name, _init)(M_F(name,_ct) my) { \
|
|
M_MAP(M_TUPL3_DEFINE_INIT_FUNC , __VA_ARGS__) {} \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_INIT_FUNC(a) \
|
|
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, my -> M_TUPL3_GET_FIELD a)
|
|
|
|
/* Define the INIT_SET method calling the INIT_SET method for all params */
|
|
#define M_TUPL3_DEFINE_INIT_SET(name, ...) \
|
|
M_INLINE void M_F(name, _init_set)(M_F(name,_ct) my , M_F(name,_ct) const org) { \
|
|
M_TUPL3_CONTRACT(org); \
|
|
M_MAP(M_TUPL3_DEFINE_INIT_SET_FUNC , __VA_ARGS__) {} \
|
|
}
|
|
#define M_TUPL3_DEFINE_INIT_SET_FUNC(a) \
|
|
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, \
|
|
my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a )
|
|
|
|
/* Define the INIT_WITH method calling the INIT_SET method for all params. */
|
|
#define M_TUPL3_DEFINE_INIT_SET2(name, ...) \
|
|
M_INLINE void M_F(name, _init_emplace)(M_F(name,_ct) my \
|
|
M_MAP(M_TUPL3_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
|
|
) { \
|
|
M_MAP(M_TUPL3_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) {} \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_INIT_SET2_PROTO(a) \
|
|
, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a
|
|
|
|
#define M_TUPL3_DEFINE_INIT_SET2_FUNC(a) \
|
|
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, \
|
|
my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a )
|
|
|
|
|
|
/* Define the SET method calling the SET method for all params. */
|
|
#define M_TUPL3_DEFINE_SET(name, ...) \
|
|
M_INLINE void M_F(name, _set)(M_F(name,_ct) my , \
|
|
M_F(name,_ct) const org) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
M_TUPL3_CONTRACT(org); \
|
|
M_MAP(M_TUPL3_DEFINE_SET_FUNC , __VA_ARGS__) \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_SET_FUNC(a) \
|
|
M_TUPL3_CALL_SET(a, my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a );
|
|
|
|
|
|
/* Define the SET_WITH method calling the SET method for all params. */
|
|
#define M_TUPL3_DEFINE_SET2(name, ...) \
|
|
M_INLINE void M_F(name, _emplace)(M_F(name,_ct) my \
|
|
M_MAP(M_TUPL3_DEFINE_SET2_PROTO, __VA_ARGS__) \
|
|
) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
M_MAP(M_TUPL3_DEFINE_SET2_FUNC , __VA_ARGS__) \
|
|
}
|
|
#define M_TUPL3_DEFINE_SET2_PROTO(a) \
|
|
, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a
|
|
|
|
#define M_TUPL3_DEFINE_SET2_FUNC(a) \
|
|
M_TUPL3_CALL_SET(a, my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a );
|
|
|
|
|
|
/* Define the CLEAR method calling the CLEAR method for all params. */
|
|
#define M_TUPL3_DEFINE_CLEAR(name, ...) \
|
|
M_INLINE void M_F(name, _clear)(M_F(name,_ct) my) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
M_MAP(M_TUPL3_DEFINE_CLEAR_FUNC , __VA_ARGS__) \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_CLEAR_FUNC(a) \
|
|
M_TUPL3_CALL_CLEAR(a, my -> M_TUPL3_GET_FIELD a );
|
|
|
|
|
|
/* Define the GET_AT_field & CGET_AT methods for all params. */
|
|
#define M_TUPL3_DEFINE_GETTER_FIELD(name, ...) \
|
|
M_MAP3(M_TUPL3_DEFINE_GETTER_FIELD_PROTO, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_DEFINE_GETTER_FIELD_PROTO(name, num, a) \
|
|
M_INLINE M_TUPL3_GET_TYPE a * M_C3(name, _get_at_, M_TUPL3_GET_FIELD a) \
|
|
(M_F(name,_ct) my) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
return &(my->M_TUPL3_GET_FIELD a); \
|
|
} \
|
|
M_INLINE M_TUPL3_GET_TYPE a const * M_C3(name, _cget_at_, M_TUPL3_GET_FIELD a) \
|
|
(M_F(name,_ct) const my) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
return &(my->M_TUPL3_GET_FIELD a); \
|
|
} \
|
|
/* Same but uses numerical index for accessing the field (internal) */ \
|
|
M_INLINE M_TUPL3_GET_TYPE a * M_C4(m_tupl3_, name, _get_at_, num) \
|
|
(M_F(name,_ct) my) { \
|
|
return &(my->M_TUPL3_GET_FIELD a); \
|
|
} \
|
|
|
|
|
|
/* Define the SET_field methods for all params. */
|
|
#define M_TUPL3_DEFINE_SETTER_FIELD(name, ...) \
|
|
M_MAP2(M_TUPL3_DEFINE_SETTER_FIELD_PROTO, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_DEFINE_SETTER_FIELD_PROTO(name, a) \
|
|
M_INLINE void M_C3(name, _set_, M_TUPL3_GET_FIELD a) \
|
|
(M_F(name,_ct) my, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a) { \
|
|
M_TUPL3_CONTRACT(my); \
|
|
M_TUPL3_CALL_SET(a, my ->M_TUPL3_GET_FIELD a, M_TUPL3_GET_FIELD a); \
|
|
}
|
|
|
|
|
|
/* Define the EMPLACE_field methods for all params. */
|
|
#define M_TUPL3_DEFINE_EMPLACE_FIELD(name, ...) \
|
|
M_REDUCE3(M_TUPL3_DEFINE_EMPLACE_FIELD_PROTO, M_TUPL3_DEFINE_EMPLACE_G, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_DEFINE_EMPLACE_G(a, b) a b
|
|
|
|
#define M_TUPL3_DEFINE_EMPLACE_FIELD_PROTO(name, id, a) \
|
|
M_EMPLACE_QUEUE_DEF(M_TUPL3_GET_FIELD a, M_F(name, _ct), M_C3(name, _emplace_, M_TUPL3_GET_FIELD a), M_TUPL3_GET_OPLIST a, M_TUPL3_EMPLACE_DEF)
|
|
|
|
#define M_TUPL3_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
|
|
M_INLINE void \
|
|
function_name(name_t v \
|
|
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
|
|
{ \
|
|
M_CALL_CLEAR(oplist, v->name); \
|
|
M_EMPLACE_CALL_FUNC(a, init_func, oplist, v->name, exp_emplace_type); \
|
|
}
|
|
|
|
|
|
/* Define the CMP method by calling CMP methods for all params. */
|
|
#define M_TUPL3_DEFINE_CMP(name, ...) \
|
|
M_INLINE int M_F(name, _cmp)(M_F(name,_ct) const e1 , \
|
|
M_F(name,_ct) const e2) { \
|
|
int i; \
|
|
M_TUPL3_CONTRACT(e1); \
|
|
M_TUPL3_CONTRACT(e2); \
|
|
M_MAP(M_TUPL3_DEFINE_CMP_FUNC_P0, __VA_ARGS__) \
|
|
return 0; \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_CMP_FUNC_P0(a) \
|
|
M_IF(M_TUPL3_TEST_METHOD_P(CMP, a))(M_TUPL3_DEFINE_CMP_FUNC_P1, M_EAT)(a)
|
|
#define M_TUPL3_DEFINE_CMP_FUNC_P1(a) \
|
|
i = M_TUPL3_CALL_CMP(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
|
if (i != 0) return i;
|
|
|
|
/* Define the CMP_ORDER method by calling CMP methods for all params
|
|
In the right order
|
|
FIXME: _cmp_order is not supported by algorithm yet.
|
|
FIXME: All oplists shall define the CMP operator or at least one?
|
|
*/
|
|
#define M_TUPL3_DEFINE_CMP_ORDER(name, ...) \
|
|
M_INLINE int M_F(name, _cmp_order)(M_F(name,_ct) const e1 , \
|
|
M_F(name,_ct) const e2, \
|
|
const int order[]) { \
|
|
int i, r; \
|
|
M_TUPL3_CONTRACT(e1); \
|
|
M_TUPL3_CONTRACT(e2); \
|
|
while (true) { \
|
|
i=*order++; \
|
|
switch (i) { \
|
|
case 0: return 0; \
|
|
M_MAP2(M_TUPL3_DEFINE_CMP_ORDER_FUNC , name, __VA_ARGS__) \
|
|
default: M_ASSUME(0); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_CMP_ORDER_FUNC(name, a) \
|
|
case M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
|
case -M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
|
r = M_TUPL3_CALL_CMP(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
|
if (r != 0) return i < 0 ? -r : r; \
|
|
break;
|
|
|
|
|
|
/* Define a CMP_field method for all given params that export a CMP method */
|
|
#define M_TUPL3_DEFINE_CMP_FIELD(name, ...) \
|
|
M_MAP2(M_TUPL3_MAP_CMP_FIELD, name, __VA_ARGS__)
|
|
|
|
#define M_TUPL3_MAP_CMP_FIELD(name, a) \
|
|
M_IF_METHOD(CMP, M_TUPL3_GET_OPLIST a)( \
|
|
M_TUPL3_DEFINE_CMP_FIELD_FUNC(name, M_TUPL3_GET_FIELD a, M_TUPL3_GET_CMP a, M_TUPL3_GET_OPLIST a), \
|
|
)
|
|
|
|
#define M_TUPL3_DEFINE_CMP_FIELD_FUNC(name, field, func_cmp, oplist) \
|
|
M_INLINE int M_C3(name, _cmp_, field)(M_F(name,_ct) const e1 , \
|
|
M_F(name,_ct) const e2) { \
|
|
M_TUPL3_CONTRACT(e1); \
|
|
M_TUPL3_CONTRACT(e2); \
|
|
return M_APPLY_API(func_cmp, oplist, e1 -> field , e2 -> field ); \
|
|
}
|
|
|
|
|
|
/* Define a EQUAL method by calling the EQUAL methods for all params */
|
|
#define M_TUPL3_DEFINE_EQUAL(name, ...) \
|
|
M_INLINE bool M_F(name, _equal_p)(M_F(name,_ct) const e1 , \
|
|
M_F(name,_ct) const e2) { \
|
|
bool b; \
|
|
M_TUPL3_CONTRACT(e1); \
|
|
M_TUPL3_CONTRACT(e2); \
|
|
M_MAP(M_TUPL3_DEFINE_EQUAL_FUNC_P0, __VA_ARGS__) \
|
|
return true; \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_EQUAL_FUNC_P0(a) \
|
|
M_IF(M_TUPL3_TEST_METHOD_P(EQUAL, a))(M_TUPL3_DEFINE_EQUAL_FUNC_P1, M_EAT)(a)
|
|
#define M_TUPL3_DEFINE_EQUAL_FUNC_P1(a) \
|
|
b = M_TUPL3_CALL_EQUAL(a, e1 -> M_TUPL3_GET_FIELD a , e2 -> M_TUPL3_GET_FIELD a ); \
|
|
if (!b) return false;
|
|
|
|
|
|
/* Define a HASH method by calling the HASH methods for all params */
|
|
#define M_TUPL3_DEFINE_HASH(name, ...) \
|
|
M_INLINE size_t M_F(name, _hash)(M_F(name,_ct) const e1) { \
|
|
M_TUPL3_CONTRACT(e1); \
|
|
M_HASH_DECL(hash); \
|
|
M_MAP(M_TUPL3_DEFINE_HASH_FUNC_P0, __VA_ARGS__) \
|
|
return M_HASH_FINAL (hash); \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_HASH_FUNC_P0(a) \
|
|
M_IF(M_TUPL3_TEST_METHOD_P(HASH, a))(M_TUPL3_DEFINE_HASH_FUNC_P1, M_EAT)(a)
|
|
#define M_TUPL3_DEFINE_HASH_FUNC_P1(a) \
|
|
M_HASH_UP(hash, M_TUPL3_CALL_HASH(a, e1 -> M_TUPL3_GET_FIELD a) );
|
|
|
|
|
|
/* Define a GET_STR method by calling the GET_STR methods for all params */
|
|
#define M_TUPL3_DEFINE_GET_STR(name, ...) \
|
|
M_INLINE void M_F(name, _get_str)(m_string_t str, \
|
|
M_F(name,_ct) const el, \
|
|
bool append) { \
|
|
bool comma = false; \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (str != NULL); \
|
|
(append ? m_string_cat_cstr : m_string_set_cstr) (str, "("); \
|
|
M_MAP(M_TUPL3_DEFINE_GET_STR_FUNC , __VA_ARGS__) \
|
|
m_string_push_back (str, ')'); \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_GET_STR_FUNC(a) \
|
|
if (comma) m_string_push_back (str, ','); \
|
|
comma = true; \
|
|
M_TUPL3_CALL_GET_STR(a, str, el -> M_TUPL3_GET_FIELD a, true); \
|
|
|
|
|
|
/* Define a OUT_STR method by calling the OUT_STR methods for all params */
|
|
#define M_TUPL3_DEFINE_OUT_STR(name, ...) \
|
|
M_INLINE void M_F(name, _out_str)(FILE *f, \
|
|
M_F(name,_ct) const el) { \
|
|
bool comma = false; \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (f != NULL); \
|
|
fputc('(', f); \
|
|
M_MAP(M_TUPL3_DEFINE_OUT_STR_FUNC , __VA_ARGS__) \
|
|
fputc (')', f); \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_OUT_STR_FUNC(a) \
|
|
if (comma) fputc (',', f); \
|
|
comma = true; \
|
|
M_TUPL3_CALL_OUT_STR(a, f, el -> M_TUPL3_GET_FIELD a); \
|
|
|
|
|
|
/* Define a IN_STR method by calling the IN_STR methods for all params */
|
|
#define M_TUPL3_DEFINE_IN_STR(name, ...) \
|
|
M_INLINE bool M_F(name, _in_str)(M_F(name,_ct) el, FILE *f) { \
|
|
bool comma = false; \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (f != NULL); \
|
|
int c = fgetc(f); \
|
|
if (c != '(') return false; \
|
|
M_MAP(M_TUPL3_DEFINE_IN_STR_FUNC , __VA_ARGS__) \
|
|
c = fgetc(f); \
|
|
return (c == ')'); \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_IN_STR_FUNC(a) \
|
|
if (comma) { \
|
|
c = fgetc (f); \
|
|
if (c != ',' || c == EOF) return false; \
|
|
} \
|
|
comma = true; \
|
|
if (M_TUPL3_CALL_IN_STR(a, el -> M_TUPL3_GET_FIELD a, f) == false) \
|
|
return false ; \
|
|
|
|
|
|
/* Define a PARSE_STR method by calling the PARSE_STR methods for all params */
|
|
#define M_TUPL3_DEFINE_PARSE_STR(name, ...) \
|
|
M_INLINE bool M_F(name, _parse_str)(M_F(name,_ct) el, \
|
|
const char str[], \
|
|
const char **endptr) { \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (str != NULL); \
|
|
bool success = false; \
|
|
bool comma = false; \
|
|
int c = *str++; \
|
|
if (c != '(') goto exit; \
|
|
M_MAP(M_TUPL3_DEFINE_PARSE_STR_FUNC , __VA_ARGS__) \
|
|
c = *str++; \
|
|
success = (c == ')'); \
|
|
exit: \
|
|
if (endptr) *endptr = str; \
|
|
return success; \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_PARSE_STR_FUNC(a) \
|
|
if (comma) { \
|
|
c = *str++; \
|
|
if (c != ',' || c == 0) goto exit; \
|
|
} \
|
|
comma = true; \
|
|
if (M_TUPL3_CALL_PARSE_STR(a, el -> M_TUPL3_GET_FIELD a, str, &str) == false) \
|
|
goto exit ; \
|
|
|
|
|
|
/* Return the parameter name as a C string */
|
|
#define M_TUPL3_STRINGIFY_NAME(a) \
|
|
M_AS_STR(M_TUPL3_GET_FIELD a)
|
|
|
|
|
|
/* Define a OUT_SERIAL method by calling the OUT_SERIAL methods for all params */
|
|
#define M_TUPL3_DEFINE_OUT_SERIAL(name, ...) \
|
|
M_INLINE m_serial_return_code_t \
|
|
M_F(name, _out_serial)(m_serial_write_t f, \
|
|
M_F(name,_ct) const el) { \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
|
const int field_max = M_NARGS(__VA_ARGS__); \
|
|
/* Define a constant static table of all fields names */ \
|
|
static const char *const field_name[] = \
|
|
{ M_REDUCE(M_TUPL3_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
|
int index = 0; \
|
|
m_serial_local_t local; \
|
|
m_serial_return_code_t ret; \
|
|
ret = f->m_interface->write_tuple_start(local, f); \
|
|
M_MAP(M_TUPL3_DEFINE_OUT_SERIAL_FUNC , __VA_ARGS__) \
|
|
M_ASSERT( index == field_max); \
|
|
ret |= f->m_interface->write_tuple_end(local, f); \
|
|
return ret & M_SERIAL_FAIL; \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_OUT_SERIAL_FUNC(a) \
|
|
f->m_interface->write_tuple_id(local, f, field_name, field_max, index); \
|
|
M_TUPL3_CALL_OUT_SERIAL(a, f, el -> M_TUPL3_GET_FIELD a); \
|
|
index++; \
|
|
|
|
|
|
/* Define a IN_SERIAL method by calling the IN_SERIAL methods for all params */
|
|
#define M_TUPL3_DEFINE_IN_SERIAL(name, ...) \
|
|
M_INLINE m_serial_return_code_t \
|
|
M_F(name, _in_serial)(M_F(name,_ct) el, m_serial_read_t f) { \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_ASSERT (f != NULL && f->m_interface != NULL); \
|
|
int index = -1; \
|
|
const int field_max = M_NARGS(__VA_ARGS__); \
|
|
static const char *const field_name[] = \
|
|
{ M_REDUCE(M_TUPL3_STRINGIFY_NAME, M_ID, __VA_ARGS__) }; \
|
|
m_serial_local_t local; \
|
|
m_serial_return_code_t ret; \
|
|
ret = f->m_interface->read_tuple_start(local, f); \
|
|
while (ret == M_SERIAL_OK_CONTINUE) { \
|
|
ret = f->m_interface->read_tuple_id(local, f, field_name, field_max, &index); \
|
|
if (ret == M_SERIAL_OK_CONTINUE) { \
|
|
M_ASSERT (index >= 0 && index < field_max); \
|
|
switch (1+index) { \
|
|
M_MAP2(M_TUPL3_DEFINE_IN_SERIAL_FUNC , name, __VA_ARGS__) \
|
|
default: M_ASSUME(0); \
|
|
} \
|
|
ret = (ret == M_SERIAL_OK_DONE) ? M_SERIAL_OK_CONTINUE : M_SERIAL_FAIL; \
|
|
} \
|
|
} \
|
|
return ret; \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_IN_SERIAL_FUNC(name, a) \
|
|
case M_C4(name, _, M_TUPL3_GET_FIELD a, _value): \
|
|
ret = M_TUPL3_CALL_IN_SERIAL(a, el -> M_TUPL3_GET_FIELD a, f); \
|
|
break; \
|
|
|
|
|
|
/* Define a INIT_MOVE method by calling the INIT_MOVE methods for all params
|
|
INIT_MOVE cannot fail and cannot throw any exception */
|
|
#define M_TUPL3_DEFINE_INIT_MOVE(name, ...) \
|
|
M_INLINE void M_F(name, _init_move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_MAP(M_TUPL3_DEFINE_INIT_MOVE_FUNC , __VA_ARGS__) \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_INIT_MOVE_FUNC(a) \
|
|
M_TUPL3_CALL_INIT_MOVE(a, el -> M_TUPL3_GET_FIELD a, org -> M_TUPL3_GET_FIELD a);
|
|
|
|
|
|
/* Define a MOVE method by calling the MOVE methods for all params */
|
|
#define M_TUPL3_DEFINE_MOVE(name, ...) \
|
|
M_INLINE void M_F(name, _move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
|
|
M_TUPL3_CONTRACT(el); \
|
|
M_MAP(M_TUPL3_DEFINE_MOVE_FUNC , __VA_ARGS__) \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_MOVE_FUNC(a) \
|
|
M_TUPL3_CALL_MOVE(a, el -> M_TUPL3_GET_FIELD a, org -> M_TUPL3_GET_FIELD a);
|
|
|
|
|
|
/* Define a SWAP method by calling the SWAP methods for all params */
|
|
#define M_TUPL3_DEFINE_SWAP(name, ...) \
|
|
M_INLINE void M_F(name, _swap)(M_F(name,_ct) el1, M_F(name,_ct) el2) { \
|
|
M_TUPL3_CONTRACT(el1); \
|
|
M_TUPL3_CONTRACT(el2); \
|
|
M_MAP(M_TUPL3_DEFINE_SWAP_FUNC , __VA_ARGS__) \
|
|
}
|
|
|
|
#define M_TUPL3_DEFINE_SWAP_FUNC(a) \
|
|
M_TUPL3_CALL_SWAP(a, el1 -> M_TUPL3_GET_FIELD a, el2 -> M_TUPL3_GET_FIELD a);
|
|
|
|
|
|
/* Define a RESET method by calling the RESET methods for all params */
|
|
#define M_TUPL3_DEFINE_RESET(name, ...) \
|
|
M_INLINE void M_F(name, _reset)(M_F(name,_ct) el1) { \
|
|
M_TUPL3_CONTRACT(el1); \
|
|
M_MAP(M_TUPL3_DEFINE_RESET_FUNC , __VA_ARGS__) \
|
|
} \
|
|
|
|
#define M_TUPL3_DEFINE_RESET_FUNC(a) \
|
|
M_TUPL3_CALL_RESET(a, el1 -> M_TUPL3_GET_FIELD a);
|
|
|
|
|
|
/********************************** INTERNAL *********************************/
|
|
|
|
/* INIT_WITH macro enabling recursive INIT_WITH initialization
|
|
tuple = { int, m_string_t, array<m_string_t> }
|
|
USAGE:
|
|
M_LET( (x, 2, ("John"), ( ("Bear"), ("Rabbit") )), tuple_t)
|
|
|
|
"If you think it's simple, you're deluding yourself."
|
|
|
|
Several pass are done:
|
|
1) If the number of arguments doesn't match the number of oplists of the
|
|
tuple oplist, it is assumed something is wrong. It uses the _init_emplace
|
|
function to provide proper warning in such case.
|
|
2) Otherwise, it checks that the number of arguments matches the number
|
|
of arguments of the tuple definition.
|
|
3) Mix all arguments with their associated oplists to have pair (arg, oplist),
|
|
4) Map the following macro for each computed pair :
|
|
4.a) If INIT_WITH macro is not defined for this pair, it uses INIT_SET
|
|
4.b) If the argument is encapsulated with parenthesis, it uses INIT_WITH
|
|
4.c) If the oplist property LET_AS_INIT_WITH is defined, it uses INIT_WITH
|
|
4.d) Otherwise it uses INIT_SET.
|
|
*/
|
|
#define M_TUPL3_INIT_WITH(oplist, dest, ...) \
|
|
M_TUPL3_INIT_WITH_P1(M_GET_NAME oplist, M_GET_OPLIST oplist, dest, __VA_ARGS__)
|
|
#define M_TUPL3_INIT_WITH_P1(name, oplist_arglist, dest, ...) \
|
|
M_IF(M_NOTEQUAL( M_NARGS oplist_arglist, M_NARGS (__VA_ARGS__))) \
|
|
(M_TUPL3_INIT_WITH_P1_FUNC, M_TUPL3_INIT_WITH_P1_MACRO)(name, oplist_arglist, dest, __VA_ARGS__)
|
|
#define M_TUPL3_INIT_WITH_P1_FUNC(name, oplist_arglist, dest, ...) \
|
|
M_F(name, _init_emplace)(dest, __VA_ARGS__)
|
|
#define M_TUPL3_INIT_WITH_P1_MACRO(name, oplist_arglist, dest, ...) \
|
|
( M_STATIC_ASSERT( M_NARGS oplist_arglist == M_C3(m_tupl3_, name, _num_args), M_LIB_DIMENSION_ERROR, "The number of oplists given to TUPLE_OPLIST don't match the number of oplists used to create the tuple." ), \
|
|
M_STATIC_ASSERT( M_NARGS(__VA_ARGS__) == M_C3(m_tupl3_, name, _num_args), M_LIB_DIMENSION_ERROR, "Missing / Too many arguments for tuple"), \
|
|
M_MAP3(M_TUPL3_INIT_WITH_P2, (name, dest), M_OPFLAT M_MERGE_ARGLIST( oplist_arglist, (__VA_ARGS__) ) ) \
|
|
(void) 0)
|
|
#define M_TUPL3_INIT_WITH_P2(name_dest, num, pair) \
|
|
M_TUPL3_INIT_WITH_P3( M_PAIR_1 name_dest, M_PAIR_2 name_dest, num, M_PAIR_1 pair, M_PAIR_2 pair )
|
|
#define M_TUPL3_INIT_WITH_P3(name, dest, num, oplist, param) \
|
|
M_IF(M_TEST_METHOD_P(INIT_WITH, oplist))(M_TUPL3_INIT_WITH_P4, M_TUPL3_INIT_WITH_SET)(name, dest, num, oplist, param)
|
|
#define M_TUPL3_INIT_WITH_SET(name, dest, num, oplist, param) \
|
|
M_CALL_INIT_SET (oplist, *M_C4(m_tupl3_, name, _get_at_, num)(dest), param) ,
|
|
#define M_TUPL3_INIT_WITH_P4(name, dest, num, oplist, param) \
|
|
M_IF(M_PARENTHESIS_P( param))(M_TUPL3_INIT_WITH_P5, M_TUPL3_INIT_WITH_P6)(name, dest, num, oplist, param)
|
|
#define M_TUPL3_INIT_WITH_P5(name, dest, num, oplist, param) \
|
|
M_CALL_INIT_WITH(oplist, *M_C4(m_tupl3_, name, _get_at_, num)(dest), M_REMOVE_PARENTHESIS (param) ) ,
|
|
#define M_TUPL3_INIT_WITH_P6(name, dest, num, oplist, param) \
|
|
M_IF(M_GET_PROPERTY(oplist, LET_AS_INIT_WITH))(M_TUPL3_INIT_WITH_P5, M_TUPL3_INIT_WITH_SET)(name, dest, num, oplist, param)
|
|
|
|
/* Macros for testing for the presence of a method in the parameter (name, type, oplist) */
|
|
#define M_TUPL3_TEST_METHOD_P(method, trio) \
|
|
M_APPLY(M_TUPL3_TEST_METHOD2_P, method, M_OPFLAT trio)
|
|
|
|
#define M_TUPL3_TEST_METHOD2_P(method, f, t, op) \
|
|
M_TEST_METHOD_P(method, op)
|
|
|
|
|
|
/********************************** INTERNAL *********************************/
|
|
|
|
/* Macros for testing for the presence of a method in all the params */
|
|
#define M_TUPL3_IF_ALL(method, ...) \
|
|
M_IF(M_REDUCE2(M_TUPL3_TEST_METHOD_P, M_AND, method, __VA_ARGS__))
|
|
|
|
/* Macros for testing for the presence of a method in at least one params */
|
|
#define M_TUPL3_IF_ONE(method, ...) \
|
|
M_IF(M_REDUCE2(M_TUPL3_TEST_METHOD_P, M_OR, method, __VA_ARGS__))
|
|
|
|
// deferred evaluation
|
|
#define M_TUPL3_OPLIST_P1(arg) M_TUPL3_OPLIST_P2 arg
|
|
|
|
/* Validate the oplist before going further */
|
|
#define M_TUPL3_OPLIST_P2(name, ...) \
|
|
M_IF(M_REDUCE(M_OPLIST_P, M_AND, __VA_ARGS__))(M_TUPL3_OPLIST_P3, M_TUPL3_OPLIST_FAILURE)(name, __VA_ARGS__)
|
|
|
|
/* Prepare a clean compilation failure */
|
|
#define M_TUPL3_OPLIST_FAILURE(name, ...) \
|
|
((M_LIB_ERROR(ONE_ARGUMENT_OF_M_TUPL3_OPLIST_IS_NOT_AN_OPLIST, name, __VA_ARGS__)))
|
|
|
|
/* Define the TUPLE oplist */
|
|
#define M_TUPL3_OPLIST_P3(name, ...) \
|
|
(M_IF_METHOD_ALL(INIT, __VA_ARGS__)(INIT(M_F(name,_init)),), \
|
|
INIT_SET(M_F(name, _init_set)), \
|
|
INIT_WITH(API_1(M_TUPL3_INIT_WITH)), \
|
|
SET(M_F(name,_set)), \
|
|
CLEAR(M_F(name, _clear)), \
|
|
NAME(name), \
|
|
TYPE(M_F(name,_ct)), \
|
|
OPLIST( (__VA_ARGS__) ), \
|
|
M_IF_METHOD_ALL(CMP, __VA_ARGS__)(CMP(M_F(name, _cmp)),), \
|
|
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)),), \
|
|
M_IF_METHOD_ALL(PARSE_STR, __VA_ARGS__)(PARSE_STR(M_F(name, _parse_str)),), \
|
|
M_IF_METHOD_ALL(IN_STR, __VA_ARGS__)(IN_STR(M_F(name, _in_str)),), \
|
|
M_IF_METHOD_ALL(OUT_STR, __VA_ARGS__)(OUT_STR(M_F(name, _out_str)),), \
|
|
M_IF_METHOD_ALL(IN_SERIAL, __VA_ARGS__)(IN_SERIAL(M_F(name, _in_serial)),), \
|
|
M_IF_METHOD_ALL(OUT_SERIAL, __VA_ARGS__)(OUT_SERIAL(M_F(name, _out_serial)),), \
|
|
M_IF_METHOD_ALL(INIT_MOVE, __VA_ARGS__)(INIT_MOVE(M_F(name, _init_move)),), \
|
|
M_IF_METHOD_ALL(MOVE, __VA_ARGS__)(MOVE(M_F(name, _move)),), \
|
|
M_IF_METHOD_ALL(SWAP, __VA_ARGS__)(SWAP(M_F(name, _swap)),), \
|
|
M_IF_METHOD_ALL(RESET, __VA_ARGS__)(RESET(M_F(name, _reset)),), \
|
|
EMPLACE_TYPE( ( M_REDUCE2(M_TUPL3_OPLIST_SUBTYPE, M_ID, name, M_SEQ(1, M_NARGS(__VA_ARGS__))) ) ) \
|
|
)
|
|
|
|
/* Support for EMPLACE_TYPE in OPLIST. It refers the created internal type alias */
|
|
#define M_TUPL3_OPLIST_SUBTYPE(name, num) \
|
|
M_C4(name, _type_, num, _ct)
|
|
|
|
/********************************** INTERNAL *********************************/
|
|
|
|
#if M_USE_SMALL_NAME
|
|
#define TUPLE_DEF2 M_TUPLE_DEF2
|
|
#define TUPLE_DEF2_AS M_TUPLE_DEF2_AS
|
|
#define TUPLE_OPLIST M_TUPLE_OPLIST
|
|
#define TUPLE_ORDER M_TUPLE_ORDER
|
|
#endif
|
|
|
|
#endif
|