diff options
| author | Tyge Løvset <[email protected]> | 2021-12-29 15:14:37 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-12-29 15:14:37 +0100 |
| commit | a53b2f4269951e0b5340723670137b4fdf96534c (patch) | |
| tree | e5d36c28d0fd548873216426bb00a6b59d2730dd | |
| parent | 183a89859ba9914ee0546e4482b40be199e52292 (diff) | |
| parent | 92f5421493932d00e63b33152331a36cc4fc9491 (diff) | |
| download | STC-modified-a53b2f4269951e0b5340723670137b4fdf96534c.tar.gz STC-modified-a53b2f4269951e0b5340723670137b4fdf96534c.zip | |
Merge pull request #17 from tylov/version3
Version3
Breaking changes are covered by the migration guide in the NEWS section in README.md
105 files changed, 1828 insertions, 1885 deletions
@@ -5,30 +5,59 @@ STC - Smart Template Containers for C News ---- -- 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. - -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. -- 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. +### 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 a migration guide. + +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). +- 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: **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" + +### Migration guide from version 2 to 3. +Replace (regular expression) globally in code base (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` +- `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, -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). @@ -42,7 +71,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) @@ -62,7 +91,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. @@ -89,36 +118,47 @@ 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 <stc/cvec.h> +#define i_type FVec // if not defined, vector type would be cvec_float +#define i_val float // element type +#include <stc/cvec.h> // 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_del(&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` 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 <stc/cvec.h> #define i_val struct Two -#define i_opt c_no_compare +#define i_opt c_no_cmp #define i_tag two #include <stc/cvec.h> ... @@ -133,16 +173,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 <stc/cset.h> // cset_int: unordered set #define i_val struct Point -#define i_cmp Point_compare +#define i_cmp Point_cmp #define i_tag pnt #include <stc/cvec.h> // cvec_pnt: vector of struct Point @@ -160,7 +200,7 @@ int Point_compare(const struct Point* a, const struct Point* b) { #include <stc/csmap.h> // 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) @@ -169,16 +209,17 @@ 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), 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}); + c_apply(v, csmap_int_insert(&map, c_pair(v)), + csmap_int_raw, { {20, 2}, {10, 1}, {30, 3} }); // 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); @@ -186,7 +227,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); @@ -265,31 +306,40 @@ 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_compare`, `c_no_clone`, `c_no_atomic`, `c_is_fwd` with `|` separator. +- `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_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`. +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. -- `i_keydel` - Destroy map key func - defaults to empty destructor. +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_keyraw` => `i_key` - defaults to simple copy. **[required]** if `i_keydel` is defined. -- `i_keyto` - Convertion func `i_key` => `i_keyraw` - defaults to simple copy. +- `i_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`. -- `i_valdel` - Destroy mapped or value func - defaults to empty destruct. +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_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`. **[required]** if `i_valdrop` is defined. Works as *clone* when `i_valraw` == `i_val` type. +- `i_valto` - Convertion func `i_val *` => `i_valraw`. -Instead of defining `i_cmp`, you may define `i_opt c_no_compare` to disable methods using comparison. +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. -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 -compile errors are generated. +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_*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 -------------------------------------------------- @@ -318,8 +368,8 @@ and non-emplace methods: #define i_val_str // special macro to enable container of cstr #include <stc/cvec.h> // 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* @@ -413,4 +463,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/benchmarks/picobench/picobench_cmap.cpp b/benchmarks/picobench/picobench_cmap.cpp index 330c5e51..f54b3d32 100644 --- a/benchmarks/picobench/picobench_cmap.cpp +++ b/benchmarks/picobench/picobench_cmap.cpp @@ -82,16 +82,16 @@ 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());
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)
@@ -102,16 +102,16 @@ 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());
s.set_result(cmap_x_size(map));
- cmap_x_del(&map);
+ cmap_x_drop(&map);
}
#define P samples(S1).iterations({N1/4})
@@ -151,9 +151,9 @@ 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_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})
@@ -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;
}
@@ -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..71d54832 100644 --- a/benchmarks/picobench/picobench_csmap.cpp +++ b/benchmarks/picobench/picobench_csmap.cpp @@ -50,9 +50,9 @@ 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_del(&map);
+ csmap_i_drop(&map);
}
s.set_result(result);
}
@@ -84,9 +84,9 @@ 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_del(&map);
+ csmap_i_drop(&map);
}
#define P samples(S1).iterations({N1})
@@ -130,19 +130,19 @@ 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())
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})
@@ -178,12 +178,12 @@ 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);
}
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})
@@ -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;
}
@@ -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..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);
@@ -82,12 +82,12 @@ 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);
- 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;
@@ -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 <stc/crandom.h>
#define i_val float
-#define i_cmp -c_default_compare
+#define i_cmp -c_default_cmp
#define i_tag f
#include <stc/cpque.h>
@@ -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..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);
@@ -82,12 +82,12 @@ 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);
- 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;
@@ -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/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 <stdbool.h> +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); +<cmt>\n ++yylineno; +<cmt>\*\/ BEGIN(INITIAL); +<cmt>. ; +^[ \t]*#.*\\\n { ++yylineno; BEGIN(prep); } +<prep>.*\\\n ++yylineno; +<prep>.*\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 <string.h> + +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 = "<stdin>"; + yyin = stdin; + } else { + fname = argv[1]; + yyin = fopen(fname, "r"); + } + + yylex(); +} 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 <stc/carc.h> +``` +`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 <stc/csmap.h> + +#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 <stc/carc.h> + +#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 <stc/cstack.h> + +#define i_type List +#define i_val_sptr Arc // as above +#include <stc/clist.h> + +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/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..e05e69f0 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 +# 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_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,37 +20,36 @@ 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 <stc/cbox.h> ``` `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_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_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_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_compare(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_compare' +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 @@ -66,39 +65,39 @@ int cbox_X_compare(const cbox_X* x, const cbox_X* y); // compares pointe #include <stdio.h> #include <string.h> -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. // -// 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 -#define i_del int_del // optional func, just to display elements destroyed -#define i_valfrom c_default_clone -#include <stc/cbox.h> // cbox_int +#define i_drop int_drop // optional func, just to display elements destroyed +#define i_from c_default_clone +#include <stc/cbox.h> // 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 <stc/csset.h> // csset_int (like: std::set<std::unique_ptr<int>>) +#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 <stc/csset.h> // csset_int (like: std::set<std::unique_ptr<int>>) -#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 <stc/cvec.h> // cvec_int (like: std::vector<std::unique_ptr<int>>) +#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 <stc/cvec.h> // cvec_int (like: std::vector<std::unique_ptr<int>>) 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, { + c_apply(v, cvec_int_push_back(&vec, v), cbox_int, { cbox_int_new(2021), cbox_int_new(2012), cbox_int_new(2022), @@ -130,13 +129,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..3f21d3c0 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -6,23 +6,23 @@ 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_del(&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. +scope and use **c_autoscope**. Also, **c_auto** support up to 4 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); } @@ -93,7 +93,8 @@ int main() #define i_tag ii #include <stc/csmap.h> ... -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,24 +131,29 @@ 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_raw, { {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_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,18 +165,18 @@ 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); -bool c_rawstr_equalto(const char* const* a, const char* const* b); +int c_rawstr_cmp(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/cdeq_api.md b/docs/cdeq_api.md index 554b4c7b..b884c62d 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); @@ -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 @@ -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(""); @@ -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..8f907eca 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 <stc/clist.h> ``` @@ -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 @@ -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 @@ -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 }); @@ -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: @@ -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); @@ -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: @@ -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 0fec365c..5c029a29 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -20,12 +20,12 @@ 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_keydel // destroy key func - defaults to empty destruct +#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_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 @@ -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 @@ -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 @@ -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 @@ -101,7 +101,7 @@ bool c_rawstr_equalto(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_pair(cmap_str, emplace, &u, { + 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_pair(cmap_id, emplace, &idnames, { + c_apply(v, cmap_id_emplace(&idnames, c_pair(v)), cmap_id_raw, { {100, "Red"}, {110, "Blue"} }); // replace existing mapped value: @@ -200,22 +200,22 @@ 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 <stc/cmap.h> 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 Viking_eq(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 Viking_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); +} + +static inline void 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_eq Viking_eq +// #define i_hash Viking_hash +// #define i_keyfrom Viking_clone +// #define i_drop Viking_drop #include <stc/cmap.h> 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 <stc/cstr.h> -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_eq(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_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 #include <stc/cmap.h> 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(v, Vikings_emplace(&vikings, v), c_pair(v), Vikings_raw, { + {{"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 *v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"}); + if (v) v->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..7a6ef00f 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 <stc/cpque.h> @@ -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 <stdio.h> #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 <stc/cpque.h> @@ -69,13 +69,13 @@ 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. 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/cqueue_api.md b/docs/cqueue_api.md index 469b7c99..0ecae014 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); @@ -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 @@ -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..32488b81 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -8,10 +8,10 @@ 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_del // destroy key func - defaults to empty destruct
+#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
@@ -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
@@ -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 |
@@ -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 646f8c99..65f932ea 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,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_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); @@ -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_pair(csmap_str, emplace, &colors, { + c_apply(v, csmap_str_emplace(&colors, c_pair(v)), csmap_str_raw, { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"} @@ -144,9 +144,9 @@ 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, { + c_apply(v, csmap_id_emplace(&idnames, c_pair(v)), csmap_id_raw, { {100, "Red"}, {110, "Blue"}, }); @@ -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 #define i_tag vi #include <stc/csmap.h> #include <stdio.h> @@ -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 deleted file mode 100644 index 640f5cf1..00000000 --- a/docs/csptr_api.md +++ /dev/null @@ -1,176 +0,0 @@ -# STC [csptr](../include/stc/csptr.h): Shared Pointers - -**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()*; - -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 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. - -When declaring a container with shared pointers, define `i_val_ref` 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 -containers or other existing shared pointers, as they internally clone/share the input. - -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_del // 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 <stc/csptr.h> -``` -`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_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_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) -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_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. -``` - -## 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 | - -## 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_keydel(p) (printf("del name: %s\n", (p)->str), cstr_del(p)) -#include <stc/csmap.h> - -#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)) -// 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 -#include <stc/csptr.h> - -#define i_type Stack -#define i_val_ref Arc // define i_val_ref for csptr / cbox value, not i_val -#include <stc/cstack.h> - -#define i_type List -#define i_val_ref Arc // as above -#include <stc/clist.h> - -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_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { - {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} - }); - map = Stack_push(&stack, Arc_new(Map_init()))->get; - c_apply_pair (Map, emplace, map, { - {"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, { - {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} - }); - - // Share two Maps from the stack with the list using emplace (clones the csptr): - 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; - - // 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 -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 -``` diff --git a/docs/csset_api.md b/docs/csset_api.md index 501473a6..561b8f8e 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 <stc/csset.h>
```
@@ -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_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 |
@@ -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/cstack_api.md b/docs/cstack_api.md index e71b213f..672b3168 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); @@ -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 @@ -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..31f27baf 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); -bool cstr_equalto(const cstr *s1, const cstr *s2); +int cstr_cmp(const cstr *s1, const cstr *s2); +bool cstr_eq(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_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); 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..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); @@ -77,8 +76,8 @@ bool cstr_ends_with_v(cstr s, csview sub); ``` #### Helper methods ```c -int csview_compare(const csview* x, const csview* y); -bool csview_equalto(const csview* x, const csview* y); +int csview_cmp(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 @@ -118,7 +117,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: @@ -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; } @@ -166,9 +163,9 @@ 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); + printf("[%s]\n", i.ref->str); } ``` Output: diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 00c0498c..ef145b94 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); @@ -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, @@ -84,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); ``` @@ -94,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 @@ -114,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) { @@ -152,13 +154,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 +181,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 +196,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 <stc/cvec.h> @@ -209,6 +211,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 <stdio.h> -#include <stc/cstr.h> - -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 <stc/cmap.h> - -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 <stc/cpque.h>
#define i_val point
-#define i_opt c_no_compare
+#define i_opt c_no_cmp
#include <stc/cdeq.h>
#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 <stc/csmap.h>
#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 <stc/csmap.h>
@@ -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/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/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..d97545b6 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,45 +17,54 @@ 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 PBox
+#define i_val_bind Person // binds Person_cmp, ...
#include <stc/cbox.h>
-#define i_val_ref cbox_prs
-#define i_tag prs
+#define i_type Persons
+#define i_val_sptr PBox // informs that PBox is a smart pointer.
#include <stc/cvec.h>
-
int main()
{
- c_auto (cvec_prs, vec)
- c_auto (cbox_prs, p, q)
+ c_auto (Persons, vec)
+ c_auto (PBox, p, q)
{
- p = cbox_prs_new(Person_from("Dave", "Cooper"));
+ p = PBox_from(Person_new("Laura", "Palmer"));
- q = cbox_prs_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);
- 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, 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(v, Persons_push_back(&vec, PBox_clone(v)), PBox, {p, q});
- c_foreach (i, cvec_prs, vec)
- printf("%s: %s\n", i.ref->get->name.str, i.ref->get->last.str);
+ c_foreach (i, Persons, vec)
+ printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str);
+ puts("");
- c_autovar (Person per = Person_from("Laura", "Palmer"), Person_del(&per)) {
- const cbox_prs *v = cvec_prs_get(&vec, (cbox_prs){&per});
- 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, 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/box2.c b/examples/box2.c index 48266963..fd76f8eb 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 <stc/cbox.h> // cbox_Point
#define i_val Rectangle
+#define i_opt c_no_cmp
#include <stc/cbox.h> // 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_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 <stc/cbox.h> // cbox_BoxPoint
@@ -35,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 });
}
@@ -53,16 +56,16 @@ 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 }
});
// 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/complex.c b/examples/complex.c index b6aef5a8..17a10fad 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -1,35 +1,30 @@ #include <stc/cstr.h>
-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 <stc/cstack.h>
-#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 <stc/clist.h>
+#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 <stc/cmap.h>
+#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 <stc/cmap.h>
// c++:
-// using cstack_f = std::stack<float>;
+// using FloatStack = std::stack<float>;
// using map_lst = std::unordered_map<int, std::forward_list<array2f>>;
// using map_map = std::unordered_map<std::string, map_lst>;
@@ -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/convert.c b/examples/convert.c index 83dc1b37..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_pair(cmap_str, emplace, &map, { + c_apply(v, cmap_str_emplace(&map, c_pair(v)), cmap_str_raw, { {"green", "#00ff00"}, {"blue", "#0000ff"}, {"yellow", "#ffff00"}, diff --git a/examples/cpque.c b/examples/cpque.c index b3ee4adf..d3ad2d0c 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) @@ -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..68a0378b 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_raw, { {10, "Bob"}, {11, "Rob"}, {12, "Robert"}, diff --git a/examples/csmap_find.c b/examples/csmap_find.c index 78b6bbf5..ea86d71b 100644 --- a/examples/csmap_find.c +++ b/examples/csmap_find.c @@ -7,12 +7,12 @@ #define i_tag istr #include <stc/csmap.h> -#define i_val csmap_istr_rawvalue -#define i_opt c_no_compare +#define i_val csmap_istr_raw +#define i_opt c_no_cmp #define i_tag istr #include <stc/cvec.h> -void print_elem(csmap_istr_rawvalue p) { +void print_elem(csmap_istr_raw p) { printf("(%d, %s) ", p.first, p.second); } @@ -45,23 +45,24 @@ 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_raw, + {{40, "Zr"}, {45, "Rh"}}); puts("The starting map m1 is (key, value):"); 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/csmap_insert.c b/examples/csmap_insert.c index 920cf02d..5f5813a8 100644 --- a/examples/csmap_insert.c +++ b/examples/csmap_insert.c @@ -14,8 +14,8 @@ #define i_tag istr // Map of int => cstr
#include <stc/csmap.h>
-#define i_val csmap_ii_rawvalue
-#define i_opt c_no_compare
+#define i_val csmap_ii_raw
+#define i_opt c_no_cmp
#define i_tag ii
#include <stc/cvec.h>
@@ -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_raw,
+ { { 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/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 ? "<NULL>" : &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..93192ee5 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
@@ -130,10 +130,10 @@ 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_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..8a39732a 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
@@ -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/inits.c b/examples/inits.c index 386be86e..4fdc17d5 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -12,19 +12,19 @@ #include <stc/cmap.h>
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 <stc/cvec.h>
#define i_val ipair_t
-#define i_cmp ipair_compare
+#define i_cmp ipair_cmp
#define i_tag ip
#include <stc/clist.h>
@@ -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_raw, {
{"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/mapmap.c b/examples/mapmap.c index e22a4f7b..61b55493 100644 --- a/examples/mapmap.c +++ b/examples/mapmap.c @@ -1,47 +1,67 @@ // unordered_map<string, unordered_map<string, string>>:
+#define i_type People
#define i_key_str
#define i_val_str
-#define i_tag sect
-#include <stc/csmap.h> // csmap_sect
+#define i_keydrop(p) (printf("kdrop: %s\n", (p)->str), cstr_drop(p))
+#include <stc/csmap.h>
+#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 <stc/csmap.h> // csmap_conf
+#define i_val_bind People
+#include <stc/csmap.h>
-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 <stc/cstack.h>
+
+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", "[email protected]", "Support");
+ add(&map, "Terry Dane", "[email protected]", "Development");
+ add(&map, "Kik Winston", "[email protected]", "Finance");
+ add(&map, "Nancy Drew", "[email protected]", "Development");
+ add(&map, "Nick Denton", "[email protected]", "Finance");
+ add(&map, "Stan Whiteword", "[email protected]", "Marketing");
+ add(&map, "Serena Bath", "[email protected]", "Support");
+ add(&map, "Patrick Dust", "[email protected]", "Finance");
+ add(&map, "Red Winger", "[email protected]", "Marketing");
+ add(&map, "Nick Denton", "[email protected]", "Support");
+ add(&map, "Colin Turth", "[email protected]", "Support");
+ add(&map, "Dennis Kay", "[email protected]", "Marketing");
+ add(&map, "Anne Dickens", "[email protected]", "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 <stc/clist.h>
+#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 <stc/csmap.h>
-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..472af8aa 100644 --- a/examples/multimap.c +++ b/examples/multimap.c @@ -35,7 +35,22 @@ 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);
+OlympicLocation OlympicLocation_clone(OlympicLocation loc);
+void OlympicLocation_drop(OlympicLocation* self);
+
+// Create a clist<OlympicLocation>, can be sorted by year.
+#define i_val_bind OlympicLocation // binds _cmp, _clone and _drop.
+#define i_tag OL
+#include <stc/clist.h>
+
+// Create a csmap<cstr, clist_OL> 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 <stc/csmap.h>
+
+int OlympicLocation_cmp(OlympicLocation* a, OlympicLocation* b) {
return a->year - b->year;
}
@@ -44,26 +59,10 @@ 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<OlympicLocation>, can be sorted by year.
-#define i_val OlympicLocation
-#define i_cmp OlympicLocation_compare
-#define i_del OlympicLocation_del
-#define i_from OlympicLocation_clone
-#define i_tag OL
-#include <stc/clist.h>
-
-// Create a csmap<cstr, clist_OL> where key is country name
-#define i_key_str
-#define i_val clist_OL
-#define i_valdel clist_OL_del
-#define i_valfrom clist_OL_clone
-#define i_tag OL
-#include <stc/csmap.h>
-
int main()
{
// Define the multimap with destructor defered to when block is completed.
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 <stc/cdeq.h>
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 <stc/cdeq.h>
diff --git a/examples/new_list.c b/examples/new_list.c index e07030b5..b6718d34 100644 --- a/examples/new_list.c +++ b/examples/new_list.c @@ -15,13 +15,13 @@ struct MyStruct { #include <stc/clist.h> 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 <stc/clist.h> @@ -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 8975cd77..f641a0eb 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 <stc/cmap.h>
@@ -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_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_pair(cmap_str, emplace, &smap, {
+ 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"},
});
- 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_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 <stc/cqueue.h>
diff --git a/examples/new_smap.c b/examples/new_smap.c index 7f0730db..382d27ae 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -1,10 +1,11 @@ #include <stc/cstr.h>
#include <stc/forward.h>
-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;
@@ -15,53 +16,60 @@ 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_type PMap
#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 <stc/csmap.h>
-// int => int map
+// cstr => cstr map
+#define i_type SMap
#define i_key_str
#define i_val_str
#include <stc/csmap.h>
-// string set
+// cstr set
+#define i_type SSet
#define i_key_str
#include <stc/csset.h>
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) {
- 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_foreach (i, csmap_pnt, pmap)
- printf(" (%d,%d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second);
+ 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_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/new_sptr.c b/examples/new_sptr.c index 4a715160..09bb7137 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -2,46 +2,54 @@ 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);
+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_del Person_del
-#define i_opt c_no_compare
+#define i_val_bind Person
+#define i_opt c_no_cmp
#define i_tag person
-#include <stc/csptr.h>
+#include <stc/carc.h>
// ...
-
+#define i_type SPtr
#define i_val int
-#define i_del(x) printf("del: %d\n", *(x))
-#include <stc/csptr.h>
+#define i_drop(x) printf("drop: %d\n", *(x))
+#include <stc/carc.h>
-#define i_val_ref csptr_int
+#define i_val_sptr SPtr
#define i_tag iptr
#include <stc/cstack.h>
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_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, csptr_int_new(10));
- cstack_iptr_push(&stk, csptr_int_new(20));
- cstack_iptr_push(&stk, csptr_int_new(30));
- cstack_iptr_emplace(&stk, *cstack_iptr_top(&stk));
- cstack_iptr_emplace(&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/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 <stc/cvec.h>
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 <stc/cvec.h>
@@ -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/phonebook.c b/examples/phonebook.c index 640aaec3..ccc10eaf 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_raw, {
{"Lilia Friedman", "(892) 670-4739"},
{"Tariq Beltran", "(489) 600-7575"},
{"Laiba Juarez", "(303) 885-5692"},
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..184cad9f 100644 --- a/examples/priority.c +++ b/examples/priority.c @@ -4,7 +4,7 @@ #include <stc/crandom.h>
#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 <stc/cpque.h>
@@ -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/queue.c b/examples/queue.c index 4acaa4d6..ffd0a1e7 100644 --- a/examples/queue.c +++ b/examples/queue.c @@ -2,7 +2,7 @@ #include <stdio.h>
#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 <stc/cqueue.h>
diff --git a/examples/rawptr_elements.c b/examples/rawptr_elements.c index c5416822..3ff0dc8a 100644 --- a/examples/rawptr_elements.c +++ b/examples/rawptr_elements.c @@ -6,10 +6,10 @@ 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))
+#define i_eq(x, y) c_memcmp_eq(*(x), *(y))
#define i_tag pnt
#include <stc/cset.h>
@@ -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 <stc/cmap.h>
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/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 diff --git a/examples/sidebyside.cpp b/examples/sidebyside.cpp index 0f645991..435b37f6 100644 --- a/examples/sidebyside.cpp +++ b/examples/sidebyside.cpp @@ -8,18 +8,20 @@ #define i_key int
#define i_val int
-#include <stc/cmap.h>
+#include <stc/csmap.h>
int main() {
{
- std::map<std::string, int> food = {{"burger", 5}, {"pizza", 12}, {"steak", 15}};
+ std::map<std::string, int> food =
+ {{"burger", 5}, {"pizza", 12}, {"steak", 15}};
for (auto i: food)
std::cout << i.first << ", " << i.second << std::endl;
std::cout << std::endl;
}
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_raw,
+ {{"burger", 5}, {"pizza", 12}, {"steak", 15}});
c_foreach (i, cmap_str, food)
printf("%s, %d\n", i.ref->first.str, i.ref->second);
puts("");
@@ -34,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("");
}
diff --git a/examples/splitstr.c b/examples/splitstr.c index 8bea911a..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_del(&vec), cstr_del(&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/sptr.c b/examples/sptr.c new file mode 100644 index 00000000..0c22bd68 --- /dev/null +++ b/examples/sptr.c @@ -0,0 +1,67 @@ +/* cbox: heap allocated boxed type */
+#include <stc/cstr.h>
+
+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 <stc/carc.h>
+
+#define i_type Persons
+#define i_val_sptr PSPtr // binds PSPtr_cmp, ...
+#include <stc/cvec.h>
+
+
+int main()
+{
+ c_auto (Persons, vec)
+ c_auto (PSPtr, p, q)
+ {
+ p = PSPtr_from(Person_new("Laura", "Palmer"));
+
+ // We want a deep copy -- PSPtr_clone(p) only shares!
+ 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_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!
+ c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&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 c3da5287..8626e2d4 100644 --- a/examples/sptr_demo.c +++ b/examples/sptr_demo.c @@ -1,32 +1,32 @@ #include <stdio.h>
#include <string.h>
-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,
+// 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_del int_del // optional, just to display the elements destroyed
-#include <stc/csptr.h> // iref
+#define i_drop int_drop // optional, just to display the elements destroyed
+#include <stc/carc.h> // iref
-#define i_key_ref iref // note: use i_key_ref 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 <stc/csset.h> // csset_iref (like: std::set<std::shared_ptr<int>>)
-#define i_val_ref iref // note: as above.
+#define i_val_sptr iref // note: as above.
#include <stc/cvec.h> // cvec_iref (like: std::vector<std::shared_ptr<int>>)
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))
- 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);
@@ -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..d40d8fe7 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -1,50 +1,51 @@ #include <stdio.h>
-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
-// 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.
-// See the different results by commenting out the next line.
-#define i_cmp(x, y) (*(x) - *(y))
-#include <stc/csptr.h> // csptr_int: shared pointer to int
+#define i_drop show_drop
+// 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 two differences by
+// commenting out the next line.
+#include <stc/carc.h> // Shared pointer to int
-#define i_val_ref csptr_int
-#define i_tag intp
-#include <stc/cvec.h> // cvec_intp: cvec<csptr_int>
+#define i_type Vec
+#define i_val_sptr Arc
+#include <stc/cvec.h> // Vec: cvec<Arc>
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_from(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_push_back(&vec, Arc_clone(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);
+ printf("erase vec.data[2]; or first matching value depending on compare.\n");
+ Vec_iter it;
+ it = Vec_find(&vec, *vec.data[2].get);
+ 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, 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..42bb3455 100644 --- a/examples/sptr_music.c +++ b/examples/sptr_music.c @@ -9,43 +9,44 @@ 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_type SongPtr
#define i_val Song
-#define i_del Song_del
-#define i_tag song
-#include <stc/csptr.h> // define csptr_song
+#define i_drop Song_drop
+#define i_opt c_no_cmp
+#include <stc/carc.h>
-#define i_val_ref csptr_song
-#define i_tag song
+#define i_type SongVec
+#define i_val_sptr SongPtr
#include <stc/cvec.h>
void example3()
{
- c_auto (cvec_song, v, v2)
+ c_auto (SongVec, vec, vec2)
{
- 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"))
+ 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_from("Michael Jackson", "Billie Jean")),
- csptr_song_new(Song_from("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 cfb845b6..d81d9810 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -11,14 +11,13 @@ struct Base int value;
} typedef Base;
-void Base_del(Base* b) { printf("Base::~Base()\n"); }
-
+#define i_type BaseRc
#define i_val Base
-#define i_del Base_del
-#define i_tag base
-#include <stc/csptr.h>
+#define i_valdrop(x) printf("Drop Base: %d\n", (x)->value)
+#define i_opt c_no_cmp
+#include <stc/carc.h>
-void* thr(csptr_base* lp)
+void* thr(BaseRc* lp)
{
sleep(1);
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
@@ -26,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_del(lp);
+ BaseRc_drop(lp);
return NULL;
}
int main()
{
- csptr_base p = csptr_base_new((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 a66e5b31..0873d297 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 <stc/csmap.h>
#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
-#include <stc/csptr.h>
+// no compare function available for csmap:
+#define i_opt c_no_atomic|c_no_cmp
+#include <stc/carc.h>
#define i_type Stack
-#define i_val_ref Arc // define i_val_ref for csptr/cbox value (not i_val)
+#define i_val_sptr Arc // define i_val_bind for carc/cbox value (not i_val)
#include <stc/cstack.h>
#define i_type List
-#define i_val_ref Arc // as above
+#define i_val_sptr Arc // as above
#include <stc/clist.h>
int main()
@@ -28,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_raw, {
{"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_raw, {
{"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_raw, {
{"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]);
+ // 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]));
// 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/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/examples/vikings.c b/examples/vikings.c new file mode 100644 index 00000000..5acafb3f --- /dev/null +++ b/examples/vikings.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <stc/cstr.h> + +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_eq(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_keyraw RViking +#define i_val int +// i_key_bind auto-binds these functions: +// 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 <stc/cmap.h> + +int main() +{ + c_auto (Vikings, vikings) { + c_apply(v, Vikings_emplace(&vikings, c_pair(v)), Vikings_raw, { + {{"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* 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) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.hp); + } + } +}
\ No newline at end of file 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/alt/clist.h b/include/stc/alt/clist.h index 6695a26e..38b722a4 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 <stc/ccommon.h>
@@ -61,16 +61,16 @@ _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; \
+ typedef i_valraw _cx_raw; \
\
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); \
+ 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); \
@@ -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); \
} \
\
@@ -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; i<n; ++i) _cx_memb(_push_back)(self, i_valfrom(arr[i])); \
} \
\
@@ -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..9be41054 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, char>
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');
@@ -74,7 +74,7 @@ int main(void) { typedef _i_SET_ONLY( _cx_rawkey ) \
_i_MAP_ONLY( struct { _cx_rawkey first; \
_cx_memb(_rawmapped) second; } ) \
- _cx_rawvalue; \
+ _cx_raw; \
\
STC_API _cx_self _cx_memb(_init)(void); \
STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out); \
@@ -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 \
@@ -125,7 +125,7 @@ int main(void) { } \
\
STC_INLINE 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; i<n; ++i) _i_SET_ONLY( _cx_memb(_emplace)(self, arr[i]); ) \
_i_MAP_ONLY( _cx_memb(_emplace)(self, arr[i].first, arr[i].second); ) \
} \
@@ -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..1a9280e8 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) {
@@ -166,11 +167,11 @@ 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;
}
-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 <stc/ccommon.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#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/csptr.h b/include/stc/carc.h index 4753ef12..b4e2e435 100644 --- a/include/stc/csptr.h +++ b/include/stc/carc.h @@ -21,35 +21,35 @@ * SOFTWARE.
*/
-/* csptr: shared_ptr type
+/* carc: atomic reference counted shared_ptr
#include <stc/cstr.h>
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
-#include <stc/csptr.h>
+#define i_valdrop Person_drop
+#include <stc/carc.h>
int main() {
- csptr_person p = csptr_person_new(Person_from("John", "Smiths"));
- csptr_person q = csptr_person_clone(p); // share the pointer
+ 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_del(csptr_person, &p, &q);
+ c_drop(carc_person, &p, &q);
}
*/
-#ifndef CSPTR_H_INCLUDED
-#define CSPTR_H_INCLUDED
+#ifndef CARC_H_INCLUDED
+#define CARC_H_INCLUDED
#include "ccommon.h"
#include "forward.h"
#include <stdlib.h>
@@ -67,15 +67,16 @@ int main() { #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
+#define carc_null {NULL, NULL}
+#define _cx_carc_rep struct _cx_memb(_rep_)
+#endif // CARC_H_INCLUDED
#ifndef _i_prefix
-#define _i_prefix csptr_
+#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)
@@ -85,9 +86,9 @@ int main() { #define _i_atomic_dec_and_test(v) !(--*(v))
#endif
#if !c_option(c_is_fwd)
-_cx_deftypes(_c_csptr_types, _cx_self, i_val);
+_cx_deftypes(_c_carc_types, _cx_self, i_val);
#endif
-_cx_csptr_rep { long counter; i_val value; };
+_cx_carc_rep { long counter; i_val value; };
STC_INLINE _cx_self
_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; }
@@ -96,32 +97,22 @@ 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);
+_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 _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 i_val _cx_memb(_toraw)(const _cx_self* self) {
+ return *self->get;
}
STC_INLINE _cx_self
@@ -132,10 +123,10 @@ _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);
- if (self->get != &((_cx_csptr_rep *)self->use_count)->value)
+ i_valdrop(self->get);
+ if (self->get != &((_cx_carc_rep *)self->use_count)->value)
c_free(self->get);
c_free(self->use_count);
}
@@ -143,68 +134,68 @@ _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);
- *self = _cx_memb(_with)(p);
+_cx_memb(_reset_from)(_cx_self* self, i_val val) {
+ _cx_memb(_drop)(self);
+ *self = _cx_memb(_from)(val);
}
-STC_INLINE void
-_cx_memb(_reset_new)(_cx_self* self, i_val val) {
- _cx_memb(_del)(self);
- *self = _cx_memb(_new)(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 void
- _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) {
- _cx_memb(_del)(self);
- *self = _cx_memb(_new)(i_valfrom(raw));
+#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));
}
#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(_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
- return c_hash64(&self->get, 8);
- #elif (c_option(c_no_compare) || defined _i_default_compare)
- return c_hash32(&self->get, 4);
+_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 raw = i_valto(self->get);
- return i_hash(&raw, sizeof raw);
+ i_valraw rx = i_valto(x);
+ return i_hash(&rx, sizeof rx);
#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(_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->get);
- i_valraw ry = i_valto(y->get);
+ 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"
\ No newline at end of file +#include "template.h"
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..7ed0d641 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 <stc/cbox.h>
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 <stdlib.h>
+#include <string.h>
#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_raw;
#if !c_option(c_is_fwd)
_cx_deftypes(_c_cbox_types, _cx_self, i_val);
@@ -81,17 +83,22 @@ 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) {
+_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(_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,32 +109,23 @@ _cx_memb(_move)(_cx_self* self) { STC_INLINE void
_cx_memb(_reset)(_cx_self* self) {
- _cx_memb(_del)(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 = NULL;
}
// 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; }
+_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)
+#if !defined _i_no_raw
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))};
}
-
- STC_INLINE void
- _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) {
- _cx_memb(_reset_new)(self, i_valfrom(raw));
- }
+#endif
STC_INLINE _cx_self
_cx_memb(_clone)(_cx_self other) {
@@ -138,37 +136,41 @@ _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(_drop)(self);
+ *self = _cx_memb(_clone)(other);
}
#endif
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
- return c_hash64(&self->get, 8);
- #elif (c_option(c_no_compare) || defined _i_default_compare)
- return c_hash32(&self->get, 4);
+_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 raw = i_valto(self->get);
- return i_hash(&raw, sizeof raw);
+ i_valraw rx = i_valto(x);
+ return i_hash(&rx, sizeof rx);
#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(_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->get);
- i_valraw ry = i_valto(y->get);
+ i_valraw rx = i_valto(x), ry = i_valto(x);
return i_cmp(&rx, &ry);
#endif
}
-#include "template.h"
\ No newline at end of file +
+STC_INLINE bool
+_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 2942873f..b2ae7b97 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_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_cmp(x, y) c_less_cmp(c_default_less, x, y)
+#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]
#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(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(p) c_free((char *) &**(p))
+
#define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k)))
STC_INLINE uint64_t c_strhash(const char *s) {
@@ -165,19 +169,20 @@ 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) \
- 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) \
@@ -185,28 +190,42 @@ 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 { \
- const C##_rawvalue _c_arr[] = __VA_ARGS__; \
+#define c_apply(v, method, T, ...) do { \
+ const T _c_arr[] = __VA_ARGS__; \
+ for (size_t index = 0; index < c_arraylen(_c_arr); ++index) \
+ { 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) \
+ { T v = _c_arr[index]; method; } \
+} while (0)
+#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; } \
+} while (0)
+#define c_pair(v) (v).first, (v).second
+
+// [deprecated]
+#define c_apply_OLD(C, method, cx, ...) do { \
+ const C##_raw _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 { \
- const C##_rawvalue _c_arr[] = __VA_ARGS__; \
+// [deprecated]
+#define c_apply_pair_OLD(C, method, cx, ...) do { \
+ const C##_raw _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_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..97a19311 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -38,25 +38,27 @@ struct cdeq_rep { size_t size, cap; void* base[]; }; #if !c_option(c_is_fwd)
_cx_deftypes(_c_cdeq_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(_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);
+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_rawvalue* p1, const _cx_rawvalue* p2);
+ const _cx_raw* p1, const _cx_raw* p2);
+#endif
#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);
@@ -66,13 +68,15 @@ 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) {
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 +87,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 +110,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) {
@@ -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) {
@@ -166,7 +170,7 @@ _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) {
+_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
@@ -175,7 +179,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 +205,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 +228,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 +247,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 +362,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;
@@ -366,15 +371,15 @@ _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_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);
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) {
@@ -385,7 +390,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 +402,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..e2ff694e 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -87,19 +87,20 @@ _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);
-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);
@@ -108,29 +109,28 @@ 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_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);
}
+#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; }
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 +166,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);
@@ -191,13 +191,13 @@ _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
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 +250,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 +280,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 +321,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 +343,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 +394,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..2d0b11fc 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -31,7 +31,7 @@ #include <stc/cmap.h>
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');
@@ -85,13 +85,13 @@ 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)
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);
@@ -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);
@@ -132,15 +132,16 @@ 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;
}
-
+#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);
@@ -150,25 +151,26 @@ _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_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
-_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 +251,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,15 +271,15 @@ 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)
+ #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);
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
@@ -292,7 +294,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;
}
@@ -323,7 +325,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 +365,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..bf519125 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);
@@ -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,14 +97,14 @@ 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)
- { _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 ------------------------- */
@@ -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..fb8c868e 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -32,7 +32,7 @@ #include <stc/csmap.h>
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);
@@ -91,13 +91,13 @@ 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)
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; }
@@ -128,20 +128,26 @@ _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
+_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
- #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);
@@ -166,15 +172,16 @@ _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;
}
-
+#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);
@@ -184,13 +191,14 @@ _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
_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,15 +287,15 @@ _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)
+ #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);
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 +412,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 +478,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 +499,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/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..1ceec0cb 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}; }
@@ -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;
@@ -91,14 +91,14 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { *vp = val; return vp;
}
-STC_INLINE _cx_value* _cx_memb(_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)
-
-STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_rawvalue raw)
+#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));
@@ -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..cfb2dfef 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,9 +167,9 @@ cstr_ends_with(cstr s, const char* sub) { }
/* container adaptor functions: */
-#define cstr_compare(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 ------------------------- */
@@ -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..c4844bfb 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}
@@ -114,9 +113,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_eq(xp, yp) (!csview_cmp(xp, yp))
/* -------------------------- IMPLEMENTATION ------------------------- */
@@ -137,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 : (sep.size = 0, slice.size)};
+ *start += tok.size + sep.size;
return tok;
}
diff --git a/include/stc/cvec.h b/include/stc/cvec.h index f64f7840..1faa16c3 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);
}
*/
@@ -76,10 +76,10 @@ 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(_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
@@ -97,24 +97,23 @@ 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_rawvalue* p1, const _cx_rawvalue* p2);
STC_INLINE i_val _cx_memb(_value_clone)(_cx_value val)
{ return i_valfrom(i_valto(&val)); }
STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); }
-STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw)
- { return _cx_memb(_push_back)(self, i_valfrom(raw)); }
STC_INLINE void
_cx_memb(_copy)(_cx_self *self, _cx_self other) {
if (self->data == other.data) return;
- _cx_memb(_del)(self); *self = _cx_memb(_clone)(other);
-}
-STC_INLINE _cx_iter
-_cx_memb(_emplace)(_cx_self* self, const size_t idx, i_valraw raw) {
- return _cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1);
+ _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_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
@@ -126,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; }
@@ -135,8 +135,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_valdel(p); }
+ { _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)
@@ -197,7 +200,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 +229,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 +249,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 +267,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 +283,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 +324,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;
}
@@ -345,18 +349,19 @@ _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_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);
return it;
}
#endif
+#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 +386,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/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 85c4a940..7d5c70b9 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)
@@ -40,23 +40,9 @@ #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"
-#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"
-#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
@@ -69,46 +55,56 @@ #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
+#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
+ #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_eq
+ #define i_eq c_PASTE(i_keyraw, _eq)
#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 +114,43 @@ #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)
- #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*
+#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
+ #define i_tag str
+ #endif
+#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
+ #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,23 +158,24 @@ #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
#endif
#ifndef i_keyraw
+ #define _i_no_keyraw
#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_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,22 +184,24 @@ #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
#endif
#ifndef i_valraw
+ #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
-#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 +214,32 @@ #undef i_imp
#undef i_opt
#undef i_cmp
-#undef i_del
-#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_ref
-#undef i_valdel
+#undef i_val_sptr
+#undef i_val_bind
#undef i_valraw
#undef i_valfrom
#undef i_valto
+#undef i_valdrop
#undef i_key
#undef i_key_str
-#undef i_key_ref
-#undef i_keydel
+#undef i_key_sptr
+#undef i_key_bind
#undef i_keyraw
#undef i_keyfrom
#undef i_keyto
+#undef i_keydrop
#undef _i_prefix
-#undef _i_default_compare
+#undef _i_no_raw
+#undef _i_no_keyraw
#undef _i_has_internal_clone
#undef _i_template
#endif
|
