From 9da78656f7b4a756dad2bf1c285a61a5186fd5ae Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 24 Nov 2021 22:56:09 +0100 Subject: Deprecated c_no_compare(). Define i_cmp_none instead when you have/want no element comparison for cvec, cdeq, clist, csptr. Will give compile time error if functions depending on comparisons are used. --- README.md | 31 +++++++++++++++----------- examples/complex.c | 2 +- examples/new_sptr.c | 1 - examples/sptr_ex.c | 1 - examples/sptr_pthread.c | 1 - include/stc/ccommon.h | 2 +- include/stc/cdeq.h | 6 ++++- include/stc/clist.h | 59 ++++++++++++++++++++++++++++--------------------- include/stc/csptr.h | 7 +++++- include/stc/cvec.h | 9 ++++++-- include/stc/template.h | 3 +++ 11 files changed, 75 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 7b53a8e5..aa680115 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,9 @@ Benchmark notes: Usage ----- -The usage of the containers is similar to the c++ standard containers in STL, so it should be easy if you are familiar with them. -All containers are generic/templated, except for **cstr** and **cbits**. No casting is used, so containers are type-safe like -templates in c++. A basic usage example: +The usage of the containers is similar to the c++ standard containers in STL, so it should be easy if you +are familiar with them. All containers are generic/templated, except for **cstr** and **cbits**. +No casting is used, so containers are type-safe like templates in c++. A basic usage example: ```c #define i_val float #include @@ -91,15 +91,17 @@ int main(void) { cvec_float_del(&vec); } ``` -In order to include two **cvec**s with different element types, include cvec.h twice. For structs, specify a compare function (or none), as `<` and `==` operators does not work on them (this enables sorting and searching). +In order to include two **cvec**s with different element types, include cvec.h twice. For structs, +specify a compare function (as `<` and `==` operators does not work on them), or `i_cmp_none`. +This enables sorting and searching. ```c #define i_val struct One -#define i_cmp c_no_compare +#define i_cmp_none #define i_tag one #include #define i_val struct Two -#define i_cmp c_no_compare +#define i_cmp_none #define i_tag two #include ... @@ -192,7 +194,8 @@ int main(void) { } } ``` -**Note**: Do ***not*** `return` from inside a `c_auto*`-block. Instead, first `continue`, which will jump out of the block, then call `return` after the block. +**Note**: Do ***not*** `return` from inside a `c_auto*`-block. Instead, first `continue`, which will +jump out of the block, then call `return` after the block. Output ``` @@ -208,12 +211,14 @@ After erasing elements found: Installation ------------ -Because it is headers-only, headers can simply be included in your program. The methods are static by default (some inlined). -You may add the *include* folder to the **CPATH** environment variable to let GCC, Clang, and TinyC locate the headers. - -If containers are used across several translation units with common instantiated container types, it is recommended to -build as a "library" to minimize the executable size. To enable this mode, specify **-DSTC_HEADER** as a compiler option -in your build environment and place all the instantiations of containers used in a single C-source file, e.g.: +Because it is headers-only, headers can simply be included in your program. The methods are static +by default (some inlined). You may add the *include* folder to the **CPATH** environment variable to +let GCC, Clang, and TinyC locate the headers. + +If containers are used across several translation units with common instantiated container types, +it is recommended to build as a "library" to minimize the executable size. To enable this mode, +specify **-DSTC_HEADER** as a compiler option in your build environment and place all the instantiations +of containers used in a single C-source file, e.g.: ```c // stc_libs.c #define STC_IMPLEMENTATION diff --git a/examples/complex.c b/examples/complex.c index 32dd82eb..64c1903e 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -8,7 +8,7 @@ void check_del(float* v) {printf("destroy %g\n", *v);} #include #define i_val cstack_f -#define i_cmp c_no_compare +#define i_cmp_none #define i_valdel cstack_f_del #define i_tag arr #include diff --git a/examples/new_sptr.c b/examples/new_sptr.c index 77e663b7..036ce581 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -12,7 +12,6 @@ void Person_del(Person* p) { #define i_val Person #define i_del Person_del -#define i_cmp c_no_compare #define i_tag person #include diff --git a/examples/sptr_ex.c b/examples/sptr_ex.c index 8c803db5..702edef9 100644 --- a/examples/sptr_ex.c +++ b/examples/sptr_ex.c @@ -18,7 +18,6 @@ void Song_del(Song* s) { } #define i_val Song -#define i_cmp c_no_compare #define i_del Song_del #define i_tag song #include // define csptr_song diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c index 444d0afe..63b9a7a4 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -14,7 +14,6 @@ struct Base void Base_del(Base* b) { printf("Base::~Base()\n"); } #define i_val Base -#define i_cmp c_no_compare #define i_del Base_del #define i_tag base #include diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index acf09dde..7d0eceeb 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -98,7 +98,7 @@ #define c_default_compare(x, y) c_less_compare(c_default_less, x, y) #define c_default_less(x, y) (*(x) < *(y)) -#define c_no_compare(x, y) (assert(!"c_no_compare() called"), (x)==(y)) +#define c_no_compare(x, y) (assert(!"c_no_compare() called"), (x)==(y)) // [deprecated] #define c_less_compare(less, x, y) (less(y, x) - less(x, y)) #define c_default_equalto(x, y) (*(x) == *(y)) diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index c9eb0627..6475b431 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -170,6 +170,8 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); } +#ifndef i_cmp_none + STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw); @@ -196,6 +198,7 @@ STC_INLINE void _cx_memb(_sort)(_cx_self* self) { _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_compare)); } +#endif // !i_cmp_none #endif // i_queue /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -353,6 +356,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { return c_make(_cx_iter){p1}; } +#ifndef i_cmp_none STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { for (; i1.ref != i2.ref; ++i1.ref) { @@ -368,7 +372,7 @@ _cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y) { i_valraw ry = i_valto(y); return i_cmp(&rx, &ry); } - +#endif // !i_cmp_none #endif // i_queue #endif // IMPLEMENTATION #include "template.h" diff --git a/include/stc/clist.h b/include/stc/clist.h index 247086a1..8a019b65 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -98,11 +98,13 @@ STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_val value); STC_API _cx_iter _cx_memb(_insert)(_cx_self* self, _cx_iter it, i_val value); STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); +#ifndef i_cmp_none STC_API size_t _cx_memb(_remove)(_cx_self* self, i_valraw val); +STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val); +#endif STC_API _cx_iter _cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other); STC_API _cx_self _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2); STC_API void _cx_memb(_sort)(_cx_self* self); -STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val); STC_API _cx_node* _cx_memb(_erase_after_)(_cx_self* self, _cx_node* node); STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } @@ -161,6 +163,7 @@ _cx_memb(_splice_range)(_cx_self* self, _cx_iter it, return _cx_memb(_splice)(self, it, &tmp); } +#ifndef i_cmp_none STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw val) { return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val); @@ -175,6 +178,7 @@ STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, i_valraw val) { return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val).ref; } +#endif // -------------------------- IMPLEMENTATION ------------------------- @@ -235,15 +239,6 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { return it2; } -STC_DEF _cx_iter -_cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val) { - c_foreach (it, _cx_self, it1, it2) { - i_valraw r = i_valto(it.ref); - if (i_cmp(&r, &val) == 0) return it; - } - it2.ref = NULL; return it2; -} - STC_DEF _cx_node* _cx_memb(_erase_after_)(_cx_self* self, _cx_node* node) { _cx_node* del = node->next, *next = del->next; @@ -254,21 +249,6 @@ _cx_memb(_erase_after_)(_cx_self* self, _cx_node* node) { return node; } -STC_DEF size_t -_cx_memb(_remove)(_cx_self* self, i_valraw val) { - size_t n = 0; - _cx_node* prev = self->last, *node; - while (prev) { - node = prev->next; - i_valraw r = i_valto(&node->value); - if (i_cmp(&r, &val) == 0) - prev = _cx_memb(_erase_after_)(self, prev), ++n; - else - prev = (node == self->last ? NULL : node); - } - return n; -} - STC_DEF _cx_iter _cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other) { if (!self->last) @@ -295,6 +275,32 @@ _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2) { return cx; } +#ifndef i_cmp_none + +STC_DEF _cx_iter +_cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val) { + c_foreach (it, _cx_self, it1, it2) { + i_valraw r = i_valto(it.ref); + if (i_cmp(&r, &val) == 0) return it; + } + it2.ref = NULL; return it2; +} + +STC_DEF size_t +_cx_memb(_remove)(_cx_self* self, i_valraw val) { + size_t n = 0; + _cx_node* prev = self->last, *node; + while (prev) { + node = prev->next; + i_valraw r = i_valto(&node->value); + if (i_cmp(&r, &val) == 0) + prev = _cx_memb(_erase_after_)(self, prev), ++n; + else + prev = (node == self->last ? NULL : node); + } + return n; +} + STC_DEF int _cx_memb(_sort_cmp_)(const clist_VOID_node* x, const clist_VOID_node* y) { i_valraw a = i_valto(&((const _cx_node *) x)->value); @@ -310,6 +316,7 @@ _cx_memb(_sort)(_cx_self* self) { if (self->last) self->last = (_cx_node *) _clist_mergesort((clist_VOID_node *) self->last->next, _cx_memb(_sort_cmp_)); } +#endif // !i_cmp_none #endif // TEMPLATE IMPLEMENTATION @@ -324,6 +331,7 @@ _clist_count(const clist_VOID* self) { return n; } +#ifndef i_cmp_none // Singly linked list Mergesort implementation by Simon Tatham. O(n*log n). // https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html STC_DEF clist_VOID_node * @@ -373,6 +381,7 @@ _clist_mergesort(clist_VOID_node *list, int (*cmp)(const clist_VOID_node*, const insize *= 2; } } +#endif // !i_cmp_none #endif // NON-TEMPLATE IMPLEMENTATION #include "template.h" #define CLIST_H_INCLUDED diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 6bcd8a56..7415c20a 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -167,11 +167,16 @@ _cx_memb(_take)(_cx_self* self, _cx_self ptr) { *self = ptr; } +#ifndef i_cmp_none STC_INLINE int _cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { +#ifdef i_cmp_default + return c_default_compare(&x->get, &y->get); +#else return i_cmp(x->get, y->get); +#endif } - +#endif #undef cx_csptr_rep #undef cx_increment #undef cx_decrement diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 5b58dca7..5e9a9877 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -84,9 +84,11 @@ STC_API void _cx_memb(_del)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, const size_t cap); STC_API bool _cx_memb(_resize)(_cx_self* self, const size_t size, i_val fill_val); +#ifndef i_cmp_none STC_API int _cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y); STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw raw); STC_API _cx_iter _cx_memb(_bsearch_in)(_cx_iter it1, _cx_iter it2, i_valraw raw); +#endif STC_API _cx_value* _cx_memb(_push_back)(_cx_self* self, i_val value); STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); STC_API _cx_iter _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, @@ -192,6 +194,8 @@ _cx_memb(_at)(const _cx_self* self, const size_t idx) { return self->data + idx; } +#ifndef i_cmp_none + STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw); @@ -221,7 +225,7 @@ STC_INLINE void _cx_memb(_sort)(_cx_self* self) { _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_compare)); } - +#endif // !i_cmp_none /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_imp) @@ -339,6 +343,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { return c_make(_cx_iter){.ref = p1}; } +#ifndef i_cmp_none STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { for (; i1.ref != i2.ref; ++i1.ref) { @@ -367,7 +372,7 @@ _cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y) { i_valraw ry = i_valto(y); return i_cmp(&rx, &ry); } - +#endif // !i_cmp_none #endif #include "template.h" #define CVEC_H_INCLUDED diff --git a/include/stc/template.h b/include/stc/template.h index 19ff97f2..ff1ea3fc 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -162,6 +162,7 @@ #endif #ifndef i_cmp #define i_cmp c_default_compare + #define i_cmp_default #endif #else // ------------------------------------------------------- @@ -171,6 +172,8 @@ #undef i_imp #undef i_fwd #undef i_cmp +#undef i_cmp_none +#undef i_cmp_default #undef i_del #undef i_equ #undef i_hash -- cgit v1.2.3