From 055e74d350ae12fa398524fe7b68998f7d424bdf Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 9 May 2020 16:10:56 +0200 Subject: [PATCH] Add more check for valid oplists before expanding further --- m-algo.h | 63 ++++++++++++++++++++++++++++++++---------------------- m-array.h | 1 + m-bptree.h | 15 ++++++++++++- m-list.h | 22 +++++++++++++------ 4 files changed, 69 insertions(+), 32 deletions(-) diff --git a/m-algo.h b/m-algo.h index 9e60ac65..1f30d3b3 100644 --- a/m-algo.h +++ b/m-algo.h @@ -108,39 +108,52 @@ /********************************** INTERNAL ************************************/ +/* Expand the algorithms */ #define ALGOI_DEF_P1(name, 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_IT_TYPE cont_oplist) +/* First validate the first oplist */ #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) \ - M_IF_FUNCOBJ(ALGOI_FUNCOBJ_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_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t)) \ \ 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 */) \ \ - 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) \ - 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))) \ + 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_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) \ - 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)) ) \ + 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_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 */ \ M_IF_METHOD(IT_REF, cont_oplist)( \ - ALGOI_FILL_DEF_P3(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_FILL_DEF_P5(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)( \ - ALGOI_MINMAX_DEF_P3(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_P3(name, container_t, cont_oplist, type_t, type_oplist, it_t, -, _sort_dsc) \ + ALGOI_MINMAX_DEF_P5(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ + ALGOI_SORT_DEF_P5(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_dsc) \ 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 CMP method */) \ \ @@ -152,7 +165,7 @@ , /* 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, _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, _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, _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 * ) \ -#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) { \ return order M_CALL_CMP(type_oplist, *a, *b); \ @@ -455,7 +468,7 @@ , /* 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 */ \ static inline void \ 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 \ 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 \ M_C(name, _fill) (container_t l, type_t const value) \ @@ -660,7 +673,7 @@ , /* 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 \ 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 \ 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 * \ M_C(name, _min) (const container_t l) \ @@ -809,7 +822,7 @@ *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 \ 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)( \ static inline void M_C(name, _add) (container_t dst, const container_t src) \ diff --git a/m-array.h b/m-array.h index 7adf316e..1a80a295 100644 --- a/m-array.h +++ b/m-array.h @@ -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_C(name,_t), M_C(name,_it_t)))) + /* 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 USAGE: ARRAY_OPLIST(name[, oplist of the type]) */ diff --git a/m-bptree.h b/m-bptree.h index da8270b3..1fd74de9 100644 --- a/m-bptree.h +++ b/m-bptree.h @@ -81,6 +81,7 @@ ((__VA_ARGS__, M_DEFAULT_OPLISTR ), \ (__VA_ARGS__ ))) + /* Define the oplist of a rbtree of type (from BPTREE_DEF2). USAGE: BPTREE_OPLIST2(name, key_oplist, value_oplist) 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 */ #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 - name: prefix to be used - N: size of the node @@ -229,7 +242,7 @@ - node_t: alias for M_C(name, _node_t) [ node ] - 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)( \ /* Type returned by the iterator. Due to having key and value \ diff --git a/m-list.h b/m-list.h index ef78da08..f03568fc 100644 --- a/m-list.h +++ b/m-list.h @@ -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_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, ...) \ 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_C(name,_t), M_C(name, _it_t) ))) + /* Define the oplist of a list of type. USAGE: LIST_OPLIST(name [, oplist_of_the_type]) */ #define LIST_OPLIST(...) \ @@ -820,15 +822,22 @@ so that all arguments are evaluated before further expansion */ #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 - name: prefix to be used - type: type of the elements of the array - oplist: oplist of the type of the elements 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 ] - - 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) *next; \ @@ -855,9 +864,10 @@ } it_t[1]; \ \ 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) + /* Define the internal contract of an dual-push list */ #define LISTI_DUAL_PUSH_CONTRACT(l) do { \ assert (l != NULL); \ @@ -873,7 +883,7 @@ - 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_P3(name, type, oplist, list_t, it_t) \ +#define LISTI_DUAL_PUSH_DEF_P4(name, type, oplist, list_t, it_t) \ \ static inline void \ M_C(name, _init)(list_t v) \