diff --git a/Makefile b/Makefile index 821552f2..a8481a92 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 doc/bench-array-log.png doc/bench-array.png doc/bench-list-log.png doc/bench-list.png doc/bench-oset-log.png doc/bench-oset.png doc/bench-umap-log.png doc/bench-umap.png doc/cc.sh 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 example/ex-curl.c example/ex-dict05.c example/ex-dict06.c example/exm-lib.c example/exm-main.c example/exn-lib.c example/exn-main.c example/exm-header.h example/exn-header.h diff --git a/m-core.h b/m-core.h index ddad841d..9fb291f0 100644 --- a/m-core.h +++ b/m-core.h @@ -1459,6 +1459,8 @@ M_BEGIN_PROTECTED_CODE #define M_PATTERN_TYPE_TYPE , #define M_PATTERN_SUBTYPE_SUBTYPE , #define M_PATTERN_IT_TYPE_IT_TYPE , +#define M_PATTERN_KEY_TYPE_KEY_TYPE , +#define M_PATTERN_VALUE_TYPE_VALUE_TYPE , #define M_PATTERN_M_UNDERFLOW_M_UNDERFLOW , #define M_PATTERN_M_OVERFLOW_M_OVERFLOW , #define M_PATTERN_M_OVERFLOW_M_OVERFLOW , diff --git a/m-generic.h b/m-generic.h new file mode 100644 index 00000000..802f8531 --- /dev/null +++ b/m-generic.h @@ -0,0 +1,254 @@ +/* + * 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" + +#ifdef _MSC_VER +#define m_typeof(x) decltype(x) +#elif defined(__GNUC__) +#define m_typeof(x) __typeof__(x) +#else +// Definition valid for C23, TCC +#define m_typeof(x) typeof(x) +#endif + + +// Instead of using expensive M_SEQ(1,50), precompute it: +#define M_G3N_SEQ_INT \ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, \ + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \ + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 + +/* 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_G3N_SEQ_INT)), ( M_G3N_SEQ_INT ) ) ), ( M_G3N_SEQ_INT ) ) + +#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; + +// Synonymous for some basic pointers doesn't work well with prepropressing code +typedef FILE *m_g3n_file; +typedef const char *m_g3n_cstring; +typedef const char **m_g3n_cstring_end; + +#define M_AS_LINKED_TYPE(typex, x, typey, y) _Generic(((void)0,(x)), typex: (y), default: (typey) {0}) + +#define M_G3N_IT_TYPE(oplist) m_typeof( ((void)0, (M_GET_IT_TYPE oplist()){0})) + +// Translate type' into the container type if type == TYPE, IT_TYPE into its iterator +// KEY_TYPE, VALUE_TYPE, SUBTYPE into the associated type in the oplist, +// or keep 'type' otherwise +#define M_G3N_TYPE(type, oplist) M_GET_METHOD(type, type, M_OPFLAT oplist ()) + +// Call the OPERATOR call of the oplist registered to the variable 'x' +// which takes one argument. +#define M_G3N_CALL_1(op, x) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_CALL_1_func, (op, 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_test(M_GET_GENTYPE oplist(), M_PAIR_1 x, M_PAIR_2 x, oplist) +#define M_G3N_CALL_1_func_test(gentype, op, x, oplist) \ + M_IF_METHOD(op, oplist())(M_G3N_CALL_1_func_expand, M_EAT)(gentype, op, x, oplist) +#define M_G3N_CALL_1_func_expand(gentype, op, x, oplist) \ + gentype: M_C(M_CALL_, op)(oplist(), M_AS_TYPE(gentype, x)), \ + const gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(const gentype, x, gentype, x)), + +// Call the OPERATOR call of the oplist registered to the variable 'svar' +// which takes 2 arguments of the given type +#define M_G3N_CALL_2(op, svar, type1, var1, type2, var2) \ + _Generic( ((void)0, (svar)), \ + M_MAP2(M_G3N_CALL_2_func, (op, svar, type1, var1, type2, var2) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_2_func(x, oplist) \ + M_APPLY(M_G3N_CALL_2_func_test, M_GET_GENTYPE oplist(), M_ID x, oplist) +#define M_G3N_CALL_2_func_test(gentype, op, svar, type1, var1, type2, var2, oplist) \ + M_IF_METHOD(op, oplist())(M_G3N_CALL_2_func_expand, M_EAT)(gentype, op, svar, M_G3N_TYPE(type1, oplist), var1, M_G3N_TYPE(type2, oplist), var2, oplist) +#define M_G3N_CALL_2_func_expand(gentype, op, svar, type1, var1, type2, var2, oplist) \ + gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(gentype, svar, type1, var1), M_AS_LINKED_TYPE(gentype, svar, type2, var2) ), \ + const gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(const gentype, svar, type1, var1), M_AS_LINKED_TYPE(const gentype, svar, type2, var2) ), + +// Call the OPERATOR call of the oplist registered to the variable 'svar' +// which takes 3 arguments of the given type +#define M_G3N_CALL_3(op, svar, type1, var1, type2, var2, type3, var3) \ + _Generic( ((void)0, (svar)), \ + M_MAP2(M_G3N_CALL_3_func, (op, svar, type1, var1, type2, var2, type3, var3) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_3_func(x, oplist) \ + M_APPLY(M_G3N_CALL_3_func_test, M_GET_GENTYPE oplist(), M_ID x, oplist) +#define M_G3N_CALL_3_func_test(gentype, op, svar, type1, var1, type2, var2, type3, var3, oplist) \ + M_IF_METHOD(op, oplist())(M_G3N_CALL_3_func_expand, M_EAT)(gentype, op, svar, M_G3N_TYPE(type1, oplist), var1, M_G3N_TYPE(type2, oplist), var2, M_G3N_TYPE(type3, oplist), var3, oplist) +#define M_G3N_CALL_3_func_expand(gentype, op, svar, type1, var1, type2, var2, oplist) \ + gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(gentype, svar, type1, var1), M_AS_LINKED_TYPE(gentype, svar, type2, var2) ), \ + const gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(const gentype, svar, type1, var1), M_AS_LINKED_TYPE(const gentype, svar, type2, var2) ), + +// Call the OPERATOR call of the oplist registered to the variable 'svar' +// which takes 4 arguments of the given type +#define M_G3N_CALL_4(op, svar, type1, var1, type2, var2, type3, var3, type4, var4) \ + _Generic( ((void)0, (svar)), \ + M_MAP2(M_G3N_CALL_4_func, (op, svar, type1, var1, type2, var2, type3, var3, type4, var4) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_4_func(x, oplist) \ + M_APPLY(M_G3N_CALL_4_func_test, M_GET_GENTYPE oplist(), M_ID x, oplist) +#define M_G3N_CALL_4_func_test(gentype, op, svar, type1, var1, type2, var2, type3, var3, type4, var4, oplist) \ + M_IF_METHOD(op, oplist())(M_G3N_CALL_4_func_expand, M_EAT)(gentype, op, svar, M_G3N_TYPE(type1, oplist), var1, M_G3N_TYPE(type2, oplist), var2, M_G3N_TYPE(type3, oplist), var3, M_G3N_TYPE(type4, oplist), var4, oplist) +#define M_G3N_CALL_4_func_expand(gentype, op, svar, type1, var1, type2, var2, oplist) \ + gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(gentype, svar, type1, var1), M_AS_LINKED_TYPE(gentype, svar, type2, var2) ), \ + const gentype: M_C(M_CALL_, op)(oplist(), M_AS_LINKED_TYPE(const gentype, svar, type1, var1), M_AS_LINKED_TYPE(const gentype, svar, type2, var2) ), + +// Call the OPERATOR call of the oplist registered to the variable 'x' +// which takes one argument, it_type +#define M_G3N_CALL_1i(op, x) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_CALL_1i_func, (op, x) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void)0) +#define M_G3N_CALL_1i_func(x, oplist) \ + M_G3N_CALL_1_func_test(M_G3N_IT_TYPE(oplist), M_PAIR_1 x, M_PAIR_2 x, oplist) + +// Call the OPERATOR call of the oplist registered to the variable 'svar' +// which takes 2 arguments of the given it_type +#define M_G3N_CALL_2i(op, svar, type1, var1, type2, var2) \ + _Generic( ((void)0, (svar)), \ + M_MAP2(M_G3N_CALL_2i_func, (op, svar, type1, var1, type2, var2) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void) 0) +#define M_G3N_CALL_2i_func(x, oplist) \ + M_APPLY(M_G3N_CALL_2_func_test, M_G3N_IT_TYPE(oplist), M_ID x, oplist) + +// Create a variable of type OPERATOR call of the oplist registered to the variable 'x' +#define M_G3N_TYPE_1(op, x) \ + _Generic( ((void)0, (x)), \ + M_MAP2(M_G3N_TYPE_1_func, (op, x) M_G3N_REGISTERED_ITEMS() ) \ + struct m_g3neric_dummys *: /* cannot happen */ (void)0) +#define M_G3N_TYPE_1_func(x, oplist) \ + M_G3N_TYPE_1_func_test(M_GET_GENTYPE oplist(), M_PAIR_1 x, M_PAIR_2 x, oplist) +#define M_G3N_TYPE_1_func_test(gentype, op, x, oplist) \ + M_IF_METHOD(op, oplist())(M_G3N_TYPE_1_func_expand, M_EAT)(gentype, op, x, oplist) +#define M_G3N_TYPE_1_func_expand(gentype, op, x, oplist) \ + gentype: (M_G3N_TYPE(op, oplist)){0}, \ + const gentype: (M_G3N_TYPE(op, oplist)){0}, + + +// Define the generic macro-functions +// TODO: m_ prefix? +#define init(x) M_G3N_CALL_1(INIT, x) +#define init_set(x, y) M_G3N_CALL_2(INIT_SET, x, TYPE, x, TYPE, y) +#define init_move(x, y) M_G3N_CALL_2(INIT_MOVE, x, TYPE, x, TYPE, y) +#define move(x, y) M_G3N_CALL_2(MOVE, x, TYPE, x, TYPE, y) +#define set(x, y) M_G3N_CALL_2(SET, x, TYPE, x , TYPE, y) +#define clear(x) M_G3N_CALL_1(CLEAR, x) +#define swap(x, y) M_G3N_CALL_2(SWAP, x, TYPE, x , TYPE, y) +#define hash(x) M_G3N_CALL_1(HASH, x) +#define equal(x, y) M_G3N_CALL_2(EQUAL, x, TYPE, x , TYPE, y) +#define cmp(x, y) M_G3N_CALL_2(CMP, x, TYPE, x , TYPE, y) +#define sort(x) M_G3N_CALL_1(SORT, x) +#define splice_back(d, s, i) M_G3N_CALL_3(SPLICE_BACK, d, TYPE, d, TYPE, s, IT_TYPE, i) +#define splice_at(d, id, s, is) M_G3N_CALL_4(SPLICE_BACK, d, TYPE, d, IT_TYPE, id, TYPE, s, IT_TYPE, is) +#define it_type(x) m_typeof(M_G3N_TYPE_1(IT_TYPE, x)) +#define sub_type(x) m_typeof(M_G3N_TYPE_1(SUBTYPE, x)) +#define key_type(x) m_typeof(M_G3N_TYPE_1(KEY_TYPE, x)) +#define value_type(x) m_typeof(M_G3N_TYPE_1(VALUE_TYPE, x)) +#define it_first(x, y) M_G3N_CALL_2(IT_FIRST, y, IT_TYPE, x, TYPE, y) +#define it_last(x, y) M_G3N_CALL_i2(IT_LAST, y, IT_TYPE, x, TYPE, y) +#define it_end(x, y) M_G3N_CALL_i2(IT_END, y, IT_TYPE, x, TYPE, y) +#define it_set(d, s) M_G3N_CALL_2i(IT_SET, d, IT_TYPE, d, IT_TYPE, s) +#define it_end_p(i) M_G3N_CALL_1i(IT_END_P, i) +#define it_last_p(i) M_G3N_CALL_1i(IT_LAST_P, i) +#define it_next(i) M_G3N_CALL_1i(IT_NEXT, i) +#define it_previous(i) M_G3N_CALL_1i(IT_PREVIOUS, i) +#define it_ref(i) M_G3N_CALL_1i(IT_REF, i) +#define it_cref(i) M_G3N_CALL_1i(IT_CREF, i) +#define it_equal(x, y) M_G3N_CALL_2i(IT_EQUAL, x, IT_TYPE, x, IT_TYPE, y) +#define it_insert(c, i, o) M_G2N_CALL_3(IT_INSERT, c, TYPE, c, IT_TYPE, i, SUBTYPE, o) +#define it_remove(c, i) M_G3N_CALL_2(IT_REMOVE, c, TYPE, c, IT_TYPE, i) +#define empty_p(x) M_G3N_CALL_1(EMPTY_P, x) +#define add(x, y) M_G3N_CALL_2(ADD, x, TYPE, x, TYPE, y) +#define sub(x, y) M_G3N_CALL_2(SUB, x, TYPE, x, TYPE, y) +#define mul(x, y) M_G3N_CALL_2(MUL, x, TYPE, x, TYPE, y) +#define div(x, y) M_G3N_CALL_2(DIV, x, TYPE, x, TYPE, y) +#define reset(x) M_G3N_CALL_1(RESET, x) +#define get(x, y) M_G3N_CALL_2(GET_KEY, x, TYPE, x, KEY_TYPE, y) +#define set_at(x, y, z) M_G3N_CALL_3(SET_KEY, x, TYPE, x, KEY_TYPE, y, VALUE_TYPE, z) +#define safe_get(x, y) M_G3N_CALL_2(SAFE_GET_KEY, x, TYPE, x, KEY_TYPE, y) +#define erase(x, y) M_G3N_CALL_2(ERASE, x, TYPE, x, KEY_TYPE, y) +#define get_size(x) M_G3N_CALL_1(GET_SIZE, x) +#define push(x, y) M_G3N_CALL_2(PUSH, x, TYPE, x, SUBTYPE, y) +#define pop(x, y) M_G3N_CALL_2(PUSH, x, TYPE, x, SUBTYPE, y) +#define push_move(x, y) M_G3N_CALL_2(PUSH_MOVE, x, TYPE, x, SUBTYPE *, y) +#define pop_move(x, y) M_G3N_CALL_2(PUSH, x, TYPE, x, SUBTYPE*, y) +#define reverse(x) M_G3N_CALL_1(REVERSE, x) +#define get_str(s, c, b) M_G3N_CALL_3(GET_STR, c, string_t, s, TYPE, c, bool, b) +#define parse_str(c, s, e) M_G3N_CALL_3(PARSE_STR, c, TYPE, c, m_g3n_cstring, s, m_g3n_cstring_end, e) +#define out_str(x, y) M_G3N_CALL_2(OUT_STR, y, m_g3n_file, x, TYPE, y) +#define in_str(x, y) M_G3N_CALL_2(IN_STR, x, TYPE, x, m_g3n_file, y) +#define out_serial(x, y) M_G3N_CALL_2(OUT_SERIAL, y, m_serial_write_t, x, TYPE, y) +#define in_serial(x, y) M_G3N_CALL_2(IN_SERIAL, x, TYPE, x, m_serial_read_t, y) + +// for each +#define each(item, container) \ + M_G3N_EACHI(item, container, M_C(m_local_it_, __LINE__), M_C(local_pass_, __LINE__)) + +#define M_G3N_EACHI(item, container, l_it, l_pass) \ + (bool l_pass = true; l_pass; l_pass = false) \ + for(sub_type(container) *item; l_pass ; l_pass = false) \ + for(it_type(container) l_it; l_pass ; l_pass = false) \ + for(it_first(l_it, container) ; \ + !it_end_p(l_it) \ + && (item = it_ref(l_it), true) ; \ + it_next(l_it)) + +// TODO: init_with ? How to handle the different type of parameters ? +// TODO: emplace ? +// TODO: Integrate in M_PRINT ? +// TODO: How to handle -Wunreachable-code-generic-assoc which is enabled automatically in CLANG 15? +// Generate warning: due to lvalue conversion of the controlling expression, association of type 'const float' will never be selected because it is qualified [-Wunreachable-code-generic-assoc] +// Pragma if CLANG ? + +/* 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 +*/ + +#endif diff --git a/tests/test-mgeneric.c b/tests/test-mgeneric.c new file mode 100644 index 00000000..8dd98b42 --- /dev/null +++ b/tests/test-mgeneric.c @@ -0,0 +1,116 @@ +/* + * 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-array.h" +#include "m-generic.h" + +// Generic is not supported if not C11 +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + +ARRAY_DEF(array_int, int) +#define M_OPL_array_int_t() ARRAY_OPLIST(array_int, M_BASIC_OPLIST) + +static void h(string_t x) +{ + string_set_str(x, "TEST STRING"); +} + +const string_t gx; + +#define STR1 M_OPEXTEND(STRING_OPLIST, GENTYPE(struct m_string_s *), PUSH(m_string_push_u)) +#define FLT1 (GENTYPE(float), TYPE(float), INIT(M_INIT_BASIC), INIT_SET(M_SET_BASIC), SET(M_SET_BASIC), \ + CLEAR(M_NOTHING_DEFAULT) ) +#define ARRAY1 M_OPEXTEND(M_OPL_array_int_t(), GENTYPE(struct array_int_s *)) + +//#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 + +#define M_GENERIC_ORG_3() (ARRAY) +#define M_GENERIC_ORG_ARRAY_COMP_5() (INT) +#define M_GENERIC_ORG_ARRAY_COMP_INT_OPLIST_6() ARRAY1 + +static bool test_empty(const string_t p) +{ + return empty_p(p); +} + +static void test_string(string_t p) +{ + string_t s , d; + + init(s); + h(s); + init_set(d, s); + h(d); + init_set(p, s); + bool b = test_empty(p); + assert(!b); + push(p, 'c'); + out_str(stdout, p); + clear(s); + clear(d); + + float f; + init(f); + clear(f); + + clear(p); +} + +static void test_array(void) +{ + M_LET(a, array_int_t) { + push(a, 14); + push(a, 15); + out_str(stdout, a); + for each(it, a) { + printf("=%d, ", *it); + } + } +} + +int main(void) +{ + string_t p; + test_string(p); + test_array(); + exit(0); +} + +#else +int main(void) +{ + exit(0); +} +#endif