From 92b950333c6c7002bdbf1b60af44a249dc0cef9c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 12:21:44 +0100 Subject: First commit for Version 3 of STC. Main changes are consistent rename of '_del' to '_drop' and '_compare' to '_cmp'. Also i_key_ref (earlier i_key_sptr) and i_val_ref replaced by more general i_key_bind/i_val_bind. --- README.md | 67 +++-- benchmarks/picobench/picobench_cmap.cpp | 12 +- benchmarks/picobench/picobench_csmap.cpp | 14 +- benchmarks/plotbench/cdeq_benchmark.cpp | 4 +- benchmarks/plotbench/clist_benchmark.cpp | 4 +- benchmarks/plotbench/cmap_benchmark.cpp | 4 +- benchmarks/plotbench/cpque_benchmark.cpp | 9 +- benchmarks/plotbench/csmap_benchmark.cpp | 4 +- benchmarks/plotbench/cvec_benchmark.cpp | 4 +- benchmarks/shootout_hashmaps.cpp | 2 +- docs/carray_api.md | 12 +- docs/cbits_api.md | 4 +- docs/cbox_api.md | 66 ++--- docs/ccommon_api.md | 22 +- docs/cdeq_api.md | 6 +- docs/clist_api.md | 10 +- docs/cmap_api.md | 161 ++++++------ docs/cpque_api.md | 8 +- docs/cqueue_api.md | 6 +- docs/crandom_api.md | 4 +- docs/cset_api.md | 8 +- docs/csmap_api.md | 16 +- docs/csptr_api.md | 94 +++---- docs/csset_api.md | 12 +- docs/cstack_api.md | 6 +- docs/cstr_api.md | 13 +- docs/csview_api.md | 6 +- docs/cvec_api.md | 26 +- examples/advanced.c | 68 ------ examples/astar.c | 18 +- examples/bits.c | 6 +- examples/box.c | 39 ++- examples/box2.c | 7 +- examples/complex.c | 61 +++-- examples/cpque.c | 6 +- examples/csmap_find.c | 2 +- examples/csmap_insert.c | 2 +- examples/cstr_match.c | 2 +- examples/demos.c | 12 +- examples/ex_gauss1.c | 2 +- examples/inits.c | 10 +- examples/mapmap.c | 78 +++--- examples/mmap.c | 24 +- examples/multimap.c | 12 +- examples/new_arr.c | 6 +- examples/new_deq.c | 8 +- examples/new_list.c | 8 +- examples/new_map.c | 8 +- examples/new_pque.c | 4 +- examples/new_queue.c | 8 +- examples/new_smap.c | 8 +- examples/new_sptr.c | 20 +- examples/new_vec.c | 16 +- examples/prime.c | 2 +- examples/priority.c | 2 +- examples/queue.c | 2 +- examples/rawptr_elements.c | 4 +- examples/read.c | 8 +- examples/replace.c | 2 +- examples/splitstr.c | 2 +- examples/sptr_demo.c | 16 +- examples/sptr_erase.c | 41 ++-- examples/sptr_music.c | 23 +- examples/sptr_pthread.c | 7 +- examples/sptr_to_maps.c | 11 +- examples/vikings.c | 69 ++++++ include/stc/alt/clist.h | 18 +- include/stc/alt/csmap.h | 30 +-- include/stc/alt/cstr.h | 27 +- include/stc/alt/sstr.h | 406 ------------------------------- include/stc/carr2.h | 13 +- include/stc/carr3.h | 13 +- include/stc/cbits.h | 6 +- include/stc/cbox.h | 63 ++--- include/stc/ccommon.h | 34 +-- include/stc/cdeq.h | 33 +-- include/stc/clist.h | 34 +-- include/stc/cmap.h | 37 +-- include/stc/cpque.h | 10 +- include/stc/cset.h | 2 +- include/stc/csmap.h | 45 ++-- include/stc/csptr.h | 60 ++--- include/stc/csset.h | 2 +- include/stc/cstack.h | 8 +- include/stc/cstr.h | 7 +- include/stc/csview.h | 8 +- include/stc/cvec.h | 41 ++-- include/stc/template.h | 162 ++++++------ 88 files changed, 982 insertions(+), 1305 deletions(-) delete mode 100644 examples/advanced.c create mode 100644 examples/vikings.c delete mode 100644 include/stc/alt/sstr.h diff --git a/README.md b/README.md index 452cc245..9d1587a8 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,36 @@ STC - Smart Template Containers for C News ---- +### Version 3.0 released. Migration guide for breaking changes from version 2.X: +There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_equalto*, and *Type_hash*. Only the functions required by the particular container needs to be defined, e.g. only **cmap** and **cset** require *Type_equalto* and *Type_hash* to be defined. +You may still define template parameters with `i_val` / `i_key` as before, which is easier for simple element types. + +Regex replace in VS Code: +- `_del\b` → `_drop` +- `_compare\b` → `_cmp` + +Whole word + Match case: +- `i_keydel` → `i_keydrop` +- `i_valdel` → `i_valdrop` +- `i_cnt` → `i_type` +- `i_key_csptr` → `i_key_bind` +- `i_val_csptr` → `i_val_bind` +- `cstr_lit` → `cstr_new` +- `csptr_X_make` → `csptr_X_new` + +### Final version 2.1 - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. - Added [**cbox**](docs/cbox_api.md) type: container of one element, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) - Added [example for **csptr**](examples/sptr_to_maps.c). - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". - Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. - Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*. -- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_ref` / `i_val_ref` when specifying containers with **csptr** or **cbox** elements. -- Deprecated `i_cnt`. Use `i_type` instead to define the full container type name. +- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_bind` / `i_val_bind` +- Deprecated `i_cnt`. Use `i_type` instead to define the complete container type name. +- Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` -Previous: -- Added `i_opt` template parameter: compile-time options: `c_no_compare`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` -- Removed: i_cmp_none and i_fwd: replaced by `c_no_compare` and `c_is_fwd` args to `i_opt`. - -VERSION 2.0 released. Two main breaking changes from V1.X. +### Version 2.0. Two main breaking changes from V1.X. - Uses a different way to instantiate templated containers, which is incompatible with v1.X. -- New **c_auto**, **c_autovar**, and **c_autoscope** macros. These are for automatic scope resource management, aka RAII. -- The new template instantiation style has multiple advantages, e.g. implementation does not contain long macro definitions for code generation. Also, specifying template arguments is more user friendly and flexible. Introduction ------------ @@ -101,24 +114,24 @@ int main(void) { c_foreach (i, cvec_float, vec) printf(" %g", *i.ref); - cvec_float_del(&vec); + cvec_float_drop(&vec); } ``` 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. +for integral types only). Alternatively, `#define i_opt c_no_cmp` to disable methods using comparison. -Similarly, if a destructor `i_del` is defined, either define a `i_valfrom` construct/clone function +Similarly, if a destructor `i_drop` 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_opt c_no_compare +#define i_opt c_no_cmp #define i_tag one #include #define i_val struct Two -#define i_opt c_no_compare +#define i_opt c_no_cmp #define i_tag two #include ... @@ -133,16 +146,16 @@ With six different containers: struct Point { float x, y; }; -int Point_compare(const struct Point* a, const struct Point* b) { - int cmp = c_default_compare(&a->x, &b->x); - return cmp ? cmp : c_default_compare(&a->y, &b->y); +int Point_cmp(const struct Point* a, const struct Point* b) { + int cmp = c_default_cmp(&a->x, &b->x); + return cmp ? cmp : c_default_cmp(&a->y, &b->y); } #define i_key int #include // cset_int: unordered set #define i_val struct Point -#define i_cmp Point_compare +#define i_cmp Point_cmp #define i_tag pnt #include // cvec_pnt: vector of struct Point @@ -160,7 +173,7 @@ int Point_compare(const struct Point* a, const struct Point* b) { #include // csmap_int: sorted map int => int int main(void) { - // define six containers with automatic call of init and del (destruction after scope exit) + // define six containers with automatic call of init and drop (destruction after scope exit) c_auto (cset_int, set) c_auto (cvec_pnt, vec) c_auto (cdeq_int, deq) @@ -267,28 +280,28 @@ The list of template parameters: - `i_tag` - Container type tag. Defaults to same as `i_key` - `i_type` - Full container type name (optional, alternative to `i_tag`). -- `i_opt` - Boolean properties: may combine `c_no_compare`, `c_no_clone`, `c_no_atomic`, `c_is_fwd` with `|` separator. +- `i_opt` - Boolean properties: may combine `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd` with `|` separator. - `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`- defaults to `!i_cmp`. -- `i_keydel` - Destroy map key func - defaults to empty destructor. +- `i_keydrop` - 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_keyfrom` - Convertion func `i_keyraw` => `i_key` - defaults to simple copy. **[required]** if `i_keydrop` 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_valdrop` - 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. -Instead of defining `i_cmp`, you may define `i_opt c_no_compare` to disable methods using comparison. +Instead of defining `i_cmp`, you may define `i_opt c_no_cmp` to disable methods using comparison. Instead of defining `i_valfrom`, you may define `i_opt c_no_clone` to disable methods using deep copy. -If a destructor `i_del` is defined, then define either `i_valfrom` or `i_opt c_no_clone`, otherwise +If a destructor `i_drop` is defined, then define either `i_valfrom` or `i_opt c_no_clone`, otherwise compile errors are generated. The *emplace* versus non-emplace container methods @@ -318,8 +331,8 @@ and non-emplace methods: #define i_val_str // special macro to enable container of cstr #include // vector of string (cstr) ... -c_auto (cvec_str, vec) // declare and call cvec_str_init() and defer cvec_str_del(&vec) -c_autovar (cstr s = cstr_new("a string literal"), cstr_del(&s)) // c_autovar is a more general c_auto. +c_auto (cvec_str, vec) // declare and call cvec_str_init() and defer cvec_str_drop(&vec) +c_autovar (cstr s = cstr_new("a string literal"), cstr_drop(&s)) // c_autovar is a more general c_auto. { const char* hello = "Hello"; cvec_str_push_back(&vec, cstr_from(hello); // construct and add string from const char* diff --git a/benchmarks/picobench/picobench_cmap.cpp b/benchmarks/picobench/picobench_cmap.cpp index 330c5e51..a045cb7c 100644 --- a/benchmarks/picobench/picobench_cmap.cpp +++ b/benchmarks/picobench/picobench_cmap.cpp @@ -91,7 +91,7 @@ static void ins_and_erase_cmap_i(picobench::state& s) c_forrange (s.iterations()) cmap_i_erase(&map, stc64_random()); s.set_result(cmap_i_size(map)); - cmap_i_del(&map); + cmap_i_drop(&map); } static void ins_and_erase_cmap_x(picobench::state& s) @@ -111,7 +111,7 @@ static void ins_and_erase_cmap_x(picobench::state& s) c_forrange (s.iterations()) cmap_x_erase(&map, stc64_random()); s.set_result(cmap_x_size(map)); - cmap_x_del(&map); + cmap_x_drop(&map); } #define P samples(S1).iterations({N1/4}) @@ -153,7 +153,7 @@ static void ins_and_access_cmap_i(picobench::state& s) c_forrange (N1) result += ++cmap_i_emplace(&map, stc64_random() & mask, 0).ref->second; s.set_result(result); - cmap_i_del(&map); + cmap_i_drop(&map); } #define P samples(S1).iterations({N1, N1, N1, N1}).args({18, 23, 25, 31}) @@ -212,8 +212,8 @@ static void ins_and_access_cmap_s(picobench::state& s) result += cmap_str_erase(&map, str.str); } s.set_result(result + cmap_str_size(map)); - cstr_del(&str); - cmap_str_del(&map); + cstr_drop(&str); + cmap_str_drop(&map); } #define P samples(S1).iterations({N1/5, N1/5, N1/5, N1/10, N1/40}).args({13, 7, 8, 100, 1000}) @@ -285,7 +285,7 @@ static void iterate_cmap_x(picobench::state& s) result += i.ref->second; } s.set_result(result); - cmap_x_del(&map); + cmap_x_drop(&map); } diff --git a/benchmarks/picobench/picobench_csmap.cpp b/benchmarks/picobench/picobench_csmap.cpp index 7a0addad..90681cd5 100644 --- a/benchmarks/picobench/picobench_csmap.cpp +++ b/benchmarks/picobench/picobench_csmap.cpp @@ -52,7 +52,7 @@ static void ctor_and_ins_one_csmap_i(picobench::state& s) csmap_i map = csmap_i_init(); csmap_i_emplace(&map, n, 0); result += csmap_i_size(map); - csmap_i_del(&map); + csmap_i_drop(&map); } s.set_result(result); } @@ -86,7 +86,7 @@ static void insert_csmap_i(picobench::state& s) c_forrange (n, s.iterations()) csmap_i_emplace(&map, stc64_random() & 0xfffffff, n); s.set_result(csmap_i_size(map)); - csmap_i_del(&map); + csmap_i_drop(&map); } #define P samples(S1).iterations({N1}) @@ -142,7 +142,7 @@ static void ins_and_erase_csmap_i(picobench::state& s) c_forrange (s.iterations()) csmap_i_erase(&map, stc64_random() & mask); s.set_result(result); - csmap_i_del(&map); + csmap_i_drop(&map); } #define P samples(S1).iterations({N1/2, N1/2, N1/2, N1/2}).args({18, 23, 25, 31}) @@ -183,7 +183,7 @@ static void ins_and_access_csmap_i(picobench::state& s) if (val) csmap_i_erase(&map, val->first); } s.set_result(result + csmap_i_size(map)); - csmap_i_del(&map); + csmap_i_drop(&map); } #define P samples(S1).iterations({N1, N1, N1, N1}).args({18, 23, 25, 31}) @@ -243,8 +243,8 @@ static void ins_and_access_csmap_s(picobench::state& s) }*/ } s.set_result(result + csmap_str_size(map)); - cstr_del(&str); - csmap_str_del(&map); + cstr_drop(&str); + csmap_str_drop(&map); } #define P samples(S1).iterations({N1/5, N1/5, N1/5, N1/10, N1/40}).args({13, 7, 8, 100, 1000}) @@ -309,7 +309,7 @@ static void iterate_csmap_x(picobench::state& s) result += i.ref->second; } s.set_result(result); - csmap_x_del(&map); + csmap_x_drop(&map); } diff --git a/benchmarks/plotbench/cdeq_benchmark.cpp b/benchmarks/plotbench/cdeq_benchmark.cpp index 6db167b0..f57da6b2 100644 --- a/benchmarks/plotbench/cdeq_benchmark.cpp +++ b/benchmarks/plotbench/cdeq_benchmark.cpp @@ -81,7 +81,7 @@ Sample test_stc_deque() { c_forrange (cdeq_x_size(con)/2) { cdeq_x_pop_front(&con); cdeq_x_pop_back(&con); } s.test[ERASE].t2 = clock(); s.test[ERASE].sum = cdeq_x_size(con); - cdeq_x_del(&con); + cdeq_x_drop(&con); }{ stc64_srandom(seed); container con = cdeq_x_init(); @@ -98,7 +98,7 @@ Sample test_stc_deque() { s.test[ITER].t2 = clock(); s.test[ITER].sum = sum; s.test[DESTRUCT].t1 = clock(); - cdeq_x_del(&con); + cdeq_x_drop(&con); } s.test[DESTRUCT].t2 = clock(); s.test[DESTRUCT].sum = 0; diff --git a/benchmarks/plotbench/clist_benchmark.cpp b/benchmarks/plotbench/clist_benchmark.cpp index 676d31e7..eaa18201 100644 --- a/benchmarks/plotbench/clist_benchmark.cpp +++ b/benchmarks/plotbench/clist_benchmark.cpp @@ -78,7 +78,7 @@ Sample test_stc_forward_list() { c_forrange (N) clist_x_pop_front(&con); s.test[ERASE].t2 = clock(); s.test[ERASE].sum = 0; - clist_x_del(&con); + clist_x_drop(&con); }{ stc64_srandom(seed); container con = clist_x_init(); @@ -95,7 +95,7 @@ Sample test_stc_forward_list() { s.test[ITER].t2 = clock(); s.test[ITER].sum = sum; s.test[DESTRUCT].t1 = clock(); - clist_x_del(&con); + clist_x_drop(&con); } s.test[DESTRUCT].t2 = clock(); s.test[DESTRUCT].sum = 0; diff --git a/benchmarks/plotbench/cmap_benchmark.cpp b/benchmarks/plotbench/cmap_benchmark.cpp index 4c9c6c16..16aec8c0 100644 --- a/benchmarks/plotbench/cmap_benchmark.cpp +++ b/benchmarks/plotbench/cmap_benchmark.cpp @@ -82,7 +82,7 @@ Sample test_stc_unordered_map() { c_forrange (N) cmap_x_erase(&con, stc64_random() & mask1); s.test[ERASE].t2 = clock(); s.test[ERASE].sum = cmap_x_size(con); - cmap_x_del(&con); + cmap_x_drop(&con); }{ container con = cmap_x_init(); stc64_srandom(seed); @@ -103,7 +103,7 @@ Sample test_stc_unordered_map() { s.test[ITER].t2 = clock(); s.test[ITER].sum = sum; s.test[DESTRUCT].t1 = clock(); - cmap_x_del(&con); + cmap_x_drop(&con); } s.test[DESTRUCT].t2 = clock(); s.test[DESTRUCT].sum = 0; diff --git a/benchmarks/plotbench/cpque_benchmark.cpp b/benchmarks/plotbench/cpque_benchmark.cpp index 19a9c701..33e55719 100644 --- a/benchmarks/plotbench/cpque_benchmark.cpp +++ b/benchmarks/plotbench/cpque_benchmark.cpp @@ -3,7 +3,7 @@ #include #define i_val float -#define i_cmp -c_default_compare +#define i_cmp -c_default_cmp #define i_tag f #include @@ -14,11 +14,12 @@ int main() int N = 10000000, M = 10; cpque_f pq = cpque_f_init(); + cpque_f_resize(&pq, N, 0.0f); rng = stc64_init(seed); clock_t start = clock(); - c_forrange (i, int, N) - cpque_f_push_back(&pq, (float) stc64_randf(&rng)*100000); + c_forrange (i, N) + pq.data[i] = (float) stc64_randf(&rng)*100000; cpque_f_make_heap(&pq); printf("Built priority queue: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC); @@ -44,5 +45,5 @@ int main() } puts(""); - cpque_f_del(&pq); + cpque_f_drop(&pq); } diff --git a/benchmarks/plotbench/csmap_benchmark.cpp b/benchmarks/plotbench/csmap_benchmark.cpp index 47762791..4d1621e3 100644 --- a/benchmarks/plotbench/csmap_benchmark.cpp +++ b/benchmarks/plotbench/csmap_benchmark.cpp @@ -82,7 +82,7 @@ Sample test_stc_map() { c_forrange (N) csmap_x_erase(&con, stc64_random() & mask1); s.test[ERASE].t2 = clock(); s.test[ERASE].sum = csmap_x_size(con); - csmap_x_del(&con); + csmap_x_drop(&con); }{ container con = csmap_x_init(); stc64_srandom(seed); @@ -103,7 +103,7 @@ Sample test_stc_map() { s.test[ITER].t2 = clock(); s.test[ITER].sum = sum; s.test[DESTRUCT].t1 = clock(); - csmap_x_del(&con); + csmap_x_drop(&con); } s.test[DESTRUCT].t2 = clock(); s.test[DESTRUCT].sum = 0; diff --git a/benchmarks/plotbench/cvec_benchmark.cpp b/benchmarks/plotbench/cvec_benchmark.cpp index c4648e34..21e7a229 100644 --- a/benchmarks/plotbench/cvec_benchmark.cpp +++ b/benchmarks/plotbench/cvec_benchmark.cpp @@ -77,7 +77,7 @@ Sample test_stc_vector() { c_forrange (N) { cvec_x_pop_back(&con); } s.test[ERASE].t2 = clock(); s.test[ERASE].sum = cvec_x_size(con); - cvec_x_del(&con); + cvec_x_drop(&con); }{ stc64_srandom(seed); container con = cvec_x_init(); @@ -94,7 +94,7 @@ Sample test_stc_vector() { s.test[ITER].t2 = clock(); s.test[ITER].sum = sum; s.test[DESTRUCT].t1 = clock(); - cvec_x_del(&con); + cvec_x_drop(&con); } s.test[DESTRUCT].t2 = clock(); s.test[DESTRUCT].sum = 0; diff --git a/benchmarks/shootout_hashmaps.cpp b/benchmarks/shootout_hashmaps.cpp index 40e0e579..6439c548 100644 --- a/benchmarks/shootout_hashmaps.cpp +++ b/benchmarks/shootout_hashmaps.cpp @@ -47,7 +47,7 @@ size_t seed; #define CMAP_SIZE(X) cmap_##X##_size(map) #define CMAP_BUCKETS(X) cmap_##X##_bucket_count(map) #define CMAP_CLEAR(X) cmap_##X##_clear(&map) -#define CMAP_DTOR(X) cmap_##X##_del(&map) +#define CMAP_DTOR(X) cmap_##X##_drop(&map) #define KMAP_SETUP(X, Key, Value) khash_t(X)* map = kh_init(X); khiter_t ki; int ret #define KMAP_PUT(X, key, val) (*(ki = kh_put(X, map, key, &ret), map->vals[ki] = val, map->vals+ki)) diff --git a/docs/carray_api.md b/docs/carray_api.md index 5e26f658..3ac6d650 100644 --- a/docs/carray_api.md +++ b/docs/carray_api.md @@ -10,8 +10,8 @@ See the c++ class [boost::multi_array](https://www.boost.org/doc/libs/release/li ```c #define i_val // value: REQUIRED -#define i_del // destroy value func - defaults to empty destruct -#define i_valfrom // func Raw => i_val - defaults to plain copy +#define i_drop // destroy value func - defaults to empty destruct +#define i_from // func Raw => i_val - defaults to plain copy #define i_valto // func i_val => Raw - defaults to plain copy #define i_tag // defaults to i_val @@ -29,7 +29,7 @@ carr2_X carr2_X_with_storage(size_t xdim, size_t ydim, i_val* array) carr2_X carr2_X_clone(carr2_X arr); void carr2_X_copy(carr2_X* self, carr2_X other); i_val* carr2_X_release(carr2_X* self); // release storage (not freed) -void carr2_X_del(carr2_X* self); +void carr2_X_drop(carr2_X* self); size_t carr2_X_size(carr2_X arr); i_val* carr2_X_data(carr2_X* self); // access storage data @@ -48,7 +48,7 @@ carr3_X carr3_X_with_storage(size_t xdim, size_t ydim, size_t zdim, carr3_X carr3_X_clone(carr3_X arr); void carr3_X_copy(carr3_X* self, carr3_X other); i_val* carr3_X_release(carr3_X* self); // release storage (not freed) -void carr3_X_del(carr3_X* self); +void carr3_X_drop(carr3_X* self); size_t carr3_X_size(carr3_X arr); i_val* carr3_X_data(carr3_X* self); // storage data @@ -91,7 +91,7 @@ int main() int xd = 30, yd = 20, zd = 10; // define arr3[30][20][10], initialized with zeros. c_autovar (carr3_f arr3 = carr3_f_with_values(xd, yd, zd, 0.0f), - carr3_f_del(&arr3)) { + carr3_f_drop(&arr3)) { arr3.data[5][4][3] = 3.14f; float *arr1 = arr3.data[5][4]; @@ -104,7 +104,7 @@ int main() // Ex2 int w = 256, h = 128; - c_autovar (carr2_i image = carr2_i_init(w, h), carr2_i_del(&image)) { + c_autovar (carr2_i image = carr2_i_init(w, h), carr2_i_drop(&image)) { int n = 0; c_foreach (i, carr2_i, image) { uint32_t t = n++ % 256; diff --git a/docs/cbits_api.md b/docs/cbits_api.md index b369b5d1..f6077d20 100644 --- a/docs/cbits_api.md +++ b/docs/cbits_api.md @@ -27,7 +27,7 @@ cbits cbits_clone(cbits other); void cbits_clear(cbits* self); cbits* cbits_copy(cbits* self, cbits other); void cbits_resize(cbits* self, size_t size, bool value); -void cbits_del(cbits* self); +void cbits_drop(cbits* self); cbits* cbits_take(cbits* self, cbits other); // give other to self cbits cbits_move(cbits* self); // transfer self to caller @@ -103,7 +103,7 @@ int main(void) if (cbits_test(primes, i>>1)) printf(" %zu", i); puts(""); - cbits_del(&primes); + cbits_drop(&primes); } ``` Output: diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 83cec830..8580e7d7 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -1,12 +1,12 @@ # STC [cbox](../include/stc/cbox.h): (Boxed) Heap Allocated Objects **cbox** is a A box is a smart pointer to a heap allocated value of type X. A **cbox** can -be empty. The *cbox_X_compare()*, *cbox_X_del()* methods are defined based on the `i_cmp` -and `i_valdel` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the +be empty. The *cbox_X_cmp()*, *cbox_X_drop()* methods are defined based on the `i_cmp` +and `i_valdrop` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the `i_valfrom` macro if defined. -When declaring a container of **cbox** values, it is recommended to define `i_val_ref` to the -cbox type instead of defining `i_val`. This will auto-set `i_del`, `i_from`, and `i_cmp` using +When declaring a container of **cbox** values, it is recommended to define `i_val_bind` to the +cbox type instead of defining `i_val`. This will auto-set `i_drop`, `i_from`, and `i_cmp` using functions defined by the specified **cbox**. For containers, make sure to pass the result of create functions like *cbox_X_new()* **only** to @@ -20,21 +20,21 @@ See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type -#define i_del // destroy value func - defaults to empty destruct -#define i_from // create from raw/clone func - REQUIRED if i_del is defined, +#define i_drop // destroy value func - defaults to empty destruct +#define i_from // create from raw/clone func - REQUIRED if i_drop is defined, // unless 'i_opt c_no_clone' is defined. #define i_tag // type name tag, defaults to i_val #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. -Define `i_opt` with `c_no_compare` if comparison between i_val's is not needed/available. Will then +Define `i_opt` with `c_no_cmp` if comparison between i_val's is not needed/available. Will then compare the pointer addresses when used. Additionally, `c_no_clone` or `i_is_fwd` may be defined. ## Methods ```c cbox_X cbox_X_init(); // return an empty cbox cbox_X cbox_X_new(i_val val); // allocate new heap object with val. Take ownership of val. -cbox_X cbox_X_from(i_rawval raw); // like cbox_X_new(), but create owned value from raw. +cbox_X cbox_X_from(i_valraw raw); // like cbox_X_new(), but create owned value from raw. cbox_X cbox_X_with(i_val* p); // create a cbox from a pointer. Takes ownership of p. cbox_X cbox_X_clone(cbox_X other); // return deep copied clone @@ -42,14 +42,14 @@ cbox_X cbox_X_move(cbox_X* self); // transfer owners void cbox_X_take(cbox_X* self, cbox_X other); // take ownership of other. void cbox_X_copy(cbox_X* self, cbox_X other); // deep copy to self -void cbox_X_del(cbox_X* self); // destruct the contained object and free's it. +void cbox_X_drop(cbox_X* self); // destruct the contained object and free's it. void cbox_X_reset(cbox_X* self); void cbox_X_reset_new(cbox_X* self, i_val val); // assign new cbox with value. Takes ownership of val. -void cbox_X_reset_from(cbox_X* self, i_rawval raw); // make and assign new cbox from raw value. +void cbox_X_reset_from(cbox_X* self, i_valraw raw); // make and assign new cbox from raw value. void cbox_X_reset_with(cbox_X* self, i_val* p); // create cbox with pointer p. Takes ownership of p. -int cbox_X_compare(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_compare' +int cbox_X_cmp(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_cmp' // is defined. Otherwise uses 'i_cmp' or default compare. ``` ## Types and constants @@ -66,14 +66,14 @@ int cbox_X_compare(const cbox_X* x, const cbox_X* y); // compares pointe #include #include -void int_del(int* x) { - printf("del: %d\n", *x); +void int_drop(int* x) { + printf("drop: %d\n", *x); } -// When 'i_del' is defined, you are also forced to define a clone function with -// 'i_valfrom', as it is normally required when i_del destroys resources. +// When 'i_drop' is defined, you are also forced to define a clone function with +// 'i_from', as it is normally required when i_drop destroys resources. // -// If cloning is not needed, define 'i_opt c_no_clone' instead of 'i_valfrom' +// If cloning is not needed, define 'i_opt c_no_clone' instead of 'i_from' // both for the cbox type and the container of cbox elements. It will also // disable emplace container functions. // @@ -81,22 +81,22 @@ void int_del(int* x) { // define cloning internally. #define i_val int -#define i_del int_del // optional func, just to display elements destroyed -#define i_valfrom c_default_clone -#include // cbox_int +#define i_drop int_drop // optional func, just to display elements destroyed +#define i_from c_default_clone +#include // cbox_int -#define i_key_ref cbox_int // note: use i_key_ref instead of i_key -#define i_tag int // tag otherwise defaults to 'ref' -#include // csset_int (like: std::set>) +#define i_key_bind cbox_int // note: use i_key_bind instead of i_key +#define i_tag int // tag otherwise defaults to 'ref' +#include // csset_int (like: std::set>) -#define i_val_ref cbox_int // note: use i_val_ref instead of i_val -#define i_tag int // tag otherwise defaults to 'ref' -#include // cvec_int (like: std::vector>) +#define i_val_bind cbox_int // note: use i_val_bind instead of i_val +#define i_tag int // tag otherwise defaults to 'ref' +#include // cvec_int (like: std::vector>) int main() { - c_auto (cvec_int, vec) // declare and init vec, call del at scope exit - c_auto (csset_int, set) // declare and init set, call del at scope exit + c_auto (cvec_int, vec) // declare and init vec, call drop at scope exit + c_auto (csset_int, set) // declare and init set, call drop at scope exit { c_apply(cvec_int, push_back, &vec, { cbox_int_new(2021), @@ -130,13 +130,13 @@ int main() Output: ``` vec: 2021 2012 2022 2015 -del: 2015 -del: 2022 +drop: 2015 +drop: 2022 vec: 2021 2012 set: 2015 2021 Done -del: 2021 -del: 2015 -del: 2021 -del: 2012 +drop: 2021 +drop: 2015 +drop: 2021 +drop: 2012 ``` diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 740df9a4..cc021001 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -13,7 +13,7 @@ macros, as one must always make sure to unwind temporary allocated resources bef | Usage | Description | |:---------------------------------------|:---------------------------------------------------| -| `c_auto (Type, var...)` | `c_autovar (Type var=Type_init(), Type_del(&var))` | +| `c_auto (Type, var...)` | `c_autovar (Type var=Type_init(), Type_drop(&var))` | | `c_autovar (Type var=init, end...)` | Declare `var`. Defer `end...` to end of block | | `c_autoscope (init, end...)` | Execute `init`. Defer `end...` to end of block | | `c_autodefer (end...)` | Defer `end...` to end of block | @@ -22,7 +22,7 @@ macros, as one must always make sure to unwind temporary allocated resources bef For multiple variables, use either multiple **c_autovar** in sequence, or declare variable outside scope and use **c_autoscope**. Also, **c_auto** support up to 3 variables. ```c -c_autovar (cstr s = cstr_new("Hello"), cstr_del(&s)) +c_autovar (cstr s = cstr_new("Hello"), cstr_drop(&s)) { cstr_append(&s, " world"); printf("%s\n", s.str); @@ -46,7 +46,7 @@ c_autoscope (mydata_init(&data), mydata_destroy(&data)) } cstr s1 = cstr_new("Hello"), s2 = cstr_new("world"); -c_autodefer (cstr_del(&s1), cstr_del(&s2)) +c_autodefer (cstr_drop(&s1), cstr_drop(&s2)) { printf("%s %s\n", s1.str, s2.str); } @@ -65,7 +65,7 @@ cvec_str readFile(const char* name) cvec_str vec = cvec_str_init(); // returned c_autovar (FILE* fp = fopen(name, "r"), fclose(fp)) - c_autovar (cstr line = cstr_null, cstr_del(&line)) + c_autovar (cstr line = cstr_null, cstr_drop(&line)) while (cstr_getline(&line, fp)) cvec_str_emplace_back(&vec, line.str); return vec; @@ -73,7 +73,7 @@ cvec_str readFile(const char* name) int main() { - c_autovar (cvec_str x = readFile(__FILE__), cvec_str_del(&x)) + c_autovar (cvec_str x = readFile(__FILE__), cvec_str_drop(&x)) c_foreach (i, cvec_str, x) printf("%s\n", i.ref->str); } @@ -140,14 +140,14 @@ int arr[] = {1, 2, 3}; c_apply_n(cvec_i, push_back, &vec, arr, c_arraylen(arr)); ``` -### c_new, c_alloc, c_alloc_n, c_del, c_make +### c_new, c_alloc, c_alloc_n, c_drop, c_make | Usage | Meaning | |:-------------------------------|:----------------------------------------| | `c_new (type, value)` | Move value to a new object on the heap | | `c_alloc (type)` | `(type *) c_malloc(sizeof(type))` | | `c_alloc_n (type, N)` | `(type *) c_malloc((N)*sizeof(type))` | -| `c_del (ctype, &c1, ..., &cN)` | `ctype_del(&c1); ... ctype_del(&cN)` | +| `c_drop (ctype, &c1, ..., &cN)` | `ctype_drop(&c1); ... ctype_drop(&cN)` | | `c_make(type){value...}` | `(type){value...}` // c++ compatability | ```c @@ -159,17 +159,17 @@ int* array = c_alloc_n (int, 100); c_free(array); cstr a = cstr_new("Hello"), b = cstr_new("World"); -c_del(cstr, &a, &b); +c_drop(cstr, &a, &b); ``` ### General predefined template parameter functions ``` -int c_default_compare(const Type*, const Type*); +int c_default_cmp(const Type*, const Type*); Type c_default_clone(Type val); // simple copy Type c_default_toraw(const Type* val); // dereference val -void c_default_del(Type* val); // does nothing +void c_default_drop(Type* val); // does nothing -int c_rawstr_compare(const char* const* a, const char* const* b); +int c_rawstr_cmp(const char* const* a, const char* const* b); bool c_rawstr_equalto(const char* const* a, const char* const* b); ``` diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 554b4c7b..1985c2ab 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -10,7 +10,7 @@ See the c++ class [std::deque](https://en.cppreference.com/w/cpp/container/deque ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val #define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy @@ -31,7 +31,7 @@ void cdeq_X_copy(cdeq_X* self, cdeq_X other); bool cdeq_X_reserve(cdeq_X* self, size_t cap); void cdeq_X_shrink_to_fit(cdeq_X* self); void cdeq_X_swap(cdeq_X* a, cdeq_X* b); -void cdeq_X_del(cdeq_X* self); // destructor +void cdeq_X_drop(cdeq_X* self); // destructor bool cdeq_X_empty(cdeq_X deq); size_t cdeq_X_size(cdeq_X deq); @@ -119,7 +119,7 @@ int main() { c_foreach (i, cdeq_i, q) printf(" %d", *i.ref); puts(""); - cdeq_i_del(&q); + cdeq_i_drop(&q); } ``` Output: diff --git a/docs/clist_api.md b/docs/clist_api.md index b45108a7..0817737b 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -24,10 +24,10 @@ See the c++ class [std::list](https://en.cppreference.com/w/cpp/container/list) ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy +#define i_from // convertion func i_valraw => i_val - defaults to plain copy #define i_tag // defaults to i_val #include ``` @@ -42,7 +42,7 @@ clist_X clist_X_clone(clist_X list); void clist_X_clear(clist_X* self); void clist_X_copy(clist_X* self, clist_X other); -void clist_X_del(clist_X* self); // destructor +void clist_X_drop(clist_X* self); // destructor bool clist_X_empty(clist_X list); size_t clist_X_count(clist_X list); // size() in O(n) time @@ -125,7 +125,7 @@ int main() { c_foreach (i, clist_d, list) printf(" %g", *i.ref); - clist_d_del(&list); + clist_d_drop(&list); } ``` Output: @@ -161,7 +161,7 @@ int main () c_foreach (x, clist_i, L) printf(" %d", *x.ref); puts(""); - clist_i_del(&L); + clist_i_drop(&L); } ``` Output: diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 0fec365c..e2cb668f 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -21,13 +21,13 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_keyraw*: REQUIRED IF i_keyraw is non-integral type #define i_equ // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp -#define i_keydel // destroy key func - defaults to empty destruct +#define i_keydrop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_valdel // destroy value func - defaults to empty destruct +#define i_valdrop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy +#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy #define i_tag // defaults to i_key #include @@ -47,7 +47,7 @@ void cmap_X_max_load_factor(cmap_X* self, float max_load); bool cmap_X_reserve(cmap_X* self, size_t size); void cmap_X_shrink_to_fit(cmap_X* self); void cmap_X_swap(cmap_X* a, cmap_X* b); -void cmap_X_del(cmap_X* self); // destructor +void cmap_X_drop(cmap_X* self); // destructor size_t cmap_X_size(cmap_X map); size_t cmap_X_capacity(cmap_X map); // buckets * max_load_factor @@ -207,15 +207,15 @@ typedef struct { int x, y, z; } Vec3i; int main() { // Define map with defered destruct - c_autovar (cmap_vi vecs = cmap_vi_init(), cmap_vi_del(&vecs)) + c_autovar (cmap_vi vecs = cmap_vi_init(), cmap_vi_drop(&vecs)) { cmap_vi_insert(&vecs, (Vec3i){100, 0, 0}, 1); cmap_vi_insert(&vecs, (Vec3i){ 0, 100, 0}, 2); cmap_vi_insert(&vecs, (Vec3i){ 0, 0, 100}, 3); cmap_vi_insert(&vecs, (Vec3i){100, 100, 100}, 4); - c_foreach (i, cmap_vi, vecs) - printf("{ %3d, %3d, %3d }: %d\n", i.ref->first.x, i.ref->first.y, i.ref->first.z, i.ref->second); + c_forpair (vec, num, cmap_vi, vecs) + printf("{ %3d, %3d, %3d }: %d\n", _.vec.x, _.vec.y, _.vec.z, _.num); } } ``` @@ -240,15 +240,15 @@ typedef struct { int x, y, z; } Vec3i; int main() { - c_autovar (cmap_iv vecs = cmap_iv_init(), cmap_iv_del(&vecs)) + c_auto (cmap_iv, vecs) // shorthand for c_autovar with _init(), _drop(). { cmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0}); cmap_iv_insert(&vecs, 2, (Vec3i){ 0, 100, 0}); cmap_iv_insert(&vecs, 3, (Vec3i){ 0, 0, 100}); cmap_iv_insert(&vecs, 4, (Vec3i){100, 100, 100}); - c_foreach (i, cmap_iv, vecs) - printf("%d: { %3d, %3d, %3d }\n", i.ref->first, i.ref->second.x, i.ref->second.y, i.ref->second.z); + c_forpair (num, vec, cmap_iv, vecs) + printf("%d: { %3d, %3d, %3d }\n", _.num_, _.vec.x, _.vec.y, _.vec.z); } } ``` @@ -270,45 +270,56 @@ typedef struct { cstr country; } Viking; -static bool Viking_equalto(const Viking* a, const Viking* b) { +#define Viking_init() ((Viking){cstr_null, cstr_null}) + +static inline bool RViking_equalto(const Viking* a, const Viking* b) { return cstr_equals_s(a->name, b->name) && cstr_equals_s(a->country, b->country); } -static uint32_t Viking_hash(const Viking* a, int ignored) { +static inline uint32_t RViking_hash(const Viking* a, int ignored) { return c_strhash(a->name.str) ^ (c_strhash(a->country.str) >> 15); } -static void Viking_del(Viking* v) { - c_del(cstr, &v->name, &v->country); +static inline Viking Viking_clone(Viking v) { + v.name = cstr_clone(v.name); + v.country = cstr_clone(v.country); +} + +void inline Viking_drop(Viking* vk) { + cstr_drop(&vk->name); + cstr_drop(&vk->country); } -#define i_key Viking +#define i_type Vikings +#define i_key_bind Viking #define i_val int -#define i_equ Viking_equalto -#define i_hash Viking_hash -#define i_del Viking_del -#define i_tag vk +// i_key_bind auto-binds: +// #define i_equ RViking_equalto +// #define i_hash RViking_hash +// #define i_keyfrom Viking_clone +// #define i_drop Viking_drop #include int main() { // Use a HashMap to store the vikings' health points. - cmap_vk vikings = cmap_vk_init(); - - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); - cmap_vk_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); - cmap_vk_insert(&vikings, (Viking){cstr_new("Harald"), cstr_new("Iceland")}, 12); - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Denmark")}, 21); - - Viking lookup = (Viking){cstr_new("Einar"), cstr_new("Norway")}; - printf("Lookup: Einar of Norway has %d hp\n\n", *cmap_vk_at(&vikings, lookup)); - Viking_del(&lookup); - - // Print the status of the vikings. - c_foreach (i, cmap_vk, vikings) { - printf("%s of %s has %d hp\n", i.ref->first.name.str, i.ref->first.country.str, i.ref->second); + c_auto (Vikings, vikings) // uses Vikings_init(), Vikings_drop() + { + Vikings_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); + Vikings_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); + Vikings_insert(&vikings, (Viking){cstr_new("Harald"), cstr_new("Iceland")}, 12); + Vikings_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Denmark")}, 21); + + c_auto (Viking, lookup) { + lookup = (Viking){cstr_new("Einar"), cstr_new("Norway")}; + printf("Lookup: Einar of Norway has %d hp\n\n", *Vikings_at(&vikings, lookup)); + } + + // Print the status of the vikings. + c_forpair (viking, hp, Vikings, vikings) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.hp); + } } - cmap_vk_del(&vikings); } ``` Output: @@ -326,65 +337,65 @@ to add "raw" type entries (otherwise compile error): ```c #include -typedef struct { +typedef struct Viking { cstr name; cstr country; } Viking; -static void Viking_del(Viking* v) { - c_del(cstr, &v->name, &v->country); +static inline void Viking_drop(Viking* v) { + c_drop(cstr, &v->name, &v->country); } -// Define a "raw" type that does not need allocations. -// Define equals, hash, fromraw, toraw functions: +// Define Viking raw struct with hash, equalto, and convertion functions between Viking and RViking structs: -typedef struct { +typedef struct RViking { const char* name; const char* country; } RViking; -static bool RViking_equalto(const RViking* r1, const RViking* r2) - { return !strcmp(r1->name, r2->name) && !strcmp(r1->country, r2->country); } - -static uint32_t RViking_hash(const RViking* r, int ignored) - { return c_strhash(r->name) ^ (c_strhash(r->country) >> 15); } - -static Viking Viking_fromR(RViking r) - { return (Viking){cstr_from(r.name), cstr_from(r.country)}; } +static inline uint64_t RViking_hash(const RViking* raw, size_t ignore) { + uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); + return hash; +} +static inline bool RViking_equalto(const RViking* rx, const RViking* ry) { + return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; +} -static RViking Viking_toR(const Viking* v) - { return (RViking){v->name.str, v->country.str}; } +static inline Viking Viking_from(RViking raw) { + return (Viking){cstr_from(raw.name), cstr_from(raw.country)}; +} +static inline RViking Viking_toraw(const Viking* vk) { + return (RViking){vk->name.str, vk->country.str}; +} -#define i_key Viking -#define i_val int -#define i_keydel Viking_del -#define i_keyraw RViking -#define i_equ RViking_equalto -#define i_hash RViking_hash -#define i_keyfrom Viking_fromR -#define i_keyto Viking_toR -#define i_tag vk +// With this in place, we define the Viking => int hash map type: +#define i_type Vikings +#define i_key_bind Viking +#define i_val int +#define i_keyraw RViking +// i_key_bind macro will make these functions auto-bind: +// #define i_hash RViking_hash +// #define i_equ RViking_equalto +// #define i_keyfrom Viking_from // uses _from because i_keyraw is defined +// #define i_keyto Viking_toraw +// #define i_keydrop Viking_drop #include int main() { - c_auto (cmap_vk, vikings) // RAII - { - // Insert works as before, takes a constructed Viking object - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); - cmap_vk_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); - - // Emplace is simpler to use now - takes rawkey argument - cmap_vk_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12); - cmap_vk_emplace(&vikings, (RViking){"Einar", "Denmark"}, 21); + c_auto (Vikings, vikings) { + c_apply_pair(Vikings, emplace, &vikings, { + {{"Einar", "Norway"}, 20}, + {{"Olaf", "Denmark"}, 24}, + {{"Harald", "Iceland"}, 12}, + }); + Vikings_emplace_or_assign(&vikings, (RViking){"Bjorn", "Sweden"}, 10); - // Lookup also uses rawkey args, no need construct/destruct key: - printf("Lookup: Einar of Norway has %d hp\n\n", *cmap_vk_at(&vikings, (RViking){"Einar", "Norway"})); + Vikings_value *einar = Vikings_find(&vikings, (RViking){"Einar", "Norway"}).ref; + if (einar) einar->second += 3; // add 3 hp points to Einar - // Print the status of the vikings. - c_foreach (i, cmap_vk, vikings) { - printf("%s of %s has %d hp\n", i.ref->first.name.str, - i.ref->first.country.str, i.ref->second); + c_forpair (viking, health, Vikings, vikings) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.health); } } } diff --git a/docs/cpque_api.md b/docs/cpque_api.md index 5c0c9ec4..e891b7d2 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -12,7 +12,7 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valfrom // convertion func i_val => i_val - defaults to plain copy #define i_tag // defaults to i_val #include @@ -29,7 +29,7 @@ void cpque_X_clear(cpque_X* self); bool cpque_X_reserve(cpque_X* self, size_t n); void cpque_X_shrink_to_fit(cpque_X* self); void cpque_X_copy(cpque_X* self, cpque_X other); -void cpque_X_del(cpque_X* self); // destructor +void cpque_X_drop(cpque_X* self); // destructor size_t cpque_X_size(cpque_X pq); bool cpque_X_empty(cpque_X pq); @@ -59,7 +59,7 @@ cpque_X_value cpque_X_value_clone(cpque_X_value val); #include #define i_val int64_t -#define i_cmp -c_default_compare // min-heap +#define i_cmp -c_default_cmp // min-heap #define i_tag i #include @@ -69,7 +69,7 @@ int main() stc64_t rng = stc64_init(1234); stc64_uniform_t dist = stc64_uniform_init(0, N * 10); - // Declare heap, with defered del() + // Declare heap, with defered drop() c_auto (cpque_i, heap) { // Push ten million random numbers to priority queue, plus some negative ones. diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index 469b7c99..9fd2c4e0 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -9,7 +9,7 @@ See the c++ class [std::queue](https://en.cppreference.com/w/cpp/container/queue ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val #define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy @@ -27,7 +27,7 @@ cqueue_X cqueue_X_clone(cqueue_X q); void cqueue_X_clear(cqueue_X* self); void cqueue_X_copy(cqueue_X* self, cqueue_X other); -void cqueue_X_del(cqueue_X* self); // destructor +void cqueue_X_drop(cqueue_X* self); // destructor size_t cqueue_X_size(cqueue_X q); bool cqueue_X_empty(cqueue_X q); @@ -76,7 +76,7 @@ int main() { c_foreach (i, cqueue_i, Q) printf(" %d", *i.ref); - cqueue_i_del(&Q); + cqueue_i_drop(&Q); } ``` Output: diff --git a/docs/crandom_api.md b/docs/crandom_api.md index 3dd829aa..b099eeaf 100644 --- a/docs/crandom_api.md +++ b/docs/crandom_api.md @@ -108,8 +108,8 @@ int main() } } // Cleanup - cstr_del(&bar); - csmap_i_del(&mhist); + cstr_drop(&bar); + csmap_i_drop(&mhist); } ``` Output: diff --git a/docs/cset_api.md b/docs/cset_api.md index 4883664d..b70f5fb9 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -11,10 +11,10 @@ A **cset** is an associative container that contains a set of unique objects of #define i_hash // hash func: REQUIRED IF i_keyraw is a non-pod type #define i_cmp // three-way compare two i_keyraw*: REQUIRED IF i_keyraw is a non-integral type #define i_equ // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp -#define i_del // destroy key func - defaults to empty destruct +#define i_drop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy -#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy #define i_tag // defaults to i_key #include ``` @@ -33,7 +33,7 @@ void cset_X_max_load_factor(cset_X* self, float max_load); bool cset_X_reserve(cset_X* self, size_t size); void cset_X_shrink_to_fit(cset_X* self); void cset_X_swap(cset_X* a, cset_X* b); -void cset_X_del(cset_X* self); // destructor +void cset_X_drop(cset_X* self); // destructor size_t cset_X_size(cset_X set); // num. of allocated buckets size_t cset_X_capacity(cset_X set); // buckets * max_load_factor diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 646f8c99..88d58cd4 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -18,11 +18,11 @@ See the c++ class [std::map](https://en.cppreference.com/w/cpp/container/map) fo #define i_key // key: REQUIRED #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_keyraw* : REQUIRED IF i_keyraw is a non-integral type -#define i_keydel // destroy key func - defaults to empty destruct +#define i_keydrop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key #define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_valdel // destroy value func - defaults to empty destruct +#define i_valdrop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val #define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy @@ -40,12 +40,12 @@ csmap_X csmap_X_clone(csmap_x map); void csmap_X_clear(csmap_X* self); void csmap_X_copy(csmap_X* self, csmap_X other); void csmap_X_swap(csmap_X* a, csmap_X* b); -void csmap_X_del(csmap_X* self); // destructor +void csmap_X_drop(csmap_X* self); // destructor size_t csmap_X_size(csmap_X map); bool csmap_X_empty(csmap_X map); -const csmap_X_mapped* csmap_X_at(const csmap_X* self, i_keyraw rkey); // rkey must be in map. +csmap_X_mapped* csmap_X_at(const csmap_X* self, i_keyraw rkey); // rkey must be in map. const csmap_X_value* csmap_X_get(const csmap_X* self, i_keyraw rkey); // return NULL if not found csmap_X_value* csmap_X_get_mut(csmap_X* self, i_keyraw rkey); // mutable get bool csmap_X_contains(const csmap_X* self, i_keyraw rkey); @@ -144,7 +144,7 @@ int main() { uint32_t col = 0xcc7744ff; csmap_id idnames = csmap_id_init(); - c_autodefer (csmap_id_del(&idnames)) + c_autodefer (csmap_id_drop(&idnames)) { c_apply_pair(csmap_id, emplace, &idnames, { {100, "Red"}, @@ -174,7 +174,7 @@ Demonstrate csmap with plain-old-data key type Vec3i and int as mapped type: csm ```c typedef struct { int x, y, z; } Vec3i; -static int Vec3i_compare(const Vec3i* a, const Vec3i* b) { +static int Vec3i_cmp(const Vec3i* a, const Vec3i* b) { int c; if ((c = a->x - b->x) != 0) return c; if ((c = a->y - b->y) != 0) return c; @@ -183,7 +183,7 @@ static int Vec3i_compare(const Vec3i* a, const Vec3i* b) { #define i_key Vec3i #define i_val int -#define i_cmp Vec3i_compare // uses c_default_hash +#define i_cmp Vec3i_cmp // uses c_default_hash #define i_tag vi #include #include @@ -224,7 +224,7 @@ typedef struct { int x, y, z; } Vec3i; int main() { // equivalent to: c_auto (csmap_iv, vecs) - c_autovar (csmap_iv vecs = csmap_iv_init(), csmap_iv_del(&vecs)) + c_autovar (csmap_iv vecs = csmap_iv_init(), csmap_iv_drop(&vecs)) { csmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0}); csmap_iv_insert(&vecs, 2, (Vec3i){0, 100, 0}); diff --git a/docs/csptr_api.md b/docs/csptr_api.md index 640f5cf1..5cbe746f 100644 --- a/docs/csptr_api.md +++ b/docs/csptr_api.md @@ -1,19 +1,19 @@ -# STC [csptr](../include/stc/csptr.h): Shared Pointers +# STC [csptr](../include/stc/csptr.h): Atomic Reference Counted **csptr** is a smart pointer that retains shared ownership of an object through a pointer. Several **csptr** objects may own the same object. The object is destroyed and its memory -deallocated when the last remaining **csptr** owning the object is destroyed with *csptr_X_del()*; +deallocated when the last remaining **csptr** owning the object is destroyed with *csptr_X_drop()*; -The object is destroyed using *csptr_X_del()*. A **csptr** may also own no objects, in which -case it is called empty. The *csptr_X_compare()*, *csptr_X_del()* methods are defined based on -the `i_cmp` and `i_valdel` macros specified. Use *csptr_X_clone(p)* when sharing ownership of +The object is destroyed using *csptr_X_drop()*. A **csptr** may also own no objects, in which +case it is called empty. The *csptr_X_cmp()*, *csptr_X_drop()* methods are defined based on +the `i_cmp` and `i_valdrop` macros specified. Use *csptr_X_clone(p)* when sharing ownership of the pointed-to object. All **csptr** functions can be called by multiple threads on different instances of **csptr** without additional synchronization even if these instances are copies and share ownership of the same object. -**csptr** uses thread-safe atomic reference counting, through the *csptr_X_clone()* and *csptr_X_del()* methods. +**csptr** uses thread-safe atomic reference counting, through the *csptr_X_clone()* and *csptr_X_drop()* methods. -When declaring a container with shared pointers, define `i_val_ref` as the csptr type, see example. +When declaring a container with shared pointers, define `i_val_bind` as the csptr type, see example. For containers, make sure to pass the result of create functions *csptr_X_new()* **only** to *insert()*, *push_back()*, and *push()* functions. Use *emplace()* method for sharing existing **csptr**s between @@ -26,7 +26,7 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_tag // defaults to i_val #define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc. #include @@ -35,34 +35,34 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ## Methods ```c -csptr_X csptr_X_init(); // empty shared pointer -csptr_X csptr_X_new(i_val val); // create new heap allocated object. Take ownership of val. -csptr_X csptr_X_from(i_rawval raw); // like csptr_X_new(), but construct owned value from raw. -csptr_X csptr_X_with(i_val* p); // create a csptr from raw pointer. Takes ownership of p. +csptr_X csptr_X_init(); // empty shared pointer +csptr_X csptr_X_new(i_val val); // create new heap allocated object. Take ownership of val. +csptr_X csptr_X_from(i_valraw raw); // like csptr_X_new(), but construct owned value from raw. +csptr_X csptr_X_with(i_val* p); // create a csptr from raw pointer. Takes ownership of p. -csptr_X csptr_X_clone(csptr_X other); // return other with increased use count -csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr. -void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other. -void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count) +csptr_X csptr_X_clone(csptr_X other); // return other with increased use count +csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr. +void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other. +void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count) -void csptr_X_del(csptr_X* self); // destruct (decrease use count, free at 0) +void csptr_X_drop(csptr_X* self); // destruct (decrease use count, free at 0) long csptr_X_use_count(csptr_X ptr); void csptr_X_reset(csptr_X* self); void csptr_X_reset_new(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val. -void csptr_X_reset_from(csptr_X* self, i_rawval raw); // make and assign new csptr from raw value. +void csptr_X_reset_from(csptr_X* self, i_valraw raw); // make and assign new csptr from raw value. void csptr_X_reset_with(csptr_X* self, i_val* p); // create csptr with pointer p. Takes ownership of p. -int csptr_X_compare(const csptr_X* x, const csptr_X* y); // compares pointer addresses if 'i_opt c_no_compare' - // is defined. Otherwise uses 'i_cmp' or default compare. +int csptr_X_cmp(const csptr_X* x, const csptr_X* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default compare. ``` ## Types and constants -| Type name | Type definition | Used to represent... | -|:--------------------|:--------------------------------------------------|:-------------------------| -| `csptr_null` | `{NULL, NULL}` | Init nullptr const | -| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type | +| Type name | Type definition | Used to represent... | +|:-------------------|:--------------------------------------------------|:------------------------| +| `csptr_null` | `{NULL, NULL}` | Init nullptr const | +| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type | | `csptr_X_value` | `i_val` | The csptr element type | ## Example @@ -73,24 +73,24 @@ int csptr_X_compare(const csptr_X* x, const csptr_X* y); // compares poi #define i_type Map #define i_key_str // strings #define i_val int -#define i_keydel(p) (printf("del name: %s\n", (p)->str), cstr_del(p)) +#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) #include #define i_type Arc // (atomic) ref. counted type #define i_val Map #define i_from Map_clone -#define i_del(p) (printf("del Arc:\n"), Map_del(p)) +#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) // no comparison of Maps needed (or available), and // no need for atomic ref. count in single thread: -#define i_opt c_no_compare|c_no_atomic +#define i_opt c_no_cmp|c_no_atomic #include #define i_type Stack -#define i_val_ref Arc // define i_val_ref for csptr / cbox value, not i_val +#define i_val_bind Arc // define i_val_bind for csptr / cbox value, not i_val #include #define i_type List -#define i_val_ref Arc // as above +#define i_val_bind Arc // as above #include int main() @@ -155,22 +155,22 @@ LIST Joanna:1992 Joey:1990 Mary:1995 Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021 Brad:1999 CLONED:2021 Jack:1980 Rosanna:2001 -del Arc: -del name: Rick -del name: Tracy -del name: Steve -del Arc: -del name: CLONED -del name: Brad -del name: Rosanna -del name: Jack -del Arc: -del name: Brad -del name: SHARED -del name: Rosanna -del name: Jack -del Arc: -del name: Joanna -del name: Mary -del name: Joey +drop Arc: +drop name: Rick +drop name: Tracy +drop name: Steve +drop Arc: +drop name: CLONED +drop name: Brad +drop name: Rosanna +drop name: Jack +drop Arc: +drop name: Brad +drop name: SHARED +drop name: Rosanna +drop name: Jack +drop Arc: +drop name: Joanna +drop name: Mary +drop name: Joey ``` diff --git a/docs/csset_api.md b/docs/csset_api.md index 501473a6..c5cd0f88 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -10,10 +10,10 @@ See the c++ class [std::set](https://en.cppreference.com/w/cpp/container/set) fo ```c #define i_key // key: REQUIRED #define i_cmp // three-way compare two i_keyraw* : REQUIRED IF i_keyraw is a non-integral type -#define i_del // destroy key func - defaults to empty destruct +#define i_drop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy -#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy #define i_tag // defaults to i_key #include ``` @@ -28,7 +28,7 @@ csset_X csset_X_clone(csset_x set); void csset_X_clear(csset_X* self); void csset_X_copy(csset_X* self, csset_X other); void csset_X_swap(csset_X* a, csset_X* b); -void csset_X_del(csset_X* self); // destructor +void csset_X_drop(csset_X* self); // destructor size_t csset_X_size(csset_X set); bool csset_X_empty(csset_X set); @@ -59,8 +59,8 @@ csset_X_value csset_X_value_clone(csset_X_value val); | Type name | Type definition | Used to represent... | |:-------------------|:--------------------------------------------------|:----------------------------| | `csset_X` | `struct { ... }` | The csset type | -| `csset_X_rawkey` | `i_rawkey` | The raw key type | -| `csset_X_rawvalue` | `i_rawkey` | The raw key type | +| `csset_X_rawkey` | `i_keyraw` | The raw key type | +| `csset_X_rawvalue` | `i_keyraw` | The raw key type | | `csset_X_key` | `i_key` | The key type | | `csset_X_value` | `i_key ` | The value: key is immutable | | `csset_X_result` | `struct { csset_X_value* ref; bool inserted; }` | Result of insert/emplace | diff --git a/docs/cstack_api.md b/docs/cstack_api.md index e71b213f..b6992dc0 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -10,7 +10,7 @@ See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val #define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy @@ -31,7 +31,7 @@ void cstack_X_clear(cstack_X* self); bool cstack_X_reserve(cstack_X* self, size_t n); void cstack_X_shrink_to_fit(cstack_X* self); void cstack_X_copy(cstack_X* self, cstack_X other); -void cstack_X_del(cstack_X* self); // destructor +void cstack_X_drop(cstack_X* self); // destructor size_t cstack_X_size(cstack_X st); size_t cstack_X_capacity(cstack_X st); @@ -81,7 +81,7 @@ int main() { printf("top: %d\n", *cstack_i_top(&S)); - cstack_i_del(&S); + cstack_i_drop(&S); } ``` Output: diff --git a/docs/cstr_api.md b/docs/cstr_api.md index e54b3a4c..463a723c 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -26,7 +26,7 @@ cstr cstr_clone(cstr s); cstr* cstr_take(cstr* self, cstr s); // take the constructed or moved string cstr cstr_move(cstr* self); // move string to caller, leave empty string -void cstr_del(cstr *self); // destructor +void cstr_drop(cstr *self); // destructor const char* cstr_str(const cstr* self); // self->str char* cstr_data(cstr* self); // self->str @@ -85,13 +85,14 @@ Note that all methods with arguments `(..., const char* str, size_t n)`, `n` mus #### Helper methods: ```c -int cstr_compare(const cstr *s1, const cstr *s2); +int cstr_cmp(const cstr *s1, const cstr *s2); bool cstr_equalto(const cstr *s1, const cstr *s2); bool cstr_hash(const cstr *s, ...); -int c_rawstr_compare(const char** x, const char** y); -bool c_rawstr_equalto(const char** x, const char** y); -uint64_t c_rawstr_hash(const char* const* x, ...); +typedef const char* c_rawstr; +int c_rawstr_cmp(const c_rawstr* x, const c_rawstr* y); +bool c_rawstr_equalto(const c_rawstr* x, const c_rawstr* y); +uint64_t c_rawstr_hash(const c_rawstr* x, size_t dummy); uint64_t c_strhash(const char* str); char* c_strnstrn(const char* str, const char* needle, size_t slen, size_t nlen); @@ -141,7 +142,7 @@ int main() { cstr full_path = cstr_from_fmt("%s/%s.%s", "directory", "filename", "ext"); printf("%s\n", full_path.str); - c_del(cstr, &s0, &s1, &full_path); + c_drop(cstr, &s0, &s1, &full_path); } ``` Output: diff --git a/docs/csview_api.md b/docs/csview_api.md index 7daa67ee..609c5d10 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -77,7 +77,7 @@ bool cstr_ends_with_v(cstr s, csview sub); ``` #### Helper methods ```c -int csview_compare(const csview* x, const csview* y); +int csview_cmp(const csview* x, const csview* y); bool csview_equalto(const csview* x, const csview* y); uint64_t csview_hash(const csview* x, size_t dummy); ``` @@ -118,7 +118,7 @@ int main () cstr s3 = cstr_from_v(cstr_substr(s1, 0, 6)); // "Apples" printf("%s %s\n", s2, s3.str); - c_del(cstr, &str1, &s1, &s2, &s3); + c_drop(cstr, &str1, &s1, &s2, &s3); } ``` Output: @@ -166,7 +166,7 @@ int main() print_split(c_sv("This has no matching separator"), c_sv("xx")); puts(""); - c_autovar (cvec_str v = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cvec_str_del(&v)) + c_autovar (cvec_str v = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cvec_str_drop(&v)) c_foreach (i, cvec_str, v) printf("\"%s\"\n", i.ref->str); } diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 00c0498c..b9d4d2d5 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -14,7 +14,7 @@ See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vect ```c #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_del // destroy value func - defaults to empty destruct +#define i_drop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val #define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy @@ -23,7 +23,7 @@ See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vect ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. -`i_del` may be defined instead of `i_valdel` (or `i_keydel`) for all non-map containers. +`i_drop` may be defined instead of `i_valdrop` (or `i_keydrop`) for all non-map containers. ## Methods @@ -39,7 +39,7 @@ bool cvec_X_reserve(cvec_X* self, size_t cap); bool cvec_X_resize(cvec_X* self, size_t size, i_val null); void cvec_X_shrink_to_fit(cvec_X* self); void cvec_X_swap(cvec_X* a, cvec_X* b); -void cvec_X_del(cvec_X* self); // destructor +void cvec_X_drop(cvec_X* self); // destructor bool cvec_X_empty(cvec_X vec); size_t cvec_X_size(cvec_X vec); @@ -47,7 +47,7 @@ size_t cvec_X_capacity(cvec_X vec); const cvec_X_value* cvec_X_at(const cvec_X* self, size_t idx); const cvec_X_value* cvec_X_get(const cvec_X* self, i_valraw raw); // return NULL if not found -cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // get mutable value +cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // get mutable value cvec_X_iter cvec_X_find(const cvec_X* self, i_valraw raw); cvec_X_iter cvec_X_find_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw); cvec_X_iter cvec_X_bsearch(const cvec_X* self, i_valraw raw); @@ -152,13 +152,13 @@ int main() { cstr tmp = cstr_from_fmt("%d elements so far", cvec_str_size(names)); // emplace_back() will not compile if adding a new cstr type. Use push_back(): - cvec_str_push_back(&names, tmp); // tmp is moved to names, do not del() it. + cvec_str_push_back(&names, tmp); // tmp is moved to names, do not drop() it. printf("%s\n", names.data[1].str); // Access the second element c_foreach (i, cvec_str, names) printf("item: %s\n", i.ref->str); - cvec_str_del(&names); + cvec_str_drop(&names); } ``` Output: @@ -179,12 +179,12 @@ typedef struct { int id; } User; -int User_compare(const User* a, const User* b) { +int User_cmp(const User* a, const User* b) { int c = strcmp(a->name.str, b->name.str); return c != 0 ? c : a->id - b->id; } -void User_del(User* self) { - cstr_del(&self->name); +void User_drop(User* self) { + cstr_drop(&self->name); } User User_clone(User user) { user.name = cstr_clone(user.name); @@ -194,9 +194,9 @@ User User_clone(User user) { // Declare a memory managed, clonable vector of users. // Note that cvec_u_emplace_back() will clone input: #define i_val User -#define i_cmp User_compare -#define i_del User_del -#define i_valfrom User_clone +#define i_cmp User_cmp +#define i_drop User_drop +#define i_from User_clone #define i_tag u #include @@ -209,6 +209,6 @@ int main(void) { c_foreach (i, cvec_u, vec2) printf("%s: %d\n", i.ref->name.str, i.ref->id); - c_del(cvec_u, &vec, &vec2); // cleanup + c_drop(cvec_u, &vec, &vec2); // cleanup } ``` diff --git a/examples/advanced.c b/examples/advanced.c deleted file mode 100644 index 60276b09..00000000 --- a/examples/advanced.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -typedef struct Viking { - cstr name; - cstr country; -} Viking; - -void viking_del(Viking* vk) { - cstr_del(&vk->name); - cstr_del(&vk->country); -} - -// Define Viking raw struct with hash, equals, and convertion functions between Viking and VikingRaw structs: - -typedef struct VikingRaw { - const char* name; - const char* country; -} VikingRaw; - -uint64_t vikingraw_hash(const VikingRaw* raw, size_t ignore) { - uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); - return hash; -} -static inline bool vikingraw_equalto(const VikingRaw* rx, const VikingRaw* ry) { - return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; -} - -static inline Viking viking_fromRaw(VikingRaw raw) { // note: parameter is by value - return c_make(Viking){cstr_from(raw.name), cstr_from(raw.country)}; -} -static inline VikingRaw viking_toRaw(const Viking* vk) { - return c_make(VikingRaw){vk->name.str, vk->country.str}; -} - -// With this in place, we define the Viking => int hash map type: -#define i_tag vk -#define i_key Viking -#define i_val int -#define i_equ vikingraw_equalto -#define i_hash vikingraw_hash -#define i_keyraw VikingRaw -#define i_keyfrom viking_fromRaw -#define i_keyto viking_toRaw -#define i_keydel viking_del -#include - -int main() -{ - c_auto (cmap_vk, vikings) { - c_apply_pair(cmap_vk, emplace, &vikings, { - {{"Einar", "Norway"}, 20}, - {{"Olaf", "Denmark"}, 24}, - {{"Harald", "Iceland"}, 12}, - }); - VikingRaw bjorn = {"Bjorn", "Sweden"}; - cmap_vk_emplace_or_assign(&vikings, bjorn, 10); - - VikingRaw einar = {"Einar", "Norway"}; - cmap_vk_value *e = cmap_vk_find(&vikings, einar).ref; - e->second += 3; // add 3 hp points to Einar - cmap_vk_emplace(&vikings, einar, 0).ref->second += 5; // add 5 more to Einar - - c_foreach (k, cmap_vk, vikings) { - printf("%s of %s has %d hp\n", k.ref->first.name.str, k.ref->first.country.str, k.ref->second); - } - } -} \ No newline at end of file diff --git a/examples/astar.c b/examples/astar.c index 88c602ef..ee002b79 100644 --- a/examples/astar.c +++ b/examples/astar.c @@ -24,9 +24,9 @@ point_init(int x, int y, int width) } int -point_compare_priority(const point* a, const point* b) +point_cmp_priority(const point* a, const point* b) { - return c_default_compare(&a->priorty, &b->priorty); + return c_default_cmp(&a->priorty, &b->priorty); } int @@ -49,7 +49,7 @@ point_index(const point* p) } int -point_key_compare(const point* a, const point* b) +point_key_cmp(const point* a, const point* b) { int i = point_index(a); int j = point_index(b); @@ -57,22 +57,22 @@ point_key_compare(const point* a, const point* b) } #define i_val point -#define i_cmp point_compare_priority +#define i_cmp point_cmp_priority #include #define i_val point -#define i_opt c_no_compare +#define i_opt c_no_cmp #include #define i_key point #define i_val int -#define i_cmp point_key_compare +#define i_cmp point_key_cmp #define i_tag pcost #include #define i_key point #define i_val point -#define i_cmp point_key_compare +#define i_cmp point_key_cmp #define i_tag pstep #include @@ -155,10 +155,10 @@ main(void) "# # # # # # # # # #\n" "# @ # ##### ##### ##### ######### ##### # ######### # #\n" "# # # # # # #\n" - "#########################################################################\n"), cstr_del(&maze)) + "#########################################################################\n"), cstr_drop(&maze)) { int width = cstr_find(maze, "\n") + 1; - c_autovar (cdeq_point path = astar(&maze, width), cdeq_point_del(&path)) + c_autovar (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path)) { c_foreach (it, cdeq_point, path) maze.str[point_index(it.ref)] = 'x'; printf("%s", maze.str); diff --git a/examples/bits.c b/examples/bits.c index fbdee3e8..ac59bd32 100644 --- a/examples/bits.c +++ b/examples/bits.c @@ -3,13 +3,13 @@ int main() { - c_autovar (cbits set = cbits_with_size(23, true), cbits_del(&set)) { + c_autovar (cbits set = cbits_with_size(23, true), cbits_drop(&set)) { printf("count %zu, %zu\n", cbits_count(set), set.size); cbits s1 = cbits_new("1110100110111"); char buf[256]; cbits_to_str(s1, buf, 0, -1); printf("buf: %s: %zu\n", buf, cbits_count(s1)); - cbits_del(&s1); + cbits_drop(&s1); cbits_reset(&set, 9); cbits_resize(&set, 43, false); @@ -36,7 +36,7 @@ int main() printf("%d", cbits_test(set, i)); puts(""); - c_autovar (cbits s2 = cbits_clone(set), cbits_del(&s2)) { + c_autovar (cbits s2 = cbits_clone(set), cbits_drop(&s2)) { cbits_flip_all(&s2); cbits_set(&s2, 16); cbits_set(&s2, 17); diff --git a/examples/box.c b/examples/box.c index c7763bb8..d400799b 100644 --- a/examples/box.c +++ b/examples/box.c @@ -3,7 +3,7 @@ typedef struct { cstr name, last; } Person; -Person Person_from(const char* name, const char* last) { +Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } @@ -17,44 +17,43 @@ Person Person_clone(Person p) { p.last = cstr_clone(p.last); return p; } -void Person_del(Person* p) { - printf("del: %s %s\n", p->name.str, p->last.str); - c_del(cstr, &p->name, &p->last); + +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); } -#define i_val Person -#define i_cmp Person_cmp -#define i_from Person_clone -#define i_del Person_del -#define i_tag prs +#define i_type PPtr +#define i_val_bind Person // binds Person_cmp, ... #include -#define i_val_ref cbox_prs -#define i_tag prs +#define i_type Persons +#define i_val_bind PPtr // binds PPtr_cmp, ... #include int main() { - c_auto (cvec_prs, vec) - c_auto (cbox_prs, p, q) + c_auto (Persons, vec) + c_auto (PPtr, p, q) { - p = cbox_prs_new(Person_from("Dave", "Cooper")); + p = PPtr_new(Person_new("Dave", "Cooper")); - q = cbox_prs_clone(p); + q = PPtr_clone(p); cstr_assign(&q.get->name, "Dale"); printf("%s %s.\n", p.get->name.str, p.get->last.str); printf("%s %s.\n", q.get->name.str, q.get->last.str); - cvec_prs_push_back(&vec, cbox_prs_new(Person_from("Laura", "Palmer"))); - cvec_prs_push_back(&vec, cbox_prs_new(Person_from("Shelly", "Johnson"))); + Persons_push_back(&vec, PPtr_new(Person_new("Laura", "Palmer"))); + Persons_push_back(&vec, PPtr_new(Person_new("Shelly", "Johnson"))); - c_foreach (i, cvec_prs, vec) + c_foreach (i, Persons, vec) printf("%s: %s\n", i.ref->get->name.str, i.ref->get->last.str); - c_autovar (Person per = Person_from("Laura", "Palmer"), Person_del(&per)) { - const cbox_prs *v = cvec_prs_get(&vec, (cbox_prs){&per}); + // Look-up Shelly! + c_autovar (Person s = Person_new("Shelly", "Johnson"), Person_drop(&s)) { + const PPtr *v = Persons_get(&vec, (PPtr){&s}); if (v) printf("found: %s: %s\n", v->get->name.str, v->get->last.str); } } diff --git a/examples/box2.c b/examples/box2.c index 48266963..5549dade 100644 --- a/examples/box2.c +++ b/examples/box2.c @@ -18,14 +18,17 @@ struct { } typedef Rectangle; #define i_val Point +#define i_opt c_no_cmp #include // cbox_Point #define i_val Rectangle +#define i_opt c_no_cmp #include // cbox_Rectangle // Box in box: -#define i_val_ref cbox_Point // NB: adviced to use i_val_ref when value is a cbox or csptr! - // it will auto-set i_del, i_from, i_cmp for you. +#define i_val_bind cbox_Point // NB: adviced to use i_val_arc when value is a cbox or csptr! + // it will auto-set i_drop, i_from, i_cmp for you. +#define i_opt c_no_cmp #define i_tag BoxPoint #include // cbox_BoxPoint diff --git a/examples/complex.c b/examples/complex.c index b6aef5a8..17a10fad 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -1,35 +1,30 @@ #include -void check_del(float* v) {printf("destroy %g\n", *v);} +void check_drop(float* v) {printf("destroy %g\n", *v);} +#define i_type FloatStack #define i_val float -#define i_valdel check_del -#define i_opt c_no_clone -#define i_tag f +#define i_drop check_drop +#define i_from c_default_clone #include -#define i_val cstack_f -#define i_opt c_no_clone|c_no_compare -#define i_valdel cstack_f_del -#define i_tag arr +#define i_type StackList +#define i_val_bind FloatStack +#define i_opt c_no_cmp #include +#define i_type ListMap #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 +#define i_val_bind StackList #include +#define i_type MapMap #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 +#define i_val_bind ListMap #include // c++: -// using cstack_f = std::stack; +// using FloatStack = std::stack; // using map_lst = std::unordered_map>; // using map_map = std::unordered_map; @@ -38,29 +33,29 @@ int main() { int x = 1, y = 3, tableKey = 42; const char* strKey = "first"; - c_auto (cmap_map, myMap) + c_auto (MapMap, mmap) { - cstack_f stk = cstack_f_with_capacity(xdim * ydim); - memset(stk.data, 0, xdim*ydim*sizeof *stk.data); - stk.size = stk.capacity; + FloatStack stack = FloatStack_with_capacity(xdim * ydim); + memset(stack.data, 0, xdim*ydim*sizeof *stack.data); + stack.size = stack.capacity; // Put in some data in stack array - stk.data[x] = 3.1415927f; - printf("stk size: %zu\n", cstack_f_size(stk)); + stack.data[x] = 3.1415927f; + printf("stack size: %zu\n", FloatStack_size(stack)); - clist_arr tableList = clist_arr_init(); - clist_arr_push_back(&tableList, stk); + StackList list = StackList_init(); + StackList_push_back(&list, stack); - cmap_lst listMap = cmap_lst_init(); - cmap_lst_insert(&listMap, tableKey, tableList); - cmap_map_insert(&myMap, cstr_from(strKey), listMap); + ListMap lmap = ListMap_init(); + ListMap_insert(&lmap, tableKey, list); + MapMap_insert(&mmap, cstr_from(strKey), lmap); // Access the data entry - const cmap_lst* mapL = cmap_map_at(&myMap, strKey); - const clist_arr* lstA = cmap_lst_at(mapL, tableKey); - const cstack_f* arr = clist_arr_back(lstA); - printf("value (%d) is: %f\n", x, *cstack_f_at(arr, x)); + const ListMap* lmap_p = MapMap_at(&mmap, strKey); + const StackList* list_p = ListMap_at(lmap_p, tableKey); + const FloatStack* stack_p = StackList_back(list_p); + printf("value (%d) is: %f\n", x, *FloatStack_at(stack_p, x)); - stk.data[x] = 1.41421356f; // change the value in array + stack.data[x] = 1.41421356f; // change the value in array } } diff --git a/examples/cpque.c b/examples/cpque.c index b3ee4adf..0b8a610c 100644 --- a/examples/cpque.c +++ b/examples/cpque.c @@ -13,7 +13,7 @@ static int (*icmp_fn)(const int* x, const int* y); #define imix_less(left, right) ((*(left) ^ 1) < (*(right) ^ 1)) static int imax_cmp(const int* x, const int* y) { return *x - *y; } static int imin_cmp(const int* x, const int* y) { return *y - *x; } -static int imix_cmp(const int* x, const int* y) { return c_less_compare(imix_less, x, y); } +static int imix_cmp(const int* x, const int* y) { return c_less_cmp(imix_less, x, y); } void print_queue(ipque q) { ipque copy = ipque_clone(q); @@ -22,13 +22,13 @@ void print_queue(ipque q) { ipque_pop(©); } puts(""); - ipque_del(©); + ipque_drop(©); } int main() { const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data); - c_auto (ipque, q, q2, q3) // init() and defered del() + c_auto (ipque, q, q2, q3) // init() and defered drop() { icmp_fn = imax_cmp; c_forrange (i, n) diff --git a/examples/csmap_find.c b/examples/csmap_find.c index 78b6bbf5..3ca7ff87 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -8,7 +8,7 @@ #include #define i_val csmap_istr_rawvalue -#define i_opt c_no_compare +#define i_opt c_no_cmp #define i_tag istr #include diff --git a/examples/csmap_insert.c b/examples/csmap_insert.c index 920cf02d..c3690c83 100644 --- a/examples/csmap_insert.c +++ b/examples/csmap_insert.c @@ -15,7 +15,7 @@ #include #define i_val csmap_ii_rawvalue -#define i_opt c_no_compare +#define i_opt c_no_cmp #define i_tag ii #include diff --git a/examples/cstr_match.c b/examples/cstr_match.c index 041a2d84..dc1423d7 100644 --- a/examples/cstr_match.c +++ b/examples/cstr_match.c @@ -3,7 +3,7 @@ int main() { - c_autovar (cstr ss = cstr_new("The quick brown fox jumps over the lazy dog.JPG"), cstr_del(&ss)) { + c_autovar (cstr ss = cstr_new("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) { size_t pos = cstr_find_n(ss, "brown", 0, 5); printf("%zu [%s]\n", pos, pos == cstr_npos ? "" : &ss.str[pos]); printf("equals: %d\n", cstr_equals(ss, "The quick brown fox jumps over the lazy dog.JPG")); diff --git a/examples/demos.c b/examples/demos.c index 70aa722d..32e5dde0 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -3,7 +3,7 @@ void stringdemo1() { printf("\nSTRINGDEMO1\n"); - c_autovar (cstr cs = cstr_new("one-nine-three-seven-five"), cstr_del(&cs)) + c_autovar (cstr cs = cstr_new("one-nine-three-seven-five"), cstr_drop(&cs)) { printf("%s.\n", cs.str); @@ -35,7 +35,7 @@ void stringdemo1() void vectordemo1() { printf("\nVECTORDEMO1\n"); - c_autovar (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_del(&bignums)) + c_autovar (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_drop(&bignums)) { cvec_ix_reserve(&bignums, 100); for (size_t i = 10; i <= 100; i += 10) @@ -118,7 +118,7 @@ void setdemo1() c_foreach (i, cset_i, nums) printf("set: %d\n", *i.ref); - cset_i_del(&nums); + cset_i_drop(&nums); } #define i_key int @@ -133,7 +133,7 @@ void mapdemo1() cmap_ii_emplace(&nums, 8, 64); cmap_ii_emplace(&nums, 11, 121); printf("val 8: %d\n", *cmap_ii_at(&nums, 8)); - cmap_ii_del(&nums); + cmap_ii_drop(&nums); } #define i_key_str @@ -181,7 +181,7 @@ void mapdemo3() printf("size %zu\n", cmap_str_size(table)); c_foreach (i, cmap_str, table) printf("entry: %s: %s\n", i.ref->first.str, i.ref->second.str); - cmap_str_del(&table); // frees key and value cstrs, and hash table. + cmap_str_drop(&table); // frees key and value cstrs, and hash table. } #define i_val float @@ -192,7 +192,7 @@ void arraydemo1() { printf("\nARRAYDEMO1\n"); c_autovar (carr3_f arr3 = carr3_f_with_values(30, 20, 10, 0.0f), - carr3_f_del(&arr3)) + carr3_f_drop(&arr3)) { arr3.data[5][4][3] = 10.2f; float **arr2 = arr3.data[5]; diff --git a/examples/ex_gauss1.c b/examples/ex_gauss1.c index c96562b6..6725393f 100644 --- a/examples/ex_gauss1.c +++ b/examples/ex_gauss1.c @@ -13,7 +13,7 @@ // Declare int vector with map entries that can be sorted by map keys. struct {int first; size_t second;} typedef mapval; static int compare(mapval *a, mapval *b) { - return c_default_compare(&a->first, &b->first); + return c_default_cmp(&a->first, &b->first); } #define i_val mapval diff --git a/examples/inits.c b/examples/inits.c index 386be86e..a1733caf 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -12,19 +12,19 @@ #include typedef struct {int x, y;} ipair_t; -inline static int ipair_compare(const ipair_t* a, const ipair_t* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); } #define i_val ipair_t -#define i_cmp ipair_compare +#define i_cmp ipair_cmp #define i_tag ip #include #define i_val ipair_t -#define i_cmp ipair_compare +#define i_cmp ipair_cmp #define i_tag ip #include diff --git a/examples/mapmap.c b/examples/mapmap.c index e22a4f7b..61b55493 100644 --- a/examples/mapmap.c +++ b/examples/mapmap.c @@ -1,47 +1,67 @@ // unordered_map>: +#define i_type People #define i_key_str #define i_val_str -#define i_tag sect -#include // csmap_sect +#define i_keydrop(p) (printf("kdrop: %s\n", (p)->str), cstr_drop(p)) +#include +#define i_type Departments #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 // csmap_conf +#define i_val_bind People +#include -void add(csmap_conf* map, const char* section, const char* entry, const char* value) +#define i_type Stack +#define i_val_bind People_value +#define i_opt c_no_cmp +//#define i_from People_value_clone +//#define i_drop People_value_drop +#include + +void add(Departments* deps, const char* name, const char* email, const char* dep) { - csmap_sect *smap = &csmap_conf_insert(map, cstr_from(section), csmap_sect_init()).ref->second; - csmap_sect_emplace_or_assign(smap, entry, value); + People *people = &Departments_insert(deps, cstr_from(dep), People_init()).ref->second; + People_emplace_or_assign(people, name, email); } -bool contains(csmap_conf* map, const char* section, const char* entry) +Stack contains(Departments* map, const char* name) { - const csmap_conf_value *val = csmap_conf_get(map, section); - return val && csmap_sect_get(&val->second, entry); + Stack stk = Stack_init(); + const People_value* v; + c_foreach (i, Departments, *map) + if ((v = People_get(&i.ref->second, name))) { + Stack_push(&stk, People_value_clone(*v)); + } + return stk; } int main(void) { - c_auto (csmap_conf, map) + c_auto (Departments, map) { - add(&map, "user", "name", "Joe"); - add(&map, "user", "groups", "proj1,proj3"); - add(&map, "group", "proj1", "Energy"); - add(&map, "group", "proj2", "Windy"); - add(&map, "group", "proj3", "Oil"); - add(&map, "admin", "employees", "2302"); - add(&map, "group", "proj2", "Wind"); // Update - - printf("contains: %d\n", contains(&map, "group", "employees")); - printf("contains: %d\n", contains(&map, "admin", "name")); - printf("contains: %d\n", contains(&map, "admin", "employees")); - - c_foreach (i, csmap_conf, map) - c_foreach (j, csmap_sect, i.ref->second) - printf("%s: %s - %s\n", i.ref->first.str, j.ref->first.str, j.ref->second.str); + add(&map, "Anna Kendro", "Anna@myplace.com", "Support"); + add(&map, "Terry Dane", "Terry@myplace.com", "Development"); + add(&map, "Kik Winston", "Kik@myplace.com", "Finance"); + add(&map, "Nancy Drew", "Nancy@live.com", "Development"); + add(&map, "Nick Denton", "Nick@myplace.com", "Finance"); + add(&map, "Stan Whiteword", "Stan@myplace.com", "Marketing"); + add(&map, "Serena Bath", "Serena@myplace.com", "Support"); + add(&map, "Patrick Dust", "Patrick@myplace.com", "Finance"); + add(&map, "Red Winger", "Red@gmail.com", "Marketing"); + add(&map, "Nick Denton", "Nick@yahoo.com", "Support"); + add(&map, "Colin Turth", "Colin@myplace.com", "Support"); + add(&map, "Dennis Kay", "Dennis@mail.com", "Marketing"); + add(&map, "Anne Dickens", "Anne@myplace.com", "Development"); + + c_foreach (i, Departments, map) + c_forpair (name, email, People, i.ref->second) + printf("%s: %s - %s\n", i.ref->first.str, _.name.str, _.email.str); + puts(""); + + c_auto (Stack, s) printf("found: %zu\n", Stack_size(s = contains(&map, "Nick Denton"))); + c_auto (Stack, s) printf("found: %zu\n", Stack_size(s = contains(&map, "Patrick Dust"))); + c_auto (Stack, s) printf("found: %zu\n", Stack_size(s = contains(&map, "Dennis Kay"))); + c_auto (Stack, s) printf("found: %zu\n", Stack_size(s = contains(&map, "Serena Bath"))); + puts("Done"); } } \ No newline at end of file diff --git a/examples/mmap.c b/examples/mmap.c index 26b271d1..ea08017b 100644 --- a/examples/mmap.c +++ b/examples/mmap.c @@ -1,36 +1,34 @@ // This implements the multimap c++ example found at: // https://en.cppreference.com/w/cpp/container/multimap/insert -// Map of int => clist_str. Note the negation of c_default_compare +// Map of int => clist_str. Note the negation of c_default_cmp #define i_val_str #include +#define i_type Multimap #define i_key int -#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 +#define i_val_bind clist_str +#define i_cmp -c_default_cmp #include -void print(const csmap_mult mmap) +void print(const Multimap mmap) { - c_foreach (e, csmap_mult, mmap) { + c_foreach (e, Multimap, mmap) { c_foreach (s, clist_str, e.ref->second) printf("{%d,%s} ", e.ref->first, s.ref->str); } puts(""); } -void insert(csmap_mult* mmap, int key, const char* str) +void insert(Multimap* mmap, int key, const char* str) { - clist_str *list = &csmap_mult_insert(mmap, key, clist_str_init()).ref->second; + clist_str *list = &Multimap_insert(mmap, key, clist_str_init()).ref->second; clist_str_emplace_back(list, str); } int main() { - c_auto (csmap_mult, mmap) + c_auto (Multimap, mmap) { // list-initialize struct {int i; const char* s;} vals[] = {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}}; @@ -53,12 +51,12 @@ int main() print(mmap); // erase all entries with key 5 - csmap_mult_erase(&mmap, 5); + Multimap_erase(&mmap, 5); print(mmap); // find and erase a specific entry clist_str_iter pos; - c_foreach (e, csmap_mult, mmap) + c_foreach (e, Multimap, mmap) if ((pos = clist_str_find(&e.ref->second, "bar")).ref != clist_str_end(&e.ref->second).ref) { clist_str_erase_at(&e.ref->second, pos); break; diff --git a/examples/multimap.c b/examples/multimap.c index 543b8b22..424ae606 100644 --- a/examples/multimap.c +++ b/examples/multimap.c @@ -35,7 +35,7 @@ struct OlympicsData { int year; const char *city, *country, *date; } ol_data[] = typedef struct { int year; cstr city, date; } OlympicLocation; -int OlympicLocation_compare(OlympicLocation* a, OlympicLocation* b) { +int OlympicLocation_cmp(OlympicLocation* a, OlympicLocation* b) { return a->year - b->year; } @@ -44,14 +44,14 @@ OlympicLocation OlympicLocation_clone(OlympicLocation loc) { loc.date = cstr_clone(loc.date); return loc; } -void OlympicLocation_del(OlympicLocation* self) { - c_del(cstr, &self->city, &self->date); +void OlympicLocation_drop(OlympicLocation* self) { + c_drop(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_cmp OlympicLocation_cmp +#define i_drop OlympicLocation_drop #define i_from OlympicLocation_clone #define i_tag OL #include @@ -59,7 +59,7 @@ void OlympicLocation_del(OlympicLocation* self) { // Create a csmap where key is country name #define i_key_str #define i_val clist_OL -#define i_valdel clist_OL_del +#define i_valdrop clist_OL_drop #define i_valfrom clist_OL_clone #define i_tag OL #include diff --git a/examples/new_arr.c b/examples/new_arr.c index dc597e4a..a593536e 100644 --- a/examples/new_arr.c +++ b/examples/new_arr.c @@ -15,7 +15,7 @@ int main() int w = 7, h = 5, d = 3; c_autovar (carr2_int volume = carr2_int_init(w, h), - carr2_int_del(&volume)) + carr2_int_drop(&volume)) { int *dat = carr2_int_data(&volume); for (size_t i = 0; i < carr2_int_size(volume); ++i) @@ -32,7 +32,7 @@ int main() } c_autovar (carr3_int volume = carr3_int_init(w, h, d), - carr3_int_del(&volume)) + carr3_int_drop(&volume)) { int *dat = carr3_int_data(&volume); for (size_t i = 0; i < carr3_int_size(volume); ++i) @@ -50,7 +50,7 @@ int main() } c_autovar (carr2_str text2d = carr2_str_with_values(h, d, cstr_init()), - carr2_str_del(&text2d)) + carr2_str_drop(&text2d)) { cstr_assign(&text2d.data[2][1], "hello"); cstr_assign(&text2d.data[4][0], "world"); diff --git a/examples/new_deq.c b/examples/new_deq.c index cc3ff76b..57224869 100644 --- a/examples/new_deq.c +++ b/examples/new_deq.c @@ -16,13 +16,13 @@ struct MyStruct { #include struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; } #define i_val Point -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_list.c b/examples/new_list.c index e07030b5..0867c7a6 100644 --- a/examples/new_list.c +++ b/examples/new_list.c @@ -15,13 +15,13 @@ struct MyStruct { #include struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; } #define i_val Point -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_map.c b/examples/new_map.c index 8975cd77..953ca793 100644 --- a/examples/new_map.c +++ b/examples/new_map.c @@ -16,15 +16,15 @@ struct MyStruct { // Point => int map struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; } // Point => int map #define i_key Point #define i_val int -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_pque.c b/examples/new_pque.c index 5048ea77..1485e630 100644 --- a/examples/new_pque.c +++ b/examples/new_pque.c @@ -16,8 +16,8 @@ struct MyStruct { struct Point { int x, y; } typedef Point; int Point_cmp(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); + int c = a->x - b->x; + return c ? c : a->y - b->y; } #define i_val Point diff --git a/examples/new_queue.c b/examples/new_queue.c index 3ad571bb..9219a1b4 100644 --- a/examples/new_queue.c +++ b/examples/new_queue.c @@ -6,12 +6,12 @@ forward_cqueue(cqueue_pnt, struct Point); struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); } #define i_val Point -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_smap.c b/examples/new_smap.c index 7f0730db..2cb35b99 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -15,14 +15,14 @@ struct MyStruct { // Point => int map struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; } #define i_key Point #define i_val int -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include diff --git a/examples/new_sptr.c b/examples/new_sptr.c index 4a715160..d1eed636 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -2,33 +2,33 @@ struct Person { cstr name, last; } typedef Person; -Person Person_from(const char* name, const char* last) { +Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } -void Person_del(Person* p) { - printf("del: %s %s\n", p->name.str, p->last.str); - c_del(cstr, &p->name, &p->last); +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); } #define i_val Person -#define i_del Person_del -#define i_opt c_no_compare +#define i_drop Person_drop +#define i_opt c_no_cmp #define i_tag person #include // ... #define i_val int -#define i_del(x) printf("del: %d\n", *(x)) +#define i_drop(x) printf("drop: %d\n", *(x)) #include -#define i_val_ref csptr_int +#define i_val_bind csptr_int #define i_tag iptr #include int main(void) { - c_autovar (csptr_person p = csptr_person_new(Person_from("John", "Smiths")), csptr_person_del(&p)) - c_autovar (csptr_person q = csptr_person_clone(p), csptr_person_del(&q)) // share the pointer + c_autovar (csptr_person p = csptr_person_new(Person_new("John", "Smiths")), csptr_person_drop(&p)) + c_autovar (csptr_person q = csptr_person_clone(p), csptr_person_drop(&q)) // share the pointer { printf("%s %s. uses: %lu\n", q.get->name.str, q.get->last.str, *q.use_count); } diff --git a/examples/new_vec.c b/examples/new_vec.c index 62804125..c5570942 100644 --- a/examples/new_vec.c +++ b/examples/new_vec.c @@ -15,13 +15,13 @@ struct MyStruct { #include struct Point { int x, y; } typedef Point; -int point_compare(const Point* a, const Point* b) { - int c = c_default_compare(&a->x, &b->x); - return c ? c : c_default_compare(&a->y, &b->y); +int point_cmp(const Point* a, const Point* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); } #define i_val Point -#define i_cmp point_compare +#define i_cmp point_cmp #define i_opt c_is_fwd #define i_tag pnt #include @@ -37,11 +37,11 @@ int main() { cvec_i32 vec = cvec_i32_init(); cvec_i32_push_back(&vec, 123); - cvec_i32_del(&vec); + cvec_i32_drop(&vec); cvec_float fvec = cvec_float_init(); cvec_float_push_back(&fvec, 123.3); - cvec_float_del(&fvec); + cvec_float_drop(&fvec); cvec_pnt pvec = cvec_pnt_init(); cvec_pnt_push_back(&pvec, (Point){42, 14}); @@ -51,9 +51,9 @@ int main() c_foreach (i, cvec_pnt, pvec) printf(" (%d %d)", i.ref->x, i.ref->y); puts(""); - cvec_pnt_del(&pvec); + cvec_pnt_drop(&pvec); cvec_str svec = cvec_str_init(); cvec_str_emplace_back(&svec, "Hello, friend"); - cvec_str_del(&svec); + cvec_str_drop(&svec); } \ No newline at end of file diff --git a/examples/prime.c b/examples/prime.c index f858831a..0e2ede56 100644 --- a/examples/prime.c +++ b/examples/prime.c @@ -27,7 +27,7 @@ int main(void) printf("computing prime numbers up to %zu\n", n); clock_t t1 = clock(); - c_autovar (cbits primes = sieveOfEratosthenes(n + 1), cbits_del(&primes)) { + c_autovar (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { puts("done"); size_t np = cbits_count(primes); clock_t t2 = clock(); diff --git a/examples/priority.c b/examples/priority.c index 1068cb91..5164d85d 100644 --- a/examples/priority.c +++ b/examples/priority.c @@ -4,7 +4,7 @@ #include #define i_val int64_t -#define i_cmp -c_default_compare // min-heap (increasing values) +#define i_cmp -c_default_cmp // min-heap (increasing values) #define i_tag i #include diff --git a/examples/queue.c b/examples/queue.c index 4acaa4d6..ffd0a1e7 100644 --- a/examples/queue.c +++ b/examples/queue.c @@ -2,7 +2,7 @@ #include #define i_val int -#define i_del(x) printf("drop %d\n", *(x)) +#define i_drop(x) printf("drop %d\n", *(x)) #define i_from c_default_clone #define i_tag i #include diff --git a/examples/rawptr_elements.c b/examples/rawptr_elements.c index c5416822..463a7f35 100644 --- a/examples/rawptr_elements.c +++ b/examples/rawptr_elements.c @@ -6,7 +6,7 @@ struct { double x, y; } typedef Point; // Set of Point pointers: define all template parameters "in-line" // Note it may be simpler to use a cbox for this. #define i_key Point* -#define i_keydel(x) c_free(*(x)) +#define i_keydrop(x) c_free(*(x)) #define i_keyfrom(x) c_new(Point, *(x)) #define i_hash(x, n) c_default_hash(*(x), sizeof *(x)) #define i_equ(x, y) c_memcmp_equalto(*(x), *(y)) @@ -18,7 +18,7 @@ typedef int64_t inttype; #define i_key_str #define i_valraw inttype #define i_val inttype* -#define i_valdel(x) c_free(*(x)) +#define i_valdrop(x) c_free(*(x)) #define i_valfrom(raw) c_new(inttype, raw) #define i_valto(x) **(x) #include diff --git a/examples/read.c b/examples/read.c index 4e670a10..5313cb65 100644 --- a/examples/read.c +++ b/examples/read.c @@ -6,16 +6,16 @@ cvec_str read_file(const char* name) { cvec_str vec = cvec_str_init(); c_autovar (FILE* f = fopen(name, "r"), fclose(f)) - c_autovar (cstr line = cstr_init(), cstr_del(&line)) - while (cstr_getline(&line, f)) - cvec_str_emplace_back(&vec, line.str); + c_autovar (cstr line = cstr_init(), cstr_drop(&line)) + while (cstr_getline(&line, f)) + cvec_str_emplace_back(&vec, line.str); return vec; } int main() { int n = 0; - c_autovar (cvec_str vec = read_file(__FILE__), cvec_str_del(&vec)) + c_autovar (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec)) c_foreach (i, cvec_str, vec) printf("%5d: %s\n", ++n, i.ref->str); diff --git a/examples/replace.c b/examples/replace.c index ebb40cc5..0349d9f4 100644 --- a/examples/replace.c +++ b/examples/replace.c @@ -13,7 +13,7 @@ int main () // Ustring positions: 0123456789*123456789*12345 cstr s = cstr_from(base); // "this is a test string." cstr m = cstr_clone(s); - c_autodefer (cstr_del(&s), cstr_del(&m)) { + c_autodefer (cstr_drop(&s), cstr_drop(&m)) { cstr_append(&m, m.str); cstr_append(&m, m.str); printf("%s\n", m.str); diff --git a/examples/splitstr.c b/examples/splitstr.c index 8bea911a..789b2c59 100644 --- a/examples/splitstr.c +++ b/examples/splitstr.c @@ -36,7 +36,7 @@ int main() cstr string = cstr_new("Split,this,,string,now,"); cvec_str vec = string_split(cstr_sv(string), c_sv(",")); - c_autodefer (cvec_str_del(&vec), cstr_del(&string)) + c_autodefer (cvec_str_drop(&vec), cstr_drop(&string)) c_foreach (i, cvec_str, vec) printf("\t\"%s\"\n", i.ref->str); } \ No newline at end of file diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c index c3da5287..a6b33de6 100644 --- a/examples/sptr_demo.c +++ b/examples/sptr_demo.c @@ -1,8 +1,8 @@ #include #include -void int_del(int* x) { - printf("del: %d\n", *x); +void int_drop(int* x) { + printf("drop: %d\n", *x); } // csptr implements its own clone method using reference counting, @@ -10,19 +10,19 @@ void int_del(int* x) { #define i_type iref // set type name to be defined (instead of 'csptr_int') #define i_val int -#define i_del int_del // optional, just to display the elements destroyed +#define i_drop int_drop // optional, just to display the elements destroyed #include // iref -#define i_key_ref iref // note: use i_key_ref instead of i_key for csptr/cbox elements +#define i_key_bind iref // note: use i_key_bind instead of i_key for csptr/cbox elements #include // csset_iref (like: std::set>) -#define i_val_ref iref // note: as above. +#define i_val_bind iref // note: as above. #include // cvec_iref (like: std::vector>) int main() { - c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_del() at scope exit - c_auto (csset_iref, set) // declare and init set, call csset_iref_del() at scope exit + c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_drop() at scope exit + c_auto (csset_iref, set) // declare and init set, call csset_iref_drop() at scope exit { const int years[] = {2021, 2012, 2022, 2015}; c_forrange (i, c_arraylen(years)) @@ -47,7 +47,7 @@ int main() printf("\nset:"); c_foreach (i, csset_iref, set) printf(" %d", *i.ref->get); - c_autovar (iref p = iref_clone(vec.data[0]), iref_del(&p)) { + c_autovar (iref p = iref_clone(vec.data[0]), iref_drop(&p)) { printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); } diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c index 4707abb1..d08b9072 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -1,50 +1,51 @@ #include -void show_del(int* x) { printf("del: %d\n", *x); } +void show_drop(int* x) { printf("drop: %d\n", *x); } +#define i_type Arc #define i_val int -#define i_del show_del // this "destroy" func shows which elements are destroyed +#define i_drop show_drop // this "destroy" func shows which elements are destroyed // csptr/cbox will use pointer address comparison of i_val if no i_cmp func is specified, -// or 'i_opt c_no_compare' is defined, otherwise i_cmp is used to compare object values. +// or 'i_opt c_no_cmp' is defined, otherwise i_cmp is used to compare object values. // See the different results by commenting out the next line. -#define i_cmp(x, y) (*(x) - *(y)) -#include // csptr_int: shared pointer to int +//#define i_cmp(x, y) (*(x) - *(y)) +#include // Arc: shared pointer to int -#define i_val_ref csptr_int -#define i_tag intp -#include // cvec_intp: cvec +#define i_type Vec +#define i_val_bind Arc +#include // Vec: cvec int main() { - c_auto (cvec_intp, vec) + c_auto (Vec, vec) { const int v[] = {2012, 1990, 2012, 2019, 2015}; c_forrange (i, c_arraylen(v)) - cvec_intp_push_back(&vec, csptr_int_new(v[i])); + Vec_push_back(&vec, Arc_new(v[i])); // clone the second 2012 and push it back. // note: cloning make sure that vec.data[2] has ref count 2. - cvec_intp_emplace_back(&vec, vec.data[2]); + Vec_emplace_back(&vec, vec.data[2]); printf("vec before erase :"); - c_foreach (i, cvec_intp, vec) + c_foreach (i, Vec, vec) printf(" %d", *i.ref->get); puts(""); // erase vec.data[2]; or first matching value depending on compare. - cvec_intp_iter it; - it = cvec_intp_find(&vec, vec.data[2]); - if (it.ref != cvec_intp_end(&vec).ref) - cvec_intp_erase_at(&vec, it); + Vec_iter it; + it = Vec_find(&vec, vec.data[2]); + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); int year = 2015; - it = cvec_intp_find(&vec, (csptr_int){&year}); // Ok as tmp only. - if (it.ref != cvec_intp_end(&vec).ref) - cvec_intp_erase_at(&vec, it); + it = Vec_find(&vec, (Arc){&year}); // Ok as tmp only. + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); printf("vec after erase :"); - c_foreach (i, cvec_intp, vec) + c_foreach (i, Vec, vec) printf(" %d", *i.ref->get); puts("\nDone"); diff --git a/examples/sptr_music.c b/examples/sptr_music.c index fcb7a43f..04ec28cc 100644 --- a/examples/sptr_music.c +++ b/examples/sptr_music.c @@ -9,20 +9,21 @@ struct Song cstr title; } typedef Song; -Song Song_from(const char* artist, const char* title) +Song Song_new(const char* artist, const char* title) { return (Song){cstr_from(artist), cstr_from(title)}; } -void Song_del(Song* s) { - printf("del: %s\n", s->title.str); - c_del(cstr, &s->artist, &s->title); +void Song_drop(Song* s) { + printf("drop: %s\n", s->title.str); + c_drop(cstr, &s->artist, &s->title); } #define i_val Song -#define i_del Song_del +#define i_drop Song_drop +#define i_opt c_no_cmp #define i_tag song #include // define csptr_song -#define i_val_ref csptr_song +#define i_val_bind csptr_song #define i_tag song #include @@ -31,9 +32,9 @@ void example3() c_auto (cvec_song, v, v2) { c_apply(cvec_song, push_back, &v, { - csptr_song_new(Song_from("Bob Dylan", "The Times They Are A Changing")), - csptr_song_new(Song_from("Aretha Franklin", "Bridge Over Troubled Water")), - csptr_song_new(Song_from("Thalia", "Entre El Mar y Una Estrella")) + csptr_song_new(Song_new("Bob Dylan", "The Times They Are A Changing")), + csptr_song_new(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), + csptr_song_new(Song_new("Thalia", "Entre El Mar y Una Estrella")) }); c_foreach (s, cvec_song, v) @@ -41,8 +42,8 @@ void example3() cvec_song_emplace_back(&v2, *s.ref); // note: calls csptr_song_clone() c_apply(cvec_song, push_back, &v2, { - csptr_song_new(Song_from("Michael Jackson", "Billie Jean")), - csptr_song_new(Song_from("Rihanna", "Stay")), + csptr_song_new(Song_new("Michael Jackson", "Billie Jean")), + csptr_song_new(Song_new("Rihanna", "Stay")), }); c_foreach (s, cvec_song, v2) diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c index cfb845b6..501fdcef 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -11,11 +11,10 @@ struct Base int value; } typedef Base; -void Base_del(Base* b) { printf("Base::~Base()\n"); } - #define i_val Base -#define i_del Base_del +#define i_drop(x) printf("Base::~Base()\n") #define i_tag base +#define i_opt c_no_cmp #include void* thr(csptr_base* lp) @@ -28,7 +27,7 @@ void* thr(csptr_base* lp) " p.get() = %p, p.use_count() = %ld\n", (void*)lp->get, *lp->use_count); } /* atomically decrease ref. */ - csptr_base_del(lp); + csptr_base_drop(lp); return NULL; } diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c index a66e5b31..69798563 100644 --- a/examples/sptr_to_maps.c +++ b/examples/sptr_to_maps.c @@ -3,22 +3,23 @@ #define i_type Map #define i_key_str // strings #define i_val int -#define i_keydel(p) (printf("del name: %s\n", (p)->str), cstr_del(p)) +#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) #include #define i_type Arc // (atomic) ref. counted type #define i_val Map -#define i_del(p) (printf("del Arc:\n"), Map_del(p)) +#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) // no need for atomic ref. count in single thread: -#define i_opt c_no_atomic +// no compare function available for csmap: +#define i_opt c_no_atomic|c_no_cmp #include #define i_type Stack -#define i_val_ref Arc // define i_val_ref for csptr/cbox value (not i_val) +#define i_val_bind Arc // define i_val_bind for csptr/cbox value (not i_val) #include #define i_type List -#define i_val_ref Arc // as above +#define i_val_bind Arc // as above #include int main() diff --git a/examples/vikings.c b/examples/vikings.c new file mode 100644 index 00000000..87977538 --- /dev/null +++ b/examples/vikings.c @@ -0,0 +1,69 @@ +#include +#include + +typedef struct Viking { + cstr name; + cstr country; +} Viking; + +void Viking_drop(Viking* vk) { + cstr_drop(&vk->name); + cstr_drop(&vk->country); +} + +// Define Viking raw struct with hash, equals, and convertion functions between Viking and RViking structs: + +typedef struct RViking { + const char* name; + const char* country; +} RViking; + +uint64_t RViking_hash(const RViking* raw, size_t ignore) { + uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); + return hash; +} +static inline bool RViking_equalto(const RViking* rx, const RViking* ry) { + return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; +} + +static inline Viking Viking_from(RViking raw) { // note: parameter is by value + return c_make(Viking){cstr_from(raw.name), cstr_from(raw.country)}; +} +static inline RViking Viking_toraw(const Viking* vk) { + return c_make(RViking){vk->name.str, vk->country.str}; +} + +// With this in place, we define the Viking => int hash map type: +#define i_type Vikings +#define i_key_bind Viking +#define i_val int +#define i_keyraw RViking +// i_key_bind auto-maps these functions: +// #define i_hash Viking_hash +// #define i_equ Viking_equalto +// #define i_keyfrom Viking_from // uses _from because i_keyraw is defined +// #define i_keyto Viking_toraw +// #define i_keydrop Viking_drop +#include + +int main() +{ + c_auto (Vikings, vikings) { + c_apply_pair(Vikings, emplace, &vikings, { + {{"Einar", "Norway"}, 20}, + {{"Olaf", "Denmark"}, 24}, + {{"Harald", "Iceland"}, 12}, + }); + RViking bjorn = {"Bjorn", "Sweden"}; + Vikings_emplace_or_assign(&vikings, bjorn, 10); + + RViking einar = {"Einar", "Norway"}; + Vikings_value *e = Vikings_find(&vikings, einar).ref; + e->second += 3; // add 3 hp points to Einar + Vikings_emplace(&vikings, einar, 0).ref->second += 5; // add 5 more to Einar + + c_forpair (viking, hp, Vikings, vikings) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.hp); + } + } +} \ No newline at end of file diff --git a/include/stc/alt/clist.h b/include/stc/alt/clist.h index 6695a26e..14abc7e4 100644 --- a/include/stc/alt/clist.h +++ b/include/stc/alt/clist.h @@ -49,7 +49,7 @@ puts("sorted"); c_foreach (i, clist_ix, list) if (++n % 10000 == 0) printf("%8d: %10zd\n", n, i.ref->value); - clist_ix_del(&list); + clist_ix_drop(&list); } */ #include @@ -61,13 +61,13 @@ _c_clist_types(clist_VOID, int); STC_API size_t _clist_count(const clist_VOID* self); #define _clist_node(_cx_self, vp) c_container_of(vp, _cx_node, value) -#define _c_using_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw, defTypes) \ +#define _c_using_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw, defTypes) \ \ defTypes( _c_clist_types(_cx_self, i_val); ) \ typedef i_valraw _cx_rawvalue; \ \ STC_API _cx_self _cx_memb(_clone)(_cx_self lst); \ - STC_API void _cx_memb(_del)(_cx_self* self); \ + STC_API void _cx_memb(_drop)(_cx_self* self); \ STC_API void _cx_memb(_push_back)(_cx_self* self, i_val value); \ STC_API void _cx_memb(_push_front)(_cx_self* self, i_val value); \ STC_API void _cx_memb(_emplace_items)(_cx_self *self, const _cx_rawvalue arr[], size_t n); \ @@ -89,7 +89,7 @@ STC_API size_t _clist_count(const clist_VOID* self); STC_INLINE size_t _cx_memb(_count)(_cx_self lst) { return _clist_count((const clist_VOID*) &lst); } \ 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(_clear)(_cx_self* self) { _cx_memb(_del)(self); } \ + STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); } \ STC_INLINE void _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) \ { _cx_memb(_push_back)(self, i_valfrom(raw)); } \ STC_INLINE void _cx_memb(_emplace_front)(_cx_self* self, i_valraw raw) \ @@ -143,13 +143,13 @@ STC_API size_t _clist_count(const clist_VOID* self); while (n-- && it.ref) _cx_memb(_next)(&it); return it; \ } \ \ - _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) \ + _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) \ +#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) \ \ STC_DEF _cx_self \ _cx_memb(_clone)(_cx_self lst) { \ @@ -160,7 +160,7 @@ STC_API size_t _clist_count(const clist_VOID* self); } \ \ STC_DEF void \ - _cx_memb(_del)(_cx_self* self) { \ + _cx_memb(_drop)(_cx_self* self) { \ while (self->last) _cx_memb(_erase_after_)(self, self->last); \ } \ \ @@ -232,7 +232,7 @@ STC_API size_t _clist_count(const clist_VOID* self); node->next = next; \ if (del == next) self->last = node = NULL; \ else if (self->last == del) self->last = node, node = NULL; \ - i_valdel(&del->value); c_free(del); \ + i_valdrop(&del->value); c_free(del); \ return node; \ } \ \ @@ -361,7 +361,7 @@ _clist_mergesort(clist_VOID_node *list, int (*cmp)(const void*, const void*)) { } #else -#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) +#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) #endif #endif diff --git a/include/stc/alt/csmap.h b/include/stc/alt/csmap.h index 5b331efb..beccf559 100644 --- a/include/stc/alt/csmap.h +++ b/include/stc/alt/csmap.h @@ -30,7 +30,7 @@ using_csmap(mx, int, char); // Sorted map int main(void) { - c_autovar (csmap_mx m = csmap_mx_init(), csmap_mx_del(&m)) + c_autovar (csmap_mx m = csmap_mx_init(), csmap_mx_drop(&m)) { csmap_mx_insert(&m, 5, 'a'); csmap_mx_insert(&m, 8, 'b'); @@ -91,8 +91,8 @@ int main(void) { \ STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.size == 0; } \ STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cx.size; } \ - STC_INLINE void _cx_memb(_del)(_cx_self* self) { _cx_memb(_del_r_)(self->root); } \ - STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); *self = _cx_memb(_init)(); } \ + STC_INLINE void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_del_r_)(self->root); } \ + STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); } \ STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) {c_swap(_cx_self, *a, *b); } \ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self cx) { return c_make(_cx_self){ _cx_memb(_clone_r_)(cx.root), cx.size}; } \ STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) \ @@ -103,9 +103,9 @@ int main(void) { {_cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } \ \ STC_INLINE void \ - _cx_memb(_value_del)(_cx_value* val) { \ - i_keydel(_i_keyref(val)); \ - _i_MAP_ONLY( i_valdel(&val->second); ) \ + _cx_memb(_value_drop)(_cx_value* val) { \ + i_keydrop(_i_keyref(val)); \ + _i_MAP_ONLY( i_valdrop(&val->second); ) \ } \ \ STC_INLINE void \ @@ -134,7 +134,7 @@ int main(void) { _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) {*_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} \ - else {i_keydel(&key); _i_MAP_ONLY( i_valdel(&mapped); )} \ + else {i_keydrop(&key); _i_MAP_ONLY( i_valdrop(&mapped); )} \ return res; \ } \ \ @@ -143,7 +143,7 @@ int main(void) { _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)); \ if (res.inserted) res.ref->first = key; \ - else {i_keydel(&key); i_valdel(&res.ref->second); } \ + else {i_keydrop(&key); i_valdrop(&res.ref->second); } \ res.ref->second = mapped; return res; \ } \ \ @@ -156,7 +156,7 @@ int main(void) { _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { \ _cx_result res = _cx_memb(_insert_entry_)(self, rkey); \ if (res.inserted) res.ref->first = i_keyfrom(rkey); \ - else i_valdel(&res.ref->second); \ + else i_valdrop(&res.ref->second); \ res.ref->second = i_valfrom(rmapped); return res; \ } \ \ @@ -191,8 +191,8 @@ int main(void) { } \ \ _c_implement_aatree(_cx_self, C, i_key, i_val, i_cmp, \ - i_valdel, i_valfrom, i_valto, i_valraw, \ - i_keydel, i_keyfrom, i_keyto, i_keyraw) \ + i_valdrop, i_valfrom, i_valto, i_valraw, \ + i_keydrop, i_keyfrom, i_keyto, i_keyraw) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -204,8 +204,8 @@ _c_aatree_complete_types(csmap_SENTINEL, csmap_); static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_sentinel, 0}; #define _c_implement_aatree(_cx_self, C, i_key, i_val, i_cmp, \ - i_valdel, i_valfrom, i_valto, i_valraw, \ - i_keydel, i_keyfrom, i_keyto, i_keyraw) \ + i_valdrop, i_valfrom, i_valto, i_valraw, \ + i_keydrop, i_keyfrom, i_keyto, i_keyraw) \ STC_DEF _cx_self \ _cx_memb(_init)(void) { \ _cx_self cx = {(_cx_node *) &_aatree_sentinel, 0}; \ @@ -330,7 +330,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti if (c != 0) \ tn->link[c < 0] = _cx_memb(_erase_r_)(tn->link[c < 0], rkey, erased); \ else { \ - if (!*erased) { _cx_memb(_value_del)(&tn->value); *erased = 1; } \ + if (!*erased) { _cx_memb(_value_drop)(&tn->value); *erased = 1; } \ if (tn->link[0]->level && tn->link[1]->level) { \ tx = tn->link[0]; \ while (tx->link[1]->level) \ @@ -395,7 +395,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti if (tn->level != 0) { \ _cx_memb(_del_r_)(tn->link[0]); \ _cx_memb(_del_r_)(tn->link[1]); \ - _cx_memb(_value_del)(&tn->value); \ + _cx_memb(_value_drop)(&tn->value); \ c_free(tn); \ } \ } diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index 76b3a800..bd135b7e 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -41,7 +41,7 @@ typedef union { /**************************** PRIVATE API **********************************/ -enum { SSO_CAP = offsetof(cstr, lon.ncap) + sizeof((cstr){{0}}.lon.ncap) - 1 }; +enum { SSO_CAP = sizeof(_cstr_rep_t) - 1 }; #define cstr_is_long(s) (bool)((s)->sso.cap_len & 128) #define cstr_select_(s, memb) (cstr_is_long(s) ? cstr_l_##memb : cstr_s_##memb) @@ -52,18 +52,18 @@ enum { SSO_CAP = offsetof(cstr, lon.ncap) + sizeof((cstr){{0}}.lon.ncap) - 1 }; #define cstr_s_end(s) ((s)->sso.data + cstr_s_size(s)) #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) -#define cstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) -#define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) + #define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) + #define cstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) #else -#define cstr_l_cap(s) (~(s)->lon.ncap) -#define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) + #define cstr_l_cap(s) (~(s)->lon.ncap) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) #endif #define cstr_l_size(s) ((s)->lon.size) #define cstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (len)] = 0) #define cstr_l_data(s) (s)->lon.data #define cstr_l_end(s) ((s)->lon.data + cstr_l_size(s)) -#define cstr_l_del(s) free((s)->lon.data) +#define cstr_l_drop(s) free((s)->lon.data) STC_API char* cstr_init_(cstr* self, size_t len, size_t cap); STC_API void cstr_internal_move_(cstr* self, size_t pos1, size_t pos2); @@ -74,15 +74,16 @@ STC_INLINE void cstr_set_size_(cstr* self, size_t len) { STC_INLINE _cstr_rep_t cstr_rep_(cstr* self) { return cstr_is_long(self) - ? c_make(_cstr_rep_t){self->lon.data, cstr_l_size(self), cstr_l_cap(self)} - : c_make(_cstr_rep_t){self->sso.data, cstr_s_size(self), cstr_s_cap(self)}; + ? c_make(_cstr_rep_t){self->lon.data, cstr_l_size(self), cstr_l_cap(self)} + : c_make(_cstr_rep_t){self->sso.data, cstr_s_size(self), cstr_s_cap(self)}; } /**************************** PUBLIC API **********************************/ #define cstr_new(literal) cstr_from_n(literal, sizeof((c_strlit){literal}) - 1) #define cstr_npos (SIZE_MAX >> 1) -#define cstr_null (cstr){.sso = {.cap_len = SSO_CAP}} +#define cstr_null (c_make(cstr){.sso = {.cap_len = SSO_CAP}}) +#define cstr_toraw(self) cstr_str(self) STC_API char* cstr_reserve(cstr* self, size_t cap); STC_API void cstr_shrink_to_fit(cstr* self); @@ -126,8 +127,8 @@ STC_INLINE cstr cstr_clone(cstr s) { return cstr_from_n(rep.data, rep.size); } -STC_INLINE void cstr_del(cstr* self) { - if (cstr_is_long(self)) cstr_l_del(self); +STC_INLINE void cstr_drop(cstr* self) { + if (cstr_is_long(self)) cstr_l_drop(self); } STC_INLINE void cstr_clear(cstr* self) { @@ -170,7 +171,7 @@ STC_INLINE bool cstr_equalto(const cstr* s1, const cstr* s2) { return strcmp(cstr_str(s1), cstr_str(s2)) == 0; } -STC_INLINE int cstr_compare(const cstr* s1, const cstr* s2) { +STC_INLINE int cstr_cmp(const cstr* s1, const cstr* s2) { return strcmp(cstr_str(s1), cstr_str(s2)); } diff --git a/include/stc/alt/sstr.h b/include/stc/alt/sstr.h deleted file mode 100644 index 2ea1033d..00000000 --- a/include/stc/alt/sstr.h +++ /dev/null @@ -1,406 +0,0 @@ -/* MIT License - * - * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* A string type with short string optimization in C99 with optimal short string - * utilization (23 characters with 24 bytes string representation). - */ -#ifndef SSTR_INCLUDED -#define SSTR_INCLUDED - -#include -#include -#include -#include - -#ifndef sstr_size_t -typedef size_t sstr_size_t; -#endif -typedef struct { char* data; sstr_size_t size, cap; } sstr_rep_t; -typedef const char sstr_literal_t[]; - -typedef union { - struct { char* data; sstr_size_t size, ncap; } lon; - struct { char data[sizeof(sstr_rep_t)]; } sso; -} sstr; - -/**************************** PRIVATE API **********************************/ - -enum { SSO_CAP = offsetof(sstr, lon.ncap) + sizeof((sstr){{0}}.lon.ncap) - 1 }; -#define sstr_is_long(s) (bool)((s)->sso.data[SSO_CAP] & 128) -#define sstr_select_(s, memb) (sstr_is_long(s) ? sstr_l_##memb : sstr_s_##memb) - -#define sstr_s_cap(s) SSO_CAP -#define sstr_s_size(s) ((sstr_size_t)(SSO_CAP - (s)->sso.data[SSO_CAP])) -#define sstr_s_set_size(s, len) ((s)->sso.data[SSO_CAP] = SSO_CAP - (len), (s)->sso.data[len] = 0) -#define sstr_s_data(s) (s)->sso.data -#define sstr_s_end(s) ((s)->sso.data + sstr_s_size(s)) - -#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) -#define sstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) -#define sstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) -#else -#define sstr_l_cap(s) (~(s)->lon.ncap) -#define sstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) -#endif -#define sstr_l_size(s) ((s)->lon.size) -#define sstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (len)] = 0) -#define sstr_l_data(s) (s)->lon.data -#define sstr_l_end(s) ((s)->lon.data + sstr_l_size(s)) -#define sstr_l_del(s) free((s)->lon.data) - -STC_API char* sstr_init_(sstr* self, sstr_size_t len, sstr_size_t cap); -STC_API void sstr_internal_move_(sstr* self, size_t pos1, size_t pos2); - -STC_INLINE void sstr_set_size_(sstr* self, sstr_size_t len) { - sstr_select_(self, set_size(self, len)); -} - -STC_INLINE sstr_rep_t sstr_rep_(sstr* self) { - return sstr_is_long(self) - ? c_make(sstr_rep_t){self->lon.data, sstr_l_size(self), sstr_l_cap(self)} - : c_make(sstr_rep_t){self->sso.data, sstr_s_size(self), sstr_s_cap(self)}; -} - -/**************************** PUBLIC API **********************************/ - -#define sstr_lit(lit) sstr_from_n(lit, sizeof((sstr_literal_t){lit}) - 1) -#define sstr_npos (~(sstr_size_t)0 >> 1) - -STC_API char* sstr_reserve(sstr* self, sstr_size_t cap); -STC_API void sstr_shrink_to_fit(sstr* self); -STC_API void sstr_resize(sstr* self, sstr_size_t size, char value); -STC_API char* strnstrn(const char *s, const char *needle, size_t slen, size_t nlen); -STC_API sstr_size_t sstr_find_n(sstr s, const char* needle, sstr_size_t pos, sstr_size_t nmax); -STC_API void sstr_assign_n(sstr* self, const char* str, sstr_size_t n); -STC_API void sstr_append_n(sstr* self, const char* str, sstr_size_t n); -STC_API bool sstr_getdelim(sstr *self, int delim, FILE *fp); -STC_API void sstr_erase_n(sstr* self, size_t pos, size_t n); - - -STC_INLINE sstr sstr_init(void) { - sstr s; - sstr_s_set_size(&s, 0); - return s; -} - -STC_INLINE sstr sstr_from_n(const char* str, sstr_size_t n) { - sstr s; - memcpy(sstr_init_(&s, n, n), str, n); - return s; -} - -STC_INLINE sstr sstr_from(const char* str) { - return sstr_from_n(str, strlen(str)); -} - -STC_INLINE sstr sstr_with_size(sstr_size_t size, char value) { - sstr s; - memset(sstr_init_(&s, size, size), value, size); - return s; -} - -STC_INLINE sstr sstr_with_capacity(sstr_size_t cap) { - sstr s; - sstr_init_(&s, 0, cap); - return s; -} - -STC_INLINE sstr sstr_clone(sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - return sstr_from_n(rep.data, rep.size); -} - -STC_INLINE void sstr_del(sstr* self) { - if (sstr_is_long(self)) sstr_l_del(self); -} - -STC_INLINE void sstr_clear(sstr* self) { - sstr_set_size_(self, 0); -} - -STC_INLINE char* sstr_data(sstr* self) { - return sstr_select_(self, data(self)); -} - -STC_INLINE const char* sstr_str(const sstr* self) { - return sstr_select_(self, data(self)); -} - -STC_INLINE bool sstr_empty(sstr s) { - return sstr_select_(&s, size(&s)) == 0; -} - -STC_INLINE sstr_size_t sstr_size(sstr s) { - return sstr_select_(&s, size(&s)); -} - -STC_INLINE sstr_size_t sstr_length(sstr s) { - return sstr_select_(&s, size(&s)); -} - -STC_INLINE sstr_size_t sstr_capacity(sstr s) { - return sstr_select_(&s, cap(&s)); -} - -STC_INLINE bool sstr_equals(sstr s1, const char* str) { - return strcmp(sstr_str(&s1), str) == 0; -} - -STC_INLINE bool sstr_equals_s(sstr s1, sstr s2) { - return strcmp(sstr_str(&s1), sstr_str(&s2)) == 0; -} - -STC_INLINE bool sstr_equalto(const sstr* s1, const sstr* s2) { - return strcmp(sstr_str(s1), sstr_str(s2)) == 0; -} - -STC_INLINE int sstr_compare(const sstr* s1, const sstr* s2) { - return strcmp(sstr_str(s1), sstr_str(s2)); -} - -STC_INLINE sstr_size_t sstr_find(sstr s, const char* needle) { - const char *str = sstr_str(&s), *res = strstr(str, needle); - return res ? res - str : sstr_npos; -} - -STC_INLINE bool sstr_find_s(sstr s, sstr needle) { - return sstr_find(s, sstr_str(&needle)); -} - -STC_INLINE bool sstr_contains(sstr s, const char* needle) { - return strstr(sstr_str(&s), needle) != NULL; -} - -STC_INLINE bool sstr_contains_s(sstr s, sstr needle) { - return strstr(sstr_str(&s), sstr_str(&needle)) != NULL; -} - -STC_INLINE bool sstr_starts_with(sstr s, const char* sub) { - const char* str = sstr_str(&s); - while (*sub && *str == *sub) ++str, ++sub; - return *sub == 0; -} - -STC_INLINE bool sstr_starts_with_s(sstr s, sstr sub) { - return sstr_starts_with(s, sstr_str(&sub)); -} - -STC_INLINE bool sstr_ends_with(sstr s, const char* sub) { - sstr_rep_t rep = sstr_rep_(&s); sstr_size_t n = strlen(sub); - return n <= rep.size && memcmp(rep.data + rep.size - n, sub, n) == 0; -} - -STC_INLINE bool sstr_ends_with_s(sstr s, sstr sub) { - return sstr_ends_with(s, sstr_str(&sub)); -} - -STC_INLINE void sstr_assign(sstr* self, const char* str) { - sstr_assign_n(self, str, strlen(str)); -} - -STC_INLINE void sstr_copy(sstr* self, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_assign_n(self, rep.data, rep.size); -} - -STC_INLINE void sstr_append(sstr* self, const char* str) { - sstr_append_n(self, str, strlen(str)); -} - -STC_INLINE void sstr_append_s(sstr* self, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_append_n(self, rep.data, rep.size); -} - -STC_INLINE void sstr_replace_n(sstr* self, size_t pos, size_t len, const char* str, size_t n) { - sstr_internal_move_(self, pos + len, pos + n); - memcpy(&sstr_data(self)[pos], str, n); -} - -STC_INLINE void sstr_replace(sstr* self, size_t pos, size_t len, const char* str) { - sstr_replace_n(self, pos, len, str, strlen(str)); -} - -STC_INLINE void sstr_replace_s(sstr* self, size_t pos, size_t len, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_replace_n(self, pos, len, rep.data, rep.size); -} - -STC_INLINE void sstr_insert_n(sstr* self, size_t pos, const char* str, size_t n) { - sstr_replace_n(self, pos, 0, str, n); -} - -STC_INLINE void sstr_insert(sstr* self, size_t pos, const char* str) { - sstr_replace_n(self, pos, 0, str, strlen(str)); -} - -STC_INLINE void sstr_insert_s(sstr* self, size_t pos, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_replace_n(self, pos, 0, rep.data, rep.size); -} - -STC_INLINE bool sstr_getline(sstr *self, FILE *fp) { - return sstr_getdelim(self, '\n', fp); -} - -/* -------------------------- IMPLEMENTATION ------------------------- */ - -#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) - -STC_DEF void sstr_internal_move_(sstr* self, size_t pos1, size_t pos2) { - if (pos1 == pos2) - return; - sstr_rep_t rep = sstr_rep_(self); - sstr_size_t newlen = rep.size + pos2 - pos1; - if (newlen > rep.cap) - rep.data = sstr_reserve(self, (rep.size*3 >> 1) + pos2 - pos1); - memmove(&rep.data[pos2], &rep.data[pos1], rep.size - pos1); - sstr_set_size_(self, newlen); -} - -STC_DEF char* sstr_init_(sstr* self, sstr_size_t len, sstr_size_t cap) { - if (cap > SSO_CAP) { - self->lon.data = (char *)malloc(cap + 1); - sstr_l_set_size(self, len); - sstr_l_set_cap(self, cap); - return self->lon.data; - } - sstr_s_set_size(self, len); - return self->sso.data; -} - -STC_DEF void sstr_shrink_to_fit(sstr* self) { - sstr_rep_t rep = sstr_rep_(self); - if (rep.size == rep.cap) - return; - if (rep.size > SSO_CAP) { - self->lon.data = (char *)realloc(self->lon.data, sstr_l_size(self) + 1); - sstr_l_set_cap(self, sstr_l_size(self)); - } else if (rep.cap > SSO_CAP) { - memcpy(self->sso.data, rep.data, rep.size + 1); - sstr_s_set_size(self, rep.size); - free(rep.data); - } -} - -STC_DEF char* sstr_reserve(sstr* self, sstr_size_t cap) { - if (sstr_is_long(self)) { - if (cap > sstr_l_cap(self)) { - self->lon.data = (char *)realloc(self->lon.data, cap + 1); - sstr_l_set_cap(self, cap); - } - return self->lon.data; - } - /* from short to long: */ - if (cap > sstr_s_cap(self)) { - char* data = (char *)malloc(cap + 1); - sstr_size_t len = sstr_s_size(self); - memcpy(data, self->sso.data, len); - self->lon.data = data; - sstr_l_set_size(self, len); - sstr_l_set_cap(self, cap); - return data; - } - return self->sso.data; -} - -STC_DEF void sstr_resize(sstr* self, sstr_size_t size, char value) { - sstr_rep_t rep = sstr_rep_(self); - if (size > rep.size) { - if (size > rep.cap) rep.data = sstr_reserve(self, size); - memset(rep.data + rep.size, value, size - rep.size); - } - sstr_set_size_(self, size); -} - -STC_DEF char* strnstrn(const char *s, const char *needle, size_t slen, size_t nlen) { - if (!nlen) return (char *)s; - if (nlen > slen) return NULL; - slen -= nlen; - do { - if (*s == *needle && !memcmp(s, needle, nlen)) return (char *)s; - ++s; - } while (slen--); - return NULL; -} - -STC_DEF sstr_size_t -sstr_find_n(sstr s, const char* needle, sstr_size_t pos, sstr_size_t nmax) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_size_t nlen = (sstr_size_t) strlen(needle); - if (pos > rep.size) return sstr_npos; - char* res = strnstrn(rep.data + pos, needle, rep.size, nmax < nlen ? nmax : nlen); - return res ? res - rep.data : sstr_npos; -} - -STC_DEF void sstr_assign_n(sstr* self, const char* str, sstr_size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (n > rep.cap) { - rep.data = (char *)realloc(sstr_is_long(self) ? rep.data : NULL, n + 1); - sstr_l_set_cap(self, n); - } - memmove(rep.data, str, n); - sstr_set_size_(self, n); -} - -STC_DEF void sstr_append_n(sstr* self, const char* str, sstr_size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (rep.size + n > rep.cap) { - sstr_size_t off = (sstr_size_t)(str - rep.data); /* handle self append */ - rep.data = sstr_reserve(self, (rep.size*3 >> 1) + n); - if (off <= rep.size) str = rep.data + off; - } - memcpy(rep.data + rep.size, str, n); - sstr_set_size_(self, rep.size + n); -} - -STC_DEF bool sstr_getdelim(sstr *self, int delim, FILE *fp) { - int c = fgetc(fp); - if (c == EOF) - return false; - sstr_size_t pos = 0; - sstr_rep_t rep = sstr_rep_(self); - for (;;) { - if (c == delim || c == EOF) { - sstr_set_size_(self, pos); - return true; - } - if (pos == rep.cap) { - sstr_set_size_(self, pos); - rep.data = sstr_reserve(self, (rep.cap = (rep.cap*3 >> 1) + 16)); - } - rep.data[pos++] = (char) c; - c = fgetc(fp); - } -} - -STC_DEF void sstr_erase_n(sstr* self, size_t pos, size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (n > rep.size - pos) n = rep.size - pos; - memmove(&rep.data[pos], &rep.data[pos + n], rep.size - (pos + n)); - sstr_set_size_(self, rep.size - n); -} - -#endif -#endif \ No newline at end of file diff --git a/include/stc/carr2.h b/include/stc/carr2.h index d1feb90b..92964d4d 100644 --- a/include/stc/carr2.h +++ b/include/stc/carr2.h @@ -34,7 +34,7 @@ int main() { int w = 7, h = 5; - c_autovar (carr2_int image = carr2_int_init(w, h), carr2_int_del(&image)) + c_autovar (carr2_int image = carr2_int_init(w, h), carr2_int_drop(&image)) { int *dat = carr2_int_data(&image); for (int i = 0; i < carr2_int_size(image); ++i) @@ -63,7 +63,7 @@ _cx_deftypes(_c_carr2_types, _cx_self, i_val); 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(_drop)(_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); @@ -124,7 +124,7 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } #endif @@ -135,10 +135,11 @@ STC_DEF _cx_value *_cx_memb(_release)(_cx_self* self) { return values; } -STC_DEF void _cx_memb(_del)(_cx_self* self) { +STC_DEF void _cx_memb(_drop)(_cx_self* self) { if (!self->data) return; - for (_cx_value* p = self->data[0], *e = p + _cx_memb(_size)(*self); p != e; ++p) - i_valdel(p); + for (_cx_value* p = self->data[0], *q = p + _cx_memb(_size)(*self); p != q; ) { + --q; i_valdrop(q); + } c_free(self->data[0]); /* values */ c_free(self->data); /* pointers */ } diff --git a/include/stc/carr3.h b/include/stc/carr3.h index 4a4a6484..31df5bdf 100644 --- a/include/stc/carr3.h +++ b/include/stc/carr3.h @@ -34,7 +34,7 @@ int main() { int w = 7, h = 5, d = 3; - c_autovar (carr3_int image = carr3_int_init(w, h, d), carr3_int_del(&image)) + c_autovar (carr3_int image = carr3_int_init(w, h, d), carr3_int_drop(&image)) { int *dat = carr3_int_data(&image); for (int i = 0; i < carr3_int_size(image); ++i) @@ -65,7 +65,7 @@ _cx_deftypes(_c_carr3_types, _cx_self, i_val); 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(_drop)(_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); @@ -130,7 +130,7 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } #endif @@ -141,10 +141,11 @@ STC_DEF _cx_value* _cx_memb(_release)(_cx_self* self) { return values; } -STC_DEF void _cx_memb(_del)(_cx_self* self) { +STC_DEF void _cx_memb(_drop)(_cx_self* self) { if (!self->data) return; - for (_cx_value* p = **self->data, *e = p + _cx_memb(_size)(*self); p != e; ++p) - i_valdel(p); + for (_cx_value* p = **self->data, *q = p + _cx_memb(_size)(*self); p != q; ) { + --q; i_valdrop(q); + } c_free(self->data[0][0]); /* data */ c_free(self->data); /* pointers */ } diff --git a/include/stc/cbits.h b/include/stc/cbits.h index b3a70edc..a6ee3948 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -30,7 +30,7 @@ Similar to boost::dynamic_bitset / std::bitset #include "cbits.h" int main() { - c_autovar (cbits bset = cbits_with_size(23, true), cbits_del(&bset)) + c_autovar (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) { cbits_reset(&bset, 9); cbits_resize(&bset, 43, false); @@ -75,14 +75,14 @@ STC_API bool cbits_disjoint(cbits set, cbits other); STC_INLINE cbits cbits_init() { return c_make(cbits){NULL, 0}; } STC_INLINE cbits cbits_from(const char* s) { return cbits_from_n(s, strlen(s)); } STC_INLINE void cbits_clear(cbits* self) { self->size = 0; } -STC_INLINE void cbits_del(cbits* self) { c_free(self->data64); } +STC_INLINE void cbits_drop(cbits* self) { c_free(self->data64); } STC_INLINE size_t cbits_size(cbits set) { return set.size; } #define cbits_new(literal) \ cbits_from_n(literal, sizeof c_make(c_strlit){literal} - 1) STC_INLINE cbits* cbits_take(cbits* self, cbits other) { - if (self->data64 != other.data64) {cbits_del(self); *self = other;} + if (self->data64 != other.data64) {cbits_drop(self); *self = other;} return self; } diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 89bd272e..51bc81a4 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -26,7 +26,7 @@ typedef struct { cstr name, last; } Person; -Person Person_from(const char* name, const char* last) { +Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } Person Person_clone(Person p) { @@ -34,21 +34,21 @@ Person Person_clone(Person p) { p.last = cstr_clone(p.last); return p; } -void Person_del(Person* p) { - printf("del: %s %s\n", p->name.str, p->last.str); - c_del(cstr, &p->name, &p->last); +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); } #define i_val Person -#define i_valdel Person_del +#define i_valdrop Person_drop #define i_valfrom Person_clone -#define i_opt c_no_compare // compare by .get addresses only +#define i_opt c_no_cmp // compare by .get addresses only #define i_tag prs #include int main() { - c_autovar (cbox_prs p = cbox_prs_new(Person_from("John", "Smiths")), cbox_prs_del(&p)) - c_autovar (cbox_prs q = cbox_prs_clone(p), cbox_prs_del(&q)) + c_autovar (cbox_prs p = cbox_prs_new(Person_new("John", "Smiths")), cbox_prs_drop(&p)) + c_autovar (cbox_prs q = cbox_prs_clone(p), cbox_prs_drop(&q)) { cstr_assign(&q.get->name, "Joe"); @@ -63,6 +63,7 @@ int main() { #include "ccommon.h" #include "forward.h" #include +#include #define cbox_null {NULL} #endif // CBOX_H_INCLUDED @@ -71,6 +72,7 @@ int main() { #define _i_prefix cbox_ #endif #include "template.h" +typedef i_valraw _cx_rawvalue; #if !c_option(c_is_fwd) _cx_deftypes(_c_cbox_types, _cx_self, i_val); @@ -90,8 +92,8 @@ _cx_memb(_new)(i_val val) { // destructor STC_INLINE void -_cx_memb(_del)(_cx_self* self) { - if (self->get) { i_valdel(self->get); c_free(self->get); } +_cx_memb(_drop)(_cx_self* self) { + if (self->get) { i_valdrop(self->get); c_free(self->get); } } STC_INLINE _cx_self @@ -102,19 +104,19 @@ _cx_memb(_move)(_cx_self* self) { STC_INLINE void _cx_memb(_reset)(_cx_self* self) { - _cx_memb(_del)(self); self->get = NULL; + _cx_memb(_drop)(self); self->get = NULL; } // take ownership of *p STC_INLINE void _cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { - _cx_memb(_del)(self); self->get = p; + _cx_memb(_drop)(self); self->get = p; } // take ownership of val STC_INLINE void _cx_memb(_reset_new)(_cx_self* self, i_val val) { - if (self->get) { i_valdel(self->get); *self->get = val; } + if (self->get) { i_valdrop(self->get); *self->get = val; } else self->get = c_new(i_val, val); } @@ -123,11 +125,10 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { _cx_memb(_from)(i_valraw raw) { return c_make(_cx_self){c_new(i_val, i_valfrom(raw))}; } - - STC_INLINE void - _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) { - _cx_memb(_reset_new)(self, i_valfrom(raw)); - } + STC_INLINE i_valraw + _cx_memb(_toraw)(const _cx_self* self) { + return i_valto(self->get); + } STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { @@ -145,30 +146,32 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self other) { - if (other.get != self->get) _cx_memb(_del)(self); + if (other.get != self->get) _cx_memb(_drop)(self); *self = other; } STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self, size_t n) { - #if (c_option(c_no_compare) || defined _i_default_compare) && SIZE_MAX >> 32 + #if c_option(c_no_cmp) && SIZE_MAX >> 32 return c_hash64(&self->get, 8); - #elif (c_option(c_no_compare) || defined _i_default_compare) + #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); #else - i_valraw raw = i_valto(self->get); - return i_hash(&raw, sizeof raw); + return i_hash(self->get, sizeof *self->get); #endif } STC_INLINE int -_cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { - #if (c_option(c_no_compare) || defined _i_default_compare) - return (int)(x->get - y->get); +_cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { + #if c_option(c_no_cmp) + return c_default_cmp(&x->get, &y->get); #else - i_valraw rx = i_valto(x->get); - i_valraw ry = i_valto(y->get); - return i_cmp(&rx, &ry); + return i_cmp(x->get, y->get); #endif } -#include "template.h" \ No newline at end of file + +STC_INLINE bool +_cx_memb(_equalto)(const _cx_self* x, const _cx_self* y) { + return !_cx_memb(_cmp)(x, y); +} +#include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 2942873f..d3664077 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -93,33 +93,37 @@ #endif typedef const char c_strlit[]; -#define c_delete(T, ptr) do { T *_c_p = ptr; T##_del(_c_p); c_free(_c_p); } while (0) +#define c_delete(T, ptr) do { T *_c_p = ptr; T##_drop(_c_p); c_free(_c_p); } while (0) #define c_swap(T, x, y) do { T _c_t = x; x = y; y = _c_t; } while (0) #define c_arraylen(a) (sizeof (a)/sizeof (a)[0]) -#define c_less_compare(less, x, y) (less(y, x) - less(x, y)) +#define c_less_cmp(less, x, y) (less(y, x) - less(x, y)) #define c_default_less(x, y) (*(x) < *(y)) -#define c_default_compare(x, y) c_less_compare(c_default_less, x, y) +#define c_default_cmp(x, y) c_less_cmp(c_default_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(x, dummy) c_strhash(*(x)) - #define c_default_clone(x) (x) #define c_default_fromraw(x) (x) // [deprecated] #define c_default_toraw(ptr) (*(ptr)) -#define c_default_del(ptr) ((void) (ptr)) +#define c_default_drop(ptr) ((void) (ptr)) #define c_option(flag) ((i_opt) & (flag)) #define c_is_fwd 1 #define c_no_atomic 2 #define c_no_clone 4 -#define c_no_compare 8 +#define c_no_cmp 8 /* Generic algorithms */ +typedef char* c_mutstr; +typedef const char* c_rawstr; +#define c_rawstr_cmp(x, y) strcmp(*(x), *(y)) +#define c_rawstr_equalto(x, y) (strcmp(*(x), *(y)) == 0) +#define c_rawstr_hash(x, dummy) c_strhash(*(x)) +#define c_rawstr_clone(s) strcpy((char*)c_malloc(strlen(s) + 1), s) +#define c_rawstr_drop(x) c_free((char *) &**(x)) + #define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) STC_INLINE uint64_t c_strhash(const char *s) { @@ -168,16 +172,16 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { #define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) #define c_auto_2(C, a) \ - c_autovar(C a = C##_init(), C##_del(&a)) + c_autovar(C a = C##_init(), C##_drop(&a)) #define c_auto_3(C, a, b) \ c_autovar(c_EXPAND(C a = C##_init(), b = C##_init()), \ - C##_del(&b), C##_del(&a)) + C##_drop(&b), C##_drop(&a)) #define c_auto_4(C, a, b, c) \ c_autovar(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init()), \ - C##_del(&c), C##_del(&b), C##_del(&a)) + C##_drop(&c), C##_drop(&b), C##_drop(&a)) #define c_auto_5(C, a, b, c, d) \ c_autovar(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ - C##_del(&d), C##_del(&c), C##_del(&b), C##_del(&a)) + C##_drop(&d), C##_drop(&c), C##_drop(&b), C##_drop(&a)) #define c_autobuf(b, type, n) c_autobuf_N(b, type, n, 256) #define c_autobuf_N(b, type, n, BYTES) \ @@ -203,10 +207,10 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { C##_##method(_c_cx, *_c_i); \ } while (0) -#define c_del(C, ...) do { \ +#define c_drop(C, ...) do { \ C* _c_arr[] = {__VA_ARGS__}; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ - C##_del(_c_arr[_c_i]); \ + C##_drop(_c_arr[_c_i]); \ } while (0) #if defined(__SIZEOF_INT128__) diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index f8cc1d52..050f9e67 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -42,7 +42,7 @@ typedef i_valraw _cx_rawvalue; STC_API _cx_self _cx_memb(_init)(void); STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API void _cx_memb(_del)(_cx_self* self); +STC_API void _cx_memb(_drop)(_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 @@ -54,9 +54,9 @@ STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* po const _cx_rawvalue* p1, const _cx_rawvalue* p2); #endif // !c_no_clone -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) 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); +STC_API int _cx_memb(_value_cmp)(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); @@ -72,7 +72,7 @@ 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } #endif STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return !cdeq_rep_(&cx)->size; } @@ -83,7 +83,7 @@ STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfro 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; } + { i_valdrop(self->data); ++self->data; --cdeq_rep_(self)->size; } STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return self->data + cdeq_rep_(self)->size - 1; } STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } @@ -106,7 +106,7 @@ _cx_memb(_with_capacity)(const size_t n) { STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_value* p = &self->data[--cdeq_rep_(self)->size]; - i_valdel(p); + i_valdrop(p); } STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const size_t idx) { @@ -175,7 +175,7 @@ _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_valraw raw) { } #endif // !c_no_clone -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { @@ -201,9 +201,9 @@ _cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, 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)); + _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); } -#endif // !c_no_compare +#endif // !c_no_cmp #endif // _i_queue /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -224,8 +224,9 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { struct cdeq_rep* rep = cdeq_rep_(self); if (rep->cap) { - for (_cx_value *p = self->data, *q = p + rep->size; p != q; ++p) - i_valdel(p); + for (_cx_value *p = self->data, *q = p + rep->size; p != q; ) { + --q; i_valdrop(q); + } rep->size = 0; } } @@ -242,7 +243,7 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { } STC_DEF void -_cx_memb(_del)(_cx_self* self) { +_cx_memb(_drop)(_cx_self* self) { _cx_memb(_clear)(self); if (cdeq_rep_(self)->cap) c_free(cdeq_rep_(self)); @@ -357,7 +358,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { const size_t n = p2 - p1; if (n > 0) { _cx_value* p = p1, *end = self->data + cdeq_rep_(self)->size; - for (; p != p2; ++p) i_valdel(p); + for (; p != p2; ++p) { i_valdrop(p); } if (p1 == self->data) self->data += n; else memmove(p1, p2, (end - p2) * sizeof(i_val)); cdeq_rep_(self)->size -= n; @@ -385,7 +386,7 @@ _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, } #endif // !c_option(c_no_clone) -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { @@ -397,12 +398,12 @@ _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { } STC_DEF int -_cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y) { +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { i_valraw rx = i_valto(x); i_valraw ry = i_valto(y); return i_cmp(&rx, &ry); } -#endif // !c_no_compare +#endif // !c_no_cmp #endif // !_i_queue #endif // IMPLEMENTATION #include "template.h" diff --git a/include/stc/clist.h b/include/stc/clist.h index 7cd2df50..c239fdd9 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -91,15 +91,16 @@ typedef i_valraw _cx_rawvalue; STC_API size_t _clist_count(const clist_VOID* self); -STC_API void _cx_memb(_del)(_cx_self* self); +STC_API void _cx_memb(_drop)(_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); -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) 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); +STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); #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); @@ -114,14 +115,13 @@ 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 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } #endif STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } @@ -129,8 +129,7 @@ STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { return tr 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(_clear)(_cx_self* self) { _cx_memb(_drop)(self); } 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; } @@ -166,7 +165,7 @@ _cx_memb(_splice_range)(_cx_self* self, _cx_iter it, return _cx_memb(_splice)(self, it, &tmp); } -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) 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); @@ -197,7 +196,7 @@ _cx_memb(_clone)(_cx_self cx) { #endif STC_DEF void -_cx_memb(_del)(_cx_self* self) { +_cx_memb(_drop)(_cx_self* self) { while (self->last) _cx_memb(_erase_after_)(self, self->last); } @@ -250,7 +249,7 @@ _cx_memb(_erase_after_)(_cx_self* self, _cx_node* node) { node->next = next; if (del == next) self->last = node = NULL; else if (self->last == del) self->last = node, node = NULL; - i_valdel(&del->value); c_free(del); + i_valdrop(&del->value); c_free(del); return node; } @@ -280,7 +279,7 @@ _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2) { return cx; } -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_valraw val) { @@ -321,7 +320,14 @@ _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 // !c_no_compare + +STC_DEF int +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { + i_valraw rx = i_valto(x); + i_valraw ry = i_valto(y); + return i_cmp(&rx, &ry); +} +#endif // !c_no_cmp #endif // TEMPLATE IMPLEMENTATION @@ -336,7 +342,7 @@ _clist_count(const clist_VOID* self) { return n; } -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) // Singly linked list Mergesort implementation by Simon Tatham. O(n*log n). // https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html @@ -387,7 +393,7 @@ _clist_mergesort(clist_VOID_node *list, int (*cmp)(const clist_VOID_node*, const insize *= 2; } } -#endif // !c_no_compare +#endif // !c_no_cmp #endif // NON-TEMPLATE IMPLEMENTATION #include "template.h" #define CLIST_H_INCLUDED diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 3d1915d3..10e9c586 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -31,7 +31,7 @@ #include int main(void) { - c_autovar (cmap_ichar m = cmap_ichar_init(), cmap_ichar_del(&m)) + c_autovar (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m)) { cmap_ichar_emplace(&m, 5, 'a'); cmap_ichar_emplace(&m, 8, 'b'); @@ -91,7 +91,7 @@ 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(_drop)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t capacity); STC_API chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr); @@ -121,7 +121,7 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) return _cx_memb(_insert_or_assign)(self, key, mapped); } - STC_INLINE const _cx_mapped* + STC_INLINE _cx_mapped* _cx_memb(_at)(const _cx_self* self, i_keyraw rkey) { chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); assert(self->_hashx[b.idx]); @@ -132,13 +132,14 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) #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); + _cx_memb(_drop)(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_value +_cx_memb(_value_clone)(_cx_value _val) { + *_i_keyref(&_val) = i_keyfrom(i_keyto(_i_keyref(&_val))); + _i_MAP_ONLY( _val.second = i_valfrom(i_valto(&_val.second)); ) + return _val; } STC_INLINE _cx_result @@ -159,16 +160,16 @@ _cx_memb(_value_toraw)(_cx_value* val) { } STC_INLINE void -_cx_memb(_value_del)(_cx_value* _val) { - i_keydel(_i_keyref(_val)); - _i_MAP_ONLY( i_valdel(&_val->second); ) +_cx_memb(_value_drop)(_cx_value* _val) { + i_keydrop(_i_keyref(_val)); + _i_MAP_ONLY( i_valdrop(&_val->second); ) } STC_INLINE _cx_result _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) { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} - else { i_keydel(&_key); _i_MAP_ONLY( i_valdel(&_mapped); )} + else { i_keydrop(&_key); _i_MAP_ONLY( i_valdrop(&_mapped); )} return _res; } @@ -249,10 +250,10 @@ STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { if (self->size == 0) return; _cx_value* e = self->table, *end = e + self->bucket_count; uint8_t *hx = self->_hashx; - for (; e != end; ++e) if (*hx++) _cx_memb(_value_del)(e); + for (; e != end; ++e) if (*hx++) _cx_memb(_value_drop)(e); } -STC_DEF void _cx_memb(_del)(_cx_self* self) { +STC_DEF void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_wipe_)(self); c_free(self->_hashx); c_free((void *) self->table); @@ -269,7 +270,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { _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)); if (_res.inserted) _res.ref->first = _key; - else { i_keydel(&_key); i_valdel(&_res.ref->second); } + else { i_keydrop(&_key); i_valdrop(&_res.ref->second); } _res.ref->second = _mapped; return _res; } #if !c_option(c_no_clone) @@ -277,7 +278,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); if (_res.inserted) _res.ref->first = i_keyfrom(rkey); - else i_valdel(&_res.ref->second); + else i_valdrop(&_res.ref->second); _res.ref->second = i_valfrom(rmapped); return _res; } #endif @@ -323,7 +324,7 @@ _cx_memb(_clone)(_cx_self m) { }; _cx_value *e = m.table, *end = e + m.bucket_count, *dst = clone.table; for (uint8_t *hx = m._hashx; e != end; ++hx, ++e, ++dst) - if (*hx) _cx_memb(_value_clone)(dst, e); + if (*hx) *dst = _cx_memb(_value_clone)(*e); return clone; } #endif @@ -363,7 +364,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { const _cx_size _cap = self->bucket_count; _cx_value* _slot = self->table; uint8_t* _hashx = self->_hashx; - _cx_memb(_value_del)(&_slot[i]); + _cx_memb(_value_drop)(&_slot[i]); for (;;) { /* delete without leaving tombstone */ if (++j == _cap) j = 0; if (! _hashx[j]) diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 49aa2406..87be1e73 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -55,7 +55,7 @@ STC_INLINE bool _cx_memb(_resize)(_cx_self* self, const size_t len, i_val null) { if (!_cx_memb(_reserve)(self, len)) return false; const size_t n = self->size; - for (size_t i = len; i < n; ++i) i_valdel(&self->data[i]); + for (size_t i = len; i < n; ++i) { i_valdrop(&self->data[i]); } for (size_t i = n; i < len; ++i) self->data[i] = null; self->size = len; return true; @@ -71,10 +71,10 @@ STC_INLINE _cx_self _cx_memb(_with_capacity)(size_t cap) { STC_INLINE void _cx_memb(_clear)(_cx_self* self) { size_t i = self->size; self->size = 0; - while (i--) i_valdel(&self->data[i]); + while (i--) { i_valdrop(&self->data[i]); } } -STC_INLINE void _cx_memb(_del)(_cx_self* self) +STC_INLINE void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_clear)(self); c_free(self->data); } STC_INLINE size_t _cx_memb(_size)(_cx_self q) @@ -97,7 +97,7 @@ 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_value val) @@ -139,7 +139,7 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self q) { STC_DEF void _cx_memb(_erase_at)(_cx_self* self, size_t idx) { - i_valdel(&self->data[idx]); + i_valdrop(&self->data[idx]); size_t n = --self->size; self->data[idx] = self->data[n]; _cx_memb(_sift_down_)(self->data - 1, idx + 1, n); diff --git a/include/stc/cset.h b/include/stc/cset.h index d74a8ccc..91e703da 100644 --- a/include/stc/cset.h +++ b/include/stc/cset.h @@ -35,7 +35,7 @@ int main(void) { c_foreach (i, cset_sx, s) printf("set %d\n", *i.ref); - cset_sx_del(&s); + cset_sx_drop(&s); } */ diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 101e7399..6ba220ab 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -32,7 +32,7 @@ #include int main(void) { - c_autovar (csmap_sx m = csmap_sx_init(), csmap_sx_del(&m)) + c_autovar (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) { csmap_sx_emplace(&m, "Testing one", 1.234); csmap_sx_emplace(&m, "Testing two", 12.34); @@ -97,7 +97,7 @@ 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 void _cx_memb(_drop)(_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); STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, i_keyraw rkey); @@ -112,7 +112,7 @@ STC_API void _cx_memb(_next)(_cx_iter* it); STC_INLINE bool _cx_memb(_empty)(_cx_self tree) { return _csmap_rep(&tree)->size == 0; } STC_INLINE size_t _cx_memb(_size)(_cx_self tree) { return _csmap_rep(&tree)->size; } STC_INLINE size_t _cx_memb(_capacity)(_cx_self tree) { return _csmap_rep(&tree)->cap; } -STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); *self = _cx_memb(_init)(); } +STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); } STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) { c_swap(_cx_self, *a, *b); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it) != NULL; } @@ -134,10 +134,16 @@ _cx_memb(_value_toraw)(_cx_value* val) { _i_MAP_ONLY( c_make(_cx_rawvalue){i_keyto(&val->first), i_valto(&val->second)} ); } +STC_INLINE int +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { + _cx_rawkey rx = i_keyto(_i_keyref(x)), ry = i_keyto(_i_keyref(y)); + return i_cmp(&rx, &ry); +} + STC_INLINE void -_cx_memb(_value_del)(_cx_value* val) { - i_keydel(_i_keyref(val)); - _i_MAP_ONLY( i_valdel(&val->second); ) +_cx_memb(_value_drop)(_cx_value* val) { + i_keydrop(_i_keyref(val)); + _i_MAP_ONLY( i_valdrop(&val->second); ) } #ifndef _i_isset @@ -150,7 +156,7 @@ _cx_memb(_value_del)(_cx_value* val) { _cx_memb(_put)(_cx_self* self, i_key key, i_val mapped) { return _cx_memb(_insert_or_assign)(self, key, mapped); } - STC_INLINE const _cx_mapped* + STC_INLINE _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 @@ -166,13 +172,14 @@ _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) { 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); + _cx_memb(_drop)(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_value +_cx_memb(_value_clone)(_cx_value _val) { + *_i_keyref(&_val) = i_keyfrom(i_keyto(_i_keyref(&_val))); + _i_MAP_ONLY( _val.second = i_valfrom(i_valto(&_val.second)); ) + return _val; } STC_INLINE _cx_result @@ -190,7 +197,7 @@ STC_INLINE _cx_result _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) { *_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} - else { i_keydel(&key); _i_MAP_ONLY( i_valdel(&mapped); )} + else { i_keydrop(&key); _i_MAP_ONLY( i_valdrop(&mapped); )} return res; } @@ -279,7 +286,7 @@ _cx_memb(_node_new_)(_cx_self* self, int level) { _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)); if (res.inserted) res.ref->first = key; - else { i_keydel(&key); i_valdel(&res.ref->second); } + else { i_keydrop(&key); i_valdrop(&res.ref->second); } res.ref->second = mapped; return res; } #if !c_option(c_no_clone) @@ -287,7 +294,7 @@ _cx_memb(_node_new_)(_cx_self* self, int level) { _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { _cx_result res = _cx_memb(_insert_entry_)(self, rkey); if (res.inserted) res.ref->first = i_keyfrom(rkey); - else i_valdel(&res.ref->second); + else i_valdrop(&res.ref->second); res.ref->second = i_valfrom(rmapped); return res; } #endif @@ -404,7 +411,7 @@ _cx_memb(_erase_r_)(_cx_node *d, _cx_size tn, const _cx_rawkey* rkey, int *erase d[tn].link[c < 0] = _cx_memb(_erase_r_)(d, d[tn].link[c < 0], rkey, erased); else { if (!(*erased)++) - _cx_memb(_value_del)(&d[tn].value); + _cx_memb(_value_drop)(&d[tn].value); if (d[tn].link[0] && d[tn].link[1]) { tx = d[tn].link[0]; while (d[tx].link[1]) @@ -470,7 +477,7 @@ STC_DEF _cx_size _cx_memb(_clone_r_)(_cx_self* self, _cx_node* src, _cx_size sn) { if (sn == 0) return 0; _cx_size tx, tn = _cx_memb(_node_new_)(self, src[sn].level); - _cx_memb(_value_clone)(&self->nodes[tn].value, &src[sn].value); + self->nodes[tn].value = _cx_memb(_value_clone)(src[sn].value); tx = _cx_memb(_clone_r_)(self, src, src[sn].link[0]); self->nodes[tn].link[0] = tx; tx = _cx_memb(_clone_r_)(self, src, src[sn].link[1]); self->nodes[tn].link[1] = tx; return tn; @@ -491,12 +498,12 @@ _cx_memb(_del_r_)(_cx_node* d, _cx_size tn) { if (tn) { _cx_memb(_del_r_)(d, d[tn].link[0]); _cx_memb(_del_r_)(d, d[tn].link[1]); - _cx_memb(_value_del)(&d[tn].value); + _cx_memb(_value_drop)(&d[tn].value); } } STC_DEF void -_cx_memb(_del)(_cx_self* self) { +_cx_memb(_drop)(_cx_self* self) { if (_csmap_rep(self)->root) { _cx_memb(_del_r_)(self->nodes, (_cx_size) _csmap_rep(self)->root); c_free(_csmap_rep(self)); diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 4753ef12..b66cd4d7 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -26,25 +26,25 @@ typedef struct { cstr name, last; } Person; -Person Person_from(const char* name, const char* last) { +Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } -void Person_del(Person* p) { - printf("del: %s %s\n", p->name.str, p->last.str); - c_del(cstr, &p->name, &p->last); +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); } #define i_tag person #define i_val Person -#define i_valdel Person_del +#define i_valdrop Person_drop #include int main() { - csptr_person p = csptr_person_new(Person_from("John", "Smiths")); + csptr_person p = csptr_person_new(Person_new("John", "Smiths")); csptr_person q = csptr_person_clone(p); // share the pointer printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count); - c_del(csptr_person, &p, &q); + c_drop(csptr_person, &p, &q); } */ @@ -76,6 +76,7 @@ int main() { #endif #define _i_has_internal_clone #include "template.h" +typedef i_valraw _cx_rawvalue; #if !c_option(c_no_atomic) #define _i_atomic_inc(v) c_atomic_inc(v) @@ -132,9 +133,9 @@ _cx_memb(_move)(_cx_self* self) { } STC_INLINE void -_cx_memb(_del)(_cx_self* self) { +_cx_memb(_drop)(_cx_self* self) { if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { - i_valdel(self->get); + i_valdrop(self->get); if (self->get != &((_cx_csptr_rep *)self->use_count)->value) c_free(self->get); c_free(self->use_count); @@ -143,19 +144,19 @@ _cx_memb(_del)(_cx_self* self) { STC_INLINE void _cx_memb(_reset)(_cx_self* self) { - _cx_memb(_del)(self); + _cx_memb(_drop)(self); self->use_count = NULL, self->get = NULL; } STC_INLINE void _cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { - _cx_memb(_del)(self); + _cx_memb(_drop)(self); *self = _cx_memb(_with)(p); } STC_INLINE void _cx_memb(_reset_new)(_cx_self* self, i_val val) { - _cx_memb(_del)(self); + _cx_memb(_drop)(self); *self = _cx_memb(_new)(val); } @@ -164,47 +165,48 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { return _cx_memb(_new)(i_valfrom(raw)); } - STC_INLINE void - _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) { - _cx_memb(_del)(self); - *self = _cx_memb(_new)(i_valfrom(raw)); + STC_INLINE i_valraw + _cx_memb(_toraw)(const _cx_self* self) { + return i_valto(self->get); } #endif STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); - _cx_memb(_del)(self); *self = ptr; + _cx_memb(_drop)(self); *self = ptr; } STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self ptr) { - if (self->get != ptr.get) _cx_memb(_del)(self); + if (self->get != ptr.get) _cx_memb(_drop)(self); *self = ptr; } STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self, size_t n) { - #if (c_option(c_no_compare) || defined _i_default_compare) && SIZE_MAX >> 32 + #if c_option(c_no_cmp) && SIZE_MAX >> 32 return c_hash64(&self->get, 8); - #elif (c_option(c_no_compare) || defined _i_default_compare) + #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); #else - i_valraw raw = i_valto(self->get); - return i_hash(&raw, sizeof raw); + return i_hash(self->get, sizeof *self->get); #endif } STC_INLINE int -_cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { - #if (c_option(c_no_compare) || defined _i_default_compare) - return (int)(x->get - y->get); +_cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { + #if c_option(c_no_cmp) + return c_default_cmp(&x->get, &y->get); #else - i_valraw rx = i_valto(x->get); - i_valraw ry = i_valto(y->get); - return i_cmp(&rx, &ry); + return i_cmp(x->get, y->get); #endif } + +STC_INLINE bool +_cx_memb(_equalto)(const _cx_self* x, const _cx_self* y) { + return !_cx_memb(_cmp)(x, y); +} #undef _i_atomic_inc #undef _i_atomic_dec_and_test -#include "template.h" \ No newline at end of file +#include "template.h" diff --git a/include/stc/csset.h b/include/stc/csset.h index e4558192..07cf4b17 100644 --- a/include/stc/csset.h +++ b/include/stc/csset.h @@ -38,7 +38,7 @@ int main(void) { c_foreach (k, csset_i, s) printf("set %d\n", *k.ref); - csset_i_del(&s); + csset_i_drop(&s); } */ diff --git a/include/stc/cstack.h b/include/stc/cstack.h index c1170f79..d43afe29 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -54,11 +54,11 @@ STC_INLINE _cx_self _cx_memb(_with_size)(size_t size, i_val fill) { STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_value *p = self->data + self->size; - while (p-- != self->data) i_valdel(p); + while (p-- != self->data) { i_valdrop(p); } self->size = 0; } -STC_INLINE void _cx_memb(_del)(_cx_self* self) +STC_INLINE void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_clear)(self); c_free(self->data); } STC_INLINE size_t _cx_memb(_size)(_cx_self v) @@ -74,7 +74,7 @@ STC_INLINE _cx_value* _cx_memb(_top)(const _cx_self* self) { return &self->data[self->size - 1]; } STC_INLINE void _cx_memb(_pop)(_cx_self* self) - { _cx_value* p = &self->data[--self->size]; i_valdel(p); } + { _cx_value* p = &self->data[--self->size]; i_valdrop(p); } STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { if (n < self->size) return true; @@ -107,7 +107,7 @@ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) diff --git a/include/stc/cstr.h b/include/stc/cstr.h index a46de3c3..730f4d16 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -68,6 +68,7 @@ STC_API int c_strncasecmp(const char* s1, const char* s2, size_t nma STC_INLINE cstr cstr_init() { return cstr_null; } #define cstr_str(self) (self)->str +#define cstr_toraw(self) (self)->str #define cstr_new(literal) \ cstr_from_n(literal, sizeof c_make(c_strlit){literal} - 1) STC_INLINE cstr cstr_from(const char* str) @@ -77,7 +78,7 @@ STC_INLINE size_t cstr_size(cstr s) { return _cstr_rep(&s)->size; } STC_INLINE size_t cstr_length(cstr s) { return _cstr_rep(&s)->size; } STC_INLINE size_t cstr_capacity(cstr s) { return _cstr_rep(&s)->cap; } STC_INLINE bool cstr_empty(cstr s) { return _cstr_rep(&s)->size == 0; } -STC_INLINE void cstr_del(cstr* self) +STC_INLINE void cstr_drop(cstr* self) { if (_cstr_rep(self)->cap) c_free(_cstr_rep(self)); } STC_INLINE cstr cstr_clone(cstr s) { return cstr_from_n(s.str, _cstr_rep(&s)->size); } @@ -166,7 +167,7 @@ cstr_ends_with(cstr s, const char* sub) { } /* container adaptor functions: */ -#define cstr_compare(xp, yp) strcmp((xp)->str, (yp)->str) +#define cstr_cmp(xp, yp) strcmp((xp)->str, (yp)->str) #define cstr_equalto(xp, yp) (strcmp((xp)->str, (yp)->str) == 0) #define cstr_hash(xp, dummy) c_strhash((xp)->str) @@ -249,7 +250,7 @@ cstr_printf(cstr* self, const char* fmt, ...) { va_start(args, fmt); int n = cstr_vfmt(&ret, fmt, args); va_end(args); - cstr_del(self); + cstr_drop(self); *self = ret; return n; } diff --git a/include/stc/csview.h b/include/stc/csview.h index 872b6e1e..ac120e15 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -114,9 +114,13 @@ STC_INLINE bool cstr_ends_with_v(cstr s, csview sub) /* ---- Container helper functions ---- */ -#define csview_compare(xp, yp) strcmp((xp)->str, (yp)->str) +STC_INLINE int csview_cmp(const csview* x, const csview* y) { + const size_t m = x->size < y->size ? x->size : y->size; + const int c = memcmp(x->str, y->str, m); + return c ? c : x->size - y->size; + } #define csview_hash(xp, dummy) c_strhash((xp)->str) -#define csview_equalto(xp, yp) (strcmp((xp)->str, (yp)->str) == 0) +#define csview_equalto(xp, yp) (csview_cmp(xp, yp) == 0) /* -------------------------- IMPLEMENTATION ------------------------- */ diff --git a/include/stc/cvec.h b/include/stc/cvec.h index f64f7840..01143d25 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -46,15 +46,15 @@ struct MyStruct { int main() { cvec_i32 vec = cvec_i32_init(); cvec_i32_push_back(&vec, 123); - cvec_i32_del(&vec); + cvec_i32_drop(&vec); cvec_float fvec = cvec_float_init(); cvec_float_push_back(&fvec, 123.3); - cvec_float_del(&fvec); + cvec_float_drop(&fvec); cvec_str svec = cvec_str_init(); cvec_str_emplace_back(&svec, "Hello, friend"); - cvec_str_del(&svec); + cvec_str_drop(&svec); } */ @@ -79,7 +79,7 @@ struct cvec_rep { size_t size, cap; void* data[]; }; typedef i_valraw _cx_rawvalue; STC_API _cx_self _cx_memb(_init)(void); -STC_API void _cx_memb(_del)(_cx_self* self); +STC_API void _cx_memb(_drop)(_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 null); @@ -87,8 +87,8 @@ 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); +#if !c_option(c_no_cmp) +STC_API int _cx_memb(_value_cmp)(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 @@ -107,7 +107,7 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw 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); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } STC_INLINE _cx_iter _cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) { @@ -136,7 +136,7 @@ STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->da STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return self->data + cvec_rep_(self)->size - 1; } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) - { _cx_value* p = &self->data[--cvec_rep_(self)->size]; i_valdel(p); } + { _cx_value* p = &self->data[--cvec_rep_(self)->size]; i_valdrop(p); } 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) @@ -197,7 +197,7 @@ _cx_memb(_at)(const _cx_self* self, const size_t idx) { return self->data + idx; } -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_valraw raw) { @@ -226,9 +226,9 @@ _cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, } 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)); + _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); } -#endif // !c_no_compare +#endif // !c_no_cmp /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) || defined(i_imp) @@ -246,14 +246,15 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { struct cvec_rep* rep = cvec_rep_(self); if (rep->cap) { - for (_cx_value *p = self->data, *q = p + rep->size; p != q; ++p) - i_valdel(p); + for (_cx_value *p = self->data, *q = p + rep->size; p != q; ) { + --q; i_valdrop(q); + } rep->size = 0; } } STC_DEF void -_cx_memb(_del)(_cx_self* self) { +_cx_memb(_drop)(_cx_self* self) { _cx_memb(_clear)(self); if (cvec_rep_(self)->cap) c_free(cvec_rep_(self)); @@ -263,7 +264,7 @@ STC_DEF bool _cx_memb(_reserve)(_cx_self* self, const size_t cap) { struct cvec_rep* rep = cvec_rep_(self); const size_t len = rep->size; - if (cap > rep->cap || cap && cap == len) { + if (cap > rep->cap || (cap && cap == len)) { rep = (struct cvec_rep*) c_realloc(rep->cap ? rep : NULL, offsetof(struct cvec_rep, data) + cap*sizeof(i_val)); if (!rep) return false; @@ -279,7 +280,7 @@ _cx_memb(_resize)(_cx_self* self, const size_t len, i_val null) { if (!_cx_memb(_reserve)(self, len)) return false; struct cvec_rep *rep = cvec_rep_(self); const size_t n = rep->size; - for (size_t i = len; i < n; ++i) i_valdel(&self->data[i]); + for (size_t i = len; i < n; ++i) { i_valdrop(&self->data[i]); } for (size_t i = n; i < len; ++i) self->data[i] = null; if (rep->cap) rep->size = len; return true; @@ -320,7 +321,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { intptr_t len = p2 - p1; if (len > 0) { _cx_value* p = p1, *end = self->data + cvec_rep_(self)->size; - for (; p != p2; ++p) i_valdel(p); + for (; p != p2; ++p) { i_valdrop(p); } memmove(p1, p2, (end - p2) * sizeof(i_val)); cvec_rep_(self)->size -= len; } @@ -356,7 +357,7 @@ _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, } #endif -#if !c_option(c_no_compare) +#if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { @@ -381,12 +382,12 @@ _cx_memb(_bsearch_in)(_cx_iter i1, _cx_iter i2, i_valraw raw) { } STC_DEF int -_cx_memb(_value_compare)(const _cx_value* x, const _cx_value* y) { +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { i_valraw rx = i_valto(x); i_valraw ry = i_valto(y); return i_cmp(&rx, &ry); } -#endif // !c_no_compare +#endif // !c_no_cmp #endif #include "template.h" #define CVEC_H_INCLUDED diff --git a/include/stc/template.h b/include/stc/template.h index 85c4a940..61befb2b 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -40,19 +40,13 @@ #define _cx_size _cx_memb(_size_t) #endif -#if defined i_valraw && !(defined i_valto && defined i_valfrom) - #error "if i_valraw or i_valto defined, i_valfrom must be defined" -#endif -#if defined i_keyraw && !(defined i_keyto && defined i_keyfrom) - #error "if i_keyraw or i_keyto defined, i_keyfrom a must be defined" -#endif -#ifdef i_key_csptr // [deprecated] - #define i_key_ref i_key_csptr - #error "i_key_csptr no longer supported: use new name i_key_ref" +#if defined i_key_csptr || defined i_key_ref // [deprecated] + #define i_key_bind i_key_csptr + #error "i_key_csptr/ref no longer supported: use new name i_key_bind" #endif -#ifdef i_val_csptr // [deprecated] - #define i_val_ref i_val_csptr - #error "i_val_csptr no longer supported: use new name i_val_ref" +#if defined i_val_csptr || defined i_val_ref // [deprecated] + #define i_val_bind i_val_csptr + #error "i_val_sptr/ref no longer supported: use new name i_val_bind" #endif #ifdef i_cnt // [deprecated] #define i_type i_cnt @@ -69,46 +63,53 @@ #include "cstr.h" #endif -#if defined i_key_ref - #define i_key i_key_ref - #define i_keyfrom c_PASTE(i_key, _clone) - #ifndef i_cmp - #define i_cmp c_PASTE(i_key, _compare) - #endif - #ifndef i_hash - #define i_hash c_PASTE(i_key, _hash) - #endif - #ifndef i_keydel - #define i_keydel c_PASTE(i_key, _del) - #endif - -#elif defined i_key_str - - #define i_key cstr - #define i_keyfrom cstr_from - #define i_keyto cstr_str - #define i_keyraw const char* +#ifdef i_key_str + #define i_key_bind cstr + #define i_keyraw c_rawstr #ifndef i_tag #define i_tag str #endif - #ifndef i_cmp - #define i_cmp c_rawstr_compare +#endif + +#ifdef i_key_bind + #define i_key i_key_bind + #ifndef i_keyraw + #ifndef i_keyfrom + #define i_keyfrom c_PASTE(i_key, _clone) + #endif + #else + #ifndef i_keyfrom + #define i_keyfrom c_PASTE(i_key, _from) + #endif + #ifndef i_keyto + #define i_keyto c_PASTE(i_key, _toraw) + #endif + #endif + #ifndef i_cmp + #define i_cmp c_PASTE(i_keyraw, _cmp) + #endif + #ifndef i_equ + #define i_equ c_PASTE(i_keyraw, _equalto) #endif #ifndef i_hash - #define i_hash c_rawstr_hash + #define i_hash c_PASTE(i_keyraw, _hash) #endif - #if !defined i_keydel - #define i_keydel cstr_del + #ifndef i_keydrop + #define i_keydrop c_PASTE(i_key, _drop) #endif #endif -/* Resolve i_del and i_from here */ -#if defined i_del && defined i_isset - #define i_keydel i_del -#elif defined i_del && !defined i_key - #define i_valdel i_del -#elif defined i_del - #error "i_del not supported for maps, define i_keydel / i_valdel instead." +#if defined i_keyraw && !(defined i_keyto && defined i_keyfrom) + #error "if i_keyraw defined, i_keyfrom and i_keyto must be defined" +#endif + +/* Resolve i_drop and i_from here */ +#if defined i_drop && defined i_isset + #define i_keydrop i_drop +#elif defined i_drop && !defined i_key + #define i_valdrop i_drop +#elif defined i_drop + #error "i_drop not supported for maps, define i_keydrop / i_valdrop instead." #endif #if defined i_from && defined i_isset #define i_keyfrom i_from @@ -118,33 +119,40 @@ #error "i_from not supported for maps, define i_keyfrom / i_valfrom instead." #endif -#if defined i_val_ref - #define i_val i_val_ref - #define i_valfrom c_PASTE(i_val, _clone) - #if !defined i_cmp && !defined i_key - #define i_cmp c_PASTE(i_val, _compare) - #endif - #if !defined i_valdel - #define i_valdel c_PASTE(i_val, _del) +#ifdef i_val_str + #define i_val_bind cstr + #define i_valraw c_rawstr + #if !defined i_tag && !defined i_key + #define i_tag str #endif +#endif -#elif defined i_val_str - - #define i_val cstr - #define i_valfrom cstr_from - #define i_valto cstr_str - #define i_valraw const char* - #if !defined i_tag && !defined i_key - #define i_tag str +#ifdef i_val_bind + #define i_val i_val_bind + #ifndef i_valraw + #ifndef i_valfrom + #define i_valfrom c_PASTE(i_val, _clone) + #endif + #else + #ifndef i_valfrom + #define i_valfrom c_PASTE(i_val, _from) + #endif + #ifndef i_valto + #define i_valto c_PASTE(i_val, _toraw) + #endif #endif #if !defined i_cmp && !defined i_key - #define i_cmp c_rawstr_compare + #define i_cmp c_PASTE(i_valraw, _cmp) #endif - #if !defined i_valdel - #define i_valdel cstr_del + #ifndef i_valdrop + #define i_valdrop c_PASTE(i_val, _drop) #endif #endif +#if defined i_valraw && !(defined i_valto && defined i_valfrom) + #error "if i_valraw defined, i_valfrom and i_valto must be defined" +#endif + #ifdef i_key #ifdef _i_isset #define i_val i_key @@ -152,8 +160,8 @@ #ifndef i_tag #define i_tag i_key #endif - #if !defined _i_has_internal_clone && defined i_keydel && !defined i_keyfrom && !c_option(c_no_clone) - #error "i_keydel defined but not i_keyfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" + #if !defined _i_has_internal_clone && defined i_keydrop && !defined i_keyfrom && !c_option(c_no_clone) + #error "i_keydrop defined but not i_keyfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" #endif #if !defined i_keyfrom #define i_keyfrom c_default_clone @@ -167,8 +175,8 @@ #elif !defined i_equ #define i_equ c_default_equalto #endif - #ifndef i_keydel - #define i_keydel c_default_del + #ifndef i_keydrop + #define i_keydrop c_default_drop #endif #elif defined _i_isset #error "i_key define is missing." @@ -177,8 +185,8 @@ #ifndef i_tag #define i_tag i_val #endif -#if !defined _i_has_internal_clone && defined i_valdel && !defined i_valfrom && !c_option(c_no_clone) - #error "i_valdel/i_del defined but not i_valfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" +#if !defined _i_has_internal_clone && defined i_valdrop && !defined i_valfrom && !c_option(c_no_clone) + #error "i_valdrop/i_drop defined but not i_valfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" #endif #if !defined i_valfrom #define i_valfrom c_default_clone @@ -187,12 +195,11 @@ #define i_valraw i_val #define i_valto c_default_toraw #endif -#ifndef i_valdel - #define i_valdel c_default_del +#ifndef i_valdrop + #define i_valdrop c_default_drop #endif #ifndef i_cmp - #define _i_default_compare - #define i_cmp c_default_compare + #define i_cmp c_default_cmp #endif #ifndef i_hash #define i_hash c_default_hash @@ -205,29 +212,28 @@ #undef i_imp #undef i_opt #undef i_cmp -#undef i_del +#undef i_drop #undef i_equ #undef i_hash #undef i_from #undef i_val #undef i_val_str -#undef i_val_ref -#undef i_valdel +#undef i_val_bind +#undef i_valdrop #undef i_valraw #undef i_valfrom #undef i_valto #undef i_key #undef i_key_str -#undef i_key_ref -#undef i_keydel +#undef i_key_bind +#undef i_keydrop #undef i_keyraw #undef i_keyfrom #undef i_keyto #undef _i_prefix -#undef _i_default_compare #undef _i_has_internal_clone #undef _i_template #endif -- cgit v1.2.3 From 3fe68afddf494d6ac72f8919b2739e80774cffe8 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 13:19:25 +0100 Subject: Improved box.c and added a corresponding sptr.c example. --- examples/box.c | 41 ++++++++++++++++++++++------------- examples/sptr.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 examples/sptr.c diff --git a/examples/box.c b/examples/box.c index d400799b..598d0bdc 100644 --- a/examples/box.c +++ b/examples/box.c @@ -23,38 +23,49 @@ void Person_drop(Person* p) { c_drop(cstr, &p->name, &p->last); } -#define i_type PPtr +#define i_type PBox #define i_val_bind Person // binds Person_cmp, ... #include #define i_type Persons -#define i_val_bind PPtr // binds PPtr_cmp, ... +#define i_val_bind PBox // binds PBox_cmp, ... #include int main() { c_auto (Persons, vec) - c_auto (PPtr, p, q) + c_auto (PBox, p, q) { - p = PPtr_new(Person_new("Dave", "Cooper")); + p = PBox_new(Person_new("Laura", "Palmer")); - q = PPtr_clone(p); - cstr_assign(&q.get->name, "Dale"); + q = PBox_clone(p); + cstr_assign(&q.get->name, "Leland"); - printf("%s %s.\n", p.get->name.str, p.get->last.str); - printf("%s %s.\n", q.get->name.str, q.get->last.str); + printf("orig: %s %s\n", p.get->name.str, p.get->last.str); + printf("copy: %s %s\n", q.get->name.str, q.get->last.str); - Persons_push_back(&vec, PPtr_new(Person_new("Laura", "Palmer"))); - Persons_push_back(&vec, PPtr_new(Person_new("Shelly", "Johnson"))); + Persons_push_back(&vec, PBox_new(Person_new("Dale", "Cooper"))); + Persons_push_back(&vec, PBox_new(Person_new("Audrey", "Home"))); + + // NB! Clone p and q to the vector using emplace_back() + c_apply(Persons, emplace_back, &vec, {p, q}); c_foreach (i, Persons, vec) - printf("%s: %s\n", i.ref->get->name.str, i.ref->get->last.str); + printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); + puts(""); - // Look-up Shelly! - c_autovar (Person s = Person_new("Shelly", "Johnson"), Person_drop(&s)) { - const PPtr *v = Persons_get(&vec, (PPtr){&s}); - if (v) printf("found: %s: %s\n", v->get->name.str, v->get->last.str); + // Look-up Audrey! Use a (fake) temporary PBox for lookup. + c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { + const PBox *v = Persons_get(&vec, (PBox){&a}); + if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); } + puts(""); + + // Alternative to use cbox (when not placed in container). + Person *she = c_new(Person, Person_new("Shelly", "Johnson")); + printf("%s %s\n", she->name.str, she->last.str); + c_delete(Person, she); // drop and free + puts(""); } } diff --git a/examples/sptr.c b/examples/sptr.c new file mode 100644 index 00000000..7e0f7357 --- /dev/null +++ b/examples/sptr.c @@ -0,0 +1,66 @@ +/* cbox: heap allocated boxed type */ +#include + +typedef struct { cstr name, last; } Person; + +Person Person_new(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} + +int Person_cmp(const Person* a, const Person* b) { + int c = strcmp(a->name.str, b->name.str); + return c ? c : strcmp(a->last.str, b->last.str); +} + +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} + +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); +} + +#define i_type PSPtr +#define i_val_bind Person // binds Person_cmp, ... +#include + +#define i_type Persons +#define i_val_bind PSPtr // binds PSPtr_cmp, ... +#include + + +int main() +{ + c_auto (Persons, vec) + c_auto (PSPtr, p, q) + { + p = PSPtr_new(Person_new("Laura", "Palmer")); + + // We want a deep copy -- PSPtr_clone(p) only shares! + q = PSPtr_new(Person_clone(*p.get)); + cstr_assign(&q.get->name, "Leland"); + + printf("orig: %s %s\n", p.get->name.str, p.get->last.str); + printf("copy: %s %s\n", q.get->name.str, q.get->last.str); + + Persons_push_back(&vec, PSPtr_new(Person_new("Dale", "Cooper"))); + Persons_push_back(&vec, PSPtr_new(Person_new("Audrey", "Home"))); + + // NB! Clone/share p and q to the vector using emplace_back() + c_apply(Persons, emplace_back, &vec, {p, q}); + + c_foreach (i, Persons, vec) + printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); + puts(""); + + // Look-up Audrey! Use a (fake) temporary PSPtr for lookup. + c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { + const PSPtr *v = Persons_get(&vec, (PSPtr){&a}); + if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); + } + puts(""); + } +} -- cgit v1.2.3 From fd9386222ab102fac57834646b34d4a5014b1588 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 13:58:03 +0100 Subject: Update wrong info in doc. --- examples/sptr_erase.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c index d08b9072..240b9a58 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -4,12 +4,13 @@ void show_drop(int* x) { printf("drop: %d\n", *x); } #define i_type Arc #define i_val int -#define i_drop show_drop // this "destroy" func shows which elements are destroyed -// csptr/cbox will use pointer address comparison of i_val if no i_cmp func is specified, -// or 'i_opt c_no_cmp' is defined, otherwise i_cmp is used to compare object values. -// See the different results by commenting out the next line. -//#define i_cmp(x, y) (*(x) - *(y)) -#include // Arc: shared pointer to int +#define i_drop show_drop +// csptr/cbox will use pointer address comparison of i_val +// if 'i_opt c_no_cmp' is defined, otherwise i_cmp is used +// to compare object values. See the twodifferences by +// commenting out the next line. +//#define i_opt c_no_cmp +#include // Shared pointer to int #define i_type Vec #define i_val_bind Arc @@ -33,7 +34,7 @@ int main() printf(" %d", *i.ref->get); puts(""); - // erase vec.data[2]; or first matching value depending on compare. + printf("erase vec.data[2]; or first matching value depending on compare.\n"); Vec_iter it; it = Vec_find(&vec, vec.data[2]); if (it.ref != Vec_end(&vec).ref) -- cgit v1.2.3 From 09b696eab6ae640f6c1e07178d49fcd8646e1737 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 20:46:02 +0100 Subject: More docs, small example updates. --- README.md | 18 ++++++++++-------- docs/csmap_api.md | 2 +- examples/multimap.c | 31 +++++++++++++++---------------- examples/vikings.c | 6 +++--- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 9d1587a8..fb822b48 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ STC - Smart Template Containers for C News ---- -### Version 3.0 released. Migration guide for breaking changes from version 2.X: -There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_equalto*, and *Type_hash*. Only the functions required by the particular container needs to be defined, e.g. only **cmap** and **cset** require *Type_equalto* and *Type_hash* to be defined. -You may still define template parameters with `i_val` / `i_key` as before, which is easier for simple element types. +### Version 3.0 released +There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_equalto*, and *Type_hash*. Only the functions required by the particular container needs to be defined, e.g. only **cmap** and **cset** require *Type_equalto* and *Type_hash* to be defined. You can override these by defining `i_cmp`, `i_drop`, etc. +It's still possible define template parameters with `i_val` / `i_key` as before, which is easier for simple element types, as defaults will be assigned to missing functions. -Regex replace in VS Code: +Migration guide from version 2 to 3. Replace (regular expresion) in VS Code: - `_del\b` → `_drop` - `_compare\b` → `_cmp` -Whole word + Match case: +Replace (whole word + match case): - `i_keydel` → `i_keydrop` - `i_valdel` → `i_valdrop` - `i_cnt` → `i_type` @@ -29,7 +29,7 @@ Whole word + Match case: - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". - Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. - Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*. -- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_bind` / `i_val_bind` +- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_bind` / `i_val_bind` for types that has required functions defined. - Deprecated `i_cnt`. Use `i_type` instead to define the complete container type name. - Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` @@ -39,9 +39,11 @@ Whole word + Match case: Introduction ------------ STC is a modern, templated, user-friendly, fast, fully type-safe, and customizable container library for C99, -with a uniform API across the containers, and is similar to the c++ standard library containers API. +with a uniform API across the containers, and is similar to the c++ standard library containers API. It takes some +inspirations from Rust and Python too. + It is a compact, header-only library which includes the all the major "standard" data containers except for the -multimap/set variants. There are examples on how to create multimaps in the examples folder. +multimap/set variants. However, there are examples on how to create multimaps in the examples folder. For an introduction to templated containers, please read the blog by Ian Fisher on [type-safe generic data structures in C](https://iafisher.com/blog/2020/06/type-safe-generics-in-c). diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 88d58cd4..c4f0ff16 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -183,7 +183,7 @@ static int Vec3i_cmp(const Vec3i* a, const Vec3i* b) { #define i_key Vec3i #define i_val int -#define i_cmp Vec3i_cmp // uses c_default_hash +#define i_cmp Vec3i_cmp #define i_tag vi #include #include diff --git a/examples/multimap.c b/examples/multimap.c index 424ae606..472af8aa 100644 --- a/examples/multimap.c +++ b/examples/multimap.c @@ -35,6 +35,21 @@ struct OlympicsData { int year; const char *city, *country, *date; } ol_data[] = typedef struct { int year; cstr city, date; } OlympicLocation; +int OlympicLocation_cmp(OlympicLocation* a, OlympicLocation* b); +OlympicLocation OlympicLocation_clone(OlympicLocation loc); +void OlympicLocation_drop(OlympicLocation* self); + +// Create a clist, can be sorted by year. +#define i_val_bind OlympicLocation // binds _cmp, _clone and _drop. +#define i_tag OL +#include + +// Create a csmap where key is country name +#define i_key_str // binds cstr_equ, cstr_hash, cstr_clone, ++ +#define i_val_bind clist_OL // binds clist_OL_clone, clist_OL_drop +#define i_tag OL +#include + int OlympicLocation_cmp(OlympicLocation* a, OlympicLocation* b) { return a->year - b->year; } @@ -48,22 +63,6 @@ void OlympicLocation_drop(OlympicLocation* self) { c_drop(cstr, &self->city, &self->date); } -// Create a clist, can be sorted by year. -#define i_val OlympicLocation -#define i_cmp OlympicLocation_cmp -#define i_drop OlympicLocation_drop -#define i_from OlympicLocation_clone -#define i_tag OL -#include - -// Create a csmap where key is country name -#define i_key_str -#define i_val clist_OL -#define i_valdrop clist_OL_drop -#define i_valfrom clist_OL_clone -#define i_tag OL -#include - int main() { // Define the multimap with destructor defered to when block is completed. diff --git a/examples/vikings.c b/examples/vikings.c index 87977538..838598b5 100644 --- a/examples/vikings.c +++ b/examples/vikings.c @@ -36,12 +36,12 @@ static inline RViking Viking_toraw(const Viking* vk) { // With this in place, we define the Viking => int hash map type: #define i_type Vikings #define i_key_bind Viking -#define i_val int #define i_keyraw RViking -// i_key_bind auto-maps these functions: +#define i_val int +// i_key_bind auto-binds these functions: // #define i_hash Viking_hash // #define i_equ Viking_equalto -// #define i_keyfrom Viking_from // uses _from because i_keyraw is defined +// #define i_keyfrom Viking_from // uses _from (not _clone) because i_keyraw is defined // #define i_keyto Viking_toraw // #define i_keydrop Viking_drop #include -- cgit v1.2.3 From 0c3d711c2541aebe9a44fecb732e096bed14f72c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 21:39:25 +0100 Subject: Global rename of `_equ\b` => `_eq`. In practice `i_equ` must renamed to `i_eq` in user code if used. --- README.md | 33 +++++++++++++++++++++------------ docs/ccommon_api.md | 2 +- docs/cmap_api.md | 22 +++++++++++----------- docs/cset_api.md | 8 ++++---- docs/cstr_api.md | 4 ++-- docs/csview_api.md | 2 +- examples/rawptr_elements.c | 2 +- examples/vikings.c | 4 ++-- include/stc/alt/cstr.h | 2 +- include/stc/cbox.h | 2 +- include/stc/ccommon.h | 12 ++++++------ include/stc/cmap.h | 2 +- include/stc/csptr.h | 2 +- include/stc/cstr.h | 6 +++--- include/stc/csview.h | 2 +- include/stc/template.h | 24 ++++++++++++------------ 16 files changed, 69 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index fb822b48..6f3ceb77 100644 --- a/README.md +++ b/README.md @@ -6,21 +6,29 @@ STC - Smart Template Containers for C News ---- ### Version 3.0 released -There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_equalto*, and *Type_hash*. Only the functions required by the particular container needs to be defined, e.g. only **cmap** and **cset** require *Type_equalto* and *Type_hash* to be defined. You can override these by defining `i_cmp`, `i_drop`, etc. -It's still possible define template parameters with `i_val` / `i_key` as before, which is easier for simple element types, as defaults will be assigned to missing functions. +There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions +to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements +of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_hash*, +and *Type_eq*. Only the functions required by the particular container needs to be defined. e.g. **cmap** +and **cset** are the only types that requires *Type_hash* and *Type_eq* to be defined. +You may override these by defining `i_cmp`, `i_drop`, etc. Template parameters with `i_val` / `i_key` may +still be defined as before, which is often easier for simple element types. Migration guide from version 2 to 3. Replace (regular expresion) in VS Code: - `_del\b` → `_drop` - `_compare\b` → `_cmp` +- `_equ\b` → `_eq` Replace (whole word + match case): - `i_keydel` → `i_keydrop` - `i_valdel` → `i_valdrop` - `i_cnt` → `i_type` -- `i_key_csptr` → `i_key_bind` -- `i_val_csptr` → `i_val_bind` - `cstr_lit` → `cstr_new` - `csptr_X_make` → `csptr_X_new` +- `i_key_csptr` → `i_key_bind` +- `i_val_csptr` → `i_val_bind` +- `i_key_ref` → `i_key_bind` +- `i_val_ref` → `i_val_bind` ### Final version 2.1 - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. @@ -286,18 +294,19 @@ The list of template parameters: - `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`- defaults to `!i_cmp`. +- `i_cmp` - Three-way comparison of two `i_keyraw *` - **[required]** for non-integral `i_keyraw`. +- `i_hash` - Hash function taking `i_keyraw *` and a size - defaults to `!i_cmp`. +- `i_eq` - Equality comparison of two `i_keyraw *` - defaults to `!i_cmp`. Companion with `i_hash`. -- `i_keydrop` - Destroy map key func - defaults to empty destructor. +- `i_keydrop` - 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_keydrop` is defined. -- `i_keyto` - Convertion func `i_key` => `i_keyraw` - defaults to simple copy. +- `i_keyfrom` - Convertion func `i_key` <= `i_keyraw` - defaults to simple copy. **[required]** if `i_keydrop` is defined. +- `i_keyto` - Convertion func `i_key *` => `i_keyraw` - defaults to simple copy. -- `i_valdrop` - Destroy mapped or value func - defaults to empty destruct. +- `i_valdrop` - 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. +- `i_valfrom` - Convertion func `i_val` <= `i_valraw` - defaults to simple copy. **[required]** if `i_valdrop` is defined. +- `i_valto` - Convertion func `i_val *` => `i_valraw` - defaults to simple copy. Instead of defining `i_cmp`, you may define `i_opt c_no_cmp` to disable methods using comparison. diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index cc021001..9318b8e3 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -170,7 +170,7 @@ Type c_default_toraw(const Type* val); // dereference val void c_default_drop(Type* val); // does nothing int c_rawstr_cmp(const char* const* a, const char* const* b); -bool c_rawstr_equalto(const char* const* a, const char* const* b); +bool c_rawstr_eq(const char* const* a, const char* const* b); ``` ### c_malloc, c_calloc, c_realloc, c_free diff --git a/docs/cmap_api.md b/docs/cmap_api.md index e2cb668f..4bb367f8 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -20,14 +20,14 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain #define i_key // key: REQUIRED #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_keyraw*: REQUIRED IF i_keyraw is non-integral type -#define i_equ // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp +#define i_eq // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp #define i_keydrop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy #define i_valdrop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy +#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy #define i_tag // defaults to i_key #include @@ -89,9 +89,9 @@ uint64_t c_hash64(const void* data, size_t is8); 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) +bool c_default_eq(const i_keyraw* a, const i_keyraw* b); // *a == *b +bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !memcmp(a, b, sizeof *a) +bool c_rawstr_eq(const char* const* a, const char* const* b); // !strcmp(*a, *b) ``` ## Types @@ -200,7 +200,7 @@ typedef struct { int x, y, z; } Vec3i; #define i_key Vec3i #define i_val int -#define i_equ c_memcmp_equalto // bitwise compare, and use c_default_hash +#define i_eq c_memcmp_eq // bitwise equal, and use c_default_hash #define i_tag vi #include @@ -272,7 +272,7 @@ typedef struct { #define Viking_init() ((Viking){cstr_null, cstr_null}) -static inline bool RViking_equalto(const Viking* a, const Viking* b) { +static inline bool RViking_eq(const Viking* a, const Viking* b) { return cstr_equals_s(a->name, b->name) && cstr_equals_s(a->country, b->country); } @@ -294,7 +294,7 @@ void inline Viking_drop(Viking* vk) { #define i_key_bind Viking #define i_val int // i_key_bind auto-binds: -// #define i_equ RViking_equalto +// #define i_eq RViking_eq // #define i_hash RViking_hash // #define i_keyfrom Viking_clone // #define i_drop Viking_drop @@ -357,7 +357,7 @@ static inline uint64_t RViking_hash(const RViking* raw, size_t ignore) { uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); return hash; } -static inline bool RViking_equalto(const RViking* rx, const RViking* ry) { +static inline bool RViking_eq(const RViking* rx, const RViking* ry) { return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; } @@ -375,7 +375,7 @@ static inline RViking Viking_toraw(const Viking* vk) { #define i_keyraw RViking // i_key_bind macro will make these functions auto-bind: // #define i_hash RViking_hash -// #define i_equ RViking_equalto +// #define i_eq RViking_eq // #define i_keyfrom Viking_from // uses _from because i_keyraw is defined // #define i_keyto Viking_toraw // #define i_keydrop Viking_drop diff --git a/docs/cset_api.md b/docs/cset_api.md index b70f5fb9..2ce43309 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -8,13 +8,13 @@ A **cset** is an associative container that contains a set of unique objects of ```c #define i_key // key: REQUIRED -#define i_hash // hash func: REQUIRED IF i_keyraw is a non-pod type #define i_cmp // three-way compare two i_keyraw*: REQUIRED IF i_keyraw is a non-integral type -#define i_equ // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp +#define i_hash // hash func: REQUIRED IF i_keyraw is a non-pod type +#define i_eq // equality comparison two i_keyraw*: !i_cmp will be used if not defined. #define i_drop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy -#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy #define i_tag // defaults to i_key #include ``` diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 463a723c..31f27baf 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -86,12 +86,12 @@ Note that all methods with arguments `(..., const char* str, size_t n)`, `n` mus #### Helper methods: ```c int cstr_cmp(const cstr *s1, const cstr *s2); -bool cstr_equalto(const cstr *s1, const cstr *s2); +bool cstr_eq(const cstr *s1, const cstr *s2); bool cstr_hash(const cstr *s, ...); typedef const char* c_rawstr; int c_rawstr_cmp(const c_rawstr* x, const c_rawstr* y); -bool c_rawstr_equalto(const c_rawstr* x, const c_rawstr* y); +bool c_rawstr_eq(const c_rawstr* x, const c_rawstr* y); uint64_t c_rawstr_hash(const c_rawstr* x, size_t dummy); uint64_t c_strhash(const char* str); diff --git a/docs/csview_api.md b/docs/csview_api.md index 609c5d10..4e5d3b0e 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -78,7 +78,7 @@ bool cstr_ends_with_v(cstr s, csview sub); #### Helper methods ```c int csview_cmp(const csview* x, const csview* y); -bool csview_equalto(const csview* x, const csview* y); +bool csview_eq(const csview* x, const csview* y); uint64_t csview_hash(const csview* x, size_t dummy); ``` ## Types diff --git a/examples/rawptr_elements.c b/examples/rawptr_elements.c index 463a7f35..3ff0dc8a 100644 --- a/examples/rawptr_elements.c +++ b/examples/rawptr_elements.c @@ -9,7 +9,7 @@ struct { double x, y; } typedef Point; #define i_keydrop(x) c_free(*(x)) #define i_keyfrom(x) c_new(Point, *(x)) #define i_hash(x, n) c_default_hash(*(x), sizeof *(x)) -#define i_equ(x, y) c_memcmp_equalto(*(x), *(y)) +#define i_eq(x, y) c_memcmp_eq(*(x), *(y)) #define i_tag pnt #include diff --git a/examples/vikings.c b/examples/vikings.c index 838598b5..c4e86c73 100644 --- a/examples/vikings.c +++ b/examples/vikings.c @@ -22,7 +22,7 @@ uint64_t RViking_hash(const RViking* raw, size_t ignore) { uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); return hash; } -static inline bool RViking_equalto(const RViking* rx, const RViking* ry) { +static inline bool RViking_eq(const RViking* rx, const RViking* ry) { return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; } @@ -40,7 +40,7 @@ static inline RViking Viking_toraw(const Viking* vk) { #define i_val int // i_key_bind auto-binds these functions: // #define i_hash Viking_hash -// #define i_equ Viking_equalto +// #define i_eq Viking_eq // #define i_keyfrom Viking_from // uses _from (not _clone) because i_keyraw is defined // #define i_keyto Viking_toraw // #define i_keydrop Viking_drop diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index bd135b7e..1a9280e8 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -167,7 +167,7 @@ STC_INLINE bool cstr_equals_s(cstr s1, cstr s2) { return strcmp(cstr_str(&s1), cstr_str(&s2)) == 0; } -STC_INLINE bool cstr_equalto(const cstr* s1, const cstr* s2) { +STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { return strcmp(cstr_str(s1), cstr_str(s2)) == 0; } diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 51bc81a4..764761fe 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -171,7 +171,7 @@ _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { } STC_INLINE bool -_cx_memb(_equalto)(const _cx_self* x, const _cx_self* y) { +_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { return !_cx_memb(_cmp)(x, y); } #include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index d3664077..9cbe24a4 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -100,8 +100,8 @@ typedef const char c_strlit[]; #define c_default_less(x, y) (*(x) < *(y)) #define c_default_cmp(x, y) c_less_cmp(c_default_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_default_eq(x, y) (*(x) == *(y)) +#define c_memcmp_eq(x, y) (memcmp(x, y, sizeof *(x)) == 0) #define c_default_clone(x) (x) #define c_default_fromraw(x) (x) // [deprecated] @@ -118,11 +118,11 @@ typedef const char c_strlit[]; typedef char* c_mutstr; typedef const char* c_rawstr; -#define c_rawstr_cmp(x, y) strcmp(*(x), *(y)) -#define c_rawstr_equalto(x, y) (strcmp(*(x), *(y)) == 0) -#define c_rawstr_hash(x, dummy) c_strhash(*(x)) +#define c_rawstr_cmp(xp, yp) strcmp(*(xp), *(yp)) +#define c_rawstr_eq(xp, yp) (!strcmp(*(xp), *(yp))) +#define c_rawstr_hash(p, dummy) c_strhash(*(p)) #define c_rawstr_clone(s) strcpy((char*)c_malloc(strlen(s) + 1), s) -#define c_rawstr_drop(x) c_free((char *) &**(x)) +#define c_rawstr_drop(p) c_free((char *) &**(p)) #define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 10e9c586..c78c2472 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -293,7 +293,7 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { while ((_hx = _hashx[b.idx])) { if (_hx == b.hx) { _cx_rawkey _raw = i_keyto(_i_keyref(self->table + b.idx)); - if (i_equ(&_raw, rkeyptr)) break; + if (i_eq(&_raw, rkeyptr)) break; } if (++b.idx == _cap) b.idx = 0; } diff --git a/include/stc/csptr.h b/include/stc/csptr.h index b66cd4d7..cf1a5b12 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -204,7 +204,7 @@ _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { } STC_INLINE bool -_cx_memb(_equalto)(const _cx_self* x, const _cx_self* y) { +_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { return !_cx_memb(_cmp)(x, y); } #undef _i_atomic_inc diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 730f4d16..cfb2dfef 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -167,9 +167,9 @@ cstr_ends_with(cstr s, const char* sub) { } /* container adaptor functions: */ -#define cstr_cmp(xp, yp) strcmp((xp)->str, (yp)->str) -#define cstr_equalto(xp, yp) (strcmp((xp)->str, (yp)->str) == 0) -#define cstr_hash(xp, dummy) c_strhash((xp)->str) +#define cstr_cmp(xp, yp) strcmp((xp)->str, (yp)->str) +#define cstr_eq(xp, yp) (!cstr_cmp(xp, yp)) +#define cstr_hash(xp, dummy) c_strhash((xp)->str) /* -------------------------- IMPLEMENTATION ------------------------- */ diff --git a/include/stc/csview.h b/include/stc/csview.h index ac120e15..d0152c3d 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -120,7 +120,7 @@ STC_INLINE int csview_cmp(const csview* x, const csview* y) { return c ? c : x->size - y->size; } #define csview_hash(xp, dummy) c_strhash((xp)->str) -#define csview_equalto(xp, yp) (csview_cmp(xp, yp) == 0) +#define csview_eq(xp, yp) (!csview_cmp(xp, yp)) /* -------------------------- IMPLEMENTATION ------------------------- */ diff --git a/include/stc/template.h b/include/stc/template.h index 61befb2b..83a362d7 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -48,9 +48,9 @@ #define i_val_bind i_val_csptr #error "i_val_sptr/ref no longer supported: use new name i_val_bind" #endif -#ifdef i_cnt // [deprecated] +#if defined i_cnt || defined i_equ // [deprecated] #define i_type i_cnt - #error "i_cnt no longer supported: use new name i_type" + #error "i_cnt and i_equ no longer supported: use new name i_type / i_eq" #endif #ifdef i_type @@ -88,8 +88,8 @@ #ifndef i_cmp #define i_cmp c_PASTE(i_keyraw, _cmp) #endif - #ifndef i_equ - #define i_equ c_PASTE(i_keyraw, _equalto) + #ifndef i_eq + #define i_eq c_PASTE(i_keyraw, _eq) #endif #ifndef i_hash #define i_hash c_PASTE(i_keyraw, _hash) @@ -170,10 +170,10 @@ #define i_keyraw i_key #define i_keyto c_default_toraw #endif - #if !defined i_equ && defined i_cmp - #define i_equ !i_cmp - #elif !defined i_equ - #define i_equ c_default_equalto + #if !defined i_eq && defined i_cmp + #define i_eq !i_cmp + #elif !defined i_eq + #define i_eq c_default_eq #endif #ifndef i_keydrop #define i_keydrop c_default_drop @@ -212,26 +212,26 @@ #undef i_imp #undef i_opt #undef i_cmp -#undef i_drop -#undef i_equ +#undef i_eq #undef i_hash #undef i_from +#undef i_drop #undef i_val #undef i_val_str #undef i_val_bind -#undef i_valdrop #undef i_valraw #undef i_valfrom #undef i_valto +#undef i_valdrop #undef i_key #undef i_key_str #undef i_key_bind -#undef i_keydrop #undef i_keyraw #undef i_keyfrom #undef i_keyto +#undef i_keydrop #undef _i_prefix #undef _i_has_internal_clone -- cgit v1.2.3 From e38e9164d816bf1ee1f1dcc40f69ac158562fb1a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 20 Dec 2021 19:52:51 +0100 Subject: Some small addition to constness in API. Updated docs. --- docs/cmap_api.md | 4 ++-- docs/csmap_api.md | 2 +- docs/cvec_api.md | 6 ++++-- examples/vikings.c | 14 +++++++------- include/stc/cmap.h | 2 +- include/stc/csmap.h | 2 +- include/stc/cstack.h | 2 +- include/stc/cvec.h | 9 +++++---- 8 files changed, 22 insertions(+), 19 deletions(-) diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 4bb367f8..8531eb82 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -391,8 +391,8 @@ int main() }); Vikings_emplace_or_assign(&vikings, (RViking){"Bjorn", "Sweden"}, 10); - Vikings_value *einar = Vikings_find(&vikings, (RViking){"Einar", "Norway"}).ref; - if (einar) einar->second += 3; // add 3 hp points to Einar + Vikings_value *v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"}); + if (v) v->second += 3; // add 3 hp points to Einar c_forpair (viking, health, Vikings, vikings) { printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.health); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index c4f0ff16..a6e06b54 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -45,7 +45,7 @@ void csmap_X_drop(csmap_X* self); size_t csmap_X_size(csmap_X map); bool csmap_X_empty(csmap_X map); -csmap_X_mapped* csmap_X_at(const csmap_X* self, i_keyraw rkey); // rkey must be in map. +const csmap_X_mapped* csmap_X_at(const csmap_X* self, i_keyraw rkey); // rkey must be in map. const csmap_X_value* csmap_X_get(const csmap_X* self, i_keyraw rkey); // return NULL if not found csmap_X_value* csmap_X_get_mut(csmap_X* self, i_keyraw rkey); // mutable get bool csmap_X_contains(const csmap_X* self, i_keyraw rkey); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index b9d4d2d5..29a3efcb 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -56,15 +56,17 @@ cvec_X_iter cvec_X_bsearch_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw r cvec_X_value* cvec_X_front(const cvec_X* self); cvec_X_value* cvec_X_back(const cvec_X* self); -cvec_X_value* cvec_X_push_back(cvec_X* self, i_val value); cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); +cvec_X_value* cvec_X_push_back(cvec_X* self, i_val value); void cvec_X_pop_back(cvec_X* self); +cvec_X_value* cvec_X_emplace(cvec_X* self, i_valraw raw); // alias for emplace_back +cvec_X_value* cvec_X_push(cvec_X* self, i_val value); // alias for push_back +void cvec_X_pop(cvec_X* self); // alias for pop_back cvec_X_iter cvec_X_insert(cvec_X* self, size_t idx, i_val value); // move value cvec_X_iter cvec_X_insert_n(cvec_X* self, size_t idx, const i_val[] arr, size_t n); // move arr values cvec_X_iter cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value -cvec_X_iter cvec_X_emplace(cvec_X* self, size_t idx, i_valraw raw); cvec_X_iter cvec_X_emplace_n(cvec_X* self, size_t idx, const i_valraw[] arr, size_t n); cvec_X_iter cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw); cvec_X_iter cvec_X_emplace_range(cvec_X* self, cvec_X_iter it, diff --git a/examples/vikings.c b/examples/vikings.c index c4e86c73..7a953059 100644 --- a/examples/vikings.c +++ b/examples/vikings.c @@ -39,11 +39,11 @@ static inline RViking Viking_toraw(const Viking* vk) { #define i_keyraw RViking #define i_val int // i_key_bind auto-binds these functions: -// #define i_hash Viking_hash -// #define i_eq Viking_eq -// #define i_keyfrom Viking_from // uses _from (not _clone) because i_keyraw is defined -// #define i_keyto Viking_toraw -// #define i_keydrop Viking_drop +// i_hash => Viking_hash +// i_eq => Viking_eq +// i_keyfrom => Viking_from // not _clone because i_keyraw is defined +// i_keyto => Viking_toraw +// i_keydrop => Viking_drop #include int main() @@ -58,8 +58,8 @@ int main() Vikings_emplace_or_assign(&vikings, bjorn, 10); RViking einar = {"Einar", "Norway"}; - Vikings_value *e = Vikings_find(&vikings, einar).ref; - e->second += 3; // add 3 hp points to Einar + Vikings_value* v = Vikings_get_mut(&vikings, einar); + v->second += 3; // add 3 hp points to Einar Vikings_emplace(&vikings, einar, 0).ref->second += 5; // add 5 more to Einar c_forpair (viking, hp, Vikings, vikings) { diff --git a/include/stc/cmap.h b/include/stc/cmap.h index c78c2472..b7529871 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -121,7 +121,7 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) return _cx_memb(_insert_or_assign)(self, key, mapped); } - STC_INLINE _cx_mapped* + STC_INLINE const _cx_mapped* _cx_memb(_at)(const _cx_self* self, i_keyraw rkey) { chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); assert(self->_hashx[b.idx]); diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 6ba220ab..04dc895d 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -156,7 +156,7 @@ _cx_memb(_value_drop)(_cx_value* val) { _cx_memb(_put)(_cx_self* self, i_key key, i_val mapped) { return _cx_memb(_insert_or_assign)(self, key, mapped); } - STC_INLINE _cx_mapped* + 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 diff --git a/include/stc/cstack.h b/include/stc/cstack.h index d43afe29..fa74494d 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -91,7 +91,7 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { *vp = val; return vp; } -STC_INLINE _cx_value* _cx_memb(_at)(const _cx_self* self, size_t idx) +STC_INLINE const _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) diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 01143d25..92f6afd6 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -104,16 +104,14 @@ STC_INLINE i_val _cx_memb(_value_clone)(_cx_value 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 _cx_value* _cx_memb(_emplace)(_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(_drop)(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); } @@ -135,8 +133,11 @@ STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) { c_swap(_cx_s 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(_push)(_cx_self* self, i_val value) + { return _cx_memb(_push_back)(self, value); } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_value* p = &self->data[--cvec_rep_(self)->size]; i_valdrop(p); } +STC_INLINE void _cx_memb(_pop)(_cx_self* self) { _cx_memb(_pop_back)(self); } 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) -- cgit v1.2.3 From 85d01062dc86821513bf9c306231aceca5bab222 Mon Sep 17 00:00:00 2001 From: Tyge Løvset <60263450+tylov@users.noreply.github.com> Date: Mon, 20 Dec 2021 23:10:04 +0100 Subject: Update cmap_api.md --- docs/cmap_api.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 8531eb82..b05ae5a8 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -272,11 +272,11 @@ typedef struct { #define Viking_init() ((Viking){cstr_null, cstr_null}) -static inline bool RViking_eq(const Viking* a, const Viking* b) { +static inline bool Viking_eq(const Viking* a, const Viking* b) { return cstr_equals_s(a->name, b->name) && cstr_equals_s(a->country, b->country); } -static inline uint32_t RViking_hash(const Viking* a, int ignored) { +static inline uint32_t Viking_hash(const Viking* a, int ignored) { return c_strhash(a->name.str) ^ (c_strhash(a->country.str) >> 15); } @@ -285,7 +285,7 @@ static inline Viking Viking_clone(Viking v) { v.country = cstr_clone(v.country); } -void inline Viking_drop(Viking* vk) { +static inline void Viking_drop(Viking* vk) { cstr_drop(&vk->name); cstr_drop(&vk->country); } @@ -294,8 +294,8 @@ void inline Viking_drop(Viking* vk) { #define i_key_bind Viking #define i_val int // i_key_bind auto-binds: -// #define i_eq RViking_eq -// #define i_hash RViking_hash +// #define i_eq Viking_eq +// #define i_hash Viking_hash // #define i_keyfrom Viking_clone // #define i_drop Viking_drop #include -- cgit v1.2.3 From 99f677c8bdee5c243c1415ffc00cf7bae76f80b4 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 21 Dec 2021 10:39:25 +0100 Subject: Fixed and simplified cbox and csptr. --- include/stc/cbox.h | 22 +++++++--------------- include/stc/csptr.h | 42 +++++++++++++----------------------------- 2 files changed, 20 insertions(+), 44 deletions(-) diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 764761fe..f33e89bd 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -83,7 +83,7 @@ STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } STC_INLINE _cx_self -_cx_memb(_with)(i_val* p) { return c_make(_cx_self){p}; } +_cx_memb(_from_ptr)(i_val* p) { return c_make(_cx_self){p}; } STC_INLINE _cx_self _cx_memb(_new)(i_val val) { @@ -107,12 +107,6 @@ _cx_memb(_reset)(_cx_self* self) { _cx_memb(_drop)(self); self->get = NULL; } -// take ownership of *p -STC_INLINE void -_cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { - _cx_memb(_drop)(self); self->get = p; -} - // take ownership of val STC_INLINE void _cx_memb(_reset_new)(_cx_self* self, i_val val) { @@ -125,10 +119,6 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { _cx_memb(_from)(i_valraw raw) { return c_make(_cx_self){c_new(i_val, i_valfrom(raw))}; } - STC_INLINE i_valraw - _cx_memb(_toraw)(const _cx_self* self) { - return i_valto(self->get); - } STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { @@ -139,8 +129,8 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self other) { if (self->get == other.get) return; - if (other.get) _cx_memb(_reset_new)(self, *other.get); - else _cx_memb(_reset)(self); + _cx_memb(_reset)(self); + *self = _cx_memb(_clone)(other); } #endif @@ -157,7 +147,8 @@ _cx_memb(_hash)(const _cx_self* self, size_t n) { #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); #else - return i_hash(self->get, sizeof *self->get); + i_valraw rx = i_valto(self->get); + return i_hash(&rx, sizeof rx); #endif } @@ -166,7 +157,8 @@ _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { #if c_option(c_no_cmp) return c_default_cmp(&x->get, &y->get); #else - return i_cmp(x->get, y->get); + i_valraw rx = i_valto(x->get), ry = i_valto(x->get); + return i_cmp(&rx, &ry); #endif } diff --git a/include/stc/csptr.h b/include/stc/csptr.h index cf1a5b12..4c35c06b 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -97,18 +97,12 @@ STC_INLINE long _cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } STC_INLINE _cx_self -_cx_memb(_with)(_cx_value* p) { +_cx_memb(_from_ptr)(_cx_value* p) { _cx_self ptr = {p}; if (p) *(ptr.use_count = c_alloc(long)) = 1; return ptr; } -STC_INLINE _cx_self -_cx_memb(_view)(const _cx_value* p) { - _cx_self ptr = {(_cx_value*) p}; - return ptr; -} - STC_INLINE _cx_self _cx_memb(_new)(i_val val) { _cx_self ptr; _cx_csptr_rep *rep = c_alloc(_cx_csptr_rep); @@ -116,14 +110,6 @@ _cx_memb(_new)(i_val val) { *(ptr.get = &rep->value) = val; return ptr; } -STC_INLINE _cx_self _cx_memb(_make)(i_val val) // [deprecated] - { return _cx_memb(_new)(val); } - -STC_INLINE _cx_self // does not use i_valfrom, so we can bypass c_no_clone -_cx_memb(_clone)(_cx_self ptr) { - if (ptr.use_count) _i_atomic_inc(ptr.use_count); - return ptr; -} STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { @@ -148,12 +134,6 @@ _cx_memb(_reset)(_cx_self* self) { self->use_count = NULL, self->get = NULL; } -STC_INLINE void -_cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { - _cx_memb(_drop)(self); - *self = _cx_memb(_with)(p); -} - STC_INLINE void _cx_memb(_reset_new)(_cx_self* self, i_val val) { _cx_memb(_drop)(self); @@ -163,14 +143,16 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { #if !c_option(c_no_clone) STC_INLINE _cx_self _cx_memb(_from)(i_valraw raw) { return _cx_memb(_new)(i_valfrom(raw)); - } - - STC_INLINE i_valraw - _cx_memb(_toraw)(const _cx_self* self) { - return i_valto(self->get); - } +} #endif +// does not use i_valfrom, so we can bypass c_no_clone +STC_INLINE _cx_self +_cx_memb(_clone)(_cx_self ptr) { + if (ptr.use_count) _i_atomic_inc(ptr.use_count); + return ptr; +} + STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); @@ -190,7 +172,8 @@ _cx_memb(_hash)(const _cx_self* self, size_t n) { #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); #else - return i_hash(self->get, sizeof *self->get); + i_valraw rx = i_valto(self->get); + return i_hash(&rx, sizeof rx); #endif } @@ -199,7 +182,8 @@ _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { #if c_option(c_no_cmp) return c_default_cmp(&x->get, &y->get); #else - return i_cmp(x->get, y->get); + i_valraw rx = i_valto(x->get), ry = i_valto(x->get); + return i_cmp(&rx, &ry); #endif } -- cgit v1.2.3 From 1b90b6c3eea0f3e07f8a2d2abe3686917d1d86a8 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 21 Dec 2021 10:56:01 +0100 Subject: Minor improvement. --- include/stc/cbox.h | 4 ++-- include/stc/csptr.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/stc/cbox.h b/include/stc/cbox.h index f33e89bd..bcd9bd8c 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -129,7 +129,7 @@ _cx_memb(_reset_new)(_cx_self* self, i_val val) { STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self other) { if (self->get == other.get) return; - _cx_memb(_reset)(self); + _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } #endif @@ -142,7 +142,7 @@ _cx_memb(_take)(_cx_self* self, _cx_self other) { STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self, size_t n) { - #if c_option(c_no_cmp) && SIZE_MAX >> 32 + #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX return c_hash64(&self->get, 8); #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 4c35c06b..92ed05ef 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -156,7 +156,8 @@ _cx_memb(_clone)(_cx_self ptr) { STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); - _cx_memb(_drop)(self); *self = ptr; + _cx_memb(_drop)(self); + *self = ptr; } STC_INLINE void @@ -167,7 +168,7 @@ _cx_memb(_take)(_cx_self* self, _cx_self ptr) { STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self, size_t n) { - #if c_option(c_no_cmp) && SIZE_MAX >> 32 + #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX return c_hash64(&self->get, 8); #elif c_option(c_no_cmp) return c_hash32(&self->get, 4); -- cgit v1.2.3 From 6e65e30c6e3c2bc271d3885e749ceb0289bbd9cf Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 08:49:19 +0100 Subject: Changed the c_apply() and c_apply_pair() to one new c_apply() API. Added c_pair(v) for convenience. --- README.md | 23 +++++++++++++---------- docs/cbox_api.md | 17 ++++++++--------- docs/ccommon_api.md | 18 ++++++++++++------ docs/cdeq_api.md | 2 +- docs/clist_api.md | 8 ++++---- docs/cmap_api.md | 6 +++--- docs/cpque_api.md | 2 +- docs/cset_api.md | 6 ++++-- docs/csmap_api.md | 4 ++-- docs/csptr_api.md | 42 +++++++++++++++++++++--------------------- docs/csset_api.md | 6 ++++-- docs/cvec_api.md | 2 +- examples/box.c | 12 ++++++------ examples/convert.c | 2 +- examples/cpque.c | 4 ++-- examples/csmap_erase.c | 4 ++-- examples/csmap_find.c | 3 ++- examples/csmap_insert.c | 3 ++- examples/csset_erase.c | 3 ++- examples/inits.c | 10 ++++++---- examples/list.c | 2 +- examples/list_erase.c | 2 +- examples/list_splice.c | 4 ++-- examples/new_list.c | 6 ++++-- examples/new_map.c | 6 +++--- examples/new_sptr.c | 8 ++++---- examples/phonebook.c | 5 +++-- examples/priority.c | 2 +- examples/sidebyside.cpp | 3 ++- examples/sptr.c | 23 ++++++++++++----------- examples/sptr_demo.c | 8 ++++---- examples/sptr_erase.c | 11 +++++------ examples/sptr_music.c | 30 +++++++++++++++--------------- examples/sptr_pthread.c | 2 +- examples/sptr_to_maps.c | 22 +++++++++++----------- examples/vikings.c | 2 +- examples/words.c | 2 +- include/stc/cbox.h | 33 ++++++++++++++++++++------------- include/stc/ccommon.h | 28 +++++++++++++++++++++------- include/stc/csptr.h | 36 ++++++++++++++++++++---------------- include/stc/template.h | 20 ++++++++++++-------- 41 files changed, 241 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index 6f3ceb77..ad286305 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ still be defined as before, which is often easier for simple element types. Migration guide from version 2 to 3. Replace (regular expresion) in VS Code: - `_del\b` → `_drop` - `_compare\b` → `_cmp` +- `csptr` → `cref` +- `_rawvalue\b` → `_raw` - `_equ\b` → `_eq` Replace (whole word + match case): @@ -25,10 +27,10 @@ Replace (whole word + match case): - `i_cnt` → `i_type` - `cstr_lit` → `cstr_new` - `csptr_X_make` → `csptr_X_new` -- `i_key_csptr` → `i_key_bind` -- `i_val_csptr` → `i_val_bind` -- `i_key_ref` → `i_key_bind` -- `i_val_ref` → `i_val_bind` +- `i_key_csptr` → `i_key_sptr` +- `i_val_csptr` → `i_val_sptr` +- `c_apply` → `c_apply_OLD` // replaced by new `c_apply` +- `c_apply_pair` → `c_apply_pair_OLD` // replaced by new `c_apply` ### Final version 2.1 - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. @@ -192,12 +194,13 @@ int main(void) { c_auto (csmap_int, map) { // add some elements to each container - c_apply(cset_int, insert, &set, {10, 20, 30}); - c_apply(cvec_pnt, push_back, &vec, { {10, 1}, {20, 2}, {30, 3} }); - c_apply(cdeq_int, push_back, &deq, {10, 20, 30}); - c_apply(clist_int, push_back, &lst, {10, 20, 30}); - c_apply(cstack_int, push, &stk, {10, 20, 30}); - c_apply_pair(csmap_int, insert, &map, { {20, 2}, {10, 1}, {30, 3} }); + c_apply(v, cset_int_insert(&set, v), int, {10, 20, 30}); + c_apply(v, cvec_pnt_push_back(&vec, v), int, { {10, 1}, {20, 2}, {30, 3} }); + c_apply(v, cdeq_int_push_back(&deq, v), int, {10, 20, 30}); + c_apply(v, clist_int_push_back(&lst, v), int, {10, 20, 30}); + c_apply(v, cstack_int_push(&stk, v), int, {10, 20, 30}); + c_apply(v, csmap_int_insert(&map, c_pair(v)), + csmap_int_rawvalue, { {20, 2}, {10, 1}, {30, 3} }); // add one more element to each container cset_int_insert(&set, 40); diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 8580e7d7..011beea2 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -33,24 +33,23 @@ compare the pointer addresses when used. Additionally, `c_no_clone` or `i_is_fwd ## Methods ```c cbox_X cbox_X_init(); // return an empty cbox -cbox_X cbox_X_new(i_val val); // allocate new heap object with val. Take ownership of val. -cbox_X cbox_X_from(i_valraw raw); // like cbox_X_new(), but create owned value from raw. -cbox_X cbox_X_with(i_val* p); // create a cbox from a pointer. Takes ownership of p. +cbox_X cbox_X_new(i_valraw raw); // like cbox_X_from(), but create owned value from raw. +cbox_X cbox_X_from(i_val val); // allocate new heap object with val. Take ownership of val. +cbox_X cbox_X_from_ptr(i_val* p); // create a cbox from a pointer. Takes ownership of p. cbox_X cbox_X_clone(cbox_X other); // return deep copied clone cbox_X cbox_X_move(cbox_X* self); // transfer ownership to another cbox. void cbox_X_take(cbox_X* self, cbox_X other); // take ownership of other. void cbox_X_copy(cbox_X* self, cbox_X other); // deep copy to self - void cbox_X_drop(cbox_X* self); // destruct the contained object and free's it. void cbox_X_reset(cbox_X* self); -void cbox_X_reset_new(cbox_X* self, i_val val); // assign new cbox with value. Takes ownership of val. -void cbox_X_reset_from(cbox_X* self, i_valraw raw); // make and assign new cbox from raw value. -void cbox_X_reset_with(cbox_X* self, i_val* p); // create cbox with pointer p. Takes ownership of p. +void cbox_X_reset_from(cbox_X* self, i_val val); // assign new cbox with value. Takes ownership of val. -int cbox_X_cmp(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_cmp' +uint64_t cbox_X_value_hash(const i_val* x, size_t n); // hash value +int cbox_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' // is defined. Otherwise uses 'i_cmp' or default compare. +bool cbox_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 ``` ## Types and constants @@ -98,7 +97,7 @@ int main() c_auto (cvec_int, vec) // declare and init vec, call drop at scope exit c_auto (csset_int, set) // declare and init set, call drop at scope exit { - c_apply(cvec_int, push_back, &vec, { + c_apply(v, cvec_int_push_back(&vec, v), cbox_int, { cbox_int_new(2021), cbox_int_new(2012), cbox_int_new(2022), diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 9318b8e3..eec56490 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -93,7 +93,8 @@ int main() #define i_tag ii #include ... -c_apply_pair(csmap_ii, insert, &map, { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} }); +c_apply(v, csmap_ii_insert(&map, c_pair(v)), csmap_ii_value, + { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} }); c_foreach (i, csmap_ii, map) printf(" %d", i.ref->first); // out: 3 5 7 12 23 @@ -130,14 +131,19 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i); // 30 25 20 15 10 5 ``` -### c_apply, c_apply_pair, c_apply_n -**c_apply** will apply a method on a container with each of the elements in the given array: +### c_apply, c_apply_arr, c_apply_cnt, c_pair +**c_apply** applies an expression on a container with each of the elements in the given array: ```c -c_apply(cvec_i, push_back, &vec, {1, 2, 3}); // apply multiple push_backs -c_apply_pair(cmap_i, insert, &map, { {4, 5}, {6, 7} }); // inserts to existing map +// apply multiple push_backs +c_apply(v, cvec_i_push_back(&vec, v), int, {1, 2, 3}); +// inserts to existing map +c_apply(v, cmap_i_insert(&map, c_pair(v)), cmap_i_rawvalue, { {4, 5}, {6, 7} }); int arr[] = {1, 2, 3}; -c_apply_n(cvec_i, push_back, &vec, arr, c_arraylen(arr)); +c_apply_arr(v, cvec_i_push_back(&vec, v), int, arr, c_arraylen(arr)); + +// add keys from a map to a vec. +c_apply_cnt(v, cvec_i_push_back(&vec, v.first), cmap_i, map); ``` ### c_new, c_alloc, c_alloc_n, c_drop, c_make diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 1985c2ab..ce14184f 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -106,7 +106,7 @@ int main() { printf(" %d", *i.ref); puts(""); - c_apply(cdeq_i, push_back, &q, {1, 4, 5, 22, 33, 2}); + c_apply(v, cdeq_i_push_back(&q, v), int, {1, 4, 5, 22, 33, 2}); c_foreach (i, cdeq_i, q) printf(" %d", *i.ref); puts(""); diff --git a/docs/clist_api.md b/docs/clist_api.md index 0817737b..41fbd274 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -106,7 +106,7 @@ Interleave *push_front()* / *push_back()* then *sort()*: int main() { clist_d list = clist_d_init(); - c_apply(clist_d, push_back, &list, { + c_apply(v, clist_d_push_back(&list, v), double, { 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0 }); @@ -147,7 +147,7 @@ Use of *erase_at()* and *erase_range()*: int main () { clist_i L = clist_i_init(); - c_apply(clist_i, push_back, &L, {10, 20, 30, 40, 50}); + c_apply(v, clist_i_push_back(&L, v), int, {10, 20, 30, 40, 50}); // 10 20 30 40 50 clist_i_iter it = clist_i_begin(&L); // ^ clist_i_next(&it); @@ -182,8 +182,8 @@ Splice `[30, 40]` from *L2* into *L1* before `3`: int main() { c_auto (clist_i, L1, L2) { - c_apply(clist_i, push_back, &L1, {1, 2, 3, 4, 5}); - c_apply(clist_i, push_back, &L2, {10, 20, 30, 40, 50}); + c_apply(v, clist_i_push_back(&L1, v), int, {1, 2, 3, 4, 5}); + c_apply(v, clist_i_push_back(&L2, v), int, {10, 20, 30, 40, 50}); clist_i_iter i = clist_i_advance(clist_i_begin(&L1), 2); clist_i_iter j1 = clist_i_advance(clist_i_begin(&L2), 2), j2 = clist_i_advance(j1, 2); diff --git a/docs/cmap_api.md b/docs/cmap_api.md index b05ae5a8..b7a08e3e 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -122,7 +122,7 @@ int main() // Create an unordered_map of three strings (that map to strings) c_auto (cmap_str, u) { - c_apply_pair(cmap_str, emplace, &u, { + c_apply(v, cmap_str_emplace(&u, c_pair(v)), cmap_str_rawvalue, { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"} @@ -168,7 +168,7 @@ int main() c_auto (cmap_id, idnames) { - c_apply_pair(cmap_id, emplace, &idnames, { + c_apply(v, cmap_id_emplace(&idnames, c_pair(v)), cmap_id_rawvalue, { {100, "Red"}, {110, "Blue"} }); // replace existing mapped value: @@ -384,7 +384,7 @@ static inline RViking Viking_toraw(const Viking* vk) { int main() { c_auto (Vikings, vikings) { - c_apply_pair(Vikings, emplace, &vikings, { + c_apply(v, Vikings_emplace(&vikings, v), c_pair(v), Vikings_rawvalue, { {{"Einar", "Norway"}, 20}, {{"Olaf", "Denmark"}, 24}, {{"Harald", "Iceland"}, 12}, diff --git a/docs/cpque_api.md b/docs/cpque_api.md index e891b7d2..7a6ef00f 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -75,7 +75,7 @@ int main() // Push ten million random numbers to priority queue, plus some negative ones. c_forrange (N) cpque_i_push(&heap, stc64_uniform(&rng, &dist)); - c_apply(cpque_i, push, &heap, {-231, -32, -873, -4, -343}); + c_apply(v, cpque_i_push(&heap, v), int, {-231, -32, -873, -4, -343}); // Extract and display the fifty smallest. c_forrange (50) { diff --git a/docs/cset_api.md b/docs/cset_api.md index 2ce43309..479cf3f3 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -85,8 +85,10 @@ int main () c_auto (cset_str, first, second) c_auto (cset_str, third, fourth) { - c_apply(cset_str, emplace, &second, {"red", "green", "blue"}); - c_apply(cset_str, emplace, &third, {"orange", "pink", "yellow"}); + c_apply(v, cset_str_emplace(&second, v), const char*, + {"red", "green", "blue"}); + c_apply(v, cset_str_emplace(&third, v), const char*, + {"orange", "pink", "yellow"}); cset_str_emplace(&fourth, "potatoes"); cset_str_emplace(&fourth, "milk"); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index a6e06b54..3791347b 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -100,7 +100,7 @@ int main() // Create a sorted map of three strings (maps to string) c_auto (csmap_str, colors) // RAII { - c_apply_pair(csmap_str, emplace, &colors, { + c_apply(v, csmap_str_emplace(&colors, c_pair(v)), csmap_str_rawvalue, { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"} @@ -146,7 +146,7 @@ int main() csmap_id idnames = csmap_id_init(); c_autodefer (csmap_id_drop(&idnames)) { - c_apply_pair(csmap_id, emplace, &idnames, { + c_apply(v, csmap_id_emplace(&idnames, c_pair(v)), csmap_id_rawvalue, { {100, "Red"}, {110, "Blue"}, }); diff --git a/docs/csptr_api.md b/docs/csptr_api.md index 5cbe746f..6a48f91a 100644 --- a/docs/csptr_api.md +++ b/docs/csptr_api.md @@ -35,35 +35,35 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ## Methods ```c -csptr_X csptr_X_init(); // empty shared pointer -csptr_X csptr_X_new(i_val val); // create new heap allocated object. Take ownership of val. -csptr_X csptr_X_from(i_valraw raw); // like csptr_X_new(), but construct owned value from raw. -csptr_X csptr_X_with(i_val* p); // create a csptr from raw pointer. Takes ownership of p. +csptr_X csptr_X_init(); // empty shared pointer +csptr_X csptr_X_new(i_valraw raw); // like csptr_X_from(), but construct owned value from raw. +csptr_X csptr_X_from(i_val val); // create new heap allocated object. Take ownership of val. +csptr_X csptr_X_from_ptr(i_val* p); // create a csptr from raw pointer. Takes ownership of p. -csptr_X csptr_X_clone(csptr_X other); // return other with increased use count -csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr. -void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other. -void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count) +csptr_X csptr_X_clone(csptr_X other); // return other with increased use count +csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr. +void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other. +void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count) void csptr_X_drop(csptr_X* self); // destruct (decrease use count, free at 0) long csptr_X_use_count(csptr_X ptr); void csptr_X_reset(csptr_X* self); -void csptr_X_reset_new(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val. -void csptr_X_reset_from(csptr_X* self, i_valraw raw); // make and assign new csptr from raw value. -void csptr_X_reset_with(csptr_X* self, i_val* p); // create csptr with pointer p. Takes ownership of p. +void csptr_X_reset_from(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val. -int csptr_X_cmp(const csptr_X* x, const csptr_X* y); // compares pointer addresses if 'i_opt c_no_cmp' - // is defined. Otherwise uses 'i_cmp' or default compare. +uint64_t csptr_X_value_hash(const i_val* x, size_t n); // hash value +int csptr_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default compare. +bool csptr_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 ``` ## Types and constants -| Type name | Type definition | Used to represent... | -|:-------------------|:--------------------------------------------------|:------------------------| -| `csptr_null` | `{NULL, NULL}` | Init nullptr const | -| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type | -| `csptr_X_value` | `i_val` | The csptr element type | +| Type name | Type definition | Used to represent... | +|:-------------------|:---------------------------------------------------|:------------------------| +| `csptr_null` | `{NULL, NULL}` | Init nullptr const | +| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type | +| `csptr_X_value` | `i_val` | The csptr element type | ## Example @@ -101,17 +101,17 @@ int main() // POPULATE the stack with shared pointers to Map: Map *map; map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }); map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }); // POPULATE the list: map = List_push_back(&list, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); diff --git a/docs/csset_api.md b/docs/csset_api.md index c5cd0f88..62ccb638 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -80,8 +80,10 @@ c_auto (csset_str, fifth) c_auto (csset_str, first, second) c_auto (csset_str, third, fourth) { - c_apply(csset_str, emplace, &second, {"red", "green", "blue"}); - c_apply(csset_str, emplace, &third, {"orange", "pink", "yellow"}); + c_apply(v, csset_str_emplace(&second, v), const char*, + {"red", "green", "blue"}); + c_apply(v, csset_str_emplace(&third, v), const char*, + {"orange", "pink", "yellow"}); csset_str_emplace(&fourth, "potatoes"); csset_str_emplace(&fourth, "milk"); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 29a3efcb..2a4ceaf6 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -116,7 +116,7 @@ int main() cvec_int_push_back(&vec, 13); // Append a set of numbers - c_apply(cvec_int, push_back, &vec, {7, 5, 16, 8}); + c_apply(v, cvec_int_push_back(&vec, v), int, {7, 5, 16, 8}); printf("initial:"); c_foreach (k, cvec_int, vec) { diff --git a/examples/box.c b/examples/box.c index 598d0bdc..ae10a89f 100644 --- a/examples/box.c +++ b/examples/box.c @@ -28,7 +28,7 @@ void Person_drop(Person* p) { #include #define i_type Persons -#define i_val_bind PBox // binds PBox_cmp, ... +#define i_val_ref PBox // binds PBox_cmp, ... #include @@ -37,7 +37,7 @@ int main() c_auto (Persons, vec) c_auto (PBox, p, q) { - p = PBox_new(Person_new("Laura", "Palmer")); + p = PBox_from(Person_new("Laura", "Palmer")); q = PBox_clone(p); cstr_assign(&q.get->name, "Leland"); @@ -45,11 +45,11 @@ int main() printf("orig: %s %s\n", p.get->name.str, p.get->last.str); printf("copy: %s %s\n", q.get->name.str, q.get->last.str); - Persons_push_back(&vec, PBox_new(Person_new("Dale", "Cooper"))); - Persons_push_back(&vec, PBox_new(Person_new("Audrey", "Home"))); + Persons_push_back(&vec, PBox_from(Person_new("Dale", "Cooper"))); + Persons_push_back(&vec, PBox_from(Person_new("Audrey", "Home"))); // NB! Clone p and q to the vector using emplace_back() - c_apply(Persons, emplace_back, &vec, {p, q}); + c_apply(v, Persons_push_back(&vec, PBox_clone(v)), PBox, {p, q}); c_foreach (i, Persons, vec) printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); @@ -57,7 +57,7 @@ int main() // Look-up Audrey! Use a (fake) temporary PBox for lookup. c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { - const PBox *v = Persons_get(&vec, (PBox){&a}); + const PBox *v = Persons_get(&vec, a); if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); } puts(""); diff --git a/examples/convert.c b/examples/convert.c index 83dc1b37..034657db 100644 --- a/examples/convert.c +++ b/examples/convert.c @@ -16,7 +16,7 @@ int main() c_auto (cvec_str, keys, values) c_auto (clist_str, list) { - c_apply_pair(cmap_str, emplace, &map, { + c_apply(v, cmap_str_emplace(&map, c_pair(v)), cmap_str_rawvalue, { {"green", "#00ff00"}, {"blue", "#0000ff"}, {"yellow", "#ffff00"}, diff --git a/examples/cpque.c b/examples/cpque.c index 0b8a610c..d3ad2d0c 100644 --- a/examples/cpque.c +++ b/examples/cpque.c @@ -37,11 +37,11 @@ int main() print_queue(q); icmp_fn = imin_cmp; - c_apply_n(ipque, push, &q2, data, n); + c_apply_arr(v, ipque_push(&q2, v), int, data, n); print_queue(q2); icmp_fn = imix_cmp; - c_apply_n(ipque, push, &q3, data, n); + c_apply_arr(v, ipque_push(&q3, v), int, data, n); print_queue(q3); } } diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c index 9cf65389..7b179bef 100644 --- a/examples/csmap_erase.c +++ b/examples/csmap_erase.c @@ -36,8 +36,8 @@ int main() c_auto (mymap, m2) { - // Fill in some data to test with, one at a time, using c_apply_pair() - c_apply_pair(mymap, emplace, &m2, { + // Fill in some data to test with, one at a time, using c_apply() + c_apply(v, mymap_emplace(&m2, c_pair(v)), mymap_rawvalue, { {10, "Bob"}, {11, "Rob"}, {12, "Robert"}, diff --git a/examples/csmap_find.c b/examples/csmap_find.c index 3ca7ff87..c70e0523 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -45,7 +45,8 @@ int main() c_auto (csmap_istr, m1) c_auto (cvec_istr, v) { - c_apply_pair(csmap_istr, emplace, &m1, {{40, "Zr"}, {45, "Rh"}}); + c_apply(v, csmap_istr_emplace(&m1, c_pair(v)), csmap_istr_rawvalue, + {{40, "Zr"}, {45, "Rh"}}); puts("The starting map m1 is (key, value):"); print_collection_csmap_istr(m1); diff --git a/examples/csmap_insert.c b/examples/csmap_insert.c index c3690c83..1b89915e 100644 --- a/examples/csmap_insert.c +++ b/examples/csmap_insert.c @@ -99,7 +99,8 @@ int main() c_auto (csmap_ii, m4) { // Insert the elements from an initializer_list - c_apply_pair(csmap_ii, insert, &m4, { { 4, 44 }, { 2, 22 }, { 3, 33 }, { 1, 11 }, { 5, 55 } }); + c_apply(v, csmap_ii_insert(&m4, c_pair(v)), csmap_ii_rawvalue, + { { 4, 44 }, { 2, 22 }, { 3, 33 }, { 1, 11 }, { 5, 55 } }); puts("After initializer_list insertion, m4 contains:"); print_ii(m4); puts(""); diff --git a/examples/csset_erase.c b/examples/csset_erase.c index 95145ed8..485e78de 100644 --- a/examples/csset_erase.c +++ b/examples/csset_erase.c @@ -7,7 +7,8 @@ int main() { c_auto (csset_int, set) { - c_apply(csset_int, insert, &set, {30, 20, 80, 40, 60, 90, 10, 70, 50}); + c_apply(v, csset_int_insert(&set, v), + int, {30, 20, 80, 40, 60, 90, 10, 70, 50}); c_foreach (k, csset_int, set) printf(" %d", *k.ref); puts(""); diff --git a/examples/inits.c b/examples/inits.c index a1733caf..3f62b9fc 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -41,7 +41,7 @@ int main(void) // PRIORITY QUEUE - c_apply_n(cpque_f, push, &floats, nums, c_arraylen(nums)); + c_apply_arr(v, cpque_f_push(&floats, v), float, nums, c_arraylen(nums)); puts("\npop and show high priorites first:"); while (! cpque_f_empty(floats)) { @@ -67,7 +67,7 @@ int main(void) // CMAP CNT c_auto (cmap_cnt, countries) { - c_apply_pair(cmap_cnt, emplace, &countries, { + c_apply(v, cmap_cnt_emplace(&countries, c_pair(v)), cmap_cnt_rawvalue, { {"Norway", 100}, {"Denmark", 50}, {"Iceland", 10}, @@ -90,7 +90,8 @@ int main(void) // CVEC PAIR c_auto (cvec_ip, pairs1) { - c_apply(cvec_ip, push_back, &pairs1, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); + c_apply(p, cvec_ip_push_back(&pairs1, p), ipair_t, + {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); cvec_ip_sort(&pairs1); c_foreach (i, cvec_ip, pairs1) @@ -101,7 +102,8 @@ int main(void) // CLIST PAIR c_auto (clist_ip, pairs2) { - c_apply(clist_ip, push_back, &pairs2, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); + c_apply(p, clist_ip_push_back(&pairs2, p), ipair_t, + {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); clist_ip_sort(&pairs2); c_foreach (i, clist_ip, pairs2) diff --git a/examples/list.c b/examples/list.c index d0d377f3..84f4e24c 100644 --- a/examples/list.c +++ b/examples/list.c @@ -36,7 +36,7 @@ int main() { puts(""); clist_fx_clear(&list); - c_apply(clist_fx, push_back, &list, {10, 20, 30, 40, 30, 50}); + c_apply(v, clist_fx_push_back(&list, v), int, {10, 20, 30, 40, 30, 50}); c_foreach (i, clist_fx, list) printf(" %g", *i.ref); puts(""); diff --git a/examples/list_erase.c b/examples/list_erase.c index c567f043..b20f3fb1 100644 --- a/examples/list_erase.c +++ b/examples/list_erase.c @@ -8,7 +8,7 @@ int main () { c_auto (clist_int, L) { - c_apply(clist_int, push_back, &L, {10, 20, 30, 40, 50}); + c_apply(i, clist_int_push_back(&L, i), int, {10, 20, 30, 40, 50}); c_foreach (x, clist_int, L) printf("%d ", *x.ref); puts(""); // 10 20 30 40 50 diff --git a/examples/list_splice.c b/examples/list_splice.c index f1049288..0738e9d3 100644 --- a/examples/list_splice.c +++ b/examples/list_splice.c @@ -17,8 +17,8 @@ int main () { c_auto (clist_i, list1, list2) { - c_apply(clist_i, push_back, &list1, {1, 2, 3, 4, 5}); - c_apply(clist_i, push_back, &list2, {10, 20, 30, 40, 50}); + c_apply(v, clist_i_push_back(&list1, v), int, {1, 2, 3, 4, 5}); + c_apply(v, clist_i_push_back(&list2, v), int, {10, 20, 30, 40, 50}); print_ilist("list1:", list1); print_ilist("list2:", list2); diff --git a/examples/new_list.c b/examples/new_list.c index 0867c7a6..b6718d34 100644 --- a/examples/new_list.c +++ b/examples/new_list.c @@ -39,7 +39,8 @@ int main() clist_i32_push_back(&lst, 123); c_auto (clist_pnt, plst) { - c_apply(clist_pnt, push_back, &plst, {{42, 14}, {32, 94}, {62, 81}}); + c_apply(v, clist_pnt_push_back(&plst, v), + Point, {{42, 14}, {32, 94}, {62, 81}}); clist_pnt_sort(&plst); c_foreach (i, clist_pnt, plst) @@ -48,7 +49,8 @@ int main() } c_auto (clist_float, flst) { - c_apply(clist_float, push_back, &flst, {123.3, 321.2, -32.2, 78.2}); + c_apply(v, clist_float_push_back(&flst, v), + float, {123.3f, 321.2f, -32.2f, 78.2f}); c_foreach (i, clist_float, flst) printf(" %g", *i.ref); } diff --git a/examples/new_map.c b/examples/new_map.c index 953ca793..1c27d5bf 100644 --- a/examples/new_map.c +++ b/examples/new_map.c @@ -48,19 +48,19 @@ int main() { cmap_int_insert(&map, 123, 321); - c_apply_pair(cmap_pnt, insert, &pmap, { + c_apply(v, cmap_pnt_insert(&pmap, c_pair(v)), cmap_pnt_rawvalue, { {{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3} }); c_foreach (i, cmap_pnt, pmap) printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); puts(""); - c_apply_pair(cmap_str, emplace, &smap, { + c_apply(v, cmap_str_emplace(&smap, c_pair(v)), cmap_str_rawvalue, { {"Hello, friend", "long time no see"}, {"So long, friend", "see you around"}, }); - c_apply(cset_str, emplace, &sset, { + c_apply(v, cset_str_emplace(&sset, v), const char*, { "Hello, friend", "Nice to see you again", "So long, friend", diff --git a/examples/new_sptr.c b/examples/new_sptr.c index d1eed636..ce31478e 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -27,16 +27,16 @@ void Person_drop(Person* p) { #include int main(void) { - c_autovar (csptr_person p = csptr_person_new(Person_new("John", "Smiths")), csptr_person_drop(&p)) + c_autovar (csptr_person p = csptr_person_from(Person_new("John", "Smiths")), csptr_person_drop(&p)) c_autovar (csptr_person q = csptr_person_clone(p), csptr_person_drop(&q)) // share the pointer { printf("%s %s. uses: %lu\n", q.get->name.str, q.get->last.str, *q.use_count); } c_auto (cstack_iptr, stk) { - cstack_iptr_push(&stk, csptr_int_new(10)); - cstack_iptr_push(&stk, csptr_int_new(20)); - cstack_iptr_push(&stk, csptr_int_new(30)); + cstack_iptr_push(&stk, csptr_int_from(10)); + cstack_iptr_push(&stk, csptr_int_from(20)); + cstack_iptr_push(&stk, csptr_int_from(30)); cstack_iptr_emplace(&stk, *cstack_iptr_top(&stk)); cstack_iptr_emplace(&stk, *cstack_iptr_begin(&stk).ref); diff --git a/examples/phonebook.c b/examples/phonebook.c index 640aaec3..064de93f 100644 --- a/examples/phonebook.c +++ b/examples/phonebook.c @@ -42,14 +42,15 @@ int main(int argc, char **argv) c_static_assert(sizeof argc == 4); c_auto (cset_str, names) { - c_apply(cset_str, emplace, &names, {"Hello", "Cool", "True"}); + c_apply(v, cset_str_emplace(&names, v), const char*, + {"Hello", "Cool", "True"}); c_foreach (i, cset_str, names) printf("%s ", i.ref->str); puts(""); } bool erased; c_auto (cmap_str, phone_book) { - c_apply_pair (cmap_str, emplace, &phone_book, { + c_apply(v, cmap_str_emplace(&phone_book, c_pair(v)), cmap_str_rawvalue, { {"Lilia Friedman", "(892) 670-4739"}, {"Tariq Beltran", "(489) 600-7575"}, {"Laiba Juarez", "(303) 885-5692"}, diff --git a/examples/priority.c b/examples/priority.c index 5164d85d..184cad9f 100644 --- a/examples/priority.c +++ b/examples/priority.c @@ -20,7 +20,7 @@ int main() { cpque_i_push(&heap, stc64_uniform(&rng, &dist)); // push some negative numbers too. - c_apply(cpque_i, push, &heap, {-231, -32, -873, -4, -343}); + c_apply(v, cpque_i_push(&heap, v), int, {-231, -32, -873, -4, -343}); c_forrange (N) cpque_i_push(&heap, stc64_uniform(&rng, &dist)); diff --git a/examples/sidebyside.cpp b/examples/sidebyside.cpp index 0f645991..cf4b2f70 100644 --- a/examples/sidebyside.cpp +++ b/examples/sidebyside.cpp @@ -19,7 +19,8 @@ int main() { } c_auto (cmap_str, food) { - c_apply_pair(cmap_str, emplace, &food, {{"burger", 5}, {"pizza", 12}, {"steak", 15}}); + c_apply(v, cmap_str_emplace(&food, c_pair(v)), cmap_str_rawvalue, + {{"burger", 5}, {"pizza", 12}, {"steak", 15}}); c_foreach (i, cmap_str, food) printf("%s, %d\n", i.ref->first.str, i.ref->second); puts(""); diff --git a/examples/sptr.c b/examples/sptr.c index 7e0f7357..e1d734e0 100644 --- a/examples/sptr.c +++ b/examples/sptr.c @@ -28,7 +28,7 @@ void Person_drop(Person* p) { #include #define i_type Persons -#define i_val_bind PSPtr // binds PSPtr_cmp, ... +#define i_val_ref PSPtr // binds PSPtr_cmp, ... #include @@ -37,30 +37,31 @@ int main() c_auto (Persons, vec) c_auto (PSPtr, p, q) { - p = PSPtr_new(Person_new("Laura", "Palmer")); + p = PSPtr_from(Person_new("Laura", "Palmer")); // We want a deep copy -- PSPtr_clone(p) only shares! - q = PSPtr_new(Person_clone(*p.get)); + q = PSPtr_from(Person_clone(*p.get)); cstr_assign(&q.get->name, "Leland"); printf("orig: %s %s\n", p.get->name.str, p.get->last.str); printf("copy: %s %s\n", q.get->name.str, q.get->last.str); - Persons_push_back(&vec, PSPtr_new(Person_new("Dale", "Cooper"))); - Persons_push_back(&vec, PSPtr_new(Person_new("Audrey", "Home"))); - - // NB! Clone/share p and q to the vector using emplace_back() - c_apply(Persons, emplace_back, &vec, {p, q}); + Persons_push_back(&vec, PSPtr_from(Person_new("Dale", "Cooper"))); + Persons_push_back(&vec, PSPtr_from(Person_new("Audrey", "Home"))); + + // Clone/share p and q to the vector + c_apply(v, Persons_push_back(&vec, PSPtr_clone(v)), PSPtr, {p, q}); c_foreach (i, Persons, vec) printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); puts(""); - - // Look-up Audrey! Use a (fake) temporary PSPtr for lookup. + + // Look-up Audrey! c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { - const PSPtr *v = Persons_get(&vec, (PSPtr){&a}); + const PSPtr *v = Persons_get(&vec, a); if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); } + puts(""); } } diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c index a6b33de6..a5c642b0 100644 --- a/examples/sptr_demo.c +++ b/examples/sptr_demo.c @@ -13,10 +13,10 @@ void int_drop(int* x) { #define i_drop int_drop // optional, just to display the elements destroyed #include // iref -#define i_key_bind iref // note: use i_key_bind instead of i_key for csptr/cbox elements +#define i_key_ref iref // note: use i_key_bind instead of i_key for csptr/cbox elements #include // csset_iref (like: std::set>) -#define i_val_bind iref // note: as above. +#define i_val_ref iref // note: as above. #include // cvec_iref (like: std::vector>) int main() @@ -26,7 +26,7 @@ int main() { const int years[] = {2021, 2012, 2022, 2015}; c_forrange (i, c_arraylen(years)) - cvec_iref_push_back(&vec, iref_new(years[i])); + cvec_iref_push_back(&vec, iref_from(years[i])); printf("vec:"); c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); @@ -35,7 +35,7 @@ int main() // add odd numbers from vec to set c_foreach (i, cvec_iref, vec) if (*i.ref->get & 1) - csset_iref_emplace(&set, *i.ref); // copy shared pointer => increments counter. + csset_iref_insert(&set, iref_clone(*i.ref)); // copy shared pointer => increments counter. // erase the two last elements in vec cvec_iref_pop_back(&vec); diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c index 240b9a58..fbb141b4 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -9,11 +9,10 @@ void show_drop(int* x) { printf("drop: %d\n", *x); } // if 'i_opt c_no_cmp' is defined, otherwise i_cmp is used // to compare object values. See the twodifferences by // commenting out the next line. -//#define i_opt c_no_cmp #include // Shared pointer to int #define i_type Vec -#define i_val_bind Arc +#define i_val_ref Arc #include // Vec: cvec @@ -23,11 +22,11 @@ int main() { const int v[] = {2012, 1990, 2012, 2019, 2015}; c_forrange (i, c_arraylen(v)) - Vec_push_back(&vec, Arc_new(v[i])); + Vec_push_back(&vec, Arc_from(v[i])); // clone the second 2012 and push it back. // note: cloning make sure that vec.data[2] has ref count 2. - Vec_emplace_back(&vec, vec.data[2]); + Vec_push_back(&vec, Arc_clone(vec.data[2])); printf("vec before erase :"); c_foreach (i, Vec, vec) @@ -36,12 +35,12 @@ int main() printf("erase vec.data[2]; or first matching value depending on compare.\n"); Vec_iter it; - it = Vec_find(&vec, vec.data[2]); + it = Vec_find(&vec, *vec.data[2].get); if (it.ref != Vec_end(&vec).ref) Vec_erase_at(&vec, it); int year = 2015; - it = Vec_find(&vec, (Arc){&year}); // Ok as tmp only. + it = Vec_find(&vec, year); // Ok as tmp only. if (it.ref != Vec_end(&vec).ref) Vec_erase_at(&vec, it); diff --git a/examples/sptr_music.c b/examples/sptr_music.c index 04ec28cc..1d58cc46 100644 --- a/examples/sptr_music.c +++ b/examples/sptr_music.c @@ -17,36 +17,36 @@ void Song_drop(Song* s) { c_drop(cstr, &s->artist, &s->title); } +#define i_type SongPtr #define i_val Song #define i_drop Song_drop #define i_opt c_no_cmp -#define i_tag song -#include // define csptr_song +#include -#define i_val_bind csptr_song -#define i_tag song +#define i_type SongVec +#define i_val_ref SongPtr #include void example3() { - c_auto (cvec_song, v, v2) + c_auto (SongVec, vec, vec2) { - c_apply(cvec_song, push_back, &v, { - csptr_song_new(Song_new("Bob Dylan", "The Times They Are A Changing")), - csptr_song_new(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), - csptr_song_new(Song_new("Thalia", "Entre El Mar y Una Estrella")) + c_apply(v, SongVec_push_back(&vec, v), SongPtr, { + SongPtr_from(Song_new("Bob Dylan", "The Times They Are A Changing")), + SongPtr_from(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), + SongPtr_from(Song_new("Thalia", "Entre El Mar y Una Estrella")) }); - c_foreach (s, cvec_song, v) + c_foreach (s, SongVec, vec) if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) - cvec_song_emplace_back(&v2, *s.ref); // note: calls csptr_song_clone() + SongVec_push_back(&vec2, SongPtr_clone(*s.ref)); - c_apply(cvec_song, push_back, &v2, { - csptr_song_new(Song_new("Michael Jackson", "Billie Jean")), - csptr_song_new(Song_new("Rihanna", "Stay")), + c_apply(v, SongVec_push_back(&vec2, v), SongPtr, { + SongPtr_from(Song_new("Michael Jackson", "Billie Jean")), + SongPtr_from(Song_new("Rihanna", "Stay")), }); - c_foreach (s, cvec_song, v2) + c_foreach (s, SongVec, vec2) printf("%s - %s: refs %lu\n", s.ref->get->artist.str, s.ref->get->title.str, *s.ref->use_count); } diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c index 501fdcef..d71ce97d 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -33,7 +33,7 @@ void* thr(csptr_base* lp) int main() { - csptr_base p = csptr_base_new((Base){42}); + csptr_base p = csptr_base_from((Base){42}); printf("Created a Base\n" " p.get() = %p, p.use_count() = %ld\n", (void*)p.get, *p.use_count); diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c index 69798563..6b4dd359 100644 --- a/examples/sptr_to_maps.c +++ b/examples/sptr_to_maps.c @@ -15,11 +15,11 @@ #include #define i_type Stack -#define i_val_bind Arc // define i_val_bind for csptr/cbox value (not i_val) +#define i_val_ref Arc // define i_val_bind for csptr/cbox value (not i_val) #include #define i_type List -#define i_val_bind Arc // as above +#define i_val_ref Arc // as above #include int main() @@ -29,28 +29,28 @@ int main() { // POPULATE stack with shared pointers to Maps: Map *map; - map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }); - map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }); // POPULATE list: - map = List_push_back(&list, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { + map = List_push_back(&list, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); // Share two Maps from the stack with the list using emplace (clone the csptr): - List_emplace_back(&list, stack.data[0]); - List_emplace_back(&list, stack.data[1]); + List_push_back(&list, Arc_clone(stack.data[0])); + List_push_back(&list, Arc_clone(stack.data[1])); // Clone (deep copy) a Map from the stack to the list // List will contain two shared and two unshared maps. - map = List_push_back(&list, Arc_new(Map_clone(*stack.data[1].get)))->get; + map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; // Add one more element to the cloned map: Map_emplace_or_assign(map, "CLONED", 2021); diff --git a/examples/vikings.c b/examples/vikings.c index 7a953059..9900e9b6 100644 --- a/examples/vikings.c +++ b/examples/vikings.c @@ -49,7 +49,7 @@ static inline RViking Viking_toraw(const Viking* vk) { int main() { c_auto (Vikings, vikings) { - c_apply_pair(Vikings, emplace, &vikings, { + c_apply(v, Vikings_emplace(&vikings, c_pair(v)), Vikings_rawvalue, { {{"Einar", "Norway"}, 20}, {{"Olaf", "Denmark"}, 24}, {{"Harald", "Iceland"}, 12}, diff --git a/examples/words.c b/examples/words.c index 6c0636dc..568f9557 100644 --- a/examples/words.c +++ b/examples/words.c @@ -13,7 +13,7 @@ int main1() c_auto (cvec_str, words) c_auto (cmap_str, word_map) { - c_apply(cvec_str, emplace_back, &words, { + c_apply(v, cvec_str_emplace_back(&words, v), const char*, { "this", "sentence", "is", "not", "a", "sentence", "this", "sentence", "is", "a", "hoax" }); diff --git a/include/stc/cbox.h b/include/stc/cbox.h index bcd9bd8c..37687134 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -86,10 +86,15 @@ STC_INLINE _cx_self _cx_memb(_from_ptr)(i_val* p) { return c_make(_cx_self){p}; } STC_INLINE _cx_self -_cx_memb(_new)(i_val val) { +_cx_memb(_from)(i_val val) { return c_make(_cx_self){c_new(i_val, val)}; } +STC_INLINE i_val +_cx_memb(_toraw)(const _cx_self* self) { + return *self->get; +} + // destructor STC_INLINE void _cx_memb(_drop)(_cx_self* self) { @@ -109,16 +114,18 @@ _cx_memb(_reset)(_cx_self* self) { // take ownership of val STC_INLINE void -_cx_memb(_reset_new)(_cx_self* self, i_val val) { +_cx_memb(_reset_from)(_cx_self* self, i_val val) { if (self->get) { i_valdrop(self->get); *self->get = val; } else self->get = c_new(i_val, val); } -#if !c_option(c_no_clone) +#if !c_option(c_no_clone) + //#ifndef _i_valraw_default STC_INLINE _cx_self - _cx_memb(_from)(i_valraw raw) { + _cx_memb(_new)(i_valraw raw) { return c_make(_cx_self){c_new(i_val, i_valfrom(raw))}; } + //#endif STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { @@ -141,29 +148,29 @@ _cx_memb(_take)(_cx_self* self, _cx_self other) { } STC_INLINE uint64_t -_cx_memb(_hash)(const _cx_self* self, size_t n) { +_cx_memb(_value_hash)(const _cx_value* x, size_t n) { #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX - return c_hash64(&self->get, 8); + return c_hash64(&x, 8); #elif c_option(c_no_cmp) - return c_hash32(&self->get, 4); + return c_hash32(&x, 4); #else - i_valraw rx = i_valto(self->get); + i_valraw rx = i_valto(x); return i_hash(&rx, sizeof rx); #endif } STC_INLINE int -_cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { #if c_option(c_no_cmp) - return c_default_cmp(&x->get, &y->get); + return c_default_cmp(&x, &y); #else - i_valraw rx = i_valto(x->get), ry = i_valto(x->get); + i_valraw rx = i_valto(x), ry = i_valto(x); return i_cmp(&rx, &ry); #endif } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - return !_cx_memb(_cmp)(x, y); +_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { + return !_cx_memb(_value_cmp)(x, y); } #include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 9cbe24a4..e11fa3be 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -189,23 +189,37 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { *b = (n)*sizeof *b > (BYTES) ? c_alloc_n(type, n) : _c_b \ ; b; b != _c_b ? c_free(b) : (void)0, b = NULL) -#define c_apply(C, method, cx, ...) do { \ +#define c_apply(v, method, T, ...) do { \ + const T _c_arr[] = __VA_ARGS__; \ + for (size_t index = 0; index < c_arraylen(_c_arr); ++index) \ + { const T v = _c_arr[index]; method; } \ +} while (0) +#define c_apply_arr(v, method, T, arr, n) do { \ + const T* _c_arr = arr; size_t _n = n; \ + for (size_t index = 0; index < _n; ++index) \ + { const T v = _c_arr[index]; method; } \ +} while (0) +#define c_apply_it(v, method, C, ...) do { \ + size_t index = 0; \ + c_foreach (_it, C, __VA_ARGS__) \ + { const C##_value v = *_it.ref; method; ++index; } \ +} while (0) +#define c_pair(v) (v).first, (v).second + +// [deprecated] +#define c_apply_OLD(C, method, cx, ...) do { \ const C##_rawvalue _c_arr[] = __VA_ARGS__; \ C* _c_cx = cx; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ C##_##method(_c_cx, _c_arr[_c_i]); \ } while (0) -#define c_apply_pair(C, method, cx, ...) do { \ +// [deprecated] +#define c_apply_pair_OLD(C, method, cx, ...) do { \ const C##_rawvalue _c_arr[] = __VA_ARGS__; \ C* _c_cx = cx; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ C##_##method(_c_cx, _c_arr[_c_i].first, _c_arr[_c_i].second); \ } while (0) -#define c_apply_n(C, method, cx, arr, n) do { \ - C* _c_cx = cx; \ - for (const C##_rawvalue *_c_i = arr, *_c_end = _c_i+(n); _c_i != _c_end; ++_c_i) \ - C##_##method(_c_cx, *_c_i); \ -} while (0) #define c_drop(C, ...) do { \ C* _c_arr[] = {__VA_ARGS__}; \ diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 92ed05ef..4e9b4687 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -104,13 +104,17 @@ _cx_memb(_from_ptr)(_cx_value* p) { } STC_INLINE _cx_self -_cx_memb(_new)(i_val val) { +_cx_memb(_from)(i_val val) { _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; } +STC_INLINE i_val _cx_memb(_toraw)(const _cx_self* self) { + return *self->get; +} + STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { _cx_self ptr = *self; @@ -135,15 +139,15 @@ _cx_memb(_reset)(_cx_self* self) { } STC_INLINE void -_cx_memb(_reset_new)(_cx_self* self, i_val val) { +_cx_memb(_reset_from)(_cx_self* self, i_val val) { _cx_memb(_drop)(self); - *self = _cx_memb(_new)(val); + *self = _cx_memb(_from)(val); } -#if !c_option(c_no_clone) - STC_INLINE _cx_self _cx_memb(_from)(i_valraw raw) { - return _cx_memb(_new)(i_valfrom(raw)); -} +#if !c_option(c_no_clone) && !defined _i_valraw_default + STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { + return _cx_memb(_from)(i_valfrom(raw)); + } #endif // does not use i_valfrom, so we can bypass c_no_clone @@ -167,30 +171,30 @@ _cx_memb(_take)(_cx_self* self, _cx_self ptr) { } STC_INLINE uint64_t -_cx_memb(_hash)(const _cx_self* self, size_t n) { +_cx_memb(_value_hash)(const _cx_value* x, size_t n) { #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX - return c_hash64(&self->get, 8); + return c_hash64(&x, 8); #elif c_option(c_no_cmp) - return c_hash32(&self->get, 4); + return c_hash32(&x, 4); #else - i_valraw rx = i_valto(self->get); + i_valraw rx = i_valto(x); return i_hash(&rx, sizeof rx); #endif } STC_INLINE int -_cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { #if c_option(c_no_cmp) - return c_default_cmp(&x->get, &y->get); + return c_default_cmp(&x, &y); #else - i_valraw rx = i_valto(x->get), ry = i_valto(x->get); + i_valraw rx = i_valto(x), ry = i_valto(x); return i_cmp(&rx, &ry); #endif } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - return !_cx_memb(_cmp)(x, y); +_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { + return !_cx_memb(_value_cmp)(x, y); } #undef _i_atomic_inc #undef _i_atomic_dec_and_test diff --git a/include/stc/template.h b/include/stc/template.h index 83a362d7..675baa47 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -40,14 +40,6 @@ #define _cx_size _cx_memb(_size_t) #endif -#if defined i_key_csptr || defined i_key_ref // [deprecated] - #define i_key_bind i_key_csptr - #error "i_key_csptr/ref no longer supported: use new name i_key_bind" -#endif -#if defined i_val_csptr || defined i_val_ref // [deprecated] - #define i_val_bind i_val_csptr - #error "i_val_sptr/ref no longer supported: use new name i_val_bind" -#endif #if defined i_cnt || defined i_equ // [deprecated] #define i_type i_cnt #error "i_cnt and i_equ no longer supported: use new name i_type / i_eq" @@ -69,6 +61,9 @@ #ifndef i_tag #define i_tag str #endif +#elif defined i_key_ref + #define i_key_bind i_key_ref + #define i_keyraw c_PASTE(i_key_ref, _value) #endif #ifdef i_key_bind @@ -125,6 +120,9 @@ #if !defined i_tag && !defined i_key #define i_tag str #endif +#elif defined i_val_ref + #define i_val_bind i_val_ref + #define i_valraw c_PASTE(i_val_ref, _value) #endif #ifdef i_val_bind @@ -167,6 +165,7 @@ #define i_keyfrom c_default_clone #endif #ifndef i_keyraw + #define _i_keyraw_default #define i_keyraw i_key #define i_keyto c_default_toraw #endif @@ -192,6 +191,7 @@ #define i_valfrom c_default_clone #endif #ifndef i_valraw + #define _i_valraw_default #define i_valraw i_val #define i_valto c_default_toraw #endif @@ -219,6 +219,7 @@ #undef i_val #undef i_val_str +#undef i_val_ref #undef i_val_bind #undef i_valraw #undef i_valfrom @@ -227,6 +228,7 @@ #undef i_key #undef i_key_str +#undef i_key_ref #undef i_key_bind #undef i_keyraw #undef i_keyfrom @@ -234,6 +236,8 @@ #undef i_keydrop #undef _i_prefix +#undef _i_valraw_default +#undef _i_keyraw_default #undef _i_has_internal_clone #undef _i_template #endif -- cgit v1.2.3 From f69f26927edb7e2850a5a235ed5117f278f437a1 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 09:07:40 +0100 Subject: Renamed '_rawvalue\b' to '_raw' --- README.md | 10 +++++----- docs/ccommon_api.md | 2 +- docs/cdeq_api.md | 4 ++-- docs/clist_api.md | 4 ++-- docs/cmap_api.md | 10 +++++----- docs/cqueue_api.md | 2 +- docs/cset_api.md | 2 +- docs/csmap_api.md | 8 ++++---- docs/csptr_api.md | 6 +++--- docs/csset_api.md | 2 +- docs/cstack_api.md | 8 ++++---- docs/cvec_api.md | 4 ++-- examples/convert.c | 2 +- examples/csmap_erase.c | 2 +- examples/csmap_find.c | 6 +++--- examples/csmap_insert.c | 4 ++-- examples/inits.c | 2 +- examples/new_map.c | 4 ++-- examples/phonebook.c | 2 +- examples/sidebyside.cpp | 2 +- examples/sptr_to_maps.c | 6 +++--- examples/vikings.c | 2 +- include/stc/alt/clist.h | 6 +++--- include/stc/alt/csmap.h | 4 ++-- include/stc/cbox.h | 2 +- include/stc/ccommon.h | 4 ++-- include/stc/cdeq.h | 8 ++++---- include/stc/clist.h | 2 +- include/stc/cmap.h | 6 +++--- include/stc/cpque.h | 2 +- include/stc/csmap.h | 6 +++--- include/stc/csptr.h | 2 +- include/stc/cstack.h | 4 ++-- include/stc/cvec.h | 8 ++++---- include/stc/template.h | 2 +- 35 files changed, 75 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index ad286305..e8d9d34b 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ Replace (whole word + match case): - Added [**cbox**](docs/cbox_api.md) type: container of one element, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) - Added [example for **csptr**](examples/sptr_to_maps.c). - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". -- Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. -- Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*. -- Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_bind` / `i_val_bind` for types that has required functions defined. -- Deprecated `i_cnt`. Use `i_type` instead to define the complete container type name. +- Renamed: *csptr_X_make()* to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. +- Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. +- Renamed: `i_key_csptr` / `i_val_csptr`. Use `i_key_sptr` / `i_val_sptr` for **csptr** and **cbox**. +- Renamed: `i_cnt` to `i_type` for defining the complete container type name. - Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` ### Version 2.0. Two main breaking changes from V1.X. @@ -200,7 +200,7 @@ int main(void) { c_apply(v, clist_int_push_back(&lst, v), int, {10, 20, 30}); c_apply(v, cstack_int_push(&stk, v), int, {10, 20, 30}); c_apply(v, csmap_int_insert(&map, c_pair(v)), - csmap_int_rawvalue, { {20, 2}, {10, 1}, {30, 3} }); + csmap_int_raw, { {20, 2}, {10, 1}, {30, 3} }); // add one more element to each container cset_int_insert(&set, 40); diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index eec56490..9c872519 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -137,7 +137,7 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i); // apply multiple push_backs c_apply(v, cvec_i_push_back(&vec, v), int, {1, 2, 3}); // inserts to existing map -c_apply(v, cmap_i_insert(&map, c_pair(v)), cmap_i_rawvalue, { {4, 5}, {6, 7} }); +c_apply(v, cmap_i_insert(&map, c_pair(v)), cmap_i_raw, { {4, 5}, {6, 7} }); int arr[] = {1, 2, 3}; c_apply_arr(v, cvec_i_push_back(&vec, v), int, arr, c_arraylen(arr)); diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index ce14184f..b884c62d 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -78,7 +78,7 @@ cdeq_X_iter cdeq_X_begin(const cdeq_X* self); cdeq_X_iter cdeq_X_end(const cdeq_X* self); void cdeq_X_next(cdeq_X_iter* it); -cdeq_X_rawvalue cdeq_X_value_toraw(cdeq_X_value* pval); +cdeq_X_raw cdeq_X_value_toraw(cdeq_X_value* pval); cdeq_X_value cdeq_X_value_clone(cdeq_X_value val); ``` @@ -88,7 +88,7 @@ cdeq_X_value cdeq_X_value_clone(cdeq_X_value val); |:-------------------|:------------------------------------|:-----------------------| | `cdeq_X` | `struct { cdeq_X_value* data; }` | The cdeq type | | `cdeq_X_value` | `i_val` | The cdeq value type | -| `cdeq_X_rawvalue` | `i_valraw` | The raw value type | +| `cdeq_X_raw` | `i_valraw` | The raw value type | | `cdeq_X_iter` | `struct { cdeq_X_value* ref; }` | The iterator type | ## Examples diff --git a/docs/clist_api.md b/docs/clist_api.md index 41fbd274..fc54f40e 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -81,7 +81,7 @@ clist_X_iter clist_X_end(const clist_X* self); void clist_X_next(clist_X_iter* it); clist_X_iter clist_X_advance(clist_X_iter it, size_t n); // return n elements ahead. -clist_X_rawvalue clist_X_value_toraw(clist_X_value* pval); +clist_X_raw clist_X_value_toraw(clist_X_value* pval); clist_X_value clist_X_value_clone(clist_X_value val); ``` @@ -91,7 +91,7 @@ clist_X_value clist_X_value_clone(clist_X_value val); |:--------------------|:------------------------------------|:--------------------------| | `clist_X` | `struct { clist_X_node* last; }` | The clist type | | `clist_X_value` | `i_val` | The clist element type | -| `clist_X_rawvalue` | `i_valraw` | clist raw value type | +| `clist_X_raw` | `i_valraw` | clist raw value type | | `clist_X_iter` | `struct { clist_value *ref; ... }` | clist iterator | ## Example diff --git a/docs/cmap_api.md b/docs/cmap_api.md index b7a08e3e..38346e53 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -76,7 +76,7 @@ cmap_X_iter cmap_X_end(const cmap_X* self); void cmap_X_next(cmap_X_iter* it); cmap_X_value cmap_X_value_clone(cmap_X_value val); -cmap_X_rawvalue cmap_X_value_toraw(cmap_X_value* pval); +cmap_X_raw cmap_X_value_toraw(cmap_X_value* pval); ``` Helpers: ```c @@ -101,7 +101,7 @@ bool c_rawstr_eq(const char* const* a, const char* const* b); // | `cmap_X` | `struct { ... }` | The cmap type | | `cmap_X_rawkey` | `i_keyraw` | The raw key type | | `cmap_X_rawmapped` | `i_valraw` | The raw mapped type | -| `cmap_X_rawvalue` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw + i_valraw type | +| `cmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw + i_valraw type | | `cmap_X_key` | `i_key` | The key type | | `cmap_X_mapped` | `i_val` | The mapped type | | `cmap_X_value` | `struct { const i_key first; i_val second; }` | The value: key is immutable | @@ -122,7 +122,7 @@ int main() // Create an unordered_map of three strings (that map to strings) c_auto (cmap_str, u) { - c_apply(v, cmap_str_emplace(&u, c_pair(v)), cmap_str_rawvalue, { + c_apply(v, cmap_str_emplace(&u, c_pair(v)), cmap_str_raw, { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"} @@ -168,7 +168,7 @@ int main() c_auto (cmap_id, idnames) { - c_apply(v, cmap_id_emplace(&idnames, c_pair(v)), cmap_id_rawvalue, { + c_apply(v, cmap_id_emplace(&idnames, c_pair(v)), cmap_id_raw, { {100, "Red"}, {110, "Blue"} }); // replace existing mapped value: @@ -384,7 +384,7 @@ static inline RViking Viking_toraw(const Viking* vk) { int main() { c_auto (Vikings, vikings) { - c_apply(v, Vikings_emplace(&vikings, v), c_pair(v), Vikings_rawvalue, { + c_apply(v, Vikings_emplace(&vikings, v), c_pair(v), Vikings_raw, { {{"Einar", "Norway"}, 20}, {{"Olaf", "Denmark"}, 24}, {{"Harald", "Iceland"}, 12}, diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index 9fd2c4e0..0ecae014 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -52,7 +52,7 @@ i_val cqueue_X_value_clone(i_val value); |:--------------------|:---------------------|:-------------------------| | `cqueue_X` | `cdeq_X` | The cqueue type | | `cqueue_X_value` | `i_val` | The cqueue element type | -| `cqueue_X_rawvalue` | `i_valraw` | cqueue raw value type | +| `cqueue_X_raw` | `i_valraw` | cqueue raw value type | | `cqueue_X_iter` | `cdeq_X_iter` | cqueue iterator | ## Examples diff --git a/docs/cset_api.md b/docs/cset_api.md index 479cf3f3..18454dcf 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -65,7 +65,7 @@ cset_X_value cset_X_value_clone(cset_X_value val); |:-------------------|:-------------------------------------------------|:----------------------------| | `cset_X` | `struct { ... }` | The cset type | | `cset_X_rawkey` | `i_keyraw` | The raw key type | -| `cset_X_rawvalue` | `i_keyraw` | The raw value type | +| `cset_X_raw` | `i_keyraw` | The raw value type | | `cset_X_key` | `i_key` | The key type | | `cset_X_value` | `i_key` | The value | | `cset_X_result` | `struct { cset_X_value* ref; bool inserted; }` | Result of insert/emplace | diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 3791347b..c3f71a7c 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -73,7 +73,7 @@ void csmap_X_next(csmap_X_iter* iter); csmap_X_iter csmap_X_advance(csmap_X_iter it, size_t n); csmap_X_value csmap_X_value_clone(csmap_X_value val); -csmap_X_rawvalue csmap_X_value_toraw(csmap_X_value* pval); +csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval); ``` ## Types @@ -82,7 +82,7 @@ csmap_X_rawvalue csmap_X_value_toraw(csmap_X_value* pval); | `csmap_X` | `struct { ... }` | The csmap type | | `csmap_X_rawkey` | `i_keyraw` | The raw key type | | `csmap_X_rawmapped` | `i_valraw` | The raw mapped type | -| `csmap_X_rawvalue` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw+i_valraw type | +| `csmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw+i_valraw type | | `csmap_X_key` | `i_key` | The key type | | `csmap_X_mapped` | `i_val` | The mapped type | | `csmap_X_value` | `struct { const i_key first; i_val second; }` | The value: key is immutable | @@ -100,7 +100,7 @@ int main() // Create a sorted map of three strings (maps to string) c_auto (csmap_str, colors) // RAII { - c_apply(v, csmap_str_emplace(&colors, c_pair(v)), csmap_str_rawvalue, { + c_apply(v, csmap_str_emplace(&colors, c_pair(v)), csmap_str_raw, { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"} @@ -146,7 +146,7 @@ int main() csmap_id idnames = csmap_id_init(); c_autodefer (csmap_id_drop(&idnames)) { - c_apply(v, csmap_id_emplace(&idnames, c_pair(v)), csmap_id_rawvalue, { + c_apply(v, csmap_id_emplace(&idnames, c_pair(v)), csmap_id_raw, { {100, "Red"}, {110, "Blue"}, }); diff --git a/docs/csptr_api.md b/docs/csptr_api.md index 6a48f91a..95575417 100644 --- a/docs/csptr_api.md +++ b/docs/csptr_api.md @@ -101,17 +101,17 @@ int main() // POPULATE the stack with shared pointers to Map: Map *map; map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }); map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }); // POPULATE the list: map = List_push_back(&list, Arc_new(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); diff --git a/docs/csset_api.md b/docs/csset_api.md index 62ccb638..01926453 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -60,7 +60,7 @@ csset_X_value csset_X_value_clone(csset_X_value val); |:-------------------|:--------------------------------------------------|:----------------------------| | `csset_X` | `struct { ... }` | The csset type | | `csset_X_rawkey` | `i_keyraw` | The raw key type | -| `csset_X_rawvalue` | `i_keyraw` | The raw key type | +| `csset_X_raw` | `i_keyraw` | The raw key type | | `csset_X_key` | `i_key` | The key type | | `csset_X_value` | `i_key ` | The value: key is immutable | | `csset_X_result` | `struct { csset_X_value* ref; bool inserted; }` | Result of insert/emplace | diff --git a/docs/cstack_api.md b/docs/cstack_api.md index b6992dc0..672b3168 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -55,11 +55,11 @@ i_val cstack_X_value_clone(i_val value); ## Types -| Type name | Type definition | Used to represent... | -|:--------------------|:---------------------------------------|:----------------------------| +| Type name | Type definition | Used to represent... | +|:--------------------|:-------------------------------------|:----------------------------| | `cstack_X` | `struct { cstack_value *data; ... }` | The cstack type | -| `cstack_X_value` | `i_val` | The cstack element type | -| `cstack_X_rawvalue` | `i_valraw` | cstack raw value type | +| `cstack_X_value` | `i_val` | The cstack element type | +| `cstack_X_raw` | `i_valraw` | cstack raw value type | | `cstack_X_iter` | `struct { cstack_value *ref; }` | cstack iterator | ## Example diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 2a4ceaf6..ef145b94 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -86,7 +86,7 @@ cvec_X_iter cvec_X_begin(const cvec_X* self); cvec_X_iter cvec_X_end(const cvec_X* self); void cvec_X_next(cvec_X_iter* iter); -cvec_X_rawvalue cvec_X_value_toraw(cvec_X_value* pval); +cvec_X_raw cvec_X_value_toraw(cvec_X_value* pval); cvec_X_value cvec_X_value_clone(cvec_X_value val); ``` @@ -96,7 +96,7 @@ cvec_X_value cvec_X_value_clone(cvec_X_value val); |:-------------------|:----------------------------------|:-----------------------| | `cvec_X` | `struct { cvec_X_value* data; }` | The cvec type | | `cvec_X_value` | `i_val` | The cvec value type | -| `cvec_X_rawvalue` | `i_valraw` | The raw value type | +| `cvec_X_raw` | `i_valraw` | The raw value type | | `cvec_X_iter` | `struct { cvec_X_value* ref; }` | The iterator type | ## Examples diff --git a/examples/convert.c b/examples/convert.c index 034657db..8258e1b6 100644 --- a/examples/convert.c +++ b/examples/convert.c @@ -16,7 +16,7 @@ int main() c_auto (cvec_str, keys, values) c_auto (clist_str, list) { - c_apply(v, cmap_str_emplace(&map, c_pair(v)), cmap_str_rawvalue, { + c_apply(v, cmap_str_emplace(&map, c_pair(v)), cmap_str_raw, { {"green", "#00ff00"}, {"blue", "#0000ff"}, {"yellow", "#ffff00"}, diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c index 7b179bef..68a0378b 100644 --- a/examples/csmap_erase.c +++ b/examples/csmap_erase.c @@ -37,7 +37,7 @@ int main() c_auto (mymap, m2) { // Fill in some data to test with, one at a time, using c_apply() - c_apply(v, mymap_emplace(&m2, c_pair(v)), mymap_rawvalue, { + c_apply(v, mymap_emplace(&m2, c_pair(v)), mymap_raw, { {10, "Bob"}, {11, "Rob"}, {12, "Robert"}, diff --git a/examples/csmap_find.c b/examples/csmap_find.c index c70e0523..078c7a11 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -7,12 +7,12 @@ #define i_tag istr #include -#define i_val csmap_istr_rawvalue +#define i_val csmap_istr_raw #define i_opt c_no_cmp #define i_tag istr #include -void print_elem(csmap_istr_rawvalue p) { +void print_elem(csmap_istr_raw p) { printf("(%d, %s) ", p.first, p.second); } @@ -45,7 +45,7 @@ int main() c_auto (csmap_istr, m1) c_auto (cvec_istr, v) { - c_apply(v, csmap_istr_emplace(&m1, c_pair(v)), csmap_istr_rawvalue, + c_apply(v, csmap_istr_emplace(&m1, c_pair(v)), csmap_istr_raw, {{40, "Zr"}, {45, "Rh"}}); puts("The starting map m1 is (key, value):"); print_collection_csmap_istr(m1); diff --git a/examples/csmap_insert.c b/examples/csmap_insert.c index 1b89915e..5f5813a8 100644 --- a/examples/csmap_insert.c +++ b/examples/csmap_insert.c @@ -14,7 +14,7 @@ #define i_tag istr // Map of int => cstr #include -#define i_val csmap_ii_rawvalue +#define i_val csmap_ii_raw #define i_opt c_no_cmp #define i_tag ii #include @@ -99,7 +99,7 @@ int main() c_auto (csmap_ii, m4) { // Insert the elements from an initializer_list - c_apply(v, csmap_ii_insert(&m4, c_pair(v)), csmap_ii_rawvalue, + c_apply(v, csmap_ii_insert(&m4, c_pair(v)), csmap_ii_raw, { { 4, 44 }, { 2, 22 }, { 3, 33 }, { 1, 11 }, { 5, 55 } }); puts("After initializer_list insertion, m4 contains:"); print_ii(m4); diff --git a/examples/inits.c b/examples/inits.c index 3f62b9fc..4fdc17d5 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -67,7 +67,7 @@ int main(void) // CMAP CNT c_auto (cmap_cnt, countries) { - c_apply(v, cmap_cnt_emplace(&countries, c_pair(v)), cmap_cnt_rawvalue, { + c_apply(v, cmap_cnt_emplace(&countries, c_pair(v)), cmap_cnt_raw, { {"Norway", 100}, {"Denmark", 50}, {"Iceland", 10}, diff --git a/examples/new_map.c b/examples/new_map.c index 1c27d5bf..f641a0eb 100644 --- a/examples/new_map.c +++ b/examples/new_map.c @@ -48,14 +48,14 @@ int main() { cmap_int_insert(&map, 123, 321); - c_apply(v, cmap_pnt_insert(&pmap, c_pair(v)), cmap_pnt_rawvalue, { + c_apply(v, cmap_pnt_insert(&pmap, c_pair(v)), cmap_pnt_raw, { {{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3} }); c_foreach (i, cmap_pnt, pmap) printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); puts(""); - c_apply(v, cmap_str_emplace(&smap, c_pair(v)), cmap_str_rawvalue, { + c_apply(v, cmap_str_emplace(&smap, c_pair(v)), cmap_str_raw, { {"Hello, friend", "long time no see"}, {"So long, friend", "see you around"}, }); diff --git a/examples/phonebook.c b/examples/phonebook.c index 064de93f..ccc10eaf 100644 --- a/examples/phonebook.c +++ b/examples/phonebook.c @@ -50,7 +50,7 @@ int main(int argc, char **argv) bool erased; c_auto (cmap_str, phone_book) { - c_apply(v, cmap_str_emplace(&phone_book, c_pair(v)), cmap_str_rawvalue, { + c_apply(v, cmap_str_emplace(&phone_book, c_pair(v)), cmap_str_raw, { {"Lilia Friedman", "(892) 670-4739"}, {"Tariq Beltran", "(489) 600-7575"}, {"Laiba Juarez", "(303) 885-5692"}, diff --git a/examples/sidebyside.cpp b/examples/sidebyside.cpp index cf4b2f70..85fea774 100644 --- a/examples/sidebyside.cpp +++ b/examples/sidebyside.cpp @@ -19,7 +19,7 @@ int main() { } c_auto (cmap_str, food) { - c_apply(v, cmap_str_emplace(&food, c_pair(v)), cmap_str_rawvalue, + c_apply(v, cmap_str_emplace(&food, c_pair(v)), cmap_str_raw, {{"burger", 5}, {"pizza", 12}, {"steak", 15}}); c_foreach (i, cmap_str, food) printf("%s, %d\n", i.ref->first.str, i.ref->second); diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c index 6b4dd359..64866ba3 100644 --- a/examples/sptr_to_maps.c +++ b/examples/sptr_to_maps.c @@ -30,17 +30,17 @@ int main() // POPULATE stack with shared pointers to Maps: Map *map; map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }); map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }); // POPULATE list: map = List_push_back(&list, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_rawvalue, { + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); diff --git a/examples/vikings.c b/examples/vikings.c index 9900e9b6..5acafb3f 100644 --- a/examples/vikings.c +++ b/examples/vikings.c @@ -49,7 +49,7 @@ static inline RViking Viking_toraw(const Viking* vk) { int main() { c_auto (Vikings, vikings) { - c_apply(v, Vikings_emplace(&vikings, c_pair(v)), Vikings_rawvalue, { + c_apply(v, Vikings_emplace(&vikings, c_pair(v)), Vikings_raw, { {{"Einar", "Norway"}, 20}, {{"Olaf", "Denmark"}, 24}, {{"Harald", "Iceland"}, 12}, diff --git a/include/stc/alt/clist.h b/include/stc/alt/clist.h index 14abc7e4..38b722a4 100644 --- a/include/stc/alt/clist.h +++ b/include/stc/alt/clist.h @@ -64,13 +64,13 @@ STC_API size_t _clist_count(const clist_VOID* self); #define _c_using_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw, defTypes) \ \ defTypes( _c_clist_types(_cx_self, i_val); ) \ - typedef i_valraw _cx_rawvalue; \ + typedef i_valraw _cx_raw; \ \ STC_API _cx_self _cx_memb(_clone)(_cx_self lst); \ STC_API void _cx_memb(_drop)(_cx_self* self); \ STC_API void _cx_memb(_push_back)(_cx_self* self, i_val value); \ STC_API void _cx_memb(_push_front)(_cx_self* self, i_val value); \ - STC_API void _cx_memb(_emplace_items)(_cx_self *self, const _cx_rawvalue arr[], size_t n); \ + STC_API void _cx_memb(_emplace_items)(_cx_self *self, const _cx_raw arr[], size_t n); \ STC_API _cx_self _cx_memb(_split_after)(_cx_self* self, _cx_iter pos1, _cx_iter pos2); \ STC_API void _cx_memb(_splice_after)(_cx_self* self, _cx_iter pos, _cx_self* other); \ STC_DEF void _cx_memb(_splice_after_range)(_cx_self* self, _cx_iter pos, _cx_self* other, _cx_iter i1, _cx_iter i2); \ @@ -176,7 +176,7 @@ STC_API size_t _clist_count(const clist_VOID* self); } \ \ STC_DEF void \ - _cx_memb(_emplace_items)(_cx_self *self, const _cx_rawvalue arr[], size_t n) { \ + _cx_memb(_emplace_items)(_cx_self *self, const _cx_raw arr[], size_t n) { \ for (size_t i=0; idata + 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) { +_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -369,7 +369,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { #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) { +_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); _cx_iter it = {pos}; for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); diff --git a/include/stc/clist.h b/include/stc/clist.h index c239fdd9..2194067c 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -87,7 +87,7 @@ _c_clist_complete_types(clist_VOID, dummy); _cx_deftypes(_c_clist_types, _cx_self, i_val); #endif _cx_deftypes(_c_clist_complete_types, _cx_self, dummy); -typedef i_valraw _cx_rawvalue; +typedef i_valraw _cx_raw; STC_API size_t _clist_count(const clist_VOID* self); diff --git a/include/stc/cmap.h b/include/stc/cmap.h index b7529871..87ed7c6c 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -85,7 +85,7 @@ typedef i_valraw _cx_memb(_rawmapped); typedef _i_SET_ONLY( i_keyraw ) _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) -_cx_rawvalue; +_cx_raw; STC_API _cx_self _cx_memb(_with_capacity)(size_t cap); #if !c_option(c_no_clone) @@ -153,10 +153,10 @@ _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped) } #endif // !c_no_clone -STC_INLINE _cx_rawvalue +STC_INLINE _cx_raw _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)} ); + _i_MAP_ONLY( c_make(_cx_raw){i_keyto(&val->first), i_valto(&val->second)} ); } STC_INLINE void diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 87be1e73..caea1549 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -36,7 +36,7 @@ #if !c_option(c_is_fwd) _cx_deftypes(_c_cpque_types, _cx_self, i_val); #endif -typedef i_valraw _cx_rawvalue; +typedef i_valraw _cx_raw; STC_API void _cx_memb(_make_heap)(_cx_self* self); STC_API void _cx_memb(_erase_at)(_cx_self* self, size_t idx); diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 04dc895d..8115cf46 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -91,7 +91,7 @@ typedef i_keyraw _cx_rawkey; typedef i_valraw _cx_memb(_rawmapped); typedef _i_SET_ONLY( i_keyraw ) _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) - _cx_rawvalue; + _cx_raw; STC_API _cx_self _cx_memb(_init)(void); #if !c_option(c_no_clone) @@ -128,10 +128,10 @@ _cx_memb(_with_capacity)(const size_t cap) { return tree; } -STC_INLINE _cx_rawvalue +STC_INLINE _cx_raw _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)} ); + _i_MAP_ONLY( c_make(_cx_raw){i_keyto(&val->first), i_valto(&val->second)} ); } STC_INLINE int diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 4e9b4687..0718a4cc 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -76,7 +76,7 @@ int main() { #endif #define _i_has_internal_clone #include "template.h" -typedef i_valraw _cx_rawvalue; +typedef i_valraw _cx_raw; #if !c_option(c_no_atomic) #define _i_atomic_inc(v) c_atomic_inc(v) diff --git a/include/stc/cstack.h b/include/stc/cstack.h index fa74494d..387c0126 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -36,7 +36,7 @@ #if !c_option(c_is_fwd) _cx_deftypes(_c_cstack_types, _cx_self, i_val); #endif -typedef i_valraw _cx_rawvalue; +typedef i_valraw _cx_raw; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){0, 0, 0}; } @@ -96,7 +96,7 @@ STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, size_t idx) #if !c_option(c_no_clone) -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_rawvalue raw) +STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_valfrom(raw)); } STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 92f6afd6..3486cc37 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -76,7 +76,7 @@ struct cvec_rep { size_t size, cap; void* data[]; }; #if !c_option(c_is_fwd) _cx_deftypes(_c_cvec_types, _cx_self, i_val); #endif -typedef i_valraw _cx_rawvalue; +typedef i_valraw _cx_raw; STC_API _cx_self _cx_memb(_init)(void); STC_API void _cx_memb(_drop)(_cx_self* self); @@ -98,7 +98,7 @@ 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_raw* p1, const _cx_raw* 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); } @@ -112,7 +112,7 @@ _cx_memb(_copy)(_cx_self *self, _cx_self other) { _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_rawvalue arr[], const size_t n) { +_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -350,7 +350,7 @@ _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, 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_raw* p1, const _cx_raw* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); _cx_iter it = {pos}; for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); diff --git a/include/stc/template.h b/include/stc/template.h index 675baa47..1d1551fa 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -31,7 +31,7 @@ #define _cx_value _cx_memb(_value) #define _cx_key _cx_memb(_key) #define _cx_mapped _cx_memb(_mapped) - #define _cx_rawvalue _cx_memb(_rawvalue) + #define _cx_raw _cx_memb(_raw) #define _cx_rawkey _cx_memb(_rawkey) #define _cx_rawmapped _cx_memb(_rawmapped) #define _cx_iter _cx_memb(_iter) -- cgit v1.2.3 From 7a30e2853792870a1d85087861e46a1ae1ca6b0e Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 09:14:44 +0100 Subject: Minor example update. --- examples/sidebyside.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/sidebyside.cpp b/examples/sidebyside.cpp index 85fea774..435b37f6 100644 --- a/examples/sidebyside.cpp +++ b/examples/sidebyside.cpp @@ -8,11 +8,12 @@ #define i_key int #define i_val int -#include +#include int main() { { - std::map food = {{"burger", 5}, {"pizza", 12}, {"steak", 15}}; + std::map food = + {{"burger", 5}, {"pizza", 12}, {"steak", 15}}; for (auto i: food) std::cout << i.first << ", " << i.second << std::endl; std::cout << std::endl; @@ -35,12 +36,12 @@ int main() { std::cout << i.first << ", " << i.second << std::endl; std::cout << std::endl; } - c_auto (cmap_int, hist) + c_auto (csmap_int, hist) { - ++ cmap_int_emplace(&hist, 12, 100).ref->second; - ++ cmap_int_emplace(&hist, 13, 100).ref->second; - ++ cmap_int_emplace(&hist, 12, 100).ref->second; - c_foreach (i, cmap_int, hist) + ++ csmap_int_emplace(&hist, 12, 100).ref->second; + ++ csmap_int_emplace(&hist, 13, 100).ref->second; + ++ csmap_int_emplace(&hist, 12, 100).ref->second; + c_foreach (i, csmap_int, hist) printf("%d, %d\n", i.ref->first, i.ref->second); puts(""); } -- cgit v1.2.3 From 79c83eba7933f49e766dbeb85f9c40ee17e06edf Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 12:35:36 +0100 Subject: Renamed csptr to carc. i_key/val_ref renamed to i_key/val_sptr. Change inspired by Rust Arc/Rc. cbox name is taken from Rust Box type. --- README.md | 73 ++++++++++-------- docs/cbox_api.md | 10 +-- docs/csptr_api.md | 96 ++++++++++++----------- examples/box.c | 3 +- examples/box2.c | 8 +- examples/new_sptr.c | 16 ++-- examples/sptr.c | 4 +- examples/sptr_demo.c | 10 +-- examples/sptr_erase.c | 8 +- examples/sptr_music.c | 4 +- examples/sptr_pthread.c | 20 ++--- examples/sptr_to_maps.c | 8 +- include/stc/carc.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ include/stc/ccommon.h | 2 +- include/stc/csptr.h | 201 ------------------------------------------------ include/stc/forward.h | 4 +- include/stc/template.h | 16 ++-- 17 files changed, 350 insertions(+), 334 deletions(-) create mode 100644 include/stc/carc.h delete mode 100644 include/stc/csptr.h diff --git a/README.md b/README.md index e8d9d34b..624796bb 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,20 @@ STC - Smart Template Containers for C News ---- -### Version 3.0 released -There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions -to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements +### Version 3 released +A lot of enhancements, additions and bugfixes. There are also a number of breaking changes (mostly renamings), +see migrate guide below. + +Added are new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions +to the type specified, and may be used in place of `i_key`/`i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_hash*, and *Type_eq*. Only the functions required by the particular container needs to be defined. e.g. **cmap** -and **cset** are the only types that requires *Type_hash* and *Type_eq* to be defined. -You may override these by defining `i_cmp`, `i_drop`, etc. Template parameters with `i_val` / `i_key` may -still be defined as before, which is often easier for simple element types. +and **cset** are the only types that require *Type_hash* and *Type_eq* to be defined. -Migration guide from version 2 to 3. Replace (regular expresion) in VS Code: +### Migration guide from version 2 to 3. +Replace (regular expression) in VS Code: - `_del\b` → `_drop` - `_compare\b` → `_cmp` -- `csptr` → `cref` - `_rawvalue\b` → `_raw` - `_equ\b` → `_eq` @@ -26,24 +27,25 @@ Replace (whole word + match case): - `i_valdel` → `i_valdrop` - `i_cnt` → `i_type` - `cstr_lit` → `cstr_new` -- `csptr_X_make` → `csptr_X_new` +- `csptr_X_make` → `carc_X_from` - `i_key_csptr` → `i_key_sptr` - `i_val_csptr` → `i_val_sptr` - `c_apply` → `c_apply_OLD` // replaced by new `c_apply` - `c_apply_pair` → `c_apply_pair_OLD` // replaced by new `c_apply` -### Final version 2.1 +Non-regex, global match case replace: +- `csptr` → `carc` + +### Brief summary of changes - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. -- Added [**cbox**](docs/cbox_api.md) type: container of one element, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) -- Added [example for **csptr**](examples/sptr_to_maps.c). +- Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). Also renamed `csptr` to `carc` (atomic reference counted) smart pointer. +- Added [example for **carc**](examples/sptr_to_maps.c). - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". -- Renamed: *csptr_X_make()* to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. +- Renamed: *csptr_X_make()* to *carc_X_from()*. Corresponding **cbox** method is *cbox_X_from()*. - Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. -- Renamed: `i_key_csptr` / `i_val_csptr`. Use `i_key_sptr` / `i_val_sptr` for **csptr** and **cbox**. +- Renamed: `i_key_csptr`/`i_val_csptr` to `i_key_sptr`/`i_val_sptr` for both **carc** and **cbox** values in containers. - Renamed: `i_cnt` to `i_type` for defining the complete container type name. - Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` - -### Version 2.0. Two main breaking changes from V1.X. - Uses a different way to instantiate templated containers, which is incompatible with v1.X. Introduction @@ -67,7 +69,7 @@ which by the compiler is seen as different code because of macro name substituti - [***clist*** - **std::forward_list** alike type](docs/clist_api.md) - [***cmap*** - **std::unordered_map** alike type](docs/cmap_api.md) - [***cpque*** - **std::priority_queue** alike type](docs/cpque_api.md) -- [***csptr*** - **std::shared_ptr** alike support](docs/csptr_api.md) +- [***carc*** - **std::shared_ptr** alike support](docs/carc_api.md) - [***cqueue*** - **std::queue** alike type](docs/cqueue_api.md) - [***cset*** - **std::unordered_set** alike type](docs/cset_api.md) - [***csmap*** - **std::map** sorted map alike type](docs/csmap_api.md) @@ -87,7 +89,7 @@ Highlights - **User friendly** - Just include the headers and you are good. The API and functionality is very close to c++ STL, and is fully listed in the docs. - **Templates** - Use `#define i_{arg}` to specify container template arguments. There are templates for element-*type*, -*comparison*, -*destruction*, -*cloning*, -*conversion types*, and more. - **Unparalleled performance** - Some containers are much faster than the c++ STL containers, the rest are about equal in speed. -- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, shared pointers are supported and can be stored in containers, see ***csptr***. +- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, shared pointers are supported and can be stored in containers, see ***carc***. - **Fully type safe** - Because of templating, it avoids error-prone casting of container types and elements back and forth from the containers. - **Uniform, easy-to-learn API** - Methods to ***construct***, ***initialize***, ***iterate*** and ***destruct*** have uniform and intuitive usage across the various containers. - **Small footprint** - Small source code and generated executables. The executable from the example below with six different containers is *22 kb in size* compiled with gcc -Os on linux. @@ -114,19 +116,30 @@ The usage of the containers is similar to the c++ standard containers in STL, so 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 +#define i_type FVec // if not defined, vector type would be cvec_float +#define i_val float // element type +#include // defines the FVec type int main(void) { - cvec_float vec = cvec_float_init(); - cvec_float_push_back(&vec, 10.f); - cvec_float_push_back(&vec, 20.f); - cvec_float_push_back(&vec, 30.f); - - c_foreach (i, cvec_float, vec) - printf(" %g", *i.ref); + FVec vec = FVec_init(); + FVec_push_back(&vec, 10.f); + FVec_push_back(&vec, 20.f); + FVec_push_back(&vec, 30.f); + + for (size_t i = 0; i < FVec_size(vec); ++i) + printf(" %g", vec.data[i]); + FVec_drop(&vec); // free memory +} +``` +However, a "better" way to write the same is: +```c +int main(void) { + c_auto (FVec, vec) { // RAII + c_apply(v, FVec_push_back(&vec, v), float, {10.f, 20.f, 30.f}); - cvec_float_drop(&vec); + c_foreach (i, FVec, vec) // generic iteration and element access + printf(" %g", *i.ref); + } } ``` In order to include two **cvec**s with different element types, include cvec.h twice. For struct, a `i_cmp` @@ -195,7 +208,7 @@ int main(void) { { // add some elements to each container c_apply(v, cset_int_insert(&set, v), int, {10, 20, 30}); - c_apply(v, cvec_pnt_push_back(&vec, v), int, { {10, 1}, {20, 2}, {30, 3} }); + c_apply(v, cvec_pnt_push_back(&vec, v), cvec_pnt_raw, { {10, 1}, {20, 2}, {30, 3} }); c_apply(v, cdeq_int_push_back(&deq, v), int, {10, 20, 30}); c_apply(v, clist_int_push_back(&lst, v), int, {10, 20, 30}); c_apply(v, cstack_int_push(&stk, v), int, {10, 20, 30}); @@ -440,4 +453,4 @@ Memory efficiency - **cmap**: Type size: 4 pointers. *cmap* uses one table of keys+value, and one table of precomputed hash-value/used bucket, which occupies only one byte per bucket. The closed hashing has a default max load factor of 85%, and hash table scales by 1.6x when reaching that. - **csmap**: Type size: 1 pointer. *csmap* manages its own array of tree-nodes for allocation efficiency. Each node uses only two 32-bit ints for child nodes, and one byte for `level`. - **carr2**, **carr3**: Type size: 1 pointer plus dimension variables. Arrays are allocated as one contiguous block of heap memory, and one allocation for pointers of indices to the array. -- **csptr**: Type size: 2 pointers, one for the data and one for the reference counter. +- **carc**: Type size: 2 pointers, one for the data and one for the reference counter. diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 011beea2..e05e69f0 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -1,4 +1,4 @@ -# STC [cbox](../include/stc/cbox.h): (Boxed) Heap Allocated Objects +# STC [cbox](../include/stc/cbox.h): Smart Pointer (Boxed object) **cbox** is a A box is a smart pointer to a heap allocated value of type X. A **cbox** can be empty. The *cbox_X_cmp()*, *cbox_X_drop()* methods are defined based on the `i_cmp` @@ -21,7 +21,7 @@ See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type #define i_drop // destroy value func - defaults to empty destruct -#define i_from // create from raw/clone func - REQUIRED if i_drop is defined, +#define i_from // create from raw/clone func - REQUIRED if i_drop is defined, // unless 'i_opt c_no_clone' is defined. #define i_tag // type name tag, defaults to i_val #include @@ -76,7 +76,7 @@ void int_drop(int* x) { // both for the cbox type and the container of cbox elements. It will also // disable emplace container functions. // -// This applies to all container types, except those with csptr elements, as they +// This applies to all container types, except those with carc elements, as they // define cloning internally. #define i_val int @@ -84,11 +84,11 @@ void int_drop(int* x) { #define i_from c_default_clone #include // cbox_int -#define i_key_bind cbox_int // note: use i_key_bind instead of i_key +#define i_key_sptr cbox_int // note: use i_key_sptr instead of i_key #define i_tag int // tag otherwise defaults to 'ref' #include // csset_int (like: std::set>) -#define i_val_bind cbox_int // note: use i_val_bind instead of i_val +#define i_val_sptr cbox_int // note: use i_val_sptr instead of i_val #define i_tag int // tag otherwise defaults to 'ref' #include // cvec_int (like: std::vector>) diff --git a/docs/csptr_api.md b/docs/csptr_api.md index 95575417..e33bf410 100644 --- a/docs/csptr_api.md +++ b/docs/csptr_api.md @@ -1,23 +1,24 @@ -# STC [csptr](../include/stc/csptr.h): Atomic Reference Counted +# STC [carc](../include/stc/carc.h): Atomic Reference Counted Smart Pointer -**csptr** is a smart pointer that retains shared ownership of an object through a pointer. -Several **csptr** objects may own the same object. The object is destroyed and its memory -deallocated when the last remaining **csptr** owning the object is destroyed with *csptr_X_drop()*; +**carc** is a smart pointer that retains shared ownership of an object through a pointer. +Several **carc** objects may own the same object. The object is destroyed and its memory +deallocated when the last remaining **carc** owning the object is destroyed with *carc_X_drop()*; -The object is destroyed using *csptr_X_drop()*. A **csptr** may also own no objects, in which -case it is called empty. The *csptr_X_cmp()*, *csptr_X_drop()* methods are defined based on -the `i_cmp` and `i_valdrop` macros specified. Use *csptr_X_clone(p)* when sharing ownership of +The object is destroyed using *carc_X_drop()*. A **carc** may also own no objects, in which +case it is called empty. The *carc_X_cmp()*, *carc_X_drop()* methods are defined based on +the `i_cmp` and `i_valdrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of the pointed-to object. -All **csptr** functions can be called by multiple threads on different instances of **csptr** without +All **carc** functions can be called by multiple threads on different instances of **carc** without additional synchronization even if these instances are copies and share ownership of the same object. -**csptr** uses thread-safe atomic reference counting, through the *csptr_X_clone()* and *csptr_X_drop()* methods. +**carc** uses thread-safe atomic reference counting, through the *carc_X_clone()* and *carc_X_drop()* methods. -When declaring a container with shared pointers, define `i_val_bind` as the csptr type, see example. +When declaring a container with shared pointers, define `i_val_bind` as the carc type, see example. -For containers, make sure to pass the result of create functions *csptr_X_new()* **only** to *insert()*, -*push_back()*, and *push()* functions. Use *emplace()* method for sharing existing **csptr**s between -containers or other existing shared pointers, as they internally clone/share the input. +Make sure to pass the result of create functions like *carc_X_from()* **only** to *insert()*, +*push_back()*, and *push()* functions, as it is *moved* into the container. Use *emplace()* +method for sharing existing **carc**s between containers or other existing shared pointers, +as they clone/share the input internally. See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference, or Rust [std::sync::Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) / [std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html). @@ -29,41 +30,42 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory #define i_drop // destroy value func - defaults to empty destruct #define i_tag // defaults to i_val #define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc. -#include +#include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. ## Methods ```c -csptr_X csptr_X_init(); // empty shared pointer -csptr_X csptr_X_new(i_valraw raw); // like csptr_X_from(), but construct owned value from raw. -csptr_X csptr_X_from(i_val val); // create new heap allocated object. Take ownership of val. -csptr_X csptr_X_from_ptr(i_val* p); // create a csptr from raw pointer. Takes ownership of p. - -csptr_X csptr_X_clone(csptr_X other); // return other with increased use count -csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr. -void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other. -void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count) - -void csptr_X_drop(csptr_X* self); // destruct (decrease use count, free at 0) -long csptr_X_use_count(csptr_X ptr); - -void csptr_X_reset(csptr_X* self); -void csptr_X_reset_from(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val. - -uint64_t csptr_X_value_hash(const i_val* x, size_t n); // hash value -int csptr_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' - // is defined. Otherwise uses 'i_cmp' or default compare. -bool csptr_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 +carc_X carc_X_init(); // empty shared pointer +carc_X carc_X_new(i_valraw raw); // like carc_X_from(), but construct owned value from raw. +carc_X carc_X_from(i_val val); // create new heap allocated object. Take ownership of val. +carc_X carc_X_from_ptr(i_val* p); // create a carc from raw pointer. Takes ownership of p. + +carc_X carc_X_clone(carc_X other); // return other with increased use count +carc_X carc_X_move(carc_X* self); // transfer ownership to another carc. +void carc_X_take(carc_X* self, carc_X other); // take ownership of other. +void carc_X_copy(carc_X* self, carc_X other); // copy shared (increase use count) + +void carc_X_drop(carc_X* self); // destruct (decrease use count, free at 0) +long carc_X_use_count(carc_X ptr); + +void carc_X_reset(carc_X* self); +void carc_X_reset_from(carc_X* self, i_val val); // assign new carc with value. Takes ownership of val. + +uint64_t carc_X_value_hash(const i_val* x, size_t n); // hash value +int carc_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default compare. +bool carc_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 ``` ## Types and constants -| Type name | Type definition | Used to represent... | -|:-------------------|:---------------------------------------------------|:------------------------| -| `csptr_null` | `{NULL, NULL}` | Init nullptr const | -| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type | -| `csptr_X_value` | `i_val` | The csptr element type | +| Type name | Type definition | Used to represent... | +|:------------------|:--------------------------------------------------|:-----------------------| +| `carc_null` | `{NULL, NULL}` | Init nullptr const | +| `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | +| `carc_X_value` | `i_val` | The carc element type | +| `carc_X_raw` | `i_valraw` | Convertion type | ## Example @@ -83,14 +85,14 @@ bool csptr_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value // no comparison of Maps needed (or available), and // no need for atomic ref. count in single thread: #define i_opt c_no_cmp|c_no_atomic -#include +#include #define i_type Stack -#define i_val_bind Arc // define i_val_bind for csptr / cbox value, not i_val +#define i_val_sptr Arc // define i_val_sptr for carc/cbox value, not i_val or i_val_bind #include #define i_type List -#define i_val_bind Arc // as above +#define i_val_sptr Arc // as above #include int main() @@ -100,28 +102,28 @@ int main() { // POPULATE the stack with shared pointers to Map: Map *map; - map = Stack_push(&stack, Arc_new(Map_init()))->get; + map = Stack_push(&stack, Arc_from(Map_init()))->get; c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }); - map = Stack_push(&stack, Arc_new(Map_init()))->get; + map = Stack_push(&stack, Arc_from(Map_init()))->get; c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }); // POPULATE the list: - map = List_push_back(&list, Arc_new(Map_init()))->get; + map = List_push_back(&list, Arc_from(Map_init()))->get; c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); - // Share two Maps from the stack with the list using emplace (clones the csptr): + // Share two Maps from the stack with the list using emplace (clones the carc): List_emplace_back(&list, stack.data[0]); List_emplace_back(&list, stack.data[1]); // Clone (deep copy) a Map from the stack to the list // List will contain two shared and two unshared maps. - map = List_push_back(&list, Arc_new(Map_clone(*stack.data[1].get)))->get; + map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; // Add one more element to the cloned map: Map_emplace_or_assign(map, "CLONED", 2021); diff --git a/examples/box.c b/examples/box.c index ae10a89f..d97545b6 100644 --- a/examples/box.c +++ b/examples/box.c @@ -28,10 +28,9 @@ void Person_drop(Person* p) { #include #define i_type Persons -#define i_val_ref PBox // binds PBox_cmp, ... +#define i_val_sptr PBox // informs that PBox is a smart pointer. #include - int main() { c_auto (Persons, vec) diff --git a/examples/box2.c b/examples/box2.c index 5549dade..d79ea32d 100644 --- a/examples/box2.c +++ b/examples/box2.c @@ -26,8 +26,8 @@ struct { #include // cbox_Rectangle // Box in box: -#define i_val_bind cbox_Point // NB: adviced to use i_val_arc when value is a cbox or csptr! - // it will auto-set i_drop, i_from, i_cmp for you. +#define i_val_sptr cbox_Point // NB: adviced to use i_val_sptr when value is a cbox or carc! + // it will auto-set i_drop, i_from, i_cmp for you. #define i_opt c_no_cmp #define i_tag BoxPoint #include // cbox_BoxPoint @@ -62,10 +62,10 @@ int main(void) { }); // The output of functions can be boxed - boxed_point = cbox_Point_new(origin()); + boxed_point = cbox_Point_from(origin()); // Double indirection - box_in_a_box = cbox_BoxPoint_new(boxed_origin()); + box_in_a_box = cbox_BoxPoint_from(boxed_origin()); printf("Point occupies %zu bytes on the stack\n", sizeof(point)); diff --git a/examples/new_sptr.c b/examples/new_sptr.c index ce31478e..045eef77 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -14,29 +14,29 @@ void Person_drop(Person* p) { #define i_drop Person_drop #define i_opt c_no_cmp #define i_tag person -#include +#include // ... #define i_val int #define i_drop(x) printf("drop: %d\n", *(x)) -#include +#include -#define i_val_bind csptr_int +#define i_val_bind carc_int #define i_tag iptr #include int main(void) { - c_autovar (csptr_person p = csptr_person_from(Person_new("John", "Smiths")), csptr_person_drop(&p)) - c_autovar (csptr_person q = csptr_person_clone(p), csptr_person_drop(&q)) // share the pointer + c_autovar (carc_person p = carc_person_from(Person_new("John", "Smiths")), carc_person_drop(&p)) + c_autovar (carc_person q = carc_person_clone(p), carc_person_drop(&q)) // share the pointer { printf("%s %s. uses: %lu\n", q.get->name.str, q.get->last.str, *q.use_count); } c_auto (cstack_iptr, stk) { - cstack_iptr_push(&stk, csptr_int_from(10)); - cstack_iptr_push(&stk, csptr_int_from(20)); - cstack_iptr_push(&stk, csptr_int_from(30)); + cstack_iptr_push(&stk, carc_int_from(10)); + cstack_iptr_push(&stk, carc_int_from(20)); + cstack_iptr_push(&stk, carc_int_from(30)); cstack_iptr_emplace(&stk, *cstack_iptr_top(&stk)); cstack_iptr_emplace(&stk, *cstack_iptr_begin(&stk).ref); diff --git a/examples/sptr.c b/examples/sptr.c index e1d734e0..0c22bd68 100644 --- a/examples/sptr.c +++ b/examples/sptr.c @@ -25,10 +25,10 @@ void Person_drop(Person* p) { #define i_type PSPtr #define i_val_bind Person // binds Person_cmp, ... -#include +#include #define i_type Persons -#define i_val_ref PSPtr // binds PSPtr_cmp, ... +#define i_val_sptr PSPtr // binds PSPtr_cmp, ... #include diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c index a5c642b0..8626e2d4 100644 --- a/examples/sptr_demo.c +++ b/examples/sptr_demo.c @@ -5,18 +5,18 @@ void int_drop(int* x) { printf("drop: %d\n", *x); } -// csptr implements its own clone method using reference counting, +// carc implements its own clone method using reference counting, // so 'i_valfrom' need not be defined (will be ignored). -#define i_type iref // set type name to be defined (instead of 'csptr_int') +#define i_type iref // set type name to be defined (instead of 'carc_int') #define i_val int #define i_drop int_drop // optional, just to display the elements destroyed -#include // iref +#include // iref -#define i_key_ref iref // note: use i_key_bind instead of i_key for csptr/cbox elements +#define i_key_sptr iref // note: use i_key_bind instead of i_key for carc/cbox elements #include // csset_iref (like: std::set>) -#define i_val_ref iref // note: as above. +#define i_val_sptr iref // note: as above. #include // cvec_iref (like: std::vector>) int main() diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c index fbb141b4..d40d8fe7 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -5,14 +5,14 @@ void show_drop(int* x) { printf("drop: %d\n", *x); } #define i_type Arc #define i_val int #define i_drop show_drop -// csptr/cbox will use pointer address comparison of i_val +// carc/cbox will use pointer address comparison of i_val // if 'i_opt c_no_cmp' is defined, otherwise i_cmp is used -// to compare object values. See the twodifferences by +// to compare object values. See the two differences by // commenting out the next line. -#include // Shared pointer to int +#include // Shared pointer to int #define i_type Vec -#define i_val_ref Arc +#define i_val_sptr Arc #include // Vec: cvec diff --git a/examples/sptr_music.c b/examples/sptr_music.c index 1d58cc46..42bb3455 100644 --- a/examples/sptr_music.c +++ b/examples/sptr_music.c @@ -21,10 +21,10 @@ void Song_drop(Song* s) { #define i_val Song #define i_drop Song_drop #define i_opt c_no_cmp -#include +#include #define i_type SongVec -#define i_val_ref SongPtr +#define i_val_sptr SongPtr #include void example3() diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c index d71ce97d..d81d9810 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -11,13 +11,13 @@ struct Base int value; } typedef Base; +#define i_type BaseRc #define i_val Base -#define i_drop(x) printf("Base::~Base()\n") -#define i_tag base +#define i_valdrop(x) printf("Drop Base: %d\n", (x)->value) #define i_opt c_no_cmp -#include +#include -void* thr(csptr_base* lp) +void* thr(BaseRc* lp) { sleep(1); static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; @@ -25,30 +25,32 @@ void* thr(csptr_base* lp) { printf("local pointer in a thread:\n" " p.get() = %p, p.use_count() = %ld\n", (void*)lp->get, *lp->use_count); + /* safe to modify base here */ + lp->get->value += 1; } /* atomically decrease ref. */ - csptr_base_drop(lp); + BaseRc_drop(lp); return NULL; } int main() { - csptr_base p = csptr_base_from((Base){42}); + BaseRc p = BaseRc_from((Base){0}); printf("Created a Base\n" " p.get() = %p, p.use_count() = %ld\n", (void*)p.get, *p.use_count); enum {N = 3}; pthread_t t[N]; - csptr_base c[N]; + BaseRc c[N]; c_forrange (i, N) { - c[i] = csptr_base_clone(p); + c[i] = BaseRc_clone(p); pthread_create(&t[i], NULL, (void*(*)(void*))thr, &c[i]); } printf("Shared ownership between %d threads and released\n" "ownership from main:\n" " p.get() = %p, p.use_count() = %ld\n", N, (void*)p.get, *p.use_count); - csptr_base_reset(&p); + BaseRc_reset(&p); c_forrange (i, N) pthread_join(t[i], NULL); printf("All threads completed, the last one deleted Base\n"); diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c index 64866ba3..0873d297 100644 --- a/examples/sptr_to_maps.c +++ b/examples/sptr_to_maps.c @@ -12,14 +12,14 @@ // no need for atomic ref. count in single thread: // no compare function available for csmap: #define i_opt c_no_atomic|c_no_cmp -#include +#include #define i_type Stack -#define i_val_ref Arc // define i_val_bind for csptr/cbox value (not i_val) +#define i_val_sptr Arc // define i_val_bind for carc/cbox value (not i_val) #include #define i_type List -#define i_val_ref Arc // as above +#define i_val_sptr Arc // as above #include int main() @@ -44,7 +44,7 @@ int main() {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }); - // Share two Maps from the stack with the list using emplace (clone the csptr): + // Share two Maps from the stack with the list using emplace (clone the carc): List_push_back(&list, Arc_clone(stack.data[0])); List_push_back(&list, Arc_clone(stack.data[1])); diff --git a/include/stc/carc.h b/include/stc/carc.h new file mode 100644 index 00000000..505b47d9 --- /dev/null +++ b/include/stc/carc.h @@ -0,0 +1,201 @@ +/* MIT License + * + * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* carc: atomic reference counted shared_ptr +#include + +typedef struct { cstr name, last; } Person; + +Person Person_new(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); +} + +#define i_tag person +#define i_val Person +#define i_valdrop Person_drop +#include + +int main() { + carc_person p = carc_person_from(Person_new("John", "Smiths")); + carc_person q = carc_person_clone(p); // share the pointer + + printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count); + c_drop(carc_person, &p, &q); +} +*/ + +#ifndef CARC_H_INCLUDED +#define CARC_H_INCLUDED +#include "ccommon.h" +#include "forward.h" +#include + +#if defined(__GNUC__) || defined(__clang__) + #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) + #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) +#elif defined(_MSC_VER) + #include + #define c_atomic_inc(v) (void)_InterlockedIncrement(v) + #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) +#else + #include + #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) + #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) +#endif + +#define carc_null {NULL, NULL} +#define _cx_carc_rep struct _cx_memb(_rep_) +#endif // CARC_H_INCLUDED + +#ifndef _i_prefix +#define _i_prefix carc_ +#endif +#define _i_has_internal_clone +#include "template.h" +typedef i_valraw _cx_raw; + +#if !c_option(c_no_atomic) + #define _i_atomic_inc(v) c_atomic_inc(v) + #define _i_atomic_dec_and_test(v) c_atomic_dec_and_test(v) +#else + #define _i_atomic_inc(v) (void)(++*(v)) + #define _i_atomic_dec_and_test(v) !(--*(v)) +#endif +#if !c_option(c_is_fwd) +_cx_deftypes(_c_carc_types, _cx_self, i_val); +#endif +_cx_carc_rep { long counter; i_val value; }; + +STC_INLINE _cx_self +_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } + +STC_INLINE long +_cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } + +STC_INLINE _cx_self +_cx_memb(_from_ptr)(_cx_value* p) { + _cx_self ptr = {p}; + if (p) *(ptr.use_count = c_alloc(long)) = 1; + return ptr; +} + +STC_INLINE _cx_self +_cx_memb(_from)(i_val val) { + _cx_self ptr; _cx_carc_rep *rep = c_alloc(_cx_carc_rep); + *(ptr.use_count = &rep->counter) = 1; + *(ptr.get = &rep->value) = val; + return ptr; +} + +STC_INLINE i_val _cx_memb(_toraw)(const _cx_self* self) { + return *self->get; +} + +STC_INLINE _cx_self +_cx_memb(_move)(_cx_self* self) { + _cx_self ptr = *self; + self->get = NULL, self->use_count = NULL; + return ptr; +} + +STC_INLINE void +_cx_memb(_drop)(_cx_self* self) { + if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { + i_valdrop(self->get); + if (self->get != &((_cx_carc_rep *)self->use_count)->value) + c_free(self->get); + c_free(self->use_count); + } +} + +STC_INLINE void +_cx_memb(_reset)(_cx_self* self) { + _cx_memb(_drop)(self); + self->use_count = NULL, self->get = NULL; +} + +STC_INLINE void +_cx_memb(_reset_from)(_cx_self* self, i_val val) { + _cx_memb(_drop)(self); + *self = _cx_memb(_from)(val); +} + +#if !c_option(c_no_clone) && !defined _i_valraw_default + STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { + return _cx_memb(_from)(i_valfrom(raw)); + } +#endif + +// does not use i_valfrom, so we can bypass c_no_clone +STC_INLINE _cx_self +_cx_memb(_clone)(_cx_self ptr) { + if (ptr.use_count) _i_atomic_inc(ptr.use_count); + return ptr; +} + +STC_INLINE void +_cx_memb(_copy)(_cx_self* self, _cx_self ptr) { + if (ptr.use_count) _i_atomic_inc(ptr.use_count); + _cx_memb(_drop)(self); + *self = ptr; +} + +STC_INLINE void +_cx_memb(_take)(_cx_self* self, _cx_self ptr) { + if (self->get != ptr.get) _cx_memb(_drop)(self); + *self = ptr; +} + +STC_INLINE uint64_t +_cx_memb(_value_hash)(const _cx_value* x, size_t n) { + #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX + return c_hash64(&x, 8); + #elif c_option(c_no_cmp) + return c_hash32(&x, 4); + #else + i_valraw rx = i_valto(x); + return i_hash(&rx, sizeof rx); + #endif +} + +STC_INLINE int +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { + #if c_option(c_no_cmp) + return c_default_cmp(&x, &y); + #else + i_valraw rx = i_valto(x), ry = i_valto(x); + return i_cmp(&rx, &ry); + #endif +} + +STC_INLINE bool +_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { + return !_cx_memb(_value_cmp)(x, y); +} +#undef _i_atomic_inc +#undef _i_atomic_dec_and_test +#include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index ac6e9d31..4e2ee97d 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -199,7 +199,7 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { for (size_t index = 0; index < _n; ++index) \ { const T v = _c_arr[index]; method; } \ } while (0) -#define c_apply_it(v, method, C, ...) do { \ +#define c_apply_cnt(v, method, C, ...) do { \ size_t index = 0; \ c_foreach (_it, C, __VA_ARGS__) \ { const C##_value v = *_it.ref; method; ++index; } \ diff --git a/include/stc/csptr.h b/include/stc/csptr.h deleted file mode 100644 index 0718a4cc..00000000 --- a/include/stc/csptr.h +++ /dev/null @@ -1,201 +0,0 @@ -/* MIT License - * - * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* csptr: shared_ptr type -#include - -typedef struct { cstr name, last; } Person; - -Person Person_new(const char* name, const char* last) { - return (Person){.name = cstr_from(name), .last = cstr_from(last)}; -} -void Person_drop(Person* p) { - printf("drop: %s %s\n", p->name.str, p->last.str); - c_drop(cstr, &p->name, &p->last); -} - -#define i_tag person -#define i_val Person -#define i_valdrop Person_drop -#include - -int main() { - csptr_person p = csptr_person_new(Person_new("John", "Smiths")); - csptr_person q = csptr_person_clone(p); // share the pointer - - printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count); - c_drop(csptr_person, &p, &q); -} -*/ - -#ifndef CSPTR_H_INCLUDED -#define CSPTR_H_INCLUDED -#include "ccommon.h" -#include "forward.h" -#include - -#if defined(__GNUC__) || defined(__clang__) - #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) - #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) -#elif defined(_MSC_VER) - #include - #define c_atomic_inc(v) (void)_InterlockedIncrement(v) - #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) -#else - #include - #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) - #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) -#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_ -#endif -#define _i_has_internal_clone -#include "template.h" -typedef i_valraw _cx_raw; - -#if !c_option(c_no_atomic) - #define _i_atomic_inc(v) c_atomic_inc(v) - #define _i_atomic_dec_and_test(v) c_atomic_dec_and_test(v) -#else - #define _i_atomic_inc(v) (void)(++*(v)) - #define _i_atomic_dec_and_test(v) !(--*(v)) -#endif -#if !c_option(c_is_fwd) -_cx_deftypes(_c_csptr_types, _cx_self, i_val); -#endif -_cx_csptr_rep { long counter; i_val value; }; - -STC_INLINE _cx_self -_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } - -STC_INLINE long -_cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } - -STC_INLINE _cx_self -_cx_memb(_from_ptr)(_cx_value* p) { - _cx_self ptr = {p}; - if (p) *(ptr.use_count = c_alloc(long)) = 1; - return ptr; -} - -STC_INLINE _cx_self -_cx_memb(_from)(i_val val) { - _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; -} - -STC_INLINE i_val _cx_memb(_toraw)(const _cx_self* self) { - return *self->get; -} - -STC_INLINE _cx_self -_cx_memb(_move)(_cx_self* self) { - _cx_self ptr = *self; - self->get = NULL, self->use_count = NULL; - return ptr; -} - -STC_INLINE void -_cx_memb(_drop)(_cx_self* self) { - if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { - i_valdrop(self->get); - if (self->get != &((_cx_csptr_rep *)self->use_count)->value) - c_free(self->get); - c_free(self->use_count); - } -} - -STC_INLINE void -_cx_memb(_reset)(_cx_self* self) { - _cx_memb(_drop)(self); - self->use_count = NULL, self->get = NULL; -} - -STC_INLINE void -_cx_memb(_reset_from)(_cx_self* self, i_val val) { - _cx_memb(_drop)(self); - *self = _cx_memb(_from)(val); -} - -#if !c_option(c_no_clone) && !defined _i_valraw_default - STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { - return _cx_memb(_from)(i_valfrom(raw)); - } -#endif - -// does not use i_valfrom, so we can bypass c_no_clone -STC_INLINE _cx_self -_cx_memb(_clone)(_cx_self ptr) { - if (ptr.use_count) _i_atomic_inc(ptr.use_count); - return ptr; -} - -STC_INLINE void -_cx_memb(_copy)(_cx_self* self, _cx_self ptr) { - if (ptr.use_count) _i_atomic_inc(ptr.use_count); - _cx_memb(_drop)(self); - *self = ptr; -} - -STC_INLINE void -_cx_memb(_take)(_cx_self* self, _cx_self ptr) { - if (self->get != ptr.get) _cx_memb(_drop)(self); - *self = ptr; -} - -STC_INLINE uint64_t -_cx_memb(_value_hash)(const _cx_value* x, size_t n) { - #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX - return c_hash64(&x, 8); - #elif c_option(c_no_cmp) - return c_hash32(&x, 4); - #else - i_valraw rx = i_valto(x); - return i_hash(&rx, sizeof rx); - #endif -} - -STC_INLINE int -_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { - #if c_option(c_no_cmp) - return c_default_cmp(&x, &y); - #else - i_valraw rx = i_valto(x), ry = i_valto(x); - return i_cmp(&rx, &ry); - #endif -} - -STC_INLINE bool -_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { - return !_cx_memb(_value_cmp)(x, y); -} -#undef _i_atomic_inc -#undef _i_atomic_dec_and_test -#include "template.h" diff --git a/include/stc/forward.h b/include/stc/forward.h index bf2ba698..9a37297e 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -34,7 +34,7 @@ #define forward_cset(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, c_false, c_true) #define forward_csset(CX, KEY) _c_aatree_types(CX, KEY, KEY, c_false, c_true) #define forward_cbox(CX, VAL) _c_cbox_types(CX, VAL) -#define forward_csptr(CX, VAL) _c_csptr_types(CX, VAL) +#define forward_carc(CX, VAL) _c_carc_types(CX, VAL) #define forward_cpque(CX, VAL) _c_cpque_types(CX, VAL) #define forward_cstack(CX, VAL) _c_cstack_types(CX, VAL) #define forward_cqueue(CX, VAL) _c_cdeq_types(CX, VAL) @@ -132,7 +132,7 @@ SELF##_value* get; \ } SELF -#define _c_csptr_types(SELF, VAL) \ +#define _c_carc_types(SELF, VAL) \ typedef VAL SELF##_value; \ \ typedef struct { \ diff --git a/include/stc/template.h b/include/stc/template.h index 1d1551fa..5efe3772 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -61,9 +61,9 @@ #ifndef i_tag #define i_tag str #endif -#elif defined i_key_ref - #define i_key_bind i_key_ref - #define i_keyraw c_PASTE(i_key_ref, _value) +#elif defined i_key_sptr + #define i_key_bind i_key_sptr + #define i_keyraw c_PASTE(i_key_sptr, _value) #endif #ifdef i_key_bind @@ -120,9 +120,9 @@ #if !defined i_tag && !defined i_key #define i_tag str #endif -#elif defined i_val_ref - #define i_val_bind i_val_ref - #define i_valraw c_PASTE(i_val_ref, _value) +#elif defined i_val_sptr + #define i_val_bind i_val_sptr + #define i_valraw c_PASTE(i_val_sptr, _value) #endif #ifdef i_val_bind @@ -219,7 +219,7 @@ #undef i_val #undef i_val_str -#undef i_val_ref +#undef i_val_sptr #undef i_val_bind #undef i_valraw #undef i_valfrom @@ -228,7 +228,7 @@ #undef i_key #undef i_key_str -#undef i_key_ref +#undef i_key_sptr #undef i_key_bind #undef i_keyraw #undef i_keyfrom -- cgit v1.2.3 From 2ee20bdcf513933902c626802d78a434c4cc1b94 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 12:38:07 +0100 Subject: Forgot csptr_api.md rename. --- docs/carc_api.md | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ docs/csptr_api.md | 178 ------------------------------------------------------ 2 files changed, 178 insertions(+), 178 deletions(-) create mode 100644 docs/carc_api.md delete mode 100644 docs/csptr_api.md diff --git a/docs/carc_api.md b/docs/carc_api.md new file mode 100644 index 00000000..e33bf410 --- /dev/null +++ b/docs/carc_api.md @@ -0,0 +1,178 @@ +# STC [carc](../include/stc/carc.h): Atomic Reference Counted Smart Pointer + +**carc** is a smart pointer that retains shared ownership of an object through a pointer. +Several **carc** objects may own the same object. The object is destroyed and its memory +deallocated when the last remaining **carc** owning the object is destroyed with *carc_X_drop()*; + +The object is destroyed using *carc_X_drop()*. A **carc** may also own no objects, in which +case it is called empty. The *carc_X_cmp()*, *carc_X_drop()* methods are defined based on +the `i_cmp` and `i_valdrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of +the pointed-to object. + +All **carc** functions can be called by multiple threads on different instances of **carc** without +additional synchronization even if these instances are copies and share ownership of the same object. +**carc** uses thread-safe atomic reference counting, through the *carc_X_clone()* and *carc_X_drop()* methods. + +When declaring a container with shared pointers, define `i_val_bind` as the carc type, see example. + +Make sure to pass the result of create functions like *carc_X_from()* **only** to *insert()*, +*push_back()*, and *push()* functions, as it is *moved* into the container. Use *emplace()* +method for sharing existing **carc**s between containers or other existing shared pointers, +as they clone/share the input internally. + +See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference, or Rust [std::sync::Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) / [std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html). + +## Header file and declaration + +```c +#define i_val // value: REQUIRED +#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type +#define i_drop // destroy value func - defaults to empty destruct +#define i_tag // defaults to i_val +#define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc. +#include +``` +`X` should be replaced by the value of `i_tag` in all of the following documentation. + +## Methods +```c +carc_X carc_X_init(); // empty shared pointer +carc_X carc_X_new(i_valraw raw); // like carc_X_from(), but construct owned value from raw. +carc_X carc_X_from(i_val val); // create new heap allocated object. Take ownership of val. +carc_X carc_X_from_ptr(i_val* p); // create a carc from raw pointer. Takes ownership of p. + +carc_X carc_X_clone(carc_X other); // return other with increased use count +carc_X carc_X_move(carc_X* self); // transfer ownership to another carc. +void carc_X_take(carc_X* self, carc_X other); // take ownership of other. +void carc_X_copy(carc_X* self, carc_X other); // copy shared (increase use count) + +void carc_X_drop(carc_X* self); // destruct (decrease use count, free at 0) +long carc_X_use_count(carc_X ptr); + +void carc_X_reset(carc_X* self); +void carc_X_reset_from(carc_X* self, i_val val); // assign new carc with value. Takes ownership of val. + +uint64_t carc_X_value_hash(const i_val* x, size_t n); // hash value +int carc_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default compare. +bool carc_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 +``` + +## Types and constants + +| Type name | Type definition | Used to represent... | +|:------------------|:--------------------------------------------------|:-----------------------| +| `carc_null` | `{NULL, NULL}` | Init nullptr const | +| `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | +| `carc_X_value` | `i_val` | The carc element type | +| `carc_X_raw` | `i_valraw` | Convertion type | + +## Example + +```c +// Create a stack and a list of shared pointers to maps, +// and demonstrate sharing and cloning of maps. +#define i_type Map +#define i_key_str // strings +#define i_val int +#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) +#include + +#define i_type Arc // (atomic) ref. counted type +#define i_val Map +#define i_from Map_clone +#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) +// no comparison of Maps needed (or available), and +// no need for atomic ref. count in single thread: +#define i_opt c_no_cmp|c_no_atomic +#include + +#define i_type Stack +#define i_val_sptr Arc // define i_val_sptr for carc/cbox value, not i_val or i_val_bind +#include + +#define i_type List +#define i_val_sptr Arc // as above +#include + +int main() +{ + c_auto (Stack, stack) + c_auto (List, list) + { + // POPULATE the stack with shared pointers to Map: + Map *map; + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} + }); + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} + }); + + // POPULATE the list: + map = List_push_back(&list, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} + }); + + // Share two Maps from the stack with the list using emplace (clones the carc): + List_emplace_back(&list, stack.data[0]); + List_emplace_back(&list, stack.data[1]); + + // Clone (deep copy) a Map from the stack to the list + // List will contain two shared and two unshared maps. + map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; + + // Add one more element to the cloned map: + Map_emplace_or_assign(map, "CLONED", 2021); + + // Add one more element to the shared map: + Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021); + + + puts("STACKS"); + c_foreach (i, Stack, stack) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", _.name.str, _.year); + puts(""); + } + puts("LIST"); + c_foreach (i, List, list) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", _.name.str, _.year); + puts(""); + } + } +} +``` +Output: +``` +STACKS + Joanna:1992 Joey:1990 Mary:1995 + Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021 +LIST + Rick:1974 Steve:1979 Tracy:2003 + Joanna:1992 Joey:1990 Mary:1995 + Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021 + Brad:1999 CLONED:2021 Jack:1980 Rosanna:2001 +drop Arc: +drop name: Rick +drop name: Tracy +drop name: Steve +drop Arc: +drop name: CLONED +drop name: Brad +drop name: Rosanna +drop name: Jack +drop Arc: +drop name: Brad +drop name: SHARED +drop name: Rosanna +drop name: Jack +drop Arc: +drop name: Joanna +drop name: Mary +drop name: Joey +``` diff --git a/docs/csptr_api.md b/docs/csptr_api.md deleted file mode 100644 index e33bf410..00000000 --- a/docs/csptr_api.md +++ /dev/null @@ -1,178 +0,0 @@ -# STC [carc](../include/stc/carc.h): Atomic Reference Counted Smart Pointer - -**carc** is a smart pointer that retains shared ownership of an object through a pointer. -Several **carc** objects may own the same object. The object is destroyed and its memory -deallocated when the last remaining **carc** owning the object is destroyed with *carc_X_drop()*; - -The object is destroyed using *carc_X_drop()*. A **carc** may also own no objects, in which -case it is called empty. The *carc_X_cmp()*, *carc_X_drop()* methods are defined based on -the `i_cmp` and `i_valdrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of -the pointed-to object. - -All **carc** functions can be called by multiple threads on different instances of **carc** without -additional synchronization even if these instances are copies and share ownership of the same object. -**carc** uses thread-safe atomic reference counting, through the *carc_X_clone()* and *carc_X_drop()* methods. - -When declaring a container with shared pointers, define `i_val_bind` as the carc type, see example. - -Make sure to pass the result of create functions like *carc_X_from()* **only** to *insert()*, -*push_back()*, and *push()* functions, as it is *moved* into the container. Use *emplace()* -method for sharing existing **carc**s between containers or other existing shared pointers, -as they clone/share the input internally. - -See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference, or Rust [std::sync::Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) / [std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html). - -## Header file and declaration - -```c -#define i_val // value: REQUIRED -#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type -#define i_drop // destroy value func - defaults to empty destruct -#define i_tag // defaults to i_val -#define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc. -#include -``` -`X` should be replaced by the value of `i_tag` in all of the following documentation. - -## Methods -```c -carc_X carc_X_init(); // empty shared pointer -carc_X carc_X_new(i_valraw raw); // like carc_X_from(), but construct owned value from raw. -carc_X carc_X_from(i_val val); // create new heap allocated object. Take ownership of val. -carc_X carc_X_from_ptr(i_val* p); // create a carc from raw pointer. Takes ownership of p. - -carc_X carc_X_clone(carc_X other); // return other with increased use count -carc_X carc_X_move(carc_X* self); // transfer ownership to another carc. -void carc_X_take(carc_X* self, carc_X other); // take ownership of other. -void carc_X_copy(carc_X* self, carc_X other); // copy shared (increase use count) - -void carc_X_drop(carc_X* self); // destruct (decrease use count, free at 0) -long carc_X_use_count(carc_X ptr); - -void carc_X_reset(carc_X* self); -void carc_X_reset_from(carc_X* self, i_val val); // assign new carc with value. Takes ownership of val. - -uint64_t carc_X_value_hash(const i_val* x, size_t n); // hash value -int carc_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' - // is defined. Otherwise uses 'i_cmp' or default compare. -bool carc_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 -``` - -## Types and constants - -| Type name | Type definition | Used to represent... | -|:------------------|:--------------------------------------------------|:-----------------------| -| `carc_null` | `{NULL, NULL}` | Init nullptr const | -| `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | -| `carc_X_value` | `i_val` | The carc element type | -| `carc_X_raw` | `i_valraw` | Convertion type | - -## Example - -```c -// Create a stack and a list of shared pointers to maps, -// and demonstrate sharing and cloning of maps. -#define i_type Map -#define i_key_str // strings -#define i_val int -#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) -#include - -#define i_type Arc // (atomic) ref. counted type -#define i_val Map -#define i_from Map_clone -#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) -// no comparison of Maps needed (or available), and -// no need for atomic ref. count in single thread: -#define i_opt c_no_cmp|c_no_atomic -#include - -#define i_type Stack -#define i_val_sptr Arc // define i_val_sptr for carc/cbox value, not i_val or i_val_bind -#include - -#define i_type List -#define i_val_sptr Arc // as above -#include - -int main() -{ - c_auto (Stack, stack) - c_auto (List, list) - { - // POPULATE the stack with shared pointers to Map: - Map *map; - map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} - }); - map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} - }); - - // POPULATE the list: - map = List_push_back(&list, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} - }); - - // Share two Maps from the stack with the list using emplace (clones the carc): - List_emplace_back(&list, stack.data[0]); - List_emplace_back(&list, stack.data[1]); - - // Clone (deep copy) a Map from the stack to the list - // List will contain two shared and two unshared maps. - map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; - - // Add one more element to the cloned map: - Map_emplace_or_assign(map, "CLONED", 2021); - - // Add one more element to the shared map: - Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021); - - - puts("STACKS"); - c_foreach (i, Stack, stack) { - c_forpair (name, year, Map, *i.ref->get) - printf(" %s:%d", _.name.str, _.year); - puts(""); - } - puts("LIST"); - c_foreach (i, List, list) { - c_forpair (name, year, Map, *i.ref->get) - printf(" %s:%d", _.name.str, _.year); - puts(""); - } - } -} -``` -Output: -``` -STACKS - Joanna:1992 Joey:1990 Mary:1995 - Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021 -LIST - Rick:1974 Steve:1979 Tracy:2003 - Joanna:1992 Joey:1990 Mary:1995 - Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021 - Brad:1999 CLONED:2021 Jack:1980 Rosanna:2001 -drop Arc: -drop name: Rick -drop name: Tracy -drop name: Steve -drop Arc: -drop name: CLONED -drop name: Brad -drop name: Rosanna -drop name: Jack -drop Arc: -drop name: Brad -drop name: SHARED -drop name: Rosanna -drop name: Jack -drop Arc: -drop name: Joanna -drop name: Mary -drop name: Joey -``` -- cgit v1.2.3 From 279d9a7dec444369547b8adb599106a792cfecc6 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 14:20:47 +0100 Subject: Updated README.md --- README.md | 110 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 624796bb..bb56231a 100644 --- a/README.md +++ b/README.md @@ -6,41 +6,19 @@ STC - Smart Template Containers for C News ---- ### Version 3 released -A lot of enhancements, additions and bugfixes. There are also a number of breaking changes (mostly renamings), -see migrate guide below. +Lots of enhancements, additions and bugfixes. There are also a number of breaking changes (mostly renamings), +see migration guide below. -Added are new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions -to the type specified, and may be used in place of `i_key`/`i_val`. Use the `_bind` variant for elements -of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_hash*, -and *Type_eq*. Only the functions required by the particular container needs to be defined. e.g. **cmap** -and **cset** are the only types that require *Type_hash* and *Type_eq* to be defined. - -### Migration guide from version 2 to 3. -Replace (regular expression) in VS Code: -- `_del\b` → `_drop` -- `_compare\b` → `_cmp` -- `_rawvalue\b` → `_raw` -- `_equ\b` → `_eq` - -Replace (whole word + match case): -- `i_keydel` → `i_keydrop` -- `i_valdel` → `i_valdrop` -- `i_cnt` → `i_type` -- `cstr_lit` → `cstr_new` -- `csptr_X_make` → `carc_X_from` -- `i_key_csptr` → `i_key_sptr` -- `i_val_csptr` → `i_val_sptr` -- `c_apply` → `c_apply_OLD` // replaced by new `c_apply` -- `c_apply_pair` → `c_apply_pair_OLD` // replaced by new `c_apply` - -Non-regex, global match case replace: -- `csptr` → `carc` +This version is planned to freeze the API. Changes will be handled with deprecations, +so it should be possible to build a code base with version 3 API without the need for updating code. +Expect slow development, mostly handling of bug reports, issues, and improved documentation. ### Brief summary of changes +- Added new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions +to the type specified. See template parameter description. - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. - Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). Also renamed `csptr` to `carc` (atomic reference counted) smart pointer. -- Added [example for **carc**](examples/sptr_to_maps.c). -- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". +- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding", and improved **c_apply** macros. - Renamed: *csptr_X_make()* to *carc_X_from()*. Corresponding **cbox** method is *cbox_X_from()*. - Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. - Renamed: `i_key_csptr`/`i_val_csptr` to `i_key_sptr`/`i_val_sptr` for both **carc** and **cbox** values in containers. @@ -48,6 +26,27 @@ Non-regex, global match case replace: - Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` - Uses a different way to instantiate templated containers, which is incompatible with v1.X. +### Migration guide from version 2 to 3. +Replace (regular expression) in VS Code: +- `_del\b` ⟶ `_drop` +- `_compare\b` ⟶ `_cmp` +- `_rawvalue\b` ⟶ `_raw` +- `_equ\b` ⟶ `_eq` + +Replace (whole word + match case): +- `i_keydel` ⟶ `i_keydrop` +- `i_valdel` ⟶ `i_valdrop` +- `i_cnt` ⟶ `i_type` +- `cstr_lit` ⟶ `cstr_new` +- `csptr_X_make` ⟶ `carc_X_from` +- `i_key_csptr` / `i_key_ref` ⟶ `i_key_sptr` +- `i_val_csptr` / `i_val_ref` ⟶ `i_val_sptr` +- `c_apply` ⟶ `c_apply_OLD` // replaced by new `c_apply` +- `c_apply_pair` ⟶ `c_apply_pair_OLD` // replaced by new `c_apply` + +Non-regex, global match case replace: +- `csptr` ⟶ `carc` + Introduction ------------ STC is a modern, templated, user-friendly, fast, fully type-safe, and customizable container library for C99, @@ -208,7 +207,7 @@ int main(void) { { // add some elements to each container c_apply(v, cset_int_insert(&set, v), int, {10, 20, 30}); - c_apply(v, cvec_pnt_push_back(&vec, v), cvec_pnt_raw, { {10, 1}, {20, 2}, {30, 3} }); + c_apply(v, cvec_pnt_push_back(&vec, v), struct Point, { {10, 1}, {20, 2}, {30, 3} }); c_apply(v, cdeq_int_push_back(&deq, v), int, {10, 20, 30}); c_apply(v, clist_int_push_back(&lst, v), int, {10, 20, 30}); c_apply(v, cstack_int_push(&stk, v), int, {10, 20, 30}); @@ -217,7 +216,7 @@ int main(void) { // add one more element to each container cset_int_insert(&set, 40); - cvec_pnt_push_back(&vec, (struct Point) {40, 4}); + cvec_pnt_push_back(&vec, (struct Point){40, 4}); cdeq_int_push_front(&deq, 5); clist_int_push_front(&lst, 5); cstack_int_push(&stk, 40); @@ -225,7 +224,7 @@ int main(void) { // find an element in each container cset_int_iter i1 = cset_int_find(&set, 20); - cvec_pnt_iter i2 = cvec_pnt_find(&vec, (struct Point) {20, 2}); + cvec_pnt_iter i2 = cvec_pnt_find(&vec, (struct Point){20, 2}); cdeq_int_iter i3 = cdeq_int_find(&deq, 20); clist_int_iter i4 = clist_int_find(&lst, 20); csmap_int_iter i5 = csmap_int_find(&map, 20); @@ -304,32 +303,39 @@ Each templated type requires one `#include`, even if it's the same container bas 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_type` - Full container type name (optional, alternative to `i_tag`). -- `i_opt` - Boolean properties: may combine `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd` with `|` separator. - -- `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_key` - Element key type for map/set only. **[required]**. +- `i_val` - Element value type. **[required]**. For cmap/csmap, it is the mapped value type. +- `i_cmp` - Three-way comparison of two `i_keyraw or i_valraw` pointers - **[required]** for non-integral raw types unless `i_opt c_no_cmp` is defined. - `i_hash` - Hash function taking `i_keyraw *` and a size - defaults to `!i_cmp`. - `i_eq` - Equality comparison of two `i_keyraw *` - defaults to `!i_cmp`. Companion with `i_hash`. -- `i_keydrop` - Destroy map key func - defaults to empty destructor. +Properties: +- `i_tag` - Container type name tag. Defaults to same as `i_key` +- `i_type` - Full container type name. Alternative to `i_tag`. +- `i_opt` - Boolean properties: may combine `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd` with `|` separator. + +Key: +- `i_keydrop` - Destroy map/set key func - defaults to empty destructor. - `i_keyraw` - Convertion "raw" type - defaults to `i_key` type. -- `i_keyfrom` - Convertion func `i_key` <= `i_keyraw` - defaults to simple copy. **[required]** if `i_keydrop` is defined. -- `i_keyto` - Convertion func `i_key *` => `i_keyraw` - defaults to simple copy. +- `i_keyfrom` - Convertion func `i_key` <= `i_keyraw`. **[required]** if `i_keydrop` is defined. Works as *clone* when `i_keyraw` == `i_key` type. +- `i_keyto` - Convertion func `i_key *` => `i_keyraw`. +Val: - `i_valdrop` - Destroy mapped or value func - defaults to empty destruct. - `i_valraw` - Convertion "raw" type - defaults to `i_val` type. -- `i_valfrom` - Convertion func `i_val` <= `i_valraw` - defaults to simple copy. **[required]** if `i_valdrop` is defined. -- `i_valto` - Convertion func `i_val *` => `i_valraw` - defaults to simple copy. - -Instead of defining `i_cmp`, you may define `i_opt c_no_cmp` to disable methods using comparison. - -Instead of defining `i_valfrom`, you may define `i_opt c_no_clone` to disable methods using deep copy. - -If a destructor `i_drop` is defined, then define either `i_valfrom` or `i_opt c_no_clone`, otherwise -compile errors are generated. +- `i_valfrom` - Convertion func `i_val` <= `i_valraw`. **[required]** if `i_valdrop` is defined. Works as *clone* when `i_valraw` == `i_val` type. +- `i_valto` - Convertion func `i_val *` => `i_valraw`. + +Special: +- `i_key_str` - Define key type `cstr` and container i_tag = `str`. It binds type convertion from/to const char*, and the cmp, eq, hash, and keydrop functions. +- `i_key_sptr TYPE` - Define key type where TYPE is a smart pointer `carc` or `cbox`. I.e. not to be used when defining carc/cbox types themselves. +- `i_key_bind TYPE` - General version of the two above - will auto-bind to standard named functions based on TYPE. Use for elements where the following functions are defined: *TYPE_cmp*, *TYPE_clone*, *TYPE_drop*, *TYPE_hash*, and *TYPE_eq*. Only the functions required by the particular container needs to be defined. e.g. **cmap** and **cset** are the only types that require *TYPE_hash* and *TYPE_eq* to be defined. *TYPE_cmp* and *TYPE_clone* are not required if `i_opt c_no_cmp|c_no_clone` is defined. *TYPE_drop* is always required when using `_bind`. +- `i_val_str`, `i_val_sptr`, `i_val_bind` - Same as for key. + +Notes: +- Instead of defining `i_cmp`, you may define `i_opt c_no_cmp` to exclude methods using comparison. +- Instead of defining `i_valfrom`, you may define `i_opt c_no_clone` to exclude methods using deep copy. +- If a destructor `i_drop` is defined, then either `i_valfrom` or `i_opt c_no_clone` defined is required by the compiler. The *emplace* versus non-emplace container methods -------------------------------------------------- -- cgit v1.2.3 From c0fc37b2e680db9576bac31e11acd6b224f3debe Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 14:40:48 +0100 Subject: Update. --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bb56231a..1768021c 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,13 @@ so it should be possible to build a code base with version 3 API without the nee Expect slow development, mostly handling of bug reports, issues, and improved documentation. ### Brief summary of changes +- Renamed `_del` to `_drop`, like the destructor name in Rust. Also `_compare` to `_cmp` and `_equ` to `_eq`. - Added new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions to the type specified. See template parameter description. -- Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. -- Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). Also renamed `csptr` to `carc` (atomic reference counted) smart pointer. -- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding", and improved **c_apply** macros. +- Renamed cstr constructor *cstr_lit()* to `cstr_new(literal)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. +- Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [Rust Box](https://doc.rust-lang.org/rust-by-example/std/box.html) and [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). +- Renamed **csptr** to [**carc**](docs/carc_api.md) (atomic reference counted) smart pointer. +- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding", and changed [**c_apply**](docs/ccommon_api.md) macros. - Renamed: *csptr_X_make()* to *carc_X_from()*. Corresponding **cbox** method is *cbox_X_from()*. - Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. - Renamed: `i_key_csptr`/`i_val_csptr` to `i_key_sptr`/`i_val_sptr` for both **carc** and **cbox** values in containers. -- cgit v1.2.3 From a7b11c557e89dfe6314dd07ea558359071da0f92 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 14:59:44 +0100 Subject: Finished Readme.md updates. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1768021c..744c8dff 100644 --- a/README.md +++ b/README.md @@ -335,9 +335,10 @@ Special: - `i_val_str`, `i_val_sptr`, `i_val_bind` - Same as for key. Notes: +- For non-associative containers, `i_drop` and `i_from` may be defined instead of `i_valdrop` and `i_valfrom`. - Instead of defining `i_cmp`, you may define `i_opt c_no_cmp` to exclude methods using comparison. -- Instead of defining `i_valfrom`, you may define `i_opt c_no_clone` to exclude methods using deep copy. -- If a destructor `i_drop` is defined, then either `i_valfrom` or `i_opt c_no_clone` defined is required by the compiler. +- Instead of defining `i_*from`, you may define `i_opt c_no_clone` to exclude methods using deep copy. +- If a destructor `i_*drop` is defined, then either `i_*from` or `i_opt c_no_clone` is required to be defined. The *emplace* versus non-emplace container methods -------------------------------------------------- -- cgit v1.2.3 From de411007bceda17457fb27ea72b4433adf744797 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 23 Dec 2021 13:21:21 +0100 Subject: Removed emplace functions if not i_valraw or i_keyraw is defined. Safety/optimize measure. --- benchmarks/picobench/picobench_cmap.cpp | 12 ++++++------ benchmarks/picobench/picobench_csmap.cpp | 12 ++++++------ benchmarks/plotbench/cmap_benchmark.cpp | 8 ++++---- benchmarks/plotbench/csmap_benchmark.cpp | 8 ++++---- examples/birthday.c | 4 ++-- examples/box2.c | 4 ++-- examples/csmap_find.c | 14 +++++++------- examples/demos.c | 4 ++-- examples/ex_gauss1.c | 2 +- examples/new_sptr.c | 4 ++-- include/stc/carc.h | 2 +- include/stc/cbox.h | 4 ++-- include/stc/cdeq.h | 12 ++++++++---- include/stc/clist.h | 17 +++++++++-------- include/stc/cmap.h | 7 ++++--- include/stc/cpque.h | 8 ++++---- include/stc/csmap.h | 7 ++++--- include/stc/cstack.h | 4 ++-- include/stc/cvec.h | 17 ++++++++++------- include/stc/template.h | 10 ++++++---- 20 files changed, 86 insertions(+), 74 deletions(-) diff --git a/benchmarks/picobench/picobench_cmap.cpp b/benchmarks/picobench/picobench_cmap.cpp index a045cb7c..f54b3d32 100644 --- a/benchmarks/picobench/picobench_cmap.cpp +++ b/benchmarks/picobench/picobench_cmap.cpp @@ -82,11 +82,11 @@ static void ins_and_erase_cmap_i(picobench::state& s) picobench::scope scope(s); c_forrange (s.iterations()) - cmap_i_emplace(&map, stc64_random(), 0); + cmap_i_insert(&map, stc64_random(), 0); cmap_i_clear(&map); stc64_srandom(seed); c_forrange (s.iterations()) - cmap_i_emplace(&map, stc64_random(), 0); + cmap_i_insert(&map, stc64_random(), 0); stc64_srandom(seed); c_forrange (s.iterations()) cmap_i_erase(&map, stc64_random()); @@ -102,11 +102,11 @@ static void ins_and_erase_cmap_x(picobench::state& s) picobench::scope scope(s); c_forrange (s.iterations()) - cmap_x_emplace(&map, stc64_random(), 0); + cmap_x_insert(&map, stc64_random(), 0); cmap_x_clear(&map); stc64_srandom(seed); c_forrange (s.iterations()) - cmap_x_emplace(&map, stc64_random(), 0); + cmap_x_insert(&map, stc64_random(), 0); stc64_srandom(seed); c_forrange (s.iterations()) cmap_x_erase(&map, stc64_random()); @@ -151,7 +151,7 @@ static void ins_and_access_cmap_i(picobench::state& s) picobench::scope scope(s); c_forrange (N1) - result += ++cmap_i_emplace(&map, stc64_random() & mask, 0).ref->second; + result += ++cmap_i_insert(&map, stc64_random() & mask, 0).ref->second; s.set_result(result); cmap_i_drop(&map); } @@ -270,7 +270,7 @@ static void iterate_cmap_x(picobench::state& s) // measure insert then iterate whole map c_forrange (n, s.iterations()) { - cmap_x_emplace_or_assign(&map, stc64_random(), n); + cmap_x_insert_or_assign(&map, stc64_random(), n); if (!(n & K)) c_foreach (i, cmap_x, map) result += i.ref->second; } diff --git a/benchmarks/picobench/picobench_csmap.cpp b/benchmarks/picobench/picobench_csmap.cpp index 90681cd5..71d54832 100644 --- a/benchmarks/picobench/picobench_csmap.cpp +++ b/benchmarks/picobench/picobench_csmap.cpp @@ -50,7 +50,7 @@ static void ctor_and_ins_one_csmap_i(picobench::state& s) picobench::scope scope(s); c_forrange (n, s.iterations()) { csmap_i map = csmap_i_init(); - csmap_i_emplace(&map, n, 0); + csmap_i_insert(&map, n, 0); result += csmap_i_size(map); csmap_i_drop(&map); } @@ -84,7 +84,7 @@ static void insert_csmap_i(picobench::state& s) stc64_srandom(seed); picobench::scope scope(s); c_forrange (n, s.iterations()) - csmap_i_emplace(&map, stc64_random() & 0xfffffff, n); + csmap_i_insert(&map, stc64_random() & 0xfffffff, n); s.set_result(csmap_i_size(map)); csmap_i_drop(&map); } @@ -130,13 +130,13 @@ static void ins_and_erase_csmap_i(picobench::state& s) picobench::scope scope(s); c_forrange (i, s.iterations()) - csmap_i_emplace(&map, stc64_random() & mask, i); + csmap_i_insert(&map, stc64_random() & mask, i); result = csmap_i_size(map); csmap_i_clear(&map); stc64_srandom(seed); c_forrange (i, s.iterations()) - csmap_i_emplace_or_assign(&map, stc64_random() & mask, i); + csmap_i_insert_or_assign(&map, stc64_random() & mask, i); stc64_srandom(seed); c_forrange (s.iterations()) @@ -178,7 +178,7 @@ static void ins_and_access_csmap_i(picobench::state& s) picobench::scope scope(s); c_forrange (s.iterations()) { - result += ++csmap_i_emplace(&map, stc64_random() & mask, 0).ref->second; + result += ++csmap_i_insert(&map, stc64_random() & mask, 0).ref->second; const csmap_i_value* val = csmap_i_get(&map, stc64_random() & mask); if (val) csmap_i_erase(&map, val->first); } @@ -294,7 +294,7 @@ static void iterate_csmap_x(picobench::state& s) // measure insert then iterate whole map c_forrange (n, s.iterations()) { - csmap_x_emplace_or_assign(&map, stc64_random(), n); + csmap_x_insert_or_assign(&map, stc64_random(), n); if (!(n & K)) c_foreach (i, csmap_x, map) result += i.ref->second; } diff --git a/benchmarks/plotbench/cmap_benchmark.cpp b/benchmarks/plotbench/cmap_benchmark.cpp index 16aec8c0..d8d1c6ab 100644 --- a/benchmarks/plotbench/cmap_benchmark.cpp +++ b/benchmarks/plotbench/cmap_benchmark.cpp @@ -73,8 +73,8 @@ Sample test_stc_unordered_map() { stc64_srandom(seed); s.test[INSERT].t1 = clock(); container con = cmap_x_init(); - c_forrange (i, N/2) cmap_x_emplace(&con, stc64_random() & mask1, i); - c_forrange (i, N/2) cmap_x_emplace(&con, i, i); + c_forrange (i, N/2) cmap_x_insert(&con, stc64_random() & mask1, i); + c_forrange (i, N/2) cmap_x_insert(&con, i, i); s.test[INSERT].t2 = clock(); s.test[INSERT].sum = cmap_x_size(con); stc64_srandom(seed); @@ -86,8 +86,8 @@ Sample test_stc_unordered_map() { }{ container con = cmap_x_init(); stc64_srandom(seed); - c_forrange (i, N/2) cmap_x_emplace(&con, stc64_random() & mask1, i); - c_forrange (i, N/2) cmap_x_emplace(&con, i, i); + c_forrange (i, N/2) cmap_x_insert(&con, stc64_random() & mask1, i); + c_forrange (i, N/2) cmap_x_insert(&con, i, i); stc64_srandom(seed); s.test[FIND].t1 = clock(); size_t sum = 0; diff --git a/benchmarks/plotbench/csmap_benchmark.cpp b/benchmarks/plotbench/csmap_benchmark.cpp index 4d1621e3..e7603b58 100644 --- a/benchmarks/plotbench/csmap_benchmark.cpp +++ b/benchmarks/plotbench/csmap_benchmark.cpp @@ -73,8 +73,8 @@ Sample test_stc_map() { stc64_srandom(seed); s.test[INSERT].t1 = clock(); container con = csmap_x_init(); - c_forrange (i, N/2) csmap_x_emplace(&con, stc64_random() & mask1, i); - c_forrange (i, N/2) csmap_x_emplace(&con, i, i); + c_forrange (i, N/2) csmap_x_insert(&con, stc64_random() & mask1, i); + c_forrange (i, N/2) csmap_x_insert(&con, i, i); s.test[INSERT].t2 = clock(); s.test[INSERT].sum = csmap_x_size(con); stc64_srandom(seed); @@ -86,8 +86,8 @@ Sample test_stc_map() { }{ container con = csmap_x_init(); stc64_srandom(seed); - c_forrange (i, N/2) csmap_x_emplace(&con, stc64_random() & mask1, i); - c_forrange (i, N/2) csmap_x_emplace(&con, i, i); + c_forrange (i, N/2) csmap_x_insert(&con, stc64_random() & mask1, i); + c_forrange (i, N/2) csmap_x_insert(&con, i, i); stc64_srandom(seed); s.test[FIND].t1 = clock(); size_t sum = 0; diff --git a/examples/birthday.c b/examples/birthday.c index f9b777c0..f848436c 100644 --- a/examples/birthday.c +++ b/examples/birthday.c @@ -23,7 +23,7 @@ static void test_repeats(void) cmap_ic_reserve(&m, N); c_forrange (i, N) { uint64_t k = stc64_rand(&rng) & mask; - int v = cmap_ic_emplace(&m, k, 0).ref->second += 1; + int v = cmap_ic_insert(&m, k, 0).ref->second += 1; if (v > 1) printf("repeated value %zu (%d) at 2^%d\n", k, v, (int) log2((double) i)); } } @@ -44,7 +44,7 @@ void test_distribution(void) c_auto (cmap_x, map) { c_forrange (N) { uint64_t k = stc64_rand(&rng); - cmap_x_emplace(&map, k & 0xf, 0).ref->second += 1; + cmap_x_insert(&map, k & 0xf, 0).ref->second += 1; } uint64_t sum = 0; diff --git a/examples/box2.c b/examples/box2.c index d79ea32d..fd76f8eb 100644 --- a/examples/box2.c +++ b/examples/box2.c @@ -38,7 +38,7 @@ Point origin(void) { cbox_Point boxed_origin(void) { // Allocate this point on the heap, and return a pointer to it - return cbox_Point_new((Point){ .x=0.0, .y=0.0 }); + return cbox_Point_from((Point){ .x=0.0, .y=0.0 }); } @@ -56,7 +56,7 @@ int main(void) { c_auto (cbox_Point, boxed_point) c_auto (cbox_BoxPoint, box_in_a_box) { - boxed_rectangle = cbox_Rectangle_new((Rectangle){ + boxed_rectangle = cbox_Rectangle_from((Rectangle){ .top_left = origin(), .bottom_right = (Point){ .x=3.0, .y=-4.0 } }); diff --git a/examples/csmap_find.c b/examples/csmap_find.c index 078c7a11..ea86d71b 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -51,18 +51,18 @@ int main() print_collection_csmap_istr(m1); typedef cvec_istr_value pair; - cvec_istr_emplace_back(&v, (pair){43, "Tc"}); - cvec_istr_emplace_back(&v, (pair){41, "Nb"}); - cvec_istr_emplace_back(&v, (pair){46, "Pd"}); - cvec_istr_emplace_back(&v, (pair){42, "Mo"}); - cvec_istr_emplace_back(&v, (pair){44, "Ru"}); - cvec_istr_emplace_back(&v, (pair){44, "Ru"}); // attempt a duplicate + cvec_istr_push_back(&v, (pair){43, "Tc"}); + cvec_istr_push_back(&v, (pair){41, "Nb"}); + cvec_istr_push_back(&v, (pair){46, "Pd"}); + cvec_istr_push_back(&v, (pair){42, "Mo"}); + cvec_istr_push_back(&v, (pair){44, "Ru"}); + cvec_istr_push_back(&v, (pair){44, "Ru"}); // attempt a duplicate puts("Inserting the following vector data into m1:"); print_collection_cvec_istr(v); c_foreach (i, cvec_istr, cvec_istr_begin(&v), cvec_istr_end(&v)) - csmap_istr_emplace(&m1, i.ref->first, i.ref->second); + csmap_istr_emplace(&m1, c_pair(*i.ref)); puts("The modified map m1 is (key, value):"); print_collection_csmap_istr(m1); diff --git a/examples/demos.c b/examples/demos.c index 32e5dde0..93192ee5 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -130,8 +130,8 @@ void mapdemo1() { printf("\nMAPDEMO1\n"); cmap_ii nums = cmap_ii_init(); - cmap_ii_emplace(&nums, 8, 64); - cmap_ii_emplace(&nums, 11, 121); + cmap_ii_insert(&nums, 8, 64); + cmap_ii_insert(&nums, 11, 121); printf("val 8: %d\n", *cmap_ii_at(&nums, 8)); cmap_ii_drop(&nums); } diff --git a/examples/ex_gauss1.c b/examples/ex_gauss1.c index 6725393f..8a39732a 100644 --- a/examples/ex_gauss1.c +++ b/examples/ex_gauss1.c @@ -39,7 +39,7 @@ int main() { c_forrange (N) { int index = (int) round( stc64_normalf(&rng, &dist) ); - cmap_ii_emplace(&histmap, index, 0).ref->second += 1; + cmap_ii_insert(&histmap, index, 0).ref->second += 1; } // Transfer map to vec and sort it by map keys. diff --git a/examples/new_sptr.c b/examples/new_sptr.c index 045eef77..23fe5791 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -37,8 +37,8 @@ int main(void) { cstack_iptr_push(&stk, carc_int_from(10)); cstack_iptr_push(&stk, carc_int_from(20)); cstack_iptr_push(&stk, carc_int_from(30)); - cstack_iptr_emplace(&stk, *cstack_iptr_top(&stk)); - cstack_iptr_emplace(&stk, *cstack_iptr_begin(&stk).ref); + cstack_iptr_push(&stk, *cstack_iptr_top(&stk)); + cstack_iptr_push(&stk, *cstack_iptr_begin(&stk).ref); c_foreach (i, cstack_iptr, stk) printf(" %d", *i.ref->get); diff --git a/include/stc/carc.h b/include/stc/carc.h index 505b47d9..b4e2e435 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -144,7 +144,7 @@ _cx_memb(_reset_from)(_cx_self* self, i_val val) { *self = _cx_memb(_from)(val); } -#if !c_option(c_no_clone) && !defined _i_valraw_default +#if !c_option(c_no_clone) && !defined _i_no_raw STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { return _cx_memb(_from)(i_valfrom(raw)); } diff --git a/include/stc/cbox.h b/include/stc/cbox.h index fdde5e8c..7ed0d641 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -120,12 +120,12 @@ _cx_memb(_reset_from)(_cx_self* self, i_val val) { } #if !c_option(c_no_clone) - //#ifndef _i_valraw_default +#if !defined _i_no_raw STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { return c_make(_cx_self){c_new(i_val, i_valfrom(raw))}; } - //#endif +#endif STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index f0866dad..97a19311 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -45,13 +45,15 @@ STC_API void _cx_memb(_clear)(_cx_self* self); STC_API void _cx_memb(_drop)(_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); +STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); #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); +#if !defined _i_no_raw STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2); +#endif #endif // !c_no_clone #if !c_option(c_no_cmp) @@ -66,8 +68,10 @@ STC_API _cx_iter _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos #if !c_option(c_no_clone) STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +#if !defined _i_no_raw 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 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) { @@ -150,7 +154,7 @@ _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) +#if !c_option(c_no_clone) && !defined _i_no_raw STC_INLINE _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { @@ -367,7 +371,7 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { } #if !c_option(c_no_clone) - +#if !defined _i_no_raw STC_DEF _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); @@ -375,7 +379,7 @@ _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, co for (; p1 != p2; ++p1) *pos++ = i_valfrom(*p1); return it; } - +#endif STC_DEF _cx_iter _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { diff --git a/include/stc/clist.h b/include/stc/clist.h index 2194067c..e2ff694e 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -109,20 +109,21 @@ STC_API _cx_node* _cx_memb(_erase_after_)(_cx_self* self, _cx_node* node); #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 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(_drop)(self); *self = _cx_memb(_clone)(other); } +#if !defined _i_no_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 _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)); } +#endif #endif STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { return true; } @@ -190,7 +191,7 @@ _cx_memb(_get_mut)(_cx_self* self, i_valraw val) { 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)); + c_foreach (it, _cx_self, cx) _cx_memb(_push_back)(&out, i_valfrom(i_valto(it.ref))); return out; } #endif diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 87ed7c6c..2d0b11fc 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -111,7 +111,7 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } #ifndef _i_isset - #if !c_option(c_no_clone) + #if !c_option(c_no_clone) && !defined _i_no_raw 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); @@ -141,7 +141,7 @@ _cx_memb(_value_clone)(_cx_value _val) { _i_MAP_ONLY( _val.second = i_valfrom(i_valto(&_val.second)); ) return _val; } - +#if !defined _i_no_raw STC_INLINE _cx_result _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); @@ -151,6 +151,7 @@ _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped) } return _res; } +#endif #endif // !c_no_clone STC_INLINE _cx_raw @@ -273,7 +274,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { else { i_keydrop(&_key); i_valdrop(&_res.ref->second); } _res.ref->second = _mapped; return _res; } - #if !c_option(c_no_clone) + #if !c_option(c_no_clone) && !defined _i_no_raw 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); diff --git a/include/stc/cpque.h b/include/stc/cpque.h index caea1549..bf519125 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -99,12 +99,12 @@ STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { if (self->data == other.data) return; _cx_memb(_drop)(self); *self = _cx_memb(_clone)(other); } - -STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_value val) - { _cx_memb(_push)(self, i_valfrom(val)); } - STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val) { return i_valfrom(val); } +#if !defined _i_no_raw +STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_value val) + { _cx_memb(_push)(self, i_valfrom(val)); } +#endif #endif /* -------------------------- IMPLEMENTATION ------------------------- */ diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 8115cf46..fb8c868e 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -147,7 +147,7 @@ _cx_memb(_value_drop)(_cx_value* val) { } #ifndef _i_isset - #if !c_option(c_no_clone) + #if !c_option(c_no_clone) && !defined _i_no_raw 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); @@ -181,7 +181,7 @@ _cx_memb(_value_clone)(_cx_value _val) { _i_MAP_ONLY( _val.second = i_valfrom(i_valto(&_val.second)); ) return _val; } - +#if !defined _i_no_raw STC_INLINE _cx_result _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { _cx_result res = _cx_memb(_insert_entry_)(self, rkey); @@ -191,6 +191,7 @@ _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped) } return res; } +#endif #endif // !c_no_clone STC_INLINE _cx_result @@ -289,7 +290,7 @@ _cx_memb(_node_new_)(_cx_self* self, int level) { else { i_keydrop(&key); i_valdrop(&res.ref->second); } res.ref->second = mapped; return res; } - #if !c_option(c_no_clone) + #if !c_option(c_no_clone) && !defined _i_no_raw 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); diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 387c0126..1ceec0cb 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -95,10 +95,10 @@ STC_INLINE const _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) - +#if !defined _i_no_raw STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_valfrom(raw)); } - +#endif 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)); diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 3486cc37..1faa16c3 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -97,20 +97,21 @@ STC_API _cx_iter _cx_memb(_bsearch_in)(_cx_iter it1, _cx_iter it2, i_valr 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_raw* p1, const _cx_raw* 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 _cx_value* _cx_memb(_emplace)(_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(_drop)(self); *self = _cx_memb(_clone)(other); } +#if !defined _i_no_raw +STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2); +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)(_cx_self* self, i_valraw raw) + { return _cx_memb(_push_back)(self, i_valfrom(raw)); } STC_INLINE _cx_iter _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); @@ -124,6 +125,7 @@ _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 +#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; } @@ -347,7 +349,7 @@ _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, for (; p1 != p2; ++p1) *pos++ = i_valfrom(i_valto(p1)); return it; } - +#if !defined _i_no_raw STC_DEF _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { @@ -357,6 +359,7 @@ _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, return it; } #endif +#endif #if !c_option(c_no_cmp) diff --git a/include/stc/template.h b/include/stc/template.h index 5efe3772..7d5c70b9 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -165,7 +165,7 @@ #define i_keyfrom c_default_clone #endif #ifndef i_keyraw - #define _i_keyraw_default + #define _i_no_keyraw #define i_keyraw i_key #define i_keyto c_default_toraw #endif @@ -191,7 +191,9 @@ #define i_valfrom c_default_clone #endif #ifndef i_valraw - #define _i_valraw_default + #if !defined i_key || defined _i_no_keyraw + #define _i_no_raw + #endif #define i_valraw i_val #define i_valto c_default_toraw #endif @@ -236,8 +238,8 @@ #undef i_keydrop #undef _i_prefix -#undef _i_valraw_default -#undef _i_keyraw_default +#undef _i_no_raw +#undef _i_no_keyraw #undef _i_has_internal_clone #undef _i_template #endif -- cgit v1.2.3 From d63d4a2a23dca342f418a5ccf8adf46e0d08d95a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 23 Dec 2021 15:14:47 +0100 Subject: Fix new_sptr.c example. --- examples/new_sptr.c | 34 +++++++++++++++++++++------------- include/stc/ccommon.h | 4 ++-- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/examples/new_sptr.c b/examples/new_sptr.c index 23fe5791..09bb7137 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -5,43 +5,51 @@ struct Person { cstr name, last; } typedef Person; Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } +Person Person_clone(Person p) { + p.name = cstr_clone(p.name), p.last = cstr_clone(p.last); + return p; +} void Person_drop(Person* p) { printf("drop: %s %s\n", p->name.str, p->last.str); c_drop(cstr, &p->name, &p->last); } -#define i_val Person -#define i_drop Person_drop +#define i_val_bind Person #define i_opt c_no_cmp #define i_tag person #include // ... - +#define i_type SPtr #define i_val int #define i_drop(x) printf("drop: %d\n", *(x)) #include -#define i_val_bind carc_int +#define i_val_sptr SPtr #define i_tag iptr #include int main(void) { - c_autovar (carc_person p = carc_person_from(Person_new("John", "Smiths")), carc_person_drop(&p)) - c_autovar (carc_person q = carc_person_clone(p), carc_person_drop(&q)) // share the pointer + c_auto (carc_person, p, q, r, s) { - printf("%s %s. uses: %lu\n", q.get->name.str, q.get->last.str, *q.use_count); + puts("Ex1"); + p = carc_person_from(Person_new("John", "Smiths")); + q = carc_person_clone(p); + r = carc_person_clone(p); + s = carc_person_from(Person_clone(*p.get)); // deep copy + printf("%s %s. uses: %lu\n", r.get->name.str, s.get->last.str, *p.use_count); } c_auto (cstack_iptr, stk) { - cstack_iptr_push(&stk, carc_int_from(10)); - cstack_iptr_push(&stk, carc_int_from(20)); - cstack_iptr_push(&stk, carc_int_from(30)); - cstack_iptr_push(&stk, *cstack_iptr_top(&stk)); - cstack_iptr_push(&stk, *cstack_iptr_begin(&stk).ref); + puts("Ex2"); + cstack_iptr_emplace(&stk, 10); + cstack_iptr_emplace(&stk, 20); + cstack_iptr_emplace(&stk, 30); + cstack_iptr_push(&stk, SPtr_clone(*cstack_iptr_top(&stk))); + cstack_iptr_push(&stk, SPtr_clone(*cstack_iptr_begin(&stk).ref)); c_foreach (i, cstack_iptr, stk) - printf(" %d", *i.ref->get); + printf(" (%d, uses %ld)", *i.ref->get, *i.ref->use_count); puts(""); } } \ No newline at end of file diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 4e2ee97d..8ae0dfae 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -192,12 +192,12 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { #define c_apply(v, method, T, ...) do { \ const T _c_arr[] = __VA_ARGS__; \ for (size_t index = 0; index < c_arraylen(_c_arr); ++index) \ - { const T v = _c_arr[index]; method; } \ + { T v = _c_arr[index]; method; } \ } while (0) #define c_apply_arr(v, method, T, arr, n) do { \ const T* _c_arr = arr; size_t _n = n; \ for (size_t index = 0; index < _n; ++index) \ - { const T v = _c_arr[index]; method; } \ + { T v = _c_arr[index]; method; } \ } while (0) #define c_apply_cnt(v, method, C, ...) do { \ size_t index = 0; \ -- cgit v1.2.3 From dbeb998018ce3a739500f9a29e9b62639de2c49f Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 27 Dec 2021 15:47:17 +0100 Subject: Added autocheck.l utility to check for wrong usage of c_auto*. --- autocheck.ll | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++ build_autocheck.sh | 5 +++ examples/new_smap.c | 8 +++-- 3 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 autocheck.ll create mode 100644 build_autocheck.sh diff --git a/autocheck.ll b/autocheck.ll new file mode 100644 index 00000000..9b090b1c --- /dev/null +++ b/autocheck.ll @@ -0,0 +1,101 @@ +/* Check for illegal return/break/continue usage inside a STC-lib c_auto* block (RAII). + * Copyright Tyge Løvset, (c) 2021. + */ +%{ +#include +enum { LOOP=1<<0, AUTO=1<<1 }; +enum { NORMAL, BRACES, BRACESDONE }; +static int braces_lev = 0, block_lev = 0; +static int state = NORMAL; +static unsigned int block[64] = {0}, block_type = 0; +const char* fname; +%} + +ID [_a-zA-Z][_a-zA-Z0-9]* +STR \"([^"\\]|\\.)*\" + +%option never-interactive noyymore noyywrap nounistd +%x cmt +%x prep + +%% +\/\/.* ; // line cmt +\/\* BEGIN(cmt); +\n ++yylineno; +\*\/ BEGIN(INITIAL); +. ; +^[ \t]*#.*\\\n { ++yylineno; BEGIN(prep); } +.*\\\n ++yylineno; +.*\n { ++yylineno; BEGIN(INITIAL); } +^[ \t]*#.* ; +{STR} ; +'\\?.' ; +c_foreach | +c_forrange | +for | +while | +switch { block_type |= LOOP; state = BRACES; } +do { block_type |= LOOP; state = BRACESDONE; } +if { state = BRACES; } +c_autovar | +c_autoscope | +c_autodefer | +c_auto { block_type = AUTO; state = BRACES; } +\( { if (state == BRACES) ++braces_lev; } +\) { if (state == BRACES && --braces_lev == 0) { + state = BRACESDONE; + } + } +;[ \t]*else ; +; { if (state == BRACESDONE) { + block_type = block[block_lev]; + state = NORMAL; + } + } +\{ { if (state != BRACES) { block[++block_lev] = block_type; state = NORMAL; } } +\} { if (state != BRACES) block_type = block[--block_lev]; } +return { if (block_type == AUTO) { + printf("%s:%d: error: 'return' used inside a c_auto* scope.\n" + " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); + } else if (block_type & AUTO) { + printf("%s:%d: error: 'return' used in a loop inside a c_auto* scope.\n" + " Use 'break' to exit loops, then 'c_exitauto' to exit c_auto*.\n", fname, yylineno); + } + } +break { if (block_type == AUTO) + printf("%s:%d: error: 'break' used inside a c_auto* scope.\n" + " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); + } +continue { if (block_type == AUTO) + printf("%s:%d: warning: 'continue' used inside a c_auto* scope.\n" + " It will only break out of the current c_auto* scope.\n" + " Use 'c_exitauto' instead to make it explicit.\n", fname, yylineno); + } +c_exitauto { if (block_type != AUTO) + printf("%s:%d: warning: 'c_exitauto' used outside a c_auto* scope.\n" + " Did you mean 'continue' instead?", fname, yylineno); + } +{ID} ; +\n ++yylineno; +. ; + +%% + +#include + +int main(int argc, char **argv) +{ + if (argc == 1 || strcmp(argv[1], "--help") == 0) { + printf("usage: %s [--help] {C-file | -}\n", argv[0]); + return 0; + } + if (strcmp(argv[1], "-") == 0) { + fname = ""; + yyin = stdin; + } else { + fname = argv[1]; + yyin = fopen(fname, "r"); + } + + yylex(); +} diff --git a/build_autocheck.sh b/build_autocheck.sh new file mode 100644 index 00000000..96ec7d4d --- /dev/null +++ b/build_autocheck.sh @@ -0,0 +1,5 @@ +if [ "$OS" = "Windows_NT" ]; then EXE=.exe; fi +flex autocheck.ll +gcc -O2 lex.yy.c -o autocheck$EXE +rm lex.yy.c +strip autocheck$EXE diff --git a/examples/new_smap.c b/examples/new_smap.c index 2cb35b99..e1a9b13a 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -43,9 +43,11 @@ int main() csmap_int_insert(&map, 123, 321); c_auto (csmap_pnt, pmap) { - csmap_pnt_insert(&pmap, (Point){42, 14}, 1); - csmap_pnt_insert(&pmap, (Point){32, 94}, 2); - csmap_pnt_insert(&pmap, (Point){62, 81}, 3); + c_apply(v, csmap_pnt_insert(&pmap, c_pair(v)), csmap_pnt_value, { + {{42, 14}, 1}, + {{32, 94}, 2}, + {{62, 81}, 3}, + }); c_foreach (i, csmap_pnt, pmap) printf(" (%d,%d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); puts(""); -- cgit v1.2.3 From 390e99e911c46ad59ecb966bffb275c9cba92fe1 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 28 Dec 2021 18:36:37 +0100 Subject: Some renaming of new features in previous commit. --- autocheck.ll | 101 -------------------------------------------------- build_autocheck.sh | 5 --- buildcheck.sh | 5 +++ checkauto.ll | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/ccommon_api.md | 16 ++++---- include/stc/ccommon.h | 1 + 6 files changed, 115 insertions(+), 114 deletions(-) delete mode 100644 autocheck.ll delete mode 100644 build_autocheck.sh create mode 100644 buildcheck.sh create mode 100644 checkauto.ll diff --git a/autocheck.ll b/autocheck.ll deleted file mode 100644 index 9b090b1c..00000000 --- a/autocheck.ll +++ /dev/null @@ -1,101 +0,0 @@ -/* Check for illegal return/break/continue usage inside a STC-lib c_auto* block (RAII). - * Copyright Tyge Løvset, (c) 2021. - */ -%{ -#include -enum { LOOP=1<<0, AUTO=1<<1 }; -enum { NORMAL, BRACES, BRACESDONE }; -static int braces_lev = 0, block_lev = 0; -static int state = NORMAL; -static unsigned int block[64] = {0}, block_type = 0; -const char* fname; -%} - -ID [_a-zA-Z][_a-zA-Z0-9]* -STR \"([^"\\]|\\.)*\" - -%option never-interactive noyymore noyywrap nounistd -%x cmt -%x prep - -%% -\/\/.* ; // line cmt -\/\* BEGIN(cmt); -\n ++yylineno; -\*\/ BEGIN(INITIAL); -. ; -^[ \t]*#.*\\\n { ++yylineno; BEGIN(prep); } -.*\\\n ++yylineno; -.*\n { ++yylineno; BEGIN(INITIAL); } -^[ \t]*#.* ; -{STR} ; -'\\?.' ; -c_foreach | -c_forrange | -for | -while | -switch { block_type |= LOOP; state = BRACES; } -do { block_type |= LOOP; state = BRACESDONE; } -if { state = BRACES; } -c_autovar | -c_autoscope | -c_autodefer | -c_auto { block_type = AUTO; state = BRACES; } -\( { if (state == BRACES) ++braces_lev; } -\) { if (state == BRACES && --braces_lev == 0) { - state = BRACESDONE; - } - } -;[ \t]*else ; -; { if (state == BRACESDONE) { - block_type = block[block_lev]; - state = NORMAL; - } - } -\{ { if (state != BRACES) { block[++block_lev] = block_type; state = NORMAL; } } -\} { if (state != BRACES) block_type = block[--block_lev]; } -return { if (block_type == AUTO) { - printf("%s:%d: error: 'return' used inside a c_auto* scope.\n" - " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); - } else if (block_type & AUTO) { - printf("%s:%d: error: 'return' used in a loop inside a c_auto* scope.\n" - " Use 'break' to exit loops, then 'c_exitauto' to exit c_auto*.\n", fname, yylineno); - } - } -break { if (block_type == AUTO) - printf("%s:%d: error: 'break' used inside a c_auto* scope.\n" - " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); - } -continue { if (block_type == AUTO) - printf("%s:%d: warning: 'continue' used inside a c_auto* scope.\n" - " It will only break out of the current c_auto* scope.\n" - " Use 'c_exitauto' instead to make it explicit.\n", fname, yylineno); - } -c_exitauto { if (block_type != AUTO) - printf("%s:%d: warning: 'c_exitauto' used outside a c_auto* scope.\n" - " Did you mean 'continue' instead?", fname, yylineno); - } -{ID} ; -\n ++yylineno; -. ; - -%% - -#include - -int main(int argc, char **argv) -{ - if (argc == 1 || strcmp(argv[1], "--help") == 0) { - printf("usage: %s [--help] {C-file | -}\n", argv[0]); - return 0; - } - if (strcmp(argv[1], "-") == 0) { - fname = ""; - yyin = stdin; - } else { - fname = argv[1]; - yyin = fopen(fname, "r"); - } - - yylex(); -} diff --git a/build_autocheck.sh b/build_autocheck.sh deleted file mode 100644 index 96ec7d4d..00000000 --- a/build_autocheck.sh +++ /dev/null @@ -1,5 +0,0 @@ -if [ "$OS" = "Windows_NT" ]; then EXE=.exe; fi -flex autocheck.ll -gcc -O2 lex.yy.c -o autocheck$EXE -rm lex.yy.c -strip autocheck$EXE diff --git a/buildcheck.sh b/buildcheck.sh new file mode 100644 index 00000000..5a1b2e93 --- /dev/null +++ b/buildcheck.sh @@ -0,0 +1,5 @@ +if [ "$OS" = "Windows_NT" ]; then EXE=.exe; fi +flex checkauto.ll +gcc -O2 lex.yy.c -o checkauto$EXE +rm lex.yy.c +strip checkauto$EXE diff --git a/checkauto.ll b/checkauto.ll new file mode 100644 index 00000000..a2822d9b --- /dev/null +++ b/checkauto.ll @@ -0,0 +1,101 @@ +/* Check for illegal return/break/continue usage inside a STC-lib c_auto* block (RAII). + * Copyright Tyge Løvset, (c) 2021. + */ +%{ +#include +enum { LOOP=1<<0, AUTO=1<<1 }; +enum { NORMAL, BRACES, BRACESDONE }; +static int braces_lev = 0, block_lev = 0; +static int state = NORMAL; +static unsigned int block[64] = {0}, block_type = 0; +const char* fname; +%} + +ID [_a-zA-Z][_a-zA-Z0-9]* +STR \"([^"\\]|\\.)*\" + +%option never-interactive noyymore noyywrap nounistd +%x cmt +%x prep + +%% +\/\/.* ; // line cmt +\/\* BEGIN(cmt); +\n ++yylineno; +\*\/ BEGIN(INITIAL); +. ; +^[ \t]*#.*\\\n { ++yylineno; BEGIN(prep); } +.*\\\n ++yylineno; +.*\n { ++yylineno; BEGIN(INITIAL); } +^[ \t]*#.* ; +{STR} ; +'\\?.' ; +c_foreach | +c_forrange | +for | +while | +switch { block_type |= LOOP; state = BRACES; } +do { block_type |= LOOP; state = BRACESDONE; } +if { state = BRACES; } +c_autovar | +c_autoscope | +c_autodefer | +c_auto { block_type = AUTO; state = BRACES; } +\( { if (state == BRACES) ++braces_lev; } +\) { if (state == BRACES && --braces_lev == 0) { + state = BRACESDONE; + } + } +;[ \t]*else ; +; { if (state == BRACESDONE) { + block_type = block[block_lev]; + state = NORMAL; + } + } +\{ { if (state != BRACES) { block[++block_lev] = block_type; state = NORMAL; } } +\} { if (state != BRACES) block_type = block[--block_lev]; } +return { if (block_type == AUTO) { + printf("%s:%d: error: 'return' used inside a c_auto* scope.\n" + " Use 'c_breakauto' to exit the current c_auto* scope.\n", fname, yylineno); + } else if (block_type & AUTO) { + printf("%s:%d: error: 'return' used in a loop inside a c_auto* scope.\n" + " Use 'break' to exit loops, then 'c_breakauto' to exit c_auto*.\n", fname, yylineno); + } + } +break { if (block_type == AUTO) + printf("%s:%d: error: 'break' used inside a c_auto* scope.\n" + " Use 'c_breakauto' to exit the current c_auto* scope.\n", fname, yylineno); + } +continue { if (block_type == AUTO) + printf("%s:%d: warning: 'continue' used inside a c_auto* scope.\n" + " It will only break out of the current c_auto* scope.\n" + " Use 'c_breakauto' instead to make it explicit.\n", fname, yylineno); + } +c_breakauto { if (block_type != AUTO) + printf("%s:%d: warning: 'c_breakauto' used outside a c_auto* scope.\n" + " Did you mean 'continue' instead?", fname, yylineno); + } +{ID} ; +\n ++yylineno; +. ; + +%% + +#include + +int main(int argc, char **argv) +{ + if (argc == 1 || strcmp(argv[1], "--help") == 0) { + printf("usage: %s [--help] {C-file | -}\n", argv[0]); + return 0; + } + if (strcmp(argv[1], "-") == 0) { + fname = ""; + yyin = stdin; + } else { + fname = argv[1]; + yyin = fopen(fname, "r"); + } + + yylex(); +} diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 9c872519..bd7029c4 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -6,18 +6,18 @@ The following handy macros are safe to use, i.e. have no side-effects. General ***defer*** mechanics for resource acquisition. These macros allows to specify the release of the resource where the resource acquisition takes place. Makes it easier to verify that resources are released. -**NB**: These macros are one-time executed **for-loops**. Use ***only*** `c_exitauto` in order to break out +**NB**: These macros are one-time executed **for-loops**. Use ***only*** `c_breakauto` in order to break out of these `c_auto*`-blocks! ***Do not*** use `return` or `goto` (or `break`) inside them, as they will prevent the `end`-statement to be executed when leaving scope. This is not particular to the `c_auto*()` macros, as one must always make sure to unwind temporary allocated resources before a `return` in C. -| Usage | Description | -|:---------------------------------------|:---------------------------------------------------| -| `c_auto (Type, var...)` | `c_autovar (Type var=Type_init(), Type_drop(&var))` | -| `c_autovar (Type var=init, end...)` | Declare `var`. Defer `end...` to end of block | -| `c_autoscope (init, end...)` | Execute `init`. Defer `end...` to end of block | -| `c_autodefer (end...)` | Defer `end...` to end of block | -| `c_exitauto;` | Break safely out of a `c_auto*`-block/scope | +| Usage | Description | +|:---------------------------------------|:-----------------------------------------------------| +| `c_auto (Type, var...)` | `c_autovar (Type var=Type_init(), Type_drop(&var))` | +| `c_autovar (Type var=init, end...)` | Declare `var`. Defer `end...` to end of block | +| `c_autoscope (init, end...)` | Execute `init`. Defer `end...` to end of block | +| `c_autodefer (end...)` | Defer `end...` to end of block | +| `c_breakauto;` | Break out of a `c_auto*`-block/scope without memleak | For multiple variables, use either multiple **c_autovar** in sequence, or declare variable outside scope and use **c_autoscope**. Also, **c_auto** support up to 3 variables. diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 8ae0dfae..b2ae7b97 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -169,6 +169,7 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { #define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__) #define c_autoscope(init, ...) for (int _c_ii = (init, 0); !_c_ii; ++_c_ii, __VA_ARGS__) #define c_autodefer(...) for (int _c_ii = 0; !_c_ii; ++_c_ii, __VA_ARGS__) +#define c_breakauto continue #define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) #define c_auto_2(C, a) \ -- cgit v1.2.3 From 48e9d858da36b0fee7787edd12e7f336ccdf04b4 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 29 Dec 2021 12:14:35 +0100 Subject: Fixed and simplified csview tokensizer call. --- docs/csview_api.md | 23 ++++++++++------------- examples/new_smap.c | 50 ++++++++++++++++++++++++++++---------------------- examples/splitstr.c | 35 +++++++++++++++-------------------- examples/sview_split.c | 10 ++++++---- include/stc/csview.h | 21 ++++++--------------- 5 files changed, 65 insertions(+), 74 deletions(-) diff --git a/docs/csview_api.md b/docs/csview_api.md index 4e5d3b0e..a582505f 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -41,8 +41,7 @@ void csview_clear(csview* self); csview csview_substr(csview sv, intptr_t pos, size_t n); // negative pos count from end csview csview_slice(csview sv, intptr_t p1, intptr_t p2); // negative p1, p2 count from end -csview csview_first_token(csview sv, csview sep); // see split example below. -csview csview_next_token(csview sv, csview sep, csview token); +csview csview_token(csview sv, csview sep, size_t* start); // see split example below. bool csview_equals(csview sv, csview sv2); size_t csview_find(csview sv, csview needle); @@ -135,12 +134,11 @@ and does not depend on null-terminated strings. *string_split()* function return void print_split(csview str, csview sep) { - csview token = csview_first_token(str, sep); - for (;;) { + size_t pos = 0; + while (pos != str.size) { + csview tok = csview_token(str, sep, &pos); // print non-null-terminated csview - printf("\"%.*s\"\n", csview_ARG(token)); - if (csview_end(&token).ref == csview_end(&str).ref) break; - token = csview_next_token(str, sep, token); + printf("[" c_svfmt "]\n", c_svarg(tok)); } } @@ -150,11 +148,10 @@ void print_split(csview str, csview sep) cvec_str string_split(csview str, csview sep) { cvec_str vec = cvec_str_init(); - csview token = csview_first_token(str, sep); - for (;;) { - cvec_str_push_back(&vec, cstr_from_v(token)); - if (csview_end(&token).ref == csview_end(&str).ref) break; - token = csview_next_token(str, sep, token); + size_t pos = 0; + while (pos != str.size) { + csview tok = csview_token(str, sep, &pos); + cvec_str_push_back(&vec, cstr_from_v(tok)); } return vec; } @@ -168,7 +165,7 @@ int main() c_autovar (cvec_str v = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cvec_str_drop(&v)) c_foreach (i, cvec_str, v) - printf("\"%s\"\n", i.ref->str); + printf("[%s]\n", i.ref->str); } ``` Output: diff --git a/examples/new_smap.c b/examples/new_smap.c index e1a9b13a..382d27ae 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -1,10 +1,11 @@ #include #include -forward_csmap(csmap_pnt, struct Point, int); +forward_csmap(PMap, struct Point, int); +// Use forward declared PMap in struct struct MyStruct { - csmap_pnt pntmap; + PMap pntmap; cstr name; } typedef MyStruct; @@ -20,50 +21,55 @@ int point_cmp(const Point* a, const Point* b) { return c ? c : a->y - b->y; } +#define i_type PMap #define i_key Point #define i_val int #define i_cmp point_cmp #define i_opt c_is_fwd -#define i_tag pnt #include -// int => int map +// cstr => cstr map +#define i_type SMap #define i_key_str #define i_val_str #include -// string set +// cstr set +#define i_type SSet #define i_key_str #include int main() { - c_auto (csmap_int, map) - csmap_int_insert(&map, 123, 321); + c_auto (csmap_int, imap) { + csmap_int_insert(&imap, 123, 321); + } - c_auto (csmap_pnt, pmap) { - c_apply(v, csmap_pnt_insert(&pmap, c_pair(v)), csmap_pnt_value, { + c_auto (PMap, pmap) { + c_apply(v, PMap_insert(&pmap, c_pair(v)), PMap_value, { {{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}, }); - c_foreach (i, csmap_pnt, pmap) - printf(" (%d,%d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); + c_forpair (p, i, PMap, pmap) + printf(" (%d,%d: %d)", _.p.x, _.p.y, _.i); puts(""); } - c_auto (csmap_str, smap) { - csmap_str_emplace(&smap, "Hello, friend", "this is the mapped value"); - csmap_str_emplace(&smap, "The brown fox", "jumped"); - csmap_str_emplace(&smap, "This is the time", "for all good things"); - c_foreach (i, csmap_str, smap) - printf(" (%s: %s)\n", i.ref->first.str, i.ref->second.str); + c_auto (SMap, smap) { + c_apply(v, SMap_emplace(&smap, c_pair(v)), SMap_raw, { + {"Hello, friend", "this is the mapped value"}, + {"The brown fox", "jumped"}, + {"This is the time", "for all good things"}, + }); + c_forpair (i, j, SMap, smap) + printf(" (%s: %s)\n", _.i.str, _.j.str); } - c_auto (csset_str, sset) { - csset_str_emplace(&sset, "Hello, friend"); - csset_str_emplace(&sset, "Goodbye, foe"); - printf("Found? %s\n", csset_str_contains(&sset, "Hello, friend") ? "true" : "false"); + c_auto (SSet, sset) { + SSet_emplace(&sset, "Hello, friend"); + SSet_emplace(&sset, "Goodbye, foe"); + printf("Found? %s\n", SSet_contains(&sset, "Hello, friend") ? "true" : "false"); } -} \ No newline at end of file +} diff --git a/examples/splitstr.c b/examples/splitstr.c index 789b2c59..75ee3022 100644 --- a/examples/splitstr.c +++ b/examples/splitstr.c @@ -2,12 +2,11 @@ void print_split(csview str, csview sep) { - csview token = csview_first_token(str, sep); - for (;;) { + size_t pos = 0; + while (pos != str.size) { + csview tok = csview_token(str, sep, &pos); // print non-null-terminated csview - printf("\t\"%.*s\"\n", c_svarg(token)); - if (csview_end(&token).ref == csview_end(&str).ref) break; - token = csview_next_token(str, sep, token); + printf("[" c_svfmt "]\n", c_svarg(tok)); } } @@ -17,26 +16,22 @@ void print_split(csview str, csview sep) cvec_str string_split(csview str, csview sep) { cvec_str vec = cvec_str_init(); - csview token = csview_first_token(str, sep); - for (;;) { - cvec_str_push_back(&vec, cstr_from_v(token)); - if (csview_end(&token).ref == csview_end(&str).ref) break; - token = csview_next_token(str, sep, token); + size_t pos = 0; + while (pos != str.size) { + csview tok = csview_token(str, sep, &pos); + cvec_str_push_back(&vec, cstr_from_v(tok)); } return vec; } int main() { - puts("Output from print_split():"); - print_split(c_sv("//This is a//double-slash//separated//string"), c_sv("//")); puts(""); - print_split(c_sv("This has no matching separator"), c_sv("xx")); puts(""); + print_split(c_sv("//This is a//double-slash//separated//string"), c_sv("//")); + puts(""); + print_split(c_sv("This has no matching separator"), c_sv("xx")); + puts(""); - puts("Output from string_split():"); - cstr string = cstr_new("Split,this,,string,now,"); - cvec_str vec = string_split(cstr_sv(string), c_sv(",")); - - c_autodefer (cvec_str_drop(&vec), cstr_drop(&string)) - c_foreach (i, cvec_str, vec) - printf("\t\"%s\"\n", i.ref->str); + c_autovar (cvec_str v = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cvec_str_drop(&v)) + c_foreach (i, cvec_str, v) + printf("[%s]\n", i.ref->str); } \ No newline at end of file diff --git a/examples/sview_split.c b/examples/sview_split.c index 3a079583..ed0365ec 100644 --- a/examples/sview_split.c +++ b/examples/sview_split.c @@ -4,11 +4,13 @@ int main() { // No memory allocations or string length calculations! const csview date = c_sv("2021/03/12"); - const csview year = csview_first_token(date, c_sv("/")); - const csview month = csview_next_token(date, c_sv("/"), year); - const csview day = csview_next_token(date, c_sv("/"), month); + size_t pos = 0; + const csview year = csview_token(date, c_sv("/"), &pos); + const csview month = csview_token(date, c_sv("/"), &pos); + const csview day = csview_token(date, c_sv("/"), &pos); - printf(c_svfmt ", " c_svfmt ", " c_svfmt "\n", c_svarg(year), c_svarg(month), c_svarg(day)); + printf(c_svfmt ", " c_svfmt ", " c_svfmt "\n", + c_svarg(year), c_svarg(month), c_svarg(day)); c_auto (cstr, y, m, d) { y = cstr_from_v(year), m = cstr_from_v(month), d = cstr_from_v(day); diff --git a/include/stc/csview.h b/include/stc/csview.h index d0152c3d..69de5749 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -38,8 +38,7 @@ typedef char csview_value; STC_API csview csview_substr(csview sv, intptr_t pos, size_t n); STC_API csview csview_slice(csview sv, intptr_t p1, intptr_t p2); -STC_API csview csview_first_token(csview sv, csview sep); -STC_API csview csview_next_token(csview sv, csview sep, csview tok); +STC_API csview csview_token(csview sv, csview sep, size_t* start); #define csview_new(literal) \ c_make(csview){literal, sizeof c_make(c_strlit){literal} - 1} @@ -141,19 +140,11 @@ csview_slice(csview sv, intptr_t p1, intptr_t p2) { } STC_DEF csview -csview_first_token(csview sv, csview sep) { - const char* res = c_strnstrn(sv.str, sep.str, sv.size, sep.size); - return c_make(csview){sv.str, (res ? res - sv.str : sv.size)}; -} - -STC_DEF csview -csview_next_token(csview sv, csview sep, csview tok) { - if (&tok.str[tok.size] == &sv.str[sv.size]) - return c_make(csview){&sv.str[sv.size], 0}; - tok.str += tok.size + sep.size; - size_t n = sv.size - (tok.str - sv.str); - const char* res = c_strnstrn(tok.str, sep.str, n, sep.size); - tok.size = res ? res - tok.str : n; +csview_token(csview sv, csview sep, size_t* start) { + csview slice = {sv.str + *start, sv.size - *start}; + const char* res = c_strnstrn(slice.str, sep.str, slice.size, sep.size); + csview tok = {slice.str, (res ? res - slice.str : slice.size)}; + *start += tok.size + (res ? sep.size : 0); return tok; } -- cgit v1.2.3 From 7115f4539b7d08ec21c5e6132841b2613a74059d Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 29 Dec 2021 12:52:21 +0100 Subject: Update of README.md docs describing version 3. --- README.md | 40 ++++++++++++++++++++-------------------- include/stc/csview.h | 4 ++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 744c8dff..923b901f 100644 --- a/README.md +++ b/README.md @@ -6,30 +6,31 @@ STC - Smart Template Containers for C News ---- ### Version 3 released -Lots of enhancements, additions and bugfixes. There are also a number of breaking changes (mostly renamings), -see migration guide below. +This version introduces lots of enhancements, bugfixes and additions. There are also +a number of breaking changes, see below for changes and the migration guide. -This version is planned to freeze the API. Changes will be handled with deprecations, -so it should be possible to build a code base with version 3 API without the need for updating code. -Expect slow development, mostly handling of bug reports, issues, and improved documentation. +Version 3 is planned to freeze the API, as far as possible. Any changes will be handled with long +lasting deprecations, so it should be ready for creating production code using it. ### Brief summary of changes -- Renamed `_del` to `_drop`, like the destructor name in Rust. Also `_compare` to `_cmp` and `_equ` to `_eq`. -- Added new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions -to the type specified. See template parameter description. -- Renamed cstr constructor *cstr_lit()* to `cstr_new(literal)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. -- Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [Rust Box](https://doc.rust-lang.org/rust-by-example/std/box.html) and [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). -- Renamed **csptr** to [**carc**](docs/carc_api.md) (atomic reference counted) smart pointer. -- Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding", and changed [**c_apply**](docs/ccommon_api.md) macros. -- Renamed: *csptr_X_make()* to *carc_X_from()*. Corresponding **cbox** method is *cbox_X_from()*. -- Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. -- Renamed: `i_key_csptr`/`i_val_csptr` to `i_key_sptr`/`i_val_sptr` for both **carc** and **cbox** values in containers. -- Renamed: `i_cnt` to `i_type` for defining the complete container type name. -- Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` -- Uses a different way to instantiate templated containers, which is incompatible with v1.X. +- Renamed: all ***_del*** to `_drop` (like destructors in Rust). +- Renamed: all ***_compare*** to `_cmp` +- Renamed: ***i_equ*** to `i_eq`, and ***_equalto*** to `_eq`. +- Renamed: ***i_cnt*** to `i_type` for defining the complete container type name. +- Renamed: type **csptr** to [**carc**](docs/carc_api.md) (atomic reference counted) smart pointer. +- Renamed: ***i_key_csptr*** / ***i_val_csptr*** to `i_key_sptr` / `i_val_sptr` for specifying **carc** and **cbox** values in containers. +- Renamed: *csptr_X_make()* to `carc_X_from()`. +- Renamed: *cstr_lit()* to `cstr_new(literal)`, and *cstr_assign_fmt()* to `cstr_printf()`. +- Renamed: *c_default_fromraw()* to `c_default_clone()`. +- Changed: the [**c_apply**](docs/ccommon_api.md) macros API. +- Replaced: *csview_first_token()* and *csview_next_token()* with one function: `csview_token()`. +- Added: new general `i_key_bind` / `i_val_bind` template parameters which auto-binds template functions. +- Added: `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` +- Added: [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [Rust Box](https://doc.rust-lang.org/rust-by-example/std/box.html) and [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). +- Added: [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding" ### Migration guide from version 2 to 3. -Replace (regular expression) in VS Code: +Replace (regular expression) globally in code base (VS Code): - `_del\b` ⟶ `_drop` - `_compare\b` ⟶ `_cmp` - `_rawvalue\b` ⟶ `_raw` @@ -40,7 +41,6 @@ Replace (whole word + match case): - `i_valdel` ⟶ `i_valdrop` - `i_cnt` ⟶ `i_type` - `cstr_lit` ⟶ `cstr_new` -- `csptr_X_make` ⟶ `carc_X_from` - `i_key_csptr` / `i_key_ref` ⟶ `i_key_sptr` - `i_val_csptr` / `i_val_ref` ⟶ `i_val_sptr` - `c_apply` ⟶ `c_apply_OLD` // replaced by new `c_apply` diff --git a/include/stc/csview.h b/include/stc/csview.h index 69de5749..c4844bfb 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -143,8 +143,8 @@ STC_DEF csview csview_token(csview sv, csview sep, size_t* start) { csview slice = {sv.str + *start, sv.size - *start}; const char* res = c_strnstrn(slice.str, sep.str, slice.size, sep.size); - csview tok = {slice.str, (res ? res - slice.str : slice.size)}; - *start += tok.size + (res ? sep.size : 0); + csview tok = {slice.str, res ? res - slice.str : (sep.size = 0, slice.size)}; + *start += tok.size + sep.size; return tok; } -- cgit v1.2.3 From 92f5421493932d00e63b33152331a36cc4fc9491 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 29 Dec 2021 14:39:56 +0100 Subject: Some more docs. --- README.md | 11 ++++++----- docs/ccommon_api.md | 2 +- docs/clist_api.md | 2 +- docs/cmap_api.md | 2 +- docs/cset_api.md | 2 +- docs/csmap_api.md | 2 +- docs/csset_api.md | 2 +- examples/runall.sh | 1 + 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 923b901f..9d294346 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ STC - Smart Template Containers for C News ---- ### Version 3 released -This version introduces lots of enhancements, bugfixes and additions. There are also -a number of breaking changes, see below for changes and the migration guide. +This version introduces lots of enhancements, bugfixes and additions. There are also +a number of breaking changes, see below for changes and a migration guide. -Version 3 is planned to freeze the API, as far as possible. Any changes will be handled with long -lasting deprecations, so it should be ready for creating production code using it. +With version 3, the API is freezed as far as possible. Any changes will be handled with long +lasting deprecations, so you may develop production code using it. ### Brief summary of changes - Renamed: all ***_del*** to `_drop` (like destructors in Rust). @@ -24,7 +24,8 @@ lasting deprecations, so it should be ready for creating production code using i - Renamed: *c_default_fromraw()* to `c_default_clone()`. - Changed: the [**c_apply**](docs/ccommon_api.md) macros API. - Replaced: *csview_first_token()* and *csview_next_token()* with one function: `csview_token()`. -- Added: new general `i_key_bind` / `i_val_bind` template parameters which auto-binds template functions. +- Added: **checkauto** tool for checking that c-source files uses `c_auto*` macros correctly. +- Added: general `i_key_bind` / `i_val_bind` template parameters which auto-binds template functions. - Added: `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` - Added: [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [Rust Box](https://doc.rust-lang.org/rust-by-example/std/box.html) and [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). - Added: [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding" diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index bd7029c4..3f21d3c0 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -20,7 +20,7 @@ macros, as one must always make sure to unwind temporary allocated resources bef | `c_breakauto;` | Break out of a `c_auto*`-block/scope without memleak | For multiple variables, use either multiple **c_autovar** in sequence, or declare variable outside -scope and use **c_autoscope**. Also, **c_auto** support up to 3 variables. +scope and use **c_autoscope**. Also, **c_auto** support up to 4 variables. ```c c_autovar (cstr s = cstr_new("Hello"), cstr_drop(&s)) { diff --git a/docs/clist_api.md b/docs/clist_api.md index fc54f40e..8f907eca 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -42,7 +42,7 @@ clist_X clist_X_clone(clist_X list); void clist_X_clear(clist_X* self); void clist_X_copy(clist_X* self, clist_X other); -void clist_X_drop(clist_X* self); // destructor +void clist_X_drop(clist_X* self); // destructor bool clist_X_empty(clist_X list); size_t clist_X_count(clist_X list); // size() in O(n) time diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 38346e53..5c029a29 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -47,7 +47,7 @@ void cmap_X_max_load_factor(cmap_X* self, float max_load); bool cmap_X_reserve(cmap_X* self, size_t size); void cmap_X_shrink_to_fit(cmap_X* self); void cmap_X_swap(cmap_X* a, cmap_X* b); -void cmap_X_drop(cmap_X* self); // destructor +void cmap_X_drop(cmap_X* self); // destructor size_t cmap_X_size(cmap_X map); size_t cmap_X_capacity(cmap_X map); // buckets * max_load_factor diff --git a/docs/cset_api.md b/docs/cset_api.md index 18454dcf..32488b81 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -33,7 +33,7 @@ void cset_X_max_load_factor(cset_X* self, float max_load); bool cset_X_reserve(cset_X* self, size_t size); void cset_X_shrink_to_fit(cset_X* self); void cset_X_swap(cset_X* a, cset_X* b); -void cset_X_drop(cset_X* self); // destructor +void cset_X_drop(cset_X* self); // destructor size_t cset_X_size(cset_X set); // num. of allocated buckets size_t cset_X_capacity(cset_X set); // buckets * max_load_factor diff --git a/docs/csmap_api.md b/docs/csmap_api.md index c3f71a7c..65f932ea 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -40,7 +40,7 @@ csmap_X csmap_X_clone(csmap_x map); void csmap_X_clear(csmap_X* self); void csmap_X_copy(csmap_X* self, csmap_X other); void csmap_X_swap(csmap_X* a, csmap_X* b); -void csmap_X_drop(csmap_X* self); // destructor +void csmap_X_drop(csmap_X* self); // destructor size_t csmap_X_size(csmap_X map); bool csmap_X_empty(csmap_X map); diff --git a/docs/csset_api.md b/docs/csset_api.md index 01926453..561b8f8e 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -28,7 +28,7 @@ csset_X csset_X_clone(csset_x set); void csset_X_clear(csset_X* self); void csset_X_copy(csset_X* self, csset_X other); void csset_X_swap(csset_X* a, csset_X* b); -void csset_X_drop(csset_X* self); // destructor +void csset_X_drop(csset_X* self); // destructor size_t csset_X_size(csset_X set); bool csset_X_empty(csset_X set); diff --git a/examples/runall.sh b/examples/runall.sh index 12c72684..e95068ff 100644 --- a/examples/runall.sh +++ b/examples/runall.sh @@ -24,6 +24,7 @@ fi if [ $run = 0 ] ; then for i in *.c ; do echo $cc -I../include $i $libs + ../checkauto $i $cc -I../include $i $libs done else -- cgit v1.2.3