Add more check for valid oplists before expanding further

This commit is contained in:
Patrick Pelissier committed 2020-05-09 16:10:56 +02:00
1 parent ac3d7568f2
commit 055e74d350
4 files changed
+69 -32

No files matched your search

+38 -25
View File
@@ -108,39 +108,52 @@
/********************************** INTERNAL ************************************/ /********************************** INTERNAL ************************************/
/* Expand the algorithms */
#define ALGOI_DEF_P1(name, cont_oplist) \ #define ALGOI_DEF_P1(name, cont_oplist) \
ALGOI_DEF_P2(name, M_GET_TYPE cont_oplist, cont_oplist, \ ALGOI_DEF_P2(name, M_GET_TYPE cont_oplist, cont_oplist, \
M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, \ M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, \
M_GET_IT_TYPE cont_oplist) M_GET_IT_TYPE cont_oplist)
/* First validate the first oplist */
#define ALGOI_DEF_P2(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_DEF_P2(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
M_IF_OPLIST(cont_oplist)(ALGOI_DEF_P3, ALGOI_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
/* First validate the second oplist */
#define ALGOI_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
M_IF_OPLIST(type_oplist)(ALGOI_DEF_P4, ALGOI_DEF_FAILURE)(name, container_t, cont_oplist, type_t, type_oplist, it_t)
/* Stop processing with a compilation failure */
#define ALGOI_DEF_FAILURE(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ALGO_DEF): one of the given argument is not a valid oplist: " M_AS_STR(cont_oplist) " / " M_AS_STR(type_oplist) )
#define ALGOI_DEF_P4(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
ALGOI_CALLBACK_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
M_IF_FUNCOBJ(ALGOI_FUNCOBJ_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t)) \ M_IF_FUNCOBJ(ALGOI_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)) \
\ \
M_IF_METHOD(EQUAL, type_oplist)( \ M_IF_METHOD(EQUAL, type_oplist)( \
ALGOI_FIND_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
, /* NO EQUAL */) \ , /* NO EQUAL */) \
\ \
ALGOI_FIND_IF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_t), M_C(name, _eq_cb_t), M_APPLY, M_APPLY) \ ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, if, M_C(name, _test_cb_t), M_C(name, _eq_cb_t), M_APPLY, M_APPLY) \
M_IF_FUNCOBJ(ALGOI_FIND_IF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, fo, M_C(name, _test_obj_t), M_C(name, _eq_obj_t), M_C(name, _test_obj_call), M_C(name, _eq_obj_call))) \ M_IF_FUNCOBJ(ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, fo, M_C(name, _test_obj_t), M_C(name, _eq_obj_t), M_C(name, _test_obj_call), M_C(name, _eq_obj_call))) \
\ \
ALGOI_MAP_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
ALGOI_ALL_OF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_t), M_APPLY) \ ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _, M_C(name, _test_cb_t), M_APPLY) \
M_IF_FUNCOBJ(ALGOI_ALL_OF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, _fo_, M_C(name, _test_obj_t), M_C(name, _test_obj_call)) ) \ M_IF_FUNCOBJ(ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, _fo_, M_C(name, _test_obj_t), M_C(name, _test_obj_call)) ) \
\ \
/* If there is a IT_REF method, we consider the container as modifiable through iterator */ \ /* If there is a IT_REF method, we consider the container as modifiable through iterator */ \
M_IF_METHOD(IT_REF, cont_oplist)( \ M_IF_METHOD(IT_REF, cont_oplist)( \
ALGOI_FILL_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
ALGOI_VECTOR_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
M_IF_METHOD(CMP, type_oplist)( \ M_IF_METHOD(CMP, type_oplist)( \
ALGOI_MINMAX_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
ALGOI_SORT_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, +, _sort) \ ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, +, _sort) \
ALGOI_SORT_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, -, _sort_dsc) \ ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, -, _sort_dsc) \
M_IF_METHOD(IT_REMOVE, cont_oplist)( \ M_IF_METHOD(IT_REMOVE, cont_oplist)( \
ALGOI_REMOVE_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ ALGOI_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
, /* No IT_REMOVE method */) \ , /* No IT_REMOVE method */) \
, /* No CMP method */) \ , /* No CMP method */) \
\ \
@@ -152,7 +165,7 @@
, /* No EXT_ALGO method */ ) \ , /* No EXT_ALGO method */ ) \
#define ALGOI_CALLBACK_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t)\ #define ALGOI_CALLBACK_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)\
\ \
typedef bool (*M_C(name, _test_cb_t))(type_t const); \ typedef bool (*M_C(name, _test_cb_t))(type_t const); \
typedef bool (*M_C(name, _eq_cb_t))(type_t const, type_t const); \ typedef bool (*M_C(name, _eq_cb_t))(type_t const, type_t const); \
@@ -160,7 +173,7 @@
typedef void (*M_C(name, _transform_cb_t))(type_t *, type_t const); \ typedef void (*M_C(name, _transform_cb_t))(type_t *, type_t const); \
typedef void (*M_C(name, _apply_cb_t))(type_t); \ typedef void (*M_C(name, _apply_cb_t))(type_t); \
#define ALGOI_FUNCOBJ_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_FUNCOBJ_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
FUNC_OBJ_ITF_DEF(M_C(name, _test_obj), bool, type_t const) \ FUNC_OBJ_ITF_DEF(M_C(name, _test_obj), bool, type_t const) \
FUNC_OBJ_ITF_DEF(M_C(name, _eq_obj), bool, type_t const, type_t const ) \ FUNC_OBJ_ITF_DEF(M_C(name, _eq_obj), bool, type_t const, type_t const ) \
@@ -169,7 +182,7 @@
FUNC_OBJ_ITF_DEF(M_C(name, _apply_obj), void, type_t * ) \ FUNC_OBJ_ITF_DEF(M_C(name, _apply_obj), void, type_t * ) \
#define ALGOI_SORT_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, order, sort_name) \ #define ALGOI_SORT_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, order, sort_name) \
\ \
static inline int M_C3(name,sort_name,_cmp)(type_t const*a,type_t const*b) { \ static inline int M_C3(name,sort_name,_cmp)(type_t const*a,type_t const*b) { \
return order M_CALL_CMP(type_oplist, *a, *b); \ return order M_CALL_CMP(type_oplist, *a, *b); \
@@ -455,7 +468,7 @@
, /* NO IT_REMOVE */ ) , /* NO IT_REMOVE */ )
#define ALGOI_FIND_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_FIND_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
/* It supposes that the container is not sorted */ \ /* It supposes that the container is not sorted */ \
static inline void \ static inline void \
M_C(name, _find_again) (it_t it, type_t const data) \ M_C(name, _find_again) (it_t it, type_t const data) \
@@ -553,7 +566,7 @@
#define ALGOI_FIND_IF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, test_t, eq_t, call_test, call_eq) \ #define ALGOI_FIND_IF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, test_t, eq_t, call_test, call_eq) \
\ \
static inline void \ static inline void \
M_C3(name, _find_again_, suffix) (it_t it, test_t func) \ M_C3(name, _find_again_, suffix) (it_t it, test_t func) \
@@ -609,7 +622,7 @@
} \ } \
#define ALGOI_FILL_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_FILL_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
static inline void \ static inline void \
M_C(name, _fill) (container_t l, type_t const value) \ M_C(name, _fill) (container_t l, type_t const value) \
@@ -660,7 +673,7 @@
, /* ADD method */ ) \ , /* ADD method */ ) \
#define ALGOI_MAP_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_MAP_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
static inline void \ static inline void \
M_C(name, _for_each) (container_t l, M_C(name, _apply_cb_t) func) \ M_C(name, _for_each) (container_t l, M_C(name, _apply_cb_t) func) \
@@ -729,7 +742,7 @@
, ) \ , ) \
#define ALGOI_ALL_OF_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, func_t, call) \ #define ALGOI_ALL_OF_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, func_t, call) \
\ \
static inline bool \ static inline bool \
M_C4(name, _any_of, suffix, p) (container_t const l, \ M_C4(name, _any_of, suffix, p) (container_t const l, \
@@ -765,7 +778,7 @@
} \ } \
#define ALGOI_MINMAX_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
static inline type_t * \ static inline type_t * \
M_C(name, _min) (const container_t l) \ M_C(name, _min) (const container_t l) \
@@ -809,7 +822,7 @@
*max_p = max; \ *max_p = max; \
} \ } \
#define ALGOI_REMOVE_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_REMOVE_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
static inline void \ static inline void \
M_C(name, _uniq)(container_t l) \ M_C(name, _uniq)(container_t l) \
@@ -863,7 +876,7 @@
} \ } \
} \ } \
#define ALGOI_VECTOR_DEF_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ #define ALGOI_VECTOR_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\ \
M_IF_METHOD(ADD, type_oplist)( \ M_IF_METHOD(ADD, type_oplist)( \
static inline void M_C(name, _add) (container_t dst, const container_t src) \ static inline void M_C(name, _add) (container_t dst, const container_t src) \
+1
View File
@@ -34,6 +34,7 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name,_it_t) ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name,_it_t) ), \
(name, __VA_ARGS__, M_C(name,_t), M_C(name,_it_t)))) (name, __VA_ARGS__, M_C(name,_t), M_C(name,_it_t))))
/* Define the oplist of a dynamic array given its name and its oplist. /* Define the oplist of a dynamic array given its name and its oplist.
If no oplist is given it is assumed to be M_DEFAULT_OPLIST If no oplist is given it is assumed to be M_DEFAULT_OPLIST
USAGE: ARRAY_OPLIST(name[, oplist of the type]) */ USAGE: ARRAY_OPLIST(name[, oplist of the type]) */
+14 -1
View File
@@ -81,6 +81,7 @@
((__VA_ARGS__, M_DEFAULT_OPLISTR ), \ ((__VA_ARGS__, M_DEFAULT_OPLISTR ), \
(__VA_ARGS__ ))) (__VA_ARGS__ )))
/* Define the oplist of a rbtree of type (from BPTREE_DEF2). /* Define the oplist of a rbtree of type (from BPTREE_DEF2).
USAGE: BPTREE_OPLIST2(name, key_oplist, value_oplist) USAGE: BPTREE_OPLIST2(name, key_oplist, value_oplist)
NOTE: IT_REF is not exported so that the contained appears as not modifiable NOTE: IT_REF is not exported so that the contained appears as not modifiable
@@ -215,6 +216,18 @@
so that all arguments are evaluated before further expansion */ so that all arguments are evaluated before further expansion */
#define BPTREEI_DEF_P1(arg) BPTREEI_DEF_P2 arg #define BPTREEI_DEF_P1(arg) BPTREEI_DEF_P2 arg
/* Validate the key oplist before going further */
#define BPTREEI_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
M_IF_OPLIST(key_oplist)(BPTREEI_DEF_P3, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t)
/* Validate the value oplist before going further */
#define BPTREEI_DEF_P3(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
M_IF_OPLIST(value_oplist)(BPTREEI_DEF_P4, BPTREEI_DEF_FAILURE)(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t)
/* Stop processing with a compilation failure */
#define BPTREEI_DEF_FAILURE(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(BPTREE*_DEF): one of the the given argument is not a valid oplist: " M_AS_STR(key_oplist) " / " M_AS_STR(value_oplist))
/* Internal b+tree definition /* Internal b+tree definition
- name: prefix to be used - name: prefix to be used
- N: size of the node - N: size of the node
@@ -229,7 +242,7 @@
- node_t: alias for M_C(name, _node_t) [ node ] - node_t: alias for M_C(name, _node_t) [ node ]
- pit_t: alias for M_C(name, _pit_t) [parent iterator] - pit_t: alias for M_C(name, _pit_t) [parent iterator]
*/ */
#define BPTREEI_DEF_P2(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \ #define BPTREEI_DEF_P4(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t) \
\ \
M_IF(isMap)( \ M_IF(isMap)( \
/* Type returned by the iterator. Due to having key and value \ /* Type returned by the iterator. Due to having key and value \
+16 -6
View File
@@ -34,13 +34,15 @@
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name, _it_t) ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name, _it_t) ), \
(name, __VA_ARGS__, M_C(name,_t), M_C(name, _it_t) ))) (name, __VA_ARGS__, M_C(name,_t), M_C(name, _it_t) )))
/* Define a dual-push singly linked list of a given type.
USAGE: LIST_DEF(name, type [, oplist_of_the_type]) */ /* Define a singly linked list of a given type allowing both push.
USAGE: LIST_DUAL_PUSH_DEF(name, type [, oplist_of_the_type]) */
#define LIST_DUAL_PUSH_DEF(name, ...) \ #define LIST_DUAL_PUSH_DEF(name, ...) \
LISTI_DUAL_PUSH_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \ LISTI_DUAL_PUSH_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name, _it_t) ), \ ((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), M_C(name,_t), M_C(name, _it_t) ), \
(name, __VA_ARGS__, M_C(name,_t), M_C(name, _it_t) ))) (name, __VA_ARGS__, M_C(name,_t), M_C(name, _it_t) )))
/* Define the oplist of a list of type. /* Define the oplist of a list of type.
USAGE: LIST_OPLIST(name [, oplist_of_the_type]) */ USAGE: LIST_OPLIST(name [, oplist_of_the_type]) */
#define LIST_OPLIST(...) \ #define LIST_OPLIST(...) \
@@ -820,15 +822,22 @@
so that all arguments are evaluated before further expansion */ so that all arguments are evaluated before further expansion */
#define LISTI_DUAL_PUSH_DEF_P1(arg) LISTI_DUAL_PUSH_DEF_P2 arg #define LISTI_DUAL_PUSH_DEF_P1(arg) LISTI_DUAL_PUSH_DEF_P2 arg
/* Validate the oplist before going further */
#define LISTI_DUAL_PUSH_DEF_P2(name, type, oplist, list_t, it_t) \
M_IF_OPLIST(oplist)(LISTI_DUAL_PUSH_DEF_P3, LISTI_DUAL_PUSH_DEF_FAILURE)(name, type, oplist, list_t, it_t)
/* Stop processing with a compilation failure */
#define LISTI_DUAL_PUSH_DEF_FAILURE(name, type, oplist, list_t, it_t) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(LIST_DUAL_PUSH_DEF): the given argument is not a valid oplist: " #oplist)
/* Internal dual-push list definition /* Internal dual-push list definition
- name: prefix to be used - name: prefix to be used
- type: type of the elements of the array - type: type of the elements of the array
- oplist: oplist of the type of the elements of the container - oplist: oplist of the type of the elements of the container
- list_t: alias for M_C(name, _t) [ type of the container ] - list_t: alias for M_C(name, _t) [ type of the container ]
- it_t: alias for M_C(name, _it_t) [ iterator of the container ] - it_t: alias for M_C(name, _it_t) [ iterator of the container ]
- node_t: alias for M_C(name, _node_t) [ node ]
*/ */
#define LISTI_DUAL_PUSH_DEF_P2(name, type, oplist, list_t, it_t) \ #define LISTI_DUAL_PUSH_DEF_P3(name, type, oplist, list_t, it_t) \
\ \
struct M_C(name, _s) { \ struct M_C(name, _s) { \
struct M_C(name, _s) *next; \ struct M_C(name, _s) *next; \
@@ -855,9 +864,10 @@
} it_t[1]; \ } it_t[1]; \
\ \
LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \ LISTI_MEMPOOL_DEF(name, type, oplist, list_t, it_t) \
LISTI_DUAL_PUSH_DEF_P3(name, type, oplist, list_t, it_t) \ LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t) LISTI_ITBASE_DEF(name, type, oplist, list_t, it_t)
/* Define the internal contract of an dual-push list */ /* Define the internal contract of an dual-push list */
#define LISTI_DUAL_PUSH_CONTRACT(l) do { \ #define LISTI_DUAL_PUSH_CONTRACT(l) do { \
assert (l != NULL); \ assert (l != NULL); \
@@ -873,7 +883,7 @@
- it_t: alias for M_C(name, _it_t) [ iterator of the container ] - it_t: alias for M_C(name, _it_t) [ iterator of the container ]
- node_t: alias for M_C(name, _node_t) [ node ] - node_t: alias for M_C(name, _node_t) [ node ]
*/ */
#define LISTI_DUAL_PUSH_DEF_P3(name, type, oplist, list_t, it_t) \ #define LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \
\ \
static inline void \ static inline void \
M_C(name, _init)(list_t v) \ M_C(name, _init)(list_t v) \