From 1d003fb3675b7a5f912aad447e6a64a7e70cf8cd Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Wed, 1 Nov 2023 11:10:36 +0100 Subject: [PATCH] WIP Generic header --- Makefile | 2 +- m-generic.h | 119 ++++++++++++++++++++++++++++++++++++++++ tests/test-mgeneric.c | 124 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 m-generic.h create mode 100644 tests/test-mgeneric.c diff --git a/Makefile b/Makefile index b91efb81..af6594d5 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ PACKAGE=m_lib-$(VERSION) VERSION=0.7.1 # Define the contain of the distribution tarball -HEADER=m-algo.h m-array.h m-atomic.h m-bitset.h m-bptree.h m-buffer.h m-c-mempool.h m-concurrent.h m-core.h m-deque.h m-dict.h m-funcobj.h m-genint.h m-i-list.h m-i-shared.h m-list.h m-mempool.h m-thread.h m-mutex.h m-prioqueue.h m-rbtree.h m-serial-bin.h m-serial-json.h m-shared.h m-snapshot.h m-string.h m-tree.h m-try.h m-tuple.h m-variant.h m-worker.h +HEADER=m-algo.h m-array.h m-atomic.h m-bitset.h m-bptree.h m-buffer.h m-c-mempool.h m-concurrent.h m-core.h m-deque.h m-dict.h m-funcobj.h m-generic.h m-genint.h m-i-list.h m-i-shared.h m-list.h m-mempool.h m-thread.h m-mutex.h m-prioqueue.h m-rbtree.h m-serial-bin.h m-serial-json.h m-shared.h m-snapshot.h m-string.h m-tree.h m-try.h m-tuple.h m-variant.h m-worker.h DOC1=LICENSE README.md DOC2=doc/API.txt doc/Container.html doc/Container.ods doc/depend.png doc/DEV.md doc/ISSUES.org doc/oplist.odp doc/oplist.png EXAMPLE=example/ex11-algo01.c example/ex11-algo02.c example/ex11-json01.c example/ex11-section.c example/ex-algo02.c example/ex-algo03.c example/ex-algo04.c example/ex-array00.c example/ex-array01.c example/ex-array02.c example/ex-array03.c example/ex-array04.c example/ex-array05.c example/ex-bptree01.c example/ex-buffer01.c example/ex-dict01.c example/ex-dict02.c example/ex-dict03.c example/ex-dict04.c example/ex-grep01.c example/ex-list01.c example/ex-mph.c example/ex-multi01.c example/ex11-multi02.c example/ex-multi03.c example/ex-multi04.c example/ex-multi05.c example/ex-rbtree01.c example/ex11-algo02.json example/ex11-json01.json example/Makefile example/ex-defer01.c example/ex-string01.c example/ex-string02.c example/ex-astar.c example/ex-string03.c example/ex11-tstc.c example/ex-no-stdio.c example/ex11-count-lines.c example/ex11-json-net.c example/ex11-rbtree02.c diff --git a/m-generic.h b/m-generic.h new file mode 100644 index 00000000..f5991896 --- /dev/null +++ b/m-generic.h @@ -0,0 +1,119 @@ +/* + * M*LIB - Generic 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_GENERIC_H +#define MSTARLIB_GENERIC_H + +#include "m-core.h" + +/* 3 levels of indirection are neeeded: + * One level is the organisation. + * One level is the component of the organisation. + * One level is the oplist within the component of the organisation + Return the list of unevaled oplist that are registered accorss all organisations, all components. + MLIB Organisation is the default organisation and is always registered + Usage Domain: Nb organizations * Nb components * Nb oplists < M_MAX_NB_ARGUMENT +*/ +#define M_G3N_REGISTERED_ITEMS() \ + M_CROSS_MAP( M_G3N_IS_PRESENT3, ( comp M_CROSS_MAP(M_G3N_IS_PRESENT2, (MLIB M_MAP(M_G3N_IS_PRESENT, M_SEQ(1, 50))), ( M_SEQ(1, 50) ) ) ), ( M_SEQ(1, 50) ) ) + +#define M_G3N_IS_PRESENT(num) \ + M_IF(M_PARENTHESIS_P(M_C(M_GENERIC_ORG_, num)() ))(M_DEFERRED_COMMA M_ID M_C(M_GENERIC_ORG_, num)(), ) + +#define M_G3N_IS_PRESENT2(el1, num) \ + M_IF(M_PARENTHESIS_P(M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()))(M_DEFERRED_COMMA M_APPLY(M_C3, el1, _COMP_, M_ID M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()), ) + +#define M_G3N_IS_PRESENT3(el1, num) \ + M_IF(M_OPLIST_P(M_C4(M_GENERIC_ORG_, el1, _OPLIST_, num)()))(M_DEFERRED_COMMA M_C4(M_GENERIC_ORG_, el1, _OPLIST_, num), ) + +// Dummy unused structure. Just to fill in default case of the _Generic +struct m_g3neric_dummys; + +// Call the OPERATOR call of the oplist registered to the variable 'x' +// which takes one argument. +#define M_G3N_CALL_1(call, x) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_CALL_1_func, (call, x) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void)0) +#define M_G3N_CALL_1_func(x, oplist) \ + M_G3N_CALL_1_func_expand(M_GET_GENTYPE oplist(), M_PAIR_1 x, M_PAIR_2 x, oplist) +#define M_G3N_CALL_1_func_expand(gentype, call, x, oplist) \ + gentype: call(oplist(), M_AS_TYPE(gentype, x)), + +// Call the OPERATOR call of the oplist registered to the variable 'x' +// which takes two argument (type, type) +#define M_G3N_CALL_2(call, x, y) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_CALL_2_func, (call, x, y) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_2_func(x, oplist) \ + M_G3N_CALL_2_func_expand(M_GET_GENTYPE oplist(), M_TRIPLE_1 x, M_TRIPLE_2 x, M_TRIPLE_3 x, oplist) +#define M_G3N_CALL_2_func_expand(gentype, call, x, y, oplist) \ + gentype: call(oplist(), M_AS_TYPE(gentype, x), M_AS_TYPE(gentype, y)), + +// Call the OPERATOR call of the oplist registered to the variable 'x' +// which takes two argument (type, subtype) +#define M_G3N_CALL_2t(call, x, y) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_CALL_2t_func, (call, x, y) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_2t_func(x, oplist) \ + M_G3N_CALL_2t_func_expand(M_GET_GENTYPE oplist(), \ + M_IF_METHOD(GENTYPE, M_GET_OPLIST oplist())(M_GET_GENTYPE M_GET_OPLIST oplist(), M_GET_SUBTYPE oplist()), \ + M_TRIPLE_1 x, M_TRIPLE_2 x, M_TRIPLE_3 x, oplist) +#define M_G3N_CALL_2t_func_expand(gentype, basictype, call, x, y, oplist) \ + gentype: call(oplist(), M_AS_TYPE(gentype, x), M_AS_TYPE(basictype, y)), + + +// Define generic functions +// TODO: m_ prefix? +#define init(x) M_G3N_CALL_1(M_CALL_INIT, x) +#define init_set(x, y) M_G3N_CALL_2(M_CALL_INIT_SET, x, y) +#define set(x, y) M_G3N_CALL_2(M_CALL_SET, x, y) +#define clear(x) M_G3N_CALL_1(M_CALL_CLEAR, x) +#define init_move(x, y) M_G3N_CALL_2(M_CALL_INIT_MOVE, x, y) +#define push(x, y) M_G3N_CALL_2t(M_CALL_PUSH, x, y) + + +/* User code has to register oplists : + +#define M_GENERIC_ORG_2() (USER) +#define M_GENERIC_ORG_USER_COMP_1() (CORE) +#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_6() FLT1 +#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_7() STR1 +*/ + +// Don't need to register M*LIB organisation as it is the default one +//#define M_GENERIC_ORG_1() (MLIB) + +// TODO: Register CORE component +// TODO: Register oplist to CORE component (m-string ? serial ?) +// TODO: Add GENTYPE to all types +//#define M_GENERIC_ORG_MLIB_COMP_1() (CORE) +//#define M_GENERIC_ORG_MLIB_COMP_CORE_OPLIST_1() STR1 +//#define M_GENERIC_ORG_MLIB_COMP_CORE_OPLIST_5() FLT1 + + + +#endif diff --git a/tests/test-mgeneric.c b/tests/test-mgeneric.c new file mode 100644 index 00000000..2b82b0c0 --- /dev/null +++ b/tests/test-mgeneric.c @@ -0,0 +1,124 @@ +/* + * 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. +*/ + +#include +#include +#include "coverage.h" + +#include "m-string.h" +#include "m-generic.h" + +// Serial json is not supported for standard types if not C11 +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + +static void h(string_t x) +{ + string_set_str(x, "TEST STRING"); +} + +const string_t gx; + + +/* + init(x) + init_set(x,y) + set(x,y) + clear(x) + init_move(x,y) + init_with(x, ...) + swap(x,y) + reset(x) + bool empty_p(x) + size_t get_size(x) + size_t hash(x) + bool equal(x, y) + int cmp(x,y) + add(x, y) + sub(x, y) + mul(x, y) + div(x, y) + T* get(x, key) + set(x, key, value) + T *safe_get(x, key) + erase(x, key) + push(x, y) + pop(x, y) + ... + pas de pb + + pb for iterator through "each": + FIXME: uses of C23 typeof + extensions ? + */ + +#define STR1 M_OPEXTEND(STRING_OPLIST, GENTYPE(struct m_string_s *)) +#define FLT1 (GENTYPE(float), TYPE(float), INIT(M_INIT_DEFAULT)) + +//#define M_GENERIC_ORG_MLIB_COMP_1() (CORE) +//#define M_GENERIC_ORG_MLIB_COMP_CORE_OPLIST_1() STR1 +//#define M_GENERIC_ORG_MLIB_COMP_CORE_OPLIST_5() FLT1 + +#define M_GENERIC_ORG_2() (USER) +#define M_GENERIC_ORG_USER_COMP_1() (CORE) +#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_6() FLT1 +#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_7() STR1 + +// typeof(_Generic(...) ) ? +// GCC/CLANG/TCC: __extension__ __typeof__ +// MSVC++: decltype +// C23; typeof + +static void test_string(string_t p) +{ + string_t s , d; + // ‘_Generic’ selector of type ‘const struct m_string_s *’ is not compatible with any association + //init(gx); + + init(s); + h(s); + init_set(d, s); + h(d); + init_set(p, gx); + clear(s); + clear(d); + + float f; + init(f); + clear(f); + clear(p); +// clear(gx); +} + +int main(void) +{ + string_t p; + test_string(p); + + exit(0); +} + +#else +int main(void) +{ + exit(0); +} +#endif