From 323f21d57aaf30ffd43d6b67146bc887ad206298 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 2 Dec 2021 14:39:42 +0100 Subject: Breaking changes for i_fwd and i_cmp_none: - Removed: i_cmp_none and i_fwd (replaced by c_no_compare and c_is_fwd args to i_opt). - Added compile-time disabling of clonable and comparable container elements, controlled by i_opt (c_no_clone | c_no_compare) - Added i_opt: can define multiple compile-time options: c_no_compare, c_no_clone, c_no_atomic, c_is_fwd: may be combined with | separator. - Except for csptr, when i_del / i_valdel / i_keydel is defined, also i_from / i_keyfrom / i_valfrom must be defined or i_opt c_no_clone. - For struct elements, either i_cmp must be defined (as before), or define i_opt c_no_compare for non-associative containers. --- README.md | 54 ++++++++++++++-- docs/ccommon_api.md | 11 ++++ docs/cmap_api.md | 28 ++++----- examples/astar.c | 2 +- examples/complex.c | 5 +- examples/csmap_find.c | 2 +- examples/csmap_insert.c | 2 +- examples/demos.c | 1 - examples/mapmap.c | 5 +- examples/mmap.c | 1 + examples/multimap.c | 10 ++- examples/new_deq.c | 4 +- examples/new_list.c | 4 +- examples/new_map.c | 2 +- examples/new_pque.c | 2 +- examples/new_queue.c | 2 +- examples/new_smap.c | 2 +- examples/new_vec.c | 6 +- examples/ptr_elems.c | 54 ++++++++++++++++ include/stc/alt/csmap.h | 48 +++++++------- include/stc/carr2.h | 31 +++++---- include/stc/carr3.h | 31 +++++---- include/stc/ccommon.h | 14 +++-- include/stc/cdeq.h | 162 ++++++++++++++++++++++++++++-------------------- include/stc/clist.h | 53 +++++++++------- include/stc/cmap.h | 111 ++++++++++++++++++--------------- include/stc/cpque.h | 24 ++++--- include/stc/cqueue.h | 8 +-- include/stc/cset.h | 6 +- include/stc/csmap.h | 117 ++++++++++++++++++---------------- include/stc/csptr.h | 41 ++++++------ include/stc/csset.h | 6 +- include/stc/cstack.h | 16 +++-- include/stc/cstr.h | 2 +- include/stc/cvec.h | 149 ++++++++++++++++++++++++-------------------- include/stc/template.h | 49 ++++++++------- 36 files changed, 636 insertions(+), 429 deletions(-) create mode 100644 examples/ptr_elems.c diff --git a/README.md b/README.md index aa680115..fd865a7e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,13 @@ STC - Smart Template Containers for C News ---- +Breaking changes for i_cmp_none and i_fwd: +- Removed: i_cmp_none and i_fwd (replaced by c_no_compare and c_is_fwd args to i_opt). +- Added compile-time disabling of clonable and comparable container elements, controlled by i_opt (c_no_clone | c_no_compare) +- Added i_opt: can define multiple compile-time options: c_no_compare, c_no_clone, c_no_atomic, c_is_fwd: may be combined with | separator. +- Except for csptr, when i_del / i_valdel / i_keydel is defined, also i_from / i_keyfrom / i_valfrom must be defined or i_opt c_no_clone. +- For struct elements, either i_cmp must be defined (as before), or define i_opt c_no_compare (for non-associative containers only). + **VERSION 2.X RELEASED**: There are two main breaking changes from V1.X. - Uses a different way to instantiate templated containers, which is incompatible with v1.X. - c_forauto, c_forvar, c_forscope macros are now renamed to **c_auto**, **c_autovar**, and **c_autoscope**. These are for automatic scope resource management, aka RAII. @@ -91,17 +98,21 @@ 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 (as `<` and `==` operators does not work on them), or `i_cmp_none`. -This enables sorting and searching. +In order to include two **cvec**s with different element types, include cvec.h twice. For struct, a `i_cmp` +compare function is required to enable sorting and searching (`<` and `==` operators is default and works +for integral types only). Alternatively, `#define i_opt c_no_compare` to disable methods using comparison. + +Similarly, if a destructor `i_del` is defined, either define a `i_valfrom` construct/clone function +or `#define i_opt c_no_clone` to disable cloning and emplace methods. Unless these requirements are met, +compile errors are generated. ```c #define i_val struct One -#define i_cmp_none +#define i_opt c_no_compare #define i_tag one #include #define i_val struct Two -#define i_cmp_none +#define i_opt c_no_compare #define i_tag two #include ... @@ -242,6 +253,37 @@ of containers used in a single C-source file, e.g.: #include // clist_pnt ``` +Specifying template parameters +------------------------------ +Each templated type requires one `#include`, even if it's the same container base type, as described earlier. +The template parameters are given by a `#define i_xxxx` statement, where *xxxx* is the parameter name. +The list of template parameters: + +- `i_tag` - Container type tag. Defaults to same as `i_key` +- `i_cnt` - Container type name. +- `i_opt` - Boolean properties: may combine `c_no_compare`, `c_no_clone`, `c_is_fwd` with `|` character. + +- `i_key` - Maps key type. **[required]** for cmap/csmap. +- `i_val` - The container **[required]** element type. For cmap/csmap, it is the mapped value. +- `i_cmp` - Three-way comparison of two `i_keyraw`, **[required]** for non-integral `i_keyraw`. +- `i_equ` - Equality comparison of two `i_keyraw`, `i_cmp` alternative. + +- `i_keydel` - Destroy map key func - defaults to empty destructor. +- `i_keyraw` - Convertion "raw" type - defaults to `i_key` type. +- `i_keyfrom` - Convertion func `i_keyraw` => `i_key` - defaults to simple copy. **[required]** if `i_keydel` is defined. +- `i_keyto` - Convertion func `i_key` => `i_keyraw` - defaults to simple copy. + +- `i_valdel` - Destroy mapped or value func - defaults to empty destruct. +- `i_valraw` - Convertion "raw" type - defaults to `i_val` type. +- `i_valfrom` - Convertion func `i_valraw` => `i_val` - defaults to simple copy. +- `i_valto` - Convertion func `i_val` => `i_valraw` - defaults to simple copy. + +An alternative to defining `i_cmp`, you may `#define i_opt c_no_compare` to disable methods using comparison. + +Similarly, if a destructor `i_del` is defined, either define `i_valfrom` constructor/clone function +or `#define i_opt c_no_clone` to disable cloning and the emplace methods. Unless these requirements are met, +compile errors are generated. + The *emplace* versus non-emplace container methods -------------------------------------------------- STC, like c++ STL, has two sets of methods for adding elements to containers. One set begins @@ -337,7 +379,7 @@ typedef struct Dataset { ... // Implementation -#define i_fwd // flag that the container was forward declared. +#define c_opt c_is_fwd // flag that the container was forward declared. #define i_val struct Point #define i_tag pnt #include diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index db89120e..3d353e6c 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -155,6 +155,17 @@ cstr a = cstr_from("Hello"), b = cstr_from("World"); c_del(cstr, &a, &b); ``` +### General predefined template parameter functions +``` +int c_default_compare(const Type*, const Type*); +Type c_default_fromraw(Type val); // simple copy +Type c_default_toraw(const Type* val); // dereference val +void c_default_del(Type* val); // does nothing + +int c_rawstr_compare(const char* const* a, const char* const* b); +bool c_rawstr_equalto(const char* const* a, const char* const* b); +``` + ### c_malloc, c_calloc, c_realloc, c_free Memory allocator for the entire library. Macros can be overloaded by the user. diff --git a/docs/cmap_api.md b/docs/cmap_api.md index a33dc5c0..e4bc266a 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -80,22 +80,18 @@ cmap_X_rawvalue cmap_X_value_toraw(cmap_X_value* pval); ``` Helpers: ```c -uint64_t c_strhash(const char *str); // utility function - -int c_rawstr_compare(const char* const* a, const char* const* b); -bool c_rawstr_equalto(const char* const* a, const char* const* b); -uint64_t c_rawstr_hash(const char* const* strp, ...); - -uint64_t c_default_hash(const void *data, size_t len); // key is any integral type -uint64_t c_hash32(const void* data, size_t is4); // key is one 32-bit int -uint64_t c_hash64(const void* data, size_t is8); // key is one 64-bit int -bool c_default_equalto(const i_keyraw* a, const i_keyraw* b); // the == operator -bool c_memcmp_equalto(const i_keyraw* a, const i_keyraw* b); // uses memcmp - -Type c_no_clone(Type val); -Type c_default_fromraw(Type val); // plain copy -Type c_default_toraw(Type* val); -void c_default_del(Type* val); // does nothing +uint64_t c_strhash(const char *str); // utility function + +// hash template parameter functions: +uint64_t c_default_hash(const void *data, size_t len); // key is any integral type +uint64_t c_hash32(const void* data, size_t is4); // key is one 32-bit int +uint64_t c_hash64(const void* data, size_t is8); // key is one 64-bit int +uint64_t c_rawstr_hash(const char* const* strp, size_t unused); + +// equalto template parameter functions: +bool c_default_equalto(const i_keyraw* a, const i_keyraw* b); // *a == *b +bool c_memcmp_equalto(const i_keyraw* a, const i_keyraw* b); // !memcmp(a, b, sizeof *a) +bool c_rawstr_equalto(const char* const* a, const char* const* b); // !strcmp(*a, *b) ``` ## Types diff --git a/examples/astar.c b/examples/astar.c index 7410de96..2bf136e3 100644 --- a/examples/astar.c +++ b/examples/astar.c @@ -61,7 +61,7 @@ point_key_compare(const point* a, const point* b) #include #define i_val point -#define i_cmp c_no_compare +#define i_opt c_no_compare #include #define i_key point diff --git a/examples/complex.c b/examples/complex.c index 64c1903e..b6aef5a8 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -4,11 +4,12 @@ void check_del(float* v) {printf("destroy %g\n", *v);} #define i_val float #define i_valdel check_del +#define i_opt c_no_clone #define i_tag f #include #define i_val cstack_f -#define i_cmp_none +#define i_opt c_no_clone|c_no_compare #define i_valdel cstack_f_del #define i_tag arr #include @@ -16,12 +17,14 @@ void check_del(float* v) {printf("destroy %g\n", *v);} #define i_key int #define i_val clist_arr #define i_valdel clist_arr_del +#define i_opt c_no_clone #define i_tag lst #include #define i_key_str #define i_val cmap_lst #define i_valdel cmap_lst_del +#define i_opt c_no_clone #define i_tag map #include diff --git a/examples/csmap_find.c b/examples/csmap_find.c index 977ae6ca..78b6bbf5 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -8,7 +8,7 @@ #include #define i_val csmap_istr_rawvalue -#define i_cmp c_no_compare +#define i_opt c_no_compare #define i_tag istr #include diff --git a/examples/csmap_insert.c b/examples/csmap_insert.c index 3e908164..32f53377 100644 --- a/examples/csmap_insert.c +++ b/examples/csmap_insert.c @@ -15,7 +15,7 @@ #include #define i_val csmap_ii_rawvalue -#define i_cmp c_no_compare +#define i_opt c_no_compare #define i_tag ii #include diff --git a/examples/demos.c b/examples/demos.c index 49ac8486..30250c5f 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -184,7 +184,6 @@ void mapdemo3() cmap_str_del(&table); // frees key and value cstrs, and hash table. } -//#define i_prefix carray3 // backward compatible. #define i_val float #define i_tag f #include diff --git a/examples/mapmap.c b/examples/mapmap.c index 73a00861..e22a4f7b 100644 --- a/examples/mapmap.c +++ b/examples/mapmap.c @@ -3,13 +3,14 @@ #define i_key_str #define i_val_str #define i_tag sect -#include +#include // csmap_sect #define i_key_str #define i_val csmap_sect #define i_valdel csmap_sect_del +#define i_valfrom csmap_sect_clone #define i_tag conf -#include +#include // csmap_conf void add(csmap_conf* map, const char* section, const char* entry, const char* value) { diff --git a/examples/mmap.c b/examples/mmap.c index e3c876ce..26b271d1 100644 --- a/examples/mmap.c +++ b/examples/mmap.c @@ -9,6 +9,7 @@ #define i_val clist_str #define i_cmp -c_default_compare #define i_valdel clist_str_del +#define i_valfrom clist_str_clone #define i_tag mult #include diff --git a/examples/multimap.c b/examples/multimap.c index 3dbe952d..543b8b22 100644 --- a/examples/multimap.c +++ b/examples/multimap.c @@ -38,14 +38,21 @@ typedef struct { int year; cstr city, date; } OlympicLocation; int OlympicLocation_compare(OlympicLocation* a, OlympicLocation* b) { return a->year - b->year; } + +OlympicLocation OlympicLocation_clone(OlympicLocation loc) { + loc.city = cstr_clone(loc.city); + loc.date = cstr_clone(loc.date); + return loc; +} void OlympicLocation_del(OlympicLocation* self) { - c_del (cstr, &self->city, &self->date); + c_del(cstr, &self->city, &self->date); } // Create a clist, can be sorted by year. #define i_val OlympicLocation #define i_cmp OlympicLocation_compare #define i_del OlympicLocation_del +#define i_from OlympicLocation_clone #define i_tag OL #include @@ -53,6 +60,7 @@ void OlympicLocation_del(OlympicLocation* self) { #define i_key_str #define i_val clist_OL #define i_valdel clist_OL_del +#define i_valfrom clist_OL_clone #define i_tag OL #include diff --git a/examples/new_deq.c b/examples/new_deq.c index 0b41b167..cc3ff76b 100644 --- a/examples/new_deq.c +++ b/examples/new_deq.c @@ -11,7 +11,7 @@ struct MyStruct { #define i_val int -#define i_fwd +#define i_opt c_is_fwd #define i_tag i32 #include @@ -23,7 +23,7 @@ int point_compare(const Point* a, const Point* b) { #define i_val Point #define i_cmp point_compare -#define i_fwd +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_list.c b/examples/new_list.c index 4d2328be..e07030b5 100644 --- a/examples/new_list.c +++ b/examples/new_list.c @@ -10,7 +10,7 @@ struct MyStruct { } typedef MyStruct; #define i_val int -#define i_fwd +#define i_opt c_is_fwd #define i_tag i32 #include @@ -22,7 +22,7 @@ int point_compare(const Point* a, const Point* b) { #define i_val Point #define i_cmp point_compare -#define i_fwd +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_map.c b/examples/new_map.c index 1094fd91..7f4d19ee 100644 --- a/examples/new_map.c +++ b/examples/new_map.c @@ -24,7 +24,7 @@ int point_compare(const Point* a, const Point* b) { #define i_key Point #define i_val int #define i_cmp point_compare -#define i_fwd // forward declared +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_pque.c b/examples/new_pque.c index 94a12fbd..5048ea77 100644 --- a/examples/new_pque.c +++ b/examples/new_pque.c @@ -22,7 +22,7 @@ int Point_cmp(const Point* a, const Point* b) { #define i_val Point #define i_cmp Point_cmp -#define i_fwd // forward declared. +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_queue.c b/examples/new_queue.c index 53a5b341..3ad571bb 100644 --- a/examples/new_queue.c +++ b/examples/new_queue.c @@ -12,7 +12,7 @@ int point_compare(const Point* a, const Point* b) { } #define i_val Point #define i_cmp point_compare -#define i_fwd +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_smap.c b/examples/new_smap.c index 1c84a961..7f0730db 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -23,7 +23,7 @@ int point_compare(const Point* a, const Point* b) { #define i_key Point #define i_val int #define i_cmp point_compare -#define i_fwd +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_vec.c b/examples/new_vec.c index 5460789a..62804125 100644 --- a/examples/new_vec.c +++ b/examples/new_vec.c @@ -9,9 +9,9 @@ struct MyStruct { cvec_pnt pntvec; } typedef MyStruct; -#define i_fwd pnt -#define i_tag i32 #define i_val int +#define i_opt c_is_fwd +#define i_tag i32 #include struct Point { int x, y; } typedef Point; @@ -22,7 +22,7 @@ int point_compare(const Point* a, const Point* b) { #define i_val Point #define i_cmp point_compare -#define i_fwd pnt +#define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/ptr_elems.c b/examples/ptr_elems.c new file mode 100644 index 00000000..1b4f881a --- /dev/null +++ b/examples/ptr_elems.c @@ -0,0 +1,54 @@ +#include +#include + +struct { double x, y; } typedef Point; + +#define i_val Point* +#define i_from(val) c_new(Point, *(val)) +#define i_del(pval) c_free(*(pval)) +#define i_tag pnt +#include + +#define i_key_str +#define i_val int* +#define i_valraw int +#define i_valfrom(raw) c_new(int, raw) +#define i_valto(pval) **(pval) +#define i_valdel(pval) c_free(*(pval)) +#include + +int main() +{ + c_auto (cvec_pnt, vec, cpy) + { + printf("Vector with pointer elements:\n"); + // c++: vec.push_back(new Point{1.2, 3.4}); + cvec_pnt_push_back(&vec, c_new(Point, {1.2, 3.4})); + cvec_pnt_push_back(&vec, c_new(Point, {6.1, 4.7})); + + cpy = cvec_pnt_clone(vec); + cpy.data[1]->x = 100; + + printf("vec:"); + c_foreach (i, cvec_pnt, vec) + printf(" (%g %g)", (*i.ref)->x, (*i.ref)->y); + printf("\ncpy:"); + c_foreach (i, cvec_pnt, cpy) + printf(" (%g %g)", (*i.ref)->x, (*i.ref)->y); + puts(""); + } + + c_auto (cmap_str, map) + { + printf("\nMap with pointer elements:\n"); + cmap_str_insert(&map, cstr_lit("testing"), c_new(int, 999)); + cmap_str_insert(&map, cstr_lit("done"), c_new(int, 111)); + + // Emplace: implicit key, val construction using i_keyfrom/i_valfrom: + cmap_str_emplace(&map, "hello", 200); + cmap_str_emplace(&map, "goodbye", 400); + + c_foreach (i, cmap_str, map) + printf("%s: %d\n", i.ref->first.str, *i.ref->second); + } +} diff --git a/include/stc/alt/csmap.h b/include/stc/alt/csmap.h index 0e1650ee..5b331efb 100644 --- a/include/stc/alt/csmap.h +++ b/include/stc/alt/csmap.h @@ -53,7 +53,7 @@ int main(void) { #define KEY_REF_csmap_(vp) (&(vp)->first) #define _c_aatree_complete_types(_cx_self, C) \ - cx_MAP_ONLY( struct _cx_value { \ + _i_MAP_ONLY( struct _cx_value { \ _cx_key first; \ _cx_mapped second; \ }; ) \ @@ -71,8 +71,8 @@ int main(void) { \ typedef i_keyraw _cx_rawkey; \ typedef i_valraw _cx_memb(_rawmapped); \ - typedef cx_SET_ONLY( _cx_rawkey ) \ - cx_MAP_ONLY( struct { _cx_rawkey first; \ + typedef _i_SET_ONLY( _cx_rawkey ) \ + _i_MAP_ONLY( struct { _cx_rawkey first; \ _cx_memb(_rawmapped) second; } ) \ _cx_rawvalue; \ \ @@ -104,41 +104,41 @@ int main(void) { \ STC_INLINE void \ _cx_memb(_value_del)(_cx_value* val) { \ - i_keydel(cx_keyref(val)); \ - cx_MAP_ONLY( i_valdel(&val->second); ) \ + i_keydel(_i_keyref(val)); \ + _i_MAP_ONLY( i_valdel(&val->second); ) \ } \ \ STC_INLINE void \ _cx_memb(_value_clone)(_cx_value* dst, _cx_value* val) { \ - *cx_keyref(dst) = i_keyfrom(i_keyto(cx_keyref(val))); \ - cx_MAP_ONLY( dst->second = i_valfrom(i_valto(&val->second)); ) \ + *_i_keyref(dst) = i_keyfrom(i_keyto(_i_keyref(val))); \ + _i_MAP_ONLY( dst->second = i_valfrom(i_valto(&val->second)); ) \ } \ \ STC_INLINE _cx_result \ - _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey cx_MAP_ONLY(, i_valraw rmapped)) { \ + _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { \ _cx_result res = _cx_memb(_insert_entry_)(self, rkey); \ if (res.inserted) { \ - *cx_keyref(res.ref) = i_keyfrom(rkey); \ - cx_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) \ + *_i_keyref(res.ref) = i_keyfrom(rkey); \ + _i_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) \ } \ return res; \ } \ \ STC_INLINE void \ _cx_memb(_emplace_items)(_cx_self* self, const _cx_rawvalue arr[], size_t n) { \ - for (size_t i=0; isecond = mapped; )} \ - else {i_keydel(&key); cx_MAP_ONLY( i_valdel(&mapped); )} \ + if (res.inserted) {*_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} \ + else {i_keydel(&key); _i_MAP_ONLY( i_valdel(&mapped); )} \ return res; \ } \ \ - cx_MAP_ONLY( \ + _i_MAP_ONLY( \ STC_INLINE _cx_result \ _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped) { \ _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto(&key)); \ @@ -231,7 +231,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti _cx_node *tn = self->root; \ out->_top = 0; \ while (tn->level) { \ - int c; _cx_rawkey rx = i_keyto(cx_keyref(&tn->value)); \ + int c; _cx_rawkey rx = i_keyto(_i_keyref(&tn->value)); \ if ((c = i_cmp(&rx, &rkey)) < 0) tn = tn->link[1]; \ else if (c > 0) {out->_st[out->_top++] = tn; tn = tn->link[0]; } \ else {out->_tn = tn->link[1]; return (out->ref = &tn->value); } \ @@ -295,7 +295,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti int c, top = 0, dir = 0; \ while (tx->level) { \ up[top++] = tx; \ - _cx_rawkey r = i_keyto(cx_keyref(&tx->value)); \ + _cx_rawkey r = i_keyto(_i_keyref(&tx->value)); \ if (!(c = i_cmp(&r, rkey))) {res->ref = &tx->value; return tn; } \ tx = tx->link[(dir = (c < 0))]; \ } \ @@ -325,7 +325,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti _cx_memb(_erase_r_)(_cx_node *tn, const _cx_rawkey* rkey, int *erased) { \ if (tn->level == 0) \ return tn; \ - _cx_rawkey raw = i_keyto(cx_keyref(&tn->value)); \ + _cx_rawkey raw = i_keyto(_i_keyref(&tn->value)); \ _cx_node *tx; int c = i_cmp(&raw, rkey); \ if (c != 0) \ tn->link[c < 0] = _cx_memb(_erase_r_)(tn->link[c < 0], rkey, erased); \ @@ -336,7 +336,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti while (tx->link[1]->level) \ tx = tx->link[1]; \ tn->value = tx->value; \ - raw = i_keyto(cx_keyref(&tn->value)); \ + raw = i_keyto(_i_keyref(&tn->value)); \ tn->link[0] = _cx_memb(_erase_r_)(tn->link[0], &raw, erased); \ } else { \ tx = tn; \ @@ -357,9 +357,9 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti } \ STC_DEF _cx_iter \ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { \ - _cx_rawkey raw = i_keyto(cx_keyref(it.ref)), nxt; \ + _cx_rawkey raw = i_keyto(_i_keyref(it.ref)), nxt; \ _cx_memb(_next)(&it); \ - if (it.ref) nxt = i_keyto(cx_keyref(it.ref)); \ + if (it.ref) nxt = i_keyto(_i_keyref(it.ref)); \ _cx_memb(_erase)(self, raw); \ if (it.ref) _cx_memb(_find_it)(self, nxt, &it); \ return it; \ @@ -369,11 +369,11 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { \ if (!it2.ref) { while (it1.ref) it1 = _cx_memb(_erase_at)(self, it1); \ return it1; } \ - _cx_key k1 = *cx_keyref(it1.ref), k2 = *cx_keyref(it2.ref); \ + _cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref); \ _cx_rawkey r1 = i_keyto(&k1); \ for (;;) { \ if (memcmp(&k1, &k2, sizeof k1) == 0) return it1; \ - _cx_memb(_next)(&it1); k1 = *cx_keyref(it1.ref); \ + _cx_memb(_next)(&it1); k1 = *_i_keyref(it1.ref); \ _cx_memb(_erase)(self, r1); \ _cx_memb(_find_it)(self, (r1 = i_keyto(&k1)), &it1); \ } \ diff --git a/include/stc/carr2.h b/include/stc/carr2.h index 439a5c2d..d1feb90b 100644 --- a/include/stc/carr2.h +++ b/include/stc/carr2.h @@ -52,20 +52,22 @@ int main() { } */ -#ifndef i_prefix -#define i_prefix carr2_ +#ifndef _i_prefix +#define _i_prefix carr2_ #endif #include "template.h" - -#ifndef i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_carr2_types, _cx_self, i_val); #endif -STC_API _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, i_val value); -STC_API _cx_self _cx_memb(_with_storage)(size_t xdim, size_t ydim, _cx_value* storage); -STC_API _cx_self _cx_memb(_clone)(_cx_self src); +STC_API _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, i_val value); +STC_API _cx_self _cx_memb(_with_storage)(size_t xdim, size_t ydim, _cx_value* storage); STC_API _cx_value* _cx_memb(_release)(_cx_self* self); -STC_API void _cx_memb(_del)(_cx_self* self); +STC_API void _cx_memb(_del)(_cx_self* self); +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self src); +STC_API void _cx_memb(_copy)(_cx_self *self, _cx_self other); +#endif STC_INLINE _cx_self _cx_memb(_init)(size_t xdim, size_t ydim) { return _cx_memb(_with_storage)(xdim, ydim, c_alloc_n(_cx_value, xdim*ydim)); @@ -85,11 +87,6 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y) { return self->ydim*x + y; } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->data == other.data) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { return c_make(_cx_iter){*self->data}; } @@ -116,6 +113,8 @@ STC_DEF _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, i_val value) { return _arr; } +#if !c_option(c_no_clone) + STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { _cx_self _arr = _cx_memb(_init)(src.xdim, src.ydim); for (_cx_value* p = _arr.data[0], *q = src.data[0], *e = p + _cx_memb(_size)(src); p != e; ++p, ++q) @@ -123,6 +122,12 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { return _arr; } +STC_DEF void _cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->data == other.data) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); +} +#endif + STC_DEF _cx_value *_cx_memb(_release)(_cx_self* self) { _cx_value *values = self->data[0]; c_free(self->data); diff --git a/include/stc/carr3.h b/include/stc/carr3.h index 80e1ef0f..4a4a6484 100644 --- a/include/stc/carr3.h +++ b/include/stc/carr3.h @@ -53,20 +53,24 @@ int main() { } */ -#ifndef i_prefix -#define i_prefix carr3_ +#ifndef _i_prefix +#define _i_prefix carr3_ #endif #include "template.h" -#ifndef i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_carr3_types, _cx_self, i_val); #endif -STC_API _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, size_t zdim, i_val value); -STC_API _cx_self _cx_memb(_with_storage)(size_t xdim, size_t ydim, size_t zdim, _cx_value* storage); -STC_API _cx_self _cx_memb(_clone)(_cx_self src); +STC_API _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, size_t zdim, i_val value); +STC_API _cx_self _cx_memb(_with_storage)(size_t xdim, size_t ydim, size_t zdim, _cx_value* storage); STC_API _cx_value* _cx_memb(_release)(_cx_self* self); -STC_API void _cx_memb(_del)(_cx_self* self); +STC_API void _cx_memb(_del)(_cx_self* self); +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self src); +STC_API void _cx_memb(_copy)(_cx_self *self, _cx_self other); +#endif + STC_INLINE _cx_self _cx_memb(_init)(size_t xdim, size_t ydim, size_t zdim) { return _cx_memb(_with_storage)(xdim, ydim, zdim, c_alloc_n(_cx_value, xdim*ydim*zdim)); @@ -87,11 +91,6 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y, size_ return self->zdim*(self->ydim*x + y) + z; } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->data == other.data) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { return c_make(_cx_iter){**self->data}; } @@ -120,6 +119,8 @@ STC_DEF _cx_self _cx_memb(_with_values)(size_t xdim, size_t ydim, size_t zdim, i return _arr; } +#if !c_option(c_no_clone) + STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { _cx_self _arr = _cx_memb(_init)(src.xdim, src.ydim, src.zdim); for (_cx_value* p = **_arr.data, *q = **src.data, *e = p + _cx_memb(_size)(src); p != e; ++p, ++q) @@ -127,6 +128,12 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { return _arr; } +STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->data == other.data) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); +} +#endif + STC_DEF _cx_value* _cx_memb(_release)(_cx_self* self) { _cx_value *values = self->data[0][0]; c_free(self->data); diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 7d0eceeb..794948e6 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -98,20 +98,22 @@ #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)) // [deprecated] +#define c_default_equalto(x, y) (*(x) == *(y)) +#define c_memcmp_equalto(x, y) (memcmp(x, y, sizeof *(x)) == 0) #define c_less_compare(less, x, y) (less(y, x) - less(x, y)) -#define c_default_equalto(x, y) (*(x) == *(y)) -#define c_memcmp_equalto(x, y) (memcmp(x, y, sizeof *(x)) == 0) - #define c_rawstr_compare(x, y) strcmp(*(x), *(y)) #define c_rawstr_equalto(x, y) (strcmp(*(x), *(y)) == 0) #define c_rawstr_hash(p, dummy) c_strhash(*(p)) -#define c_no_clone(x) (assert(!"c_no_clone() called"), x) +#define c_option(flag) ((i_opt) & (flag)) +#define c_is_fwd 1 +#define c_no_compare 2 +#define c_no_clone 4 +#define c_no_atomic 8 + #define c_default_fromraw(x) (x) #define c_default_toraw(ptr) (*(ptr)) - #define c_default_del(ptr) ((void) (ptr)) /* Generic algorithms */ diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index 3e32beb6..f8cc1d52 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -20,7 +20,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - #ifndef CDEQ_H_INCLUDED #include "ccommon.h" #include "forward.h" @@ -31,48 +30,58 @@ struct cdeq_rep { size_t size, cap; void* base[]; }; #define cdeq_rep_(self) c_container_of((self)->_base, struct cdeq_rep, base) #endif // CDEQ_H_INCLUDED -#ifndef i_prefix -#define i_prefix cdeq_ +#ifndef _i_prefix +#define _i_prefix cdeq_ #endif #include "template.h" -#if !defined i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_cdeq_types, _cx_self, i_val); #endif typedef i_valraw _cx_rawvalue; STC_API _cx_self _cx_memb(_init)(void); -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); STC_API void _cx_memb(_clear)(_cx_self* self); STC_API void _cx_memb(_del)(_cx_self* self); STC_API _cx_value* _cx_memb(_push_back)(_cx_self* self, i_val value); STC_API bool _cx_memb(_expand_right_half_)(_cx_self* self, size_t idx, size_t n); +#ifndef _i_queue +#if !c_option(c_no_clone) +STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); +STC_API _cx_iter _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, + const _cx_rawvalue* p1, const _cx_rawvalue* p2); +#endif // !c_no_clone -#ifndef i_queue +#if !c_option(c_no_compare) STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, i_valraw raw); STC_API int _cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y); +#endif STC_API _cx_value* _cx_memb(_push_front)(_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, - const _cx_value* p1, const _cx_value* p2, bool clone); -STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_rawvalue* p1, const _cx_rawvalue* p2); -#endif // i_queue + const _cx_value* p1, const _cx_value* p2); +#endif // !_i_queue -STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return !cdeq_rep_(&cx)->size; } -STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cdeq_rep_(&cx)->size; } -STC_INLINE size_t _cx_memb(_capacity)(_cx_self cx) { return cdeq_rep_(&cx)->cap; } -STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) {c_swap(_cx_self, *a, *b); } -STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } -STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* pval) { return i_valto(pval); } +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) + { return _cx_memb(_push_back)(self, i_valfrom(raw)); } STC_INLINE i_val _cx_memb(_value_clone)(i_val val) { return i_valfrom(i_valto(&val)); } STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { if (self->data == other.data) return; _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); } -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) - { return _cx_memb(_push_back)(self, i_valfrom(raw)); } +#endif +STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return !cdeq_rep_(&cx)->size; } +STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cdeq_rep_(&cx)->size; } +STC_INLINE size_t _cx_memb(_capacity)(_cx_self cx) { return cdeq_rep_(&cx)->cap; } +STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) {c_swap(_cx_self, *a, *b); } +STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } +STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* pval) { return i_valto(pval); } + STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) { i_valdel(self->data); ++self->data; --cdeq_rep_(self)->size; } STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) @@ -93,19 +102,7 @@ _cx_memb(_with_capacity)(const size_t n) { return cx; } -STC_INLINE void -_cx_memb(_shrink_to_fit)(_cx_self *self) { - if (_cx_memb(_size)(*self) != _cx_memb(_capacity)(*self)) { - _cx_self cx = _cx_memb(_clone)(*self); - _cx_memb(_del)(self); *self = cx; - } -} - -#ifndef i_queue - -STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, i_valraw raw) { - return _cx_memb(_push_front)(self, i_valfrom(raw)); -} +#ifndef _i_queue STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_value* p = &self->data[--cdeq_rep_(self)->size]; @@ -129,48 +126,56 @@ _cx_memb(_reserve)(_cx_self* self, const size_t n) { STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_val value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1, false); + return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); } STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n, false); + return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_val value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1, false); + return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); } STC_INLINE _cx_iter -_cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1); +_cx_memb(_erase_n)(_cx_self* self, const size_t idx, const size_t n) { + return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); } STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_rawvalue arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); +_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { + return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); } STC_INLINE _cx_iter -_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_valraw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { + return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); } + +#if !c_option(c_no_clone) + STC_INLINE _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_insert_range_p)(self, it.ref, it1.ref, it2.ref, true); + return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); +} + +STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, i_valraw raw) { + return _cx_memb(_push_front)(self, i_valfrom(raw)); } STC_INLINE _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const size_t idx, const size_t n) { - return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); +_cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) { + return _cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1); } STC_INLINE _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); +_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_rawvalue arr[], const size_t n) { + return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); +_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_valraw raw) { + return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); } +#endif // !c_no_clone -#ifndef i_cmp_none +#if !c_option(c_no_compare) STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { @@ -198,8 +203,8 @@ 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 +#endif // !c_no_compare +#endif // _i_queue /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_imp) @@ -225,6 +230,17 @@ _cx_memb(_clear)(_cx_self* self) { } } +STC_DEF void +_cx_memb(_shrink_to_fit)(_cx_self *self) { + if (_cx_memb(_size)(*self) != _cx_memb(_capacity)(*self)) { + struct cdeq_rep* rep = cdeq_rep_(self); + const size_t sz = rep->size; + memmove(self->_base, self->data, sz*sizeof(i_val)); + rep = (struct cdeq_rep*) c_realloc(rep, offsetof(struct cdeq_rep, base) + sz*sizeof(i_val)); + if (rep) { self->_base = self->data = (_cx_value*) rep->base; rep->cap = sz; } + } +} + STC_DEF void _cx_memb(_del)(_cx_self* self) { _cx_memb(_clear)(self); @@ -255,7 +271,7 @@ _cx_memb(_expand_right_half_)(_cx_self* self, const size_t idx, const size_t n) if (!_cx_memb(_realloc_)(self, n)) return false; memmove(self->data + idx + n, self->data + idx, (sz - idx)*sizeof(i_val)); } else { -#ifdef i_queue +#ifdef _i_queue const size_t pos = 0; #else const size_t unused = cap - (sz + n); @@ -277,6 +293,7 @@ _cx_memb(_push_back)(_cx_self* self, i_val value) { *v = value; return v; } +#if !c_option(c_no_clone) STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t sz = cdeq_rep_(&cx)->size; @@ -285,8 +302,9 @@ _cx_memb(_clone)(_cx_self cx) { for (size_t i = 0; i < sz; ++i) out.data[i] = i_valfrom(i_valto(&cx.data[i])); return out; } +#endif -#ifndef i_queue +#ifndef _i_queue STC_DEF void _cx_memb(_expand_left_half_)(_cx_self* self, const size_t idx, const size_t n) { @@ -327,19 +345,10 @@ _cx_memb(_push_front)(_cx_self* self, i_val value) { STC_DEF _cx_iter _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2, bool clone) { + const _cx_value* p1, const _cx_value* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); _cx_iter it = {pos}; - if (clone) for (; p1 != p2; ++p1) *pos++ = i_valfrom(i_valto(p1)); - else memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return it; -} - -STC_DEF _cx_iter -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_rawvalue* p1, const _cx_rawvalue* p2) { - pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); + memcpy(pos, p1, (p2 - p1)*sizeof *p1); return it; } @@ -356,7 +365,28 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { return c_make(_cx_iter){p1}; } -#ifndef i_cmp_none +#if !c_option(c_no_clone) + +STC_DEF _cx_iter +_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_rawvalue* p1, const _cx_rawvalue* p2) { + pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); + _cx_iter it = {pos}; + for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); + return it; +} + +STC_DEF _cx_iter +_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); + _cx_iter it = {pos}; + for (; p1 != p2; ++p1) *pos++ = i_valfrom(i_valto(p1)); + return it; +} +#endif // !c_option(c_no_clone) + +#if !c_option(c_no_compare) + STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { for (; i1.ref != i2.ref; ++i1.ref) { @@ -372,8 +402,8 @@ _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 // !c_no_compare +#endif // !_i_queue #endif // IMPLEMENTATION #include "template.h" #define CDEQ_H_INCLUDED diff --git a/include/stc/clist.h b/include/stc/clist.h index 8a019b65..bb090a62 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -78,12 +78,12 @@ _c_clist_complete_types(clist_VOID, dummy); #endif // CLIST_H_INCLUDED -#ifndef i_prefix -#define i_prefix clist_ +#ifndef _i_prefix +#define _i_prefix clist_ #endif #include "template.h" -#if !defined i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_clist_types, _cx_self, i_val); #endif _cx_deftypes(_c_clist_complete_types, _cx_self, dummy); @@ -91,14 +91,13 @@ typedef i_valraw _cx_rawvalue; STC_API size_t _clist_count(const clist_VOID* self); -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); STC_API void _cx_memb(_del)(_cx_self* self); STC_API _cx_value* _cx_memb(_push_back)(_cx_self* self, i_val value); 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 +#if !c_option(c_no_compare) 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 @@ -107,31 +106,34 @@ STC_API _cx_self _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_i STC_API void _cx_memb(_sort)(_cx_self* self); 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}; } -STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.last == NULL; } -STC_INLINE size_t _cx_memb(_count)(_cx_self cx) - { return _clist_count((const clist_VOID*) &cx); } -STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); } -STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } -STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* pval) { return i_valto(pval); } -STC_INLINE i_val _cx_memb(_value_clone)(i_val val) - { return i_valfrom(i_valto(&val)); } -STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) - { _cx_memb(_erase_after_)(self, self->last); } +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) { return _cx_memb(_push_back)(self, i_valfrom(raw)); } STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, i_valraw raw) { return _cx_memb(_push_front)(self, i_valfrom(raw)); } STC_INLINE _cx_iter _cx_memb(_emplace)(_cx_self* self, _cx_iter it, i_valraw raw) { return _cx_memb(_insert)(self, it, i_valfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; } - +STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) + { return i_valfrom(raw); } +STC_INLINE i_val _cx_memb(_value_clone)(i_val val) + { return i_valfrom(i_valto(&val)); } STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { if (self->last == other.last) return; _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); } +#endif +STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } +STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.last == NULL; } +STC_INLINE size_t _cx_memb(_count)(_cx_self cx) + { return _clist_count((const clist_VOID*) &cx); } +STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); } +STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* pval) { return i_valto(pval); } +STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) + { _cx_memb(_erase_after_)(self, self->last); } +STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; } +STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { @@ -163,7 +165,7 @@ _cx_memb(_splice_range)(_cx_self* self, _cx_iter it, return _cx_memb(_splice)(self, it, &tmp); } -#ifndef i_cmp_none +#if !c_option(c_no_compare) 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); @@ -184,12 +186,14 @@ _cx_memb(_get_mut)(_cx_self* self, i_valraw val) { #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_imp) +#if !c_option(c_no_clone) STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { _cx_self out = _cx_memb(_init)(); c_foreach (it, _cx_self, cx) _cx_memb(_emplace_back)(&out, i_valto(it.ref)); return out; } +#endif STC_DEF void _cx_memb(_del)(_cx_self* self) { @@ -275,7 +279,7 @@ _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2) { return cx; } -#ifndef i_cmp_none +#if !c_option(c_no_compare) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val) { @@ -316,7 +320,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 // !c_no_compare #endif // TEMPLATE IMPLEMENTATION @@ -331,7 +335,8 @@ _clist_count(const clist_VOID* self) { return n; } -#ifndef i_cmp_none +#if !c_option(c_no_compare) + // 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 * @@ -381,7 +386,7 @@ _clist_mergesort(clist_VOID_node *list, int (*cmp)(const clist_VOID_node*, const insize *= 2; } } -#endif // !i_cmp_none +#endif // !c_no_compare #endif // NON-TEMPLATE IMPLEMENTATION #include "template.h" #define CLIST_H_INCLUDED diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 979f1b44..3d1915d3 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -58,37 +58,39 @@ int main(void) { typedef struct { MAP_SIZE_T idx; uint_fast8_t hx; } chash_bucket_t; #endif // CMAP_H_INCLUDED -#ifndef i_prefix -#define i_prefix cmap_ +#ifndef _i_prefix +#define _i_prefix cmap_ #endif -#ifdef i_isset - #define cx_MAP_ONLY c_false - #define cx_SET_ONLY c_true - #define cx_keyref(vp) (vp) +#ifdef _i_isset + #define _i_MAP_ONLY c_false + #define _i_SET_ONLY c_true + #define _i_keyref(vp) (vp) #else - #define cx_MAP_ONLY c_true - #define cx_SET_ONLY c_false - #define cx_keyref(vp) (&(vp)->first) + #define _i_MAP_ONLY c_true + #define _i_SET_ONLY c_false + #define _i_keyref(vp) (&(vp)->first) #endif #include "template.h" -#ifndef i_fwd -_cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, cx_MAP_ONLY, cx_SET_ONLY); +#if !c_option(c_is_fwd) +_cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); #endif -cx_MAP_ONLY( struct _cx_value { +_i_MAP_ONLY( struct _cx_value { _cx_key first; _cx_mapped second; }; ) typedef i_keyraw _cx_rawkey; typedef i_valraw _cx_memb(_rawmapped); -typedef cx_SET_ONLY( i_keyraw ) - cx_MAP_ONLY( struct { i_keyraw first; +typedef _i_SET_ONLY( i_keyraw ) + _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) _cx_rawvalue; STC_API _cx_self _cx_memb(_with_capacity)(size_t cap); +#if !c_option(c_no_clone) STC_API _cx_self _cx_memb(_clone)(_cx_self map); +#endif 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, size_t capacity); @@ -108,9 +110,11 @@ STC_INLINE void _cx_memb(_swap)(_cx_self *map1, _cx_self *map2) {c_swap( STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } -cx_MAP_ONLY( - STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped); +#ifndef _i_isset + #if !c_option(c_no_clone) STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped); + #endif + STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped); STC_INLINE _cx_result /* short-form, like operator[]: */ _cx_memb(_put)(_cx_self* self, i_key key, i_val mapped) { @@ -123,41 +127,48 @@ cx_MAP_ONLY( assert(self->_hashx[b.idx]); return &self->table[b.idx].second; } -) - -STC_INLINE void -_cx_memb(_value_clone)(_cx_value* _dst, _cx_value* _val) { - *cx_keyref(_dst) = i_keyfrom(i_keyto(cx_keyref(_val))); - cx_MAP_ONLY( _dst->second = i_valfrom(i_valto(&_val->second)); ) -} +#endif -STC_INLINE _cx_rawvalue -_cx_memb(_value_toraw)(_cx_value* val) { - return cx_SET_ONLY( i_keyto(val) ) - cx_MAP_ONLY( c_make(_cx_rawvalue){i_keyto(&val->first), i_valto(&val->second)} ); +#if !c_option(c_no_clone) +STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->table == other.table) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); } STC_INLINE void -_cx_memb(_value_del)(_cx_value* _val) { - i_keydel(cx_keyref(_val)); - cx_MAP_ONLY( i_valdel(&_val->second); ) +_cx_memb(_value_clone)(_cx_value* _dst, _cx_value* _val) { + *_i_keyref(_dst) = i_keyfrom(i_keyto(_i_keyref(_val))); + _i_MAP_ONLY( _dst->second = i_valfrom(i_valto(&_val->second)); ) } STC_INLINE _cx_result -_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey cx_MAP_ONLY(, i_valraw rmapped)) { +_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); if (_res.inserted) { - *cx_keyref(_res.ref) = i_keyfrom(rkey); - cx_MAP_ONLY( _res.ref->second = i_valfrom(rmapped); ) + *_i_keyref(_res.ref) = i_keyfrom(rkey); + _i_MAP_ONLY( _res.ref->second = i_valfrom(rmapped); ) } return _res; } +#endif // !c_no_clone + +STC_INLINE _cx_rawvalue +_cx_memb(_value_toraw)(_cx_value* val) { + return _i_SET_ONLY( i_keyto(val) ) + _i_MAP_ONLY( c_make(_cx_rawvalue){i_keyto(&val->first), i_valto(&val->second)} ); +} + +STC_INLINE void +_cx_memb(_value_del)(_cx_value* _val) { + i_keydel(_i_keyref(_val)); + _i_MAP_ONLY( i_valdel(&_val->second); ) +} STC_INLINE _cx_result -_cx_memb(_insert)(_cx_self* self, i_key _key cx_MAP_ONLY(, i_val _mapped)) { +_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(&_key)); - if (_res.inserted) { *cx_keyref(_res.ref) = _key; cx_MAP_ONLY( _res.ref->second = _mapped; )} - else { i_keydel(&_key); cx_MAP_ONLY( i_valdel(&_mapped); )} + if (_res.inserted) { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} + else { i_keydel(&_key); _i_MAP_ONLY( i_valdel(&_mapped); )} return _res; } @@ -253,12 +264,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { memset(self->_hashx, 0, self->bucket_count); } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->table == other.table) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - -cx_MAP_ONLY( +#if !defined _i_isset STC_DEF _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped) { _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(&_key)); @@ -266,7 +272,7 @@ cx_MAP_ONLY( else { i_keydel(&_key); i_valdel(&_res.ref->second); } _res.ref->second = _mapped; return _res; } - + #if !c_option(c_no_clone) STC_DEF _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); @@ -274,7 +280,8 @@ cx_MAP_ONLY( else i_valdel(&_res.ref->second); _res.ref->second = i_valfrom(rmapped); return _res; } -) + #endif +#endif STC_DEF chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { @@ -284,7 +291,7 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { const uint8_t* _hashx = self->_hashx; while ((_hx = _hashx[b.idx])) { if (_hx == b.hx) { - _cx_rawkey _raw = i_keyto(cx_keyref(self->table + b.idx)); + _cx_rawkey _raw = i_keyto(_i_keyref(self->table + b.idx)); if (i_equ(&_raw, rkeyptr)) break; } if (++b.idx == _cap) b.idx = 0; @@ -305,6 +312,7 @@ _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey) { return res; } +#if !c_option(c_no_clone) STC_DEF _cx_self _cx_memb(_clone)(_cx_self m) { _cx_self clone = { @@ -318,6 +326,7 @@ _cx_memb(_clone)(_cx_self m) { if (*hx) _cx_memb(_value_clone)(dst, e); return clone; } +#endif STC_DEF bool _cx_memb(_reserve)(_cx_self* self, const size_t _newcap) { @@ -337,7 +346,7 @@ _cx_memb(_reserve)(_cx_self* self, const size_t _newcap) { _cx_value* e = _tmp.table, *_slot = self->table; uint8_t* _hashx = self->_hashx; for (size_t i = 0; i < _oldbuckets; ++i, ++e) if (_tmp._hashx[i]) { - _cx_rawkey _raw = i_keyto(cx_keyref(e)); + _cx_rawkey _raw = i_keyto(_i_keyref(e)); chash_bucket_t b = _cx_memb(_bucket_)(self, &_raw); _slot[b.idx] = *e; _hashx[b.idx] = (uint8_t) b.hx; @@ -359,7 +368,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (++j == _cap) j = 0; if (! _hashx[j]) break; - _cx_rawkey _raw = i_keyto(cx_keyref(_slot + j)); + _cx_rawkey _raw = i_keyto(_i_keyref(_slot + j)); k = c_PASTE(fastrange_,MAP_SIZE_T)(i_hash(&_raw, sizeof _raw), _cap); if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ _slot[i] = _slot[j], _hashx[i] = _hashx[j], i = j; @@ -369,9 +378,9 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { } #endif // TEMPLATED IMPLEMENTATION -#undef i_isset -#undef cx_keyref -#undef cx_MAP_ONLY -#undef cx_SET_ONLY +#undef _i_isset +#undef _i_keyref +#undef _i_MAP_ONLY +#undef _i_SET_ONLY #include "template.h" #define CMAP_H_INCLUDED diff --git a/include/stc/cpque.h b/include/stc/cpque.h index c43072c9..86bab2ec 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -27,13 +27,13 @@ #include "forward.h" #endif -#ifndef i_prefix -#define i_prefix cpque_ +#ifndef _i_prefix +#define _i_prefix cpque_ #endif #include "template.h" -#if !defined i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_cpque_types, _cx_self, i_val); #endif typedef i_valraw _cx_rawvalue; @@ -41,7 +41,6 @@ typedef i_valraw _cx_rawvalue; STC_API void _cx_memb(_make_heap)(_cx_self* self); STC_API void _cx_memb(_erase_at)(_cx_self* self, size_t idx); STC_API void _cx_memb(_push)(_cx_self* self, _cx_value value); -STC_API _cx_self _cx_memb(_clone)(_cx_self q); STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){0}; } @@ -65,11 +64,6 @@ STC_INLINE void _cx_memb(_clear)(_cx_self* self) { STC_INLINE void _cx_memb(_del)(_cx_self* self) { _cx_memb(_clear)(self); c_free(self->data); } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->data == other.data) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - STC_INLINE size_t _cx_memb(_size)(_cx_self q) { return q.size; } @@ -85,11 +79,20 @@ STC_INLINE _cx_value* _cx_memb(_top)(const _cx_self* self) STC_INLINE void _cx_memb(_pop)(_cx_self* self) { _cx_memb(_erase_at)(self, 0); } +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self q); + +STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->data == other.data) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); +} + STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_rawvalue raw) { _cx_memb(_push)(self, i_valfrom(raw)); } STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) { return i_valfrom(i_valto(&val)); } +#endif STC_INLINE void _cx_memb(_push_back)(_cx_self* self, _cx_value value) { @@ -121,12 +124,15 @@ _cx_memb(_make_heap)(_cx_self* self) { _cx_memb(_sift_down_)(arr, k, n); } +#if !c_option(c_no_clone) + STC_DEF _cx_self _cx_memb(_clone)(_cx_self q) { _cx_self out = _cx_memb(_with_capacity)(q.size); for (; out.size < out.capacity; ++out.size, ++q.data) out.data[out.size] = i_valfrom(i_valto(q.data)); return out; } +#endif STC_DEF void _cx_memb(_erase_at)(_cx_self* self, size_t idx) { diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 45e3c2a6..aba07726 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -53,10 +53,10 @@ int main() { } */ -#ifndef i_prefix -#define i_prefix cqueue_ +#ifndef _i_prefix +#define _i_prefix cqueue_ #endif -#define i_queue +#define _i_queue #define _push_back _push #define _pop_front _pop @@ -64,4 +64,4 @@ int main() { #undef _push_back #undef _pop_front -#undef i_queue +#undef _i_queue diff --git a/include/stc/cset.h b/include/stc/cset.h index aa2ba022..d74a8ccc 100644 --- a/include/stc/cset.h +++ b/include/stc/cset.h @@ -39,8 +39,8 @@ int main(void) { } */ -#ifndef i_prefix -#define i_prefix cset_ +#ifndef _i_prefix +#define _i_prefix cset_ #endif -#define i_isset +#define _i_isset #include "cmap.h" diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 279bdf6d..101e7399 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -59,25 +59,25 @@ struct csmap_rep { size_t root, disp, head, size, cap; void* nodes[]; }; #define _csmap_rep(self) c_container_of((self)->nodes, struct csmap_rep, nodes) #endif // CSMAP_H_INCLUDED -#ifndef i_prefix -#define i_prefix csmap_ +#ifndef _i_prefix +#define _i_prefix csmap_ #endif -#ifdef i_isset - #define cx_MAP_ONLY c_false - #define cx_SET_ONLY c_true - #define cx_keyref(vp) (vp) +#ifdef _i_isset + #define _i_MAP_ONLY c_false + #define _i_SET_ONLY c_true + #define _i_keyref(vp) (vp) #else - #define cx_MAP_ONLY c_true - #define cx_SET_ONLY c_false - #define cx_keyref(vp) (&(vp)->first) + #define _i_MAP_ONLY c_true + #define _i_SET_ONLY c_false + #define _i_keyref(vp) (&(vp)->first) #endif #include "template.h" -#ifndef i_fwd -_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, cx_MAP_ONLY, cx_SET_ONLY); +#if !c_option(c_is_fwd) +_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); #endif -cx_MAP_ONLY( struct _cx_value { +_i_MAP_ONLY( struct _cx_value { _cx_key first; _cx_mapped second; }; ) @@ -89,12 +89,14 @@ struct _cx_node { typedef i_keyraw _cx_rawkey; typedef i_valraw _cx_memb(_rawmapped); -typedef cx_SET_ONLY( i_keyraw ) - cx_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) +typedef _i_SET_ONLY( i_keyraw ) + _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) _cx_rawvalue; STC_API _cx_self _cx_memb(_init)(void); +#if !c_option(c_no_clone) STC_API _cx_self _cx_memb(_clone)(_cx_self tree); +#endif STC_API void _cx_memb(_del)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t cap); STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out); @@ -126,33 +128,23 @@ _cx_memb(_with_capacity)(const size_t cap) { return tree; } -STC_INLINE void -_cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->nodes == other.nodes) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - STC_INLINE _cx_rawvalue _cx_memb(_value_toraw)(_cx_value* val) { - return cx_SET_ONLY( i_keyto(val) ) - cx_MAP_ONLY( c_make(_cx_rawvalue){i_keyto(&val->first), i_valto(&val->second)} ); + return _i_SET_ONLY( i_keyto(val) ) + _i_MAP_ONLY( c_make(_cx_rawvalue){i_keyto(&val->first), i_valto(&val->second)} ); } STC_INLINE void _cx_memb(_value_del)(_cx_value* val) { - i_keydel(cx_keyref(val)); - cx_MAP_ONLY( i_valdel(&val->second); ) + i_keydel(_i_keyref(val)); + _i_MAP_ONLY( i_valdel(&val->second); ) } -STC_INLINE void -_cx_memb(_value_clone)(_cx_value* dst, _cx_value* val) { - *cx_keyref(dst) = i_keyfrom(i_keyto(cx_keyref(val))); - cx_MAP_ONLY( dst->second = i_valfrom(i_valto(&val->second)); ) -} - -cx_MAP_ONLY( - STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); +#ifndef _i_isset + #if !c_option(c_no_clone) STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped); + #endif + STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); STC_INLINE _cx_result _cx_memb(_put)(_cx_self* self, i_key key, i_val mapped) @@ -161,7 +153,7 @@ cx_MAP_ONLY( STC_INLINE const _cx_mapped* _cx_memb(_at)(const _cx_self* self, i_keyraw rkey) { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } -) +#endif STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) { @@ -170,21 +162,35 @@ _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) { return it; } +#if !c_option(c_no_clone) +STC_INLINE void +_cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->nodes == other.nodes) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); +} + +STC_INLINE void +_cx_memb(_value_clone)(_cx_value* dst, _cx_value* val) { + *_i_keyref(dst) = i_keyfrom(i_keyto(_i_keyref(val))); + _i_MAP_ONLY( dst->second = i_valfrom(i_valto(&val->second)); ) +} + STC_INLINE _cx_result -_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey cx_MAP_ONLY(, i_valraw rmapped)) { +_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { _cx_result res = _cx_memb(_insert_entry_)(self, rkey); if (res.inserted) { - *cx_keyref(res.ref) = i_keyfrom(rkey); - cx_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) + *_i_keyref(res.ref) = i_keyfrom(rkey); + _i_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) } return res; } +#endif // !c_no_clone STC_INLINE _cx_result -_cx_memb(_insert)(_cx_self* self, i_key key cx_MAP_ONLY(, i_val mapped)) { +_cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)) { _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto(&key)); - if (res.inserted) { *cx_keyref(res.ref) = key; cx_MAP_ONLY( res.ref->second = mapped; )} - else { i_keydel(&key); cx_MAP_ONLY( i_valdel(&mapped); )} + if (res.inserted) { *_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} + else { i_keydel(&key); _i_MAP_ONLY( i_valdel(&mapped); )} return res; } @@ -268,7 +274,7 @@ _cx_memb(_node_new_)(_cx_self* self, int level) { return (_cx_size) tn; } -cx_MAP_ONLY( +#if !defined _i_isset STC_DEF _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped) { _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto(&key)); @@ -276,7 +282,7 @@ cx_MAP_ONLY( else { i_keydel(&key); i_valdel(&res.ref->second); } res.ref->second = mapped; return res; } - + #if !c_option(c_no_clone) STC_DEF _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { _cx_result res = _cx_memb(_insert_entry_)(self, rkey); @@ -284,7 +290,8 @@ cx_MAP_ONLY( else i_valdel(&res.ref->second); res.ref->second = i_valfrom(rmapped); return res; } -) + #endif +#endif STC_DEF _cx_value* _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out) { @@ -292,7 +299,7 @@ _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out) { _cx_node *d = out->_d = self->nodes; out->_top = 0; while (tn) { - int c; _cx_rawkey raw = i_keyto(cx_keyref(&d[tn].value)); + int c; _cx_rawkey raw = i_keyto(_i_keyref(&d[tn].value)); if ((c = i_cmp(&raw, &rkey)) < 0) tn = d[tn].link[1]; else if (c > 0) @@ -360,7 +367,7 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, _cx_size tn, const _cx_rawkey* rkey, int c, top = 0, dir = 0; while (tx) { up[top++] = tx; - i_keyraw raw = i_keyto(cx_keyref(&d[tx].value)); + i_keyraw raw = i_keyto(_i_keyref(&d[tx].value)); if ((c = i_cmp(&raw, rkey)) == 0) {res->ref = &d[tx].value; return tn; } dir = (c < 0); tx = d[tx].link[dir]; @@ -391,7 +398,7 @@ STC_DEF _cx_size _cx_memb(_erase_r_)(_cx_node *d, _cx_size tn, const _cx_rawkey* rkey, int *erased) { if (tn == 0) return 0; - i_keyraw raw = i_keyto(cx_keyref(&d[tn].value)); + i_keyraw raw = i_keyto(_i_keyref(&d[tn].value)); _cx_size tx; int c = i_cmp(&raw, rkey); if (c != 0) d[tn].link[c < 0] = _cx_memb(_erase_r_)(d, d[tn].link[c < 0], rkey, erased); @@ -403,7 +410,7 @@ _cx_memb(_erase_r_)(_cx_node *d, _cx_size tn, const _cx_rawkey* rkey, int *erase while (d[tx].link[1]) tx = d[tx].link[1]; d[tn].value = d[tx].value; /* move */ - raw = i_keyto(cx_keyref(&d[tn].value)); + raw = i_keyto(_i_keyref(&d[tn].value)); d[tn].link[0] = _cx_memb(_erase_r_)(d, d[tn].link[0], &raw, erased); } else { /* unlink node */ tx = tn; @@ -436,9 +443,9 @@ _cx_memb(_erase)(_cx_self* self, i_keyraw rkey) { STC_DEF _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - _cx_rawkey raw = i_keyto(cx_keyref(it.ref)), nxt; + _cx_rawkey raw = i_keyto(_i_keyref(it.ref)), nxt; _cx_memb(_next)(&it); - if (it.ref) nxt = i_keyto(cx_keyref(it.ref)); + if (it.ref) nxt = i_keyto(_i_keyref(it.ref)); _cx_memb(_erase)(self, raw); if (it.ref) _cx_memb(_find_it)(self, nxt, &it); return it; @@ -448,16 +455,17 @@ STC_DEF _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { if (!it2.ref) { while (it1.ref) it1 = _cx_memb(_erase_at)(self, it1); return it1; } - _cx_key k1 = *cx_keyref(it1.ref), k2 = *cx_keyref(it2.ref); + _cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref); _cx_rawkey r1 = i_keyto(&k1); for (;;) { if (memcmp(&k1, &k2, sizeof k1) == 0) return it1; - _cx_memb(_next)(&it1); k1 = *cx_keyref(it1.ref); + _cx_memb(_next)(&it1); k1 = *_i_keyref(it1.ref); _cx_memb(_erase)(self, r1); _cx_memb(_find_it)(self, (r1 = i_keyto(&k1)), &it1); } } +#if !c_option(c_no_clone) STC_DEF _cx_size _cx_memb(_clone_r_)(_cx_self* self, _cx_node* src, _cx_size sn) { if (sn == 0) return 0; @@ -476,6 +484,7 @@ _cx_memb(_clone)(_cx_self tree) { _csmap_rep(&clone)->size = _csmap_rep(&tree)->size; return clone; } +#endif // !c_no_clone STC_DEF void _cx_memb(_del_r_)(_cx_node* d, _cx_size tn) { @@ -495,9 +504,9 @@ _cx_memb(_del)(_cx_self* self) { } #endif // IMPLEMENTATION -#undef i_isset -#undef cx_keyref -#undef cx_MAP_ONLY -#undef cx_SET_ONLY +#undef _i_isset +#undef _i_keyref +#undef _i_MAP_ONLY +#undef _i_SET_ONLY #include "template.h" #define CSMAP_H_INCLUDED diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 7415c20a..82d882d9 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -73,25 +73,26 @@ typedef long atomic_count_t; #endif #define csptr_null {NULL, NULL} +#define _cx_csptr_rep struct _cx_memb(_rep_) #endif // CSPTR_H_INCLUDED -#ifndef i_prefix -#define i_prefix csptr_ +#ifndef _i_prefix +#define _i_prefix csptr_ #endif +#define i_valfrom _not_to_be_used_ #include "template.h" -#ifdef i_nonatomic - #define cx_increment(v) (++*(v)) - #define cx_decrement(v) (--*(v)) +#if !c_option(c_no_atomic) + #define _i_increment(v) c_atomic_increment(v) + #define _i_decrement(v) c_atomic_decrement(v) #else - #define cx_increment(v) c_atomic_increment(v) - #define cx_decrement(v) c_atomic_decrement(v) + #define _i_increment(v) (++*(v)) + #define _i_decrement(v) (--*(v)) #endif -#ifndef i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_csptr_types, _cx_self, i_val); #endif -#define cx_csptr_rep struct _cx_memb(_rep_) -cx_csptr_rep { atomic_count_t counter; _cx_value value; }; +_cx_csptr_rep { atomic_count_t counter; _cx_value value; }; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } @@ -108,7 +109,7 @@ _cx_memb(_from)(_cx_value* p) { STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { - _cx_self ptr; cx_csptr_rep *rep = c_alloc(cx_csptr_rep); + _cx_self ptr; _cx_csptr_rep *rep = c_alloc(_cx_csptr_rep); *(ptr.use_count = &rep->counter) = 1; *(ptr.get = &rep->value) = val; return ptr; @@ -116,7 +117,7 @@ _cx_memb(_make)(_cx_value val) { STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) { - if (ptr.use_count) cx_increment(ptr.use_count); + if (ptr.use_count) _i_increment(ptr.use_count); return ptr; } @@ -129,9 +130,9 @@ _cx_memb(_move)(_cx_self* self) { STC_INLINE void _cx_memb(_del)(_cx_self* self) { - if (self->use_count && cx_decrement(self->use_count) == 0) { + if (self->use_count && _i_decrement(self->use_count) == 0) { i_valdel(self->get); - if (self->get != &((cx_csptr_rep *)self->use_count)->value) + if (self->get != &((_cx_csptr_rep *)self->use_count)->value) c_free(self->get); c_free(self->use_count); } @@ -157,7 +158,7 @@ _cx_memb(_reset_with)(_cx_self* self, _cx_value val) { STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { - if (ptr.use_count) cx_increment(ptr.use_count); + if (ptr.use_count) _i_increment(ptr.use_count); _cx_memb(_del)(self); *self = ptr; } @@ -167,18 +168,16 @@ _cx_memb(_take)(_cx_self* self, _cx_self ptr) { *self = ptr; } -#ifndef i_cmp_none +#if !c_option(c_no_compare) STC_INLINE int _cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { -#ifdef i_cmp_default +#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 -#undef i_nonatomic +#undef _i_increment +#undef _i_decrement #include "template.h" \ No newline at end of file diff --git a/include/stc/csset.h b/include/stc/csset.h index ee06ec7f..e4558192 100644 --- a/include/stc/csset.h +++ b/include/stc/csset.h @@ -42,8 +42,8 @@ int main(void) { } */ -#ifndef i_prefix -#define i_prefix csset_ +#ifndef _i_prefix +#define _i_prefix csset_ #endif -#define i_isset +#define _i_isset #include "csmap.h" diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 099c2869..c1170f79 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -28,12 +28,12 @@ #include "forward.h" #endif // CSTACK_H_INCLUDED -#ifndef i_prefix -#define i_prefix cstack_ +#ifndef _i_prefix +#define _i_prefix cstack_ #endif #include "template.h" -#if !defined i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_cstack_types, _cx_self, i_val); #endif typedef i_valraw _cx_rawvalue; @@ -91,12 +91,14 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { *vp = val; return vp; } -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_rawvalue raw) - { return _cx_memb(_push)(self, i_valfrom(raw)); } - STC_INLINE _cx_value* _cx_memb(_at)(const _cx_self* self, size_t idx) { assert(idx < self->size); return self->data + idx; } +#if !c_option(c_no_clone) + +STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_rawvalue raw) + { return _cx_memb(_push)(self, i_valfrom(raw)); } + STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { _cx_self out = {(_cx_value *) c_malloc(v.size*sizeof(_cx_value)), v.size, v.size}; for (size_t i = 0; i < v.size; ++i, ++v.data) out.data[i] = i_valfrom(i_valto(v.data)); @@ -113,6 +115,8 @@ STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* val) { return i_valto(val); } +#endif // !c_no_clone + STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { return c_make(_cx_iter){self->data}; } STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 7cb92685..f47d8a02 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -383,4 +383,4 @@ c_strnstrn(const char *s, const char *needle, size_t slen, const size_t nlen) { } #endif -#endif \ No newline at end of file +#endif diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 25c82765..626ddad5 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -38,9 +38,9 @@ struct MyStruct { #define i_val_str // special for cstr #include -#define i_fwd // forward declared -#define i_tag i32 #define i_val int +#define i_opt c_is_fwd // forward declared +#define i_tag i32 #include int main() { @@ -68,47 +68,73 @@ struct cvec_rep { size_t size, cap; void* data[]; }; #define cvec_rep_(self) c_container_of((self)->data, struct cvec_rep, data) #endif // CVEC_H_INCLUDED -#ifndef i_prefix -#define i_prefix cvec_ +#ifndef _i_prefix +#define _i_prefix cvec_ #endif #include "template.h" -#if !defined i_fwd +#if !c_option(c_is_fwd) _cx_deftypes(_c_cvec_types, _cx_self, i_val); #endif typedef i_valraw _cx_rawvalue; STC_API _cx_self _cx_memb(_init)(void); -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); 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, size_t cap); STC_API bool _cx_memb(_resize)(_cx_self* self, size_t size, i_val fill_val); -#ifndef i_cmp_none +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, + const _cx_value* p1, const _cx_value* p2); +#if !c_option(c_no_compare) 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, - const _cx_value* p1, const _cx_value* p2, bool clone); + +#if !c_option(c_no_clone) +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +STC_API _cx_iter _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_rawvalue* p1, const _cx_rawvalue* p2); + const _cx_rawvalue* p1, const _cx_rawvalue* p2); +STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) + { return i_valfrom(i_valto(&val)); } +STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } +STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) + { return _cx_memb(_push_back)(self, i_valfrom(raw)); } +STC_INLINE void +_cx_memb(_copy)(_cx_self *self, _cx_self other) { + if (self->data == other.data) return; + _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); +} +STC_INLINE _cx_iter +_cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) { + return _cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1); +} +STC_INLINE _cx_iter +_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_rawvalue arr[], const size_t n) { + return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); +} +STC_INLINE _cx_iter +_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_valraw raw) { + return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); +} +STC_INLINE _cx_iter +_cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { + return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); +} +#endif STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cvec_rep_(&cx)->size; } STC_INLINE size_t _cx_memb(_capacity)(_cx_self cx) { return cvec_rep_(&cx)->cap; } STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return !cvec_rep_(&cx)->size; } -STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } STC_INLINE i_valraw _cx_memb(_value_toraw)(_cx_value* val) { return i_valto(val); } -STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) - { return i_valfrom(i_valto(&val)); } STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) { c_swap(_cx_self, *a, *b); } STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return self->data + cvec_rep_(self)->size - 1; } -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) - { return _cx_memb(_push_back)(self, i_valfrom(raw)); } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_value* p = &self->data[--cvec_rep_(self)->size]; i_valdel(p); } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) @@ -139,40 +165,17 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { _cx_memb(_reserve)(self, _cx_memb(_size)(*self)); } -STC_INLINE void -_cx_memb(_copy)(_cx_self *self, _cx_self other) { - if (self->data == other.data) return; - _cx_memb(_del)(self); *self = _cx_memb(_clone)(other); -} - STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_val value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1, false); + return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); } STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n, false); + return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_val value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1, false); -} - -STC_INLINE _cx_iter -_cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1); -} -STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_rawvalue arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); -} -STC_INLINE _cx_iter -_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_valraw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); -} -STC_INLINE _cx_iter -_cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_insert_range_p)(self, it.ref, it1.ref, it2.ref, true); + return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); } STC_INLINE _cx_iter @@ -194,7 +197,7 @@ _cx_memb(_at)(const _cx_self* self, const size_t idx) { return self->data + idx; } -#ifndef i_cmp_none +#if !c_option(c_no_compare) STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { @@ -225,7 +228,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 // !c_no_compare /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_imp) @@ -292,14 +295,6 @@ _cx_memb(_push_back)(_cx_self* self, i_val value) { *v = value; return v; } -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - const size_t len = cvec_rep_(&cx)->size; - _cx_self out = _cx_memb(_with_capacity)(len); - _cx_memb(_insert_range_p)(&out, out.data, cx.data, cx.data + len, true); - return out; -} - STC_DEF _cx_value* _cx_memb(_insert_space_)(_cx_self* self, _cx_value* pos, const size_t len) { const size_t idx = pos - self->data, size = cvec_rep_(self)->size; @@ -314,20 +309,10 @@ _cx_memb(_insert_space_)(_cx_self* self, _cx_value* pos, const size_t len) { STC_DEF _cx_iter _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2, bool clone) { - pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - if (clone) for (; p1 != p2; ++p1) *pos++ = i_valfrom(i_valto(p1)); - else memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return it; -} - -STC_DEF _cx_iter -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_rawvalue* p1, const _cx_rawvalue* p2) { + const _cx_value* p1, const _cx_value* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); _cx_iter it = {pos}; - for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); + memcpy(pos, p1, (p2 - p1)*sizeof *p1); return it; } @@ -343,7 +328,37 @@ _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 +#if !c_option(c_no_clone) + +STC_DEF _cx_self +_cx_memb(_clone)(_cx_self cx) { + const size_t len = cvec_rep_(&cx)->size; + _cx_self out = _cx_memb(_with_capacity)(len); + _cx_memb(_clone_range_p)(&out, out.data, cx.data, cx.data + len); + return out; +} + +STC_DEF _cx_iter +_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); + _cx_iter it = {pos}; + for (; p1 != p2; ++p1) *pos++ = i_valfrom(i_valto(p1)); + return it; +} + +STC_DEF _cx_iter +_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, + const _cx_rawvalue* p1, const _cx_rawvalue* p2) { + pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); + _cx_iter it = {pos}; + for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); + return it; +} +#endif + +#if !c_option(c_no_compare) + STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { for (; i1.ref != i2.ref; ++i1.ref) { @@ -372,7 +387,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 // !c_no_compare #endif #include "template.h" #define CVEC_H_INCLUDED diff --git a/include/stc/template.h b/include/stc/template.h index ff1ea3fc..b8f6dfc4 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -20,12 +20,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef i_template -#define i_template +#ifndef _i_template +#define _i_template #ifndef STC_TEMPLATE_H_INCLUDED #define STC_TEMPLATE_H_INCLUDED - #define _cx_self c_PASTE(i_prefix, i_tag) + #define _cx_self c_PASTE(_i_prefix, i_tag) #define _cx_memb(name) c_PASTE(_cx_self, name) #define _cx_deftypes(macro, SELF, ...) c_EXPAND(macro(SELF, __VA_ARGS__)) #define _cx_value _cx_memb(_value) @@ -53,8 +53,8 @@ #ifdef i_cnt #define i_tag i_cnt - #undef i_prefix - #define i_prefix + #undef _i_prefix + #define _i_prefix #endif #ifdef i_key_csptr @@ -107,19 +107,23 @@ #elif defined i_del #error i_del not supported for maps, define i_keydel / i_valdel instead. #endif +#if defined i_from && defined i_isset + #define i_keyfrom i_from +#elif defined i_from && !defined i_key + #define i_valfrom i_from +#elif defined i_from + #error i_from not supported for maps, define i_keyfrom / i_valfrom instead. +#endif #ifdef i_key - #ifdef i_isset + #ifdef _i_isset #define i_val i_key #endif #ifndef i_tag #define i_tag i_key #endif - #if !defined i_keyfrom && defined i_keydel - #ifdef STC_DEBUG - #error i_keydel defined, but not i_keyfrom. - #endif - #define i_keyfrom c_no_clone + #if defined i_keydel && !defined i_keyfrom && !c_option(c_no_clone) + #error i_keydel defined requires defining i_keyfrom or '#define i_opt c_no_clone' #elif !defined i_keyfrom #define i_keyfrom c_default_fromraw #endif @@ -138,18 +142,15 @@ #ifndef i_keydel #define i_keydel c_default_del #endif -#elif defined i_isset || defined i_hash || defined i_equ +#elif defined _i_isset || defined i_hash || defined i_equ #error i_key define is missing. #endif #ifndef i_tag #define i_tag i_val #endif -#if !defined i_valfrom && defined i_valdel - #ifdef STC_DEBUG - #error i_del/i_valdel defined, but not i_valfrom. - #endif - #define i_valfrom c_no_clone +#if defined i_valdel && !defined i_valfrom && !c_option(c_no_clone) + #error i_del/i_valdel defined: requires also defining i_valfrom or '#define i_opt c_no_clone' #elif !defined i_valfrom #define i_valfrom c_default_fromraw #endif @@ -162,18 +163,16 @@ #endif #ifndef i_cmp #define i_cmp c_default_compare - #define i_cmp_default + #define _i_cmp_default #endif #else // ------------------------------------------------------- -#undef i_prefix +#undef i_cnt #undef i_tag #undef i_imp -#undef i_fwd +#undef i_opt #undef i_cmp -#undef i_cmp_none -#undef i_cmp_default #undef i_del #undef i_equ #undef i_hash @@ -181,6 +180,7 @@ #undef i_val_str #undef i_valdel #undef i_valfrom +#undef i_from #undef i_valto #undef i_valraw #undef i_key @@ -191,7 +191,8 @@ #undef i_keyraw #undef i_key_csptr #undef i_val_csptr -#undef i_cnt -#undef i_template +#undef _i_prefix +#undef _i_cmp_default +#undef _i_template #endif -- cgit v1.2.3