diff options
| author | Tyge Løvset <[email protected]> | 2022-08-17 09:35:40 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-17 09:35:40 +0200 |
| commit | 0681b8a9af2ac6041e937bc8ca7bc8d496dcc0d4 (patch) | |
| tree | 03825b177d4d5259f629957b751b000e1b224db1 | |
| parent | 17f1d2ed83952df00525f4be1d30a6c12e04a0f6 (diff) | |
| parent | a06463c2f0747bc142a9d5b2bf455c64aaf39890 (diff) | |
| download | STC-modified-0681b8a9af2ac6041e937bc8ca7bc8d496dcc0d4.tar.gz STC-modified-0681b8a9af2ac6041e937bc8ca7bc8d496dcc0d4.zip | |
Merge pull request #34 from tylov/iter_exp_dont_use
VERSION 4.0 RC
59 files changed, 801 insertions, 703 deletions
@@ -3,24 +3,25 @@ STC - Smart Template Containers for C ===================================== -News: Version 4.0 BETA (Aug 2022) +News: Version 4.0 Release Candidate (Aug 2022) --------------------------------------- -- Removed macro `c_apply` - usage was not intuitive. -- `c_forarray` macro replaces usages of `c_apply`. -- Minor changes in API of **cregex**, and improved documentation. -- Version 3.9: - - "ccommon API: `c_forrange` with 3 to 5 args swapped 1st <-> 2nd. -- Version 3.8: - - "Officially" added **cregex** - powerful regular expressions. - - Added back **coption** - command line argument parsing. - - Some changes in **cstr** and **csview** API. +API changes summary V3.8 - V4.0: +- Added **cregex** with documentation - powerful regular expressions. +- Updated **cstr**, now always takes self as pointer, like all containers except csview. +- Updated **cvec**, **cdeq**, changed `*_range*` function names. +- `c_with`: macro renamed from `c_autovar`, which is deprecated. Like Python's **with** statement. +- `c_scope`: macro renamed from `c_autoscope`, which is deprecated. +- `c_defer`: macro renamed from `c_autodefer`, which is deprecated. Like Go's and Zig's **defer**. +- `c_forrange` with 3 to 5 args: swapped 1st <-> 2nd arg. +- New `c_forarray` macro to replace usages of `c_apply`, which is removed. +- Added back **coption** - command line argument parsing. - [See detailed changes for version 3](#version-3). Introduction ------------ STC is a *modern*, *templated*, *user-friendly*, *type-safe*, *very fast* and *compact* container library for C99. The API is fairly similar to c++ STL, but a bit more uniform across the containers and takes -inspiration from Rust and Python too. It is an advantage to know how these containers work in other languages, like +inspiration from Rust and Python as well. It is an advantage to know how these containers work in other languages, like Java, C# or C++, but it's not required. This library allows you to manage both trivial to very complex data in a wide variety of containers @@ -67,7 +68,7 @@ Highlights - **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. +- **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 -s on linux. - **Dual mode compilation** - By default it is a simple header-only library with inline and static methods only, but you can easily switch to create a traditional library with shared symbols, without changing existing source files. See the Installation section. - **No callback functions** - All passed template argument functions/macros are directly called from the implementation, no slow callbacks which requires storage. - **Compiles with C++ and C99** - C code can be compiled with C++ (container element types must be POD). @@ -79,7 +80,7 @@ You may specify a number of "standard" template arguments for each container, bu required (two for maps). In the latter case, STC assumes the elements are basic types. For more complex types, additional template arguments must be defined. 2. the general "heterogeneous lookup"-like feature: Allows specification of an alternative type to use -for lookup in containers. E.g. for containers with string type (**cstr**) elements, `const char*` may be used +for lookup in containers. E.g. for containers with string type (**cstr**) elements, `const char*` is used as lookup type. It will then use the input `const char*` directly when comparing with the string data in the container. This avoids the construction of a new `cstr` (which possible allocates memory) for the lookup. Finally, destruction of the lookup key (i.e. string literal) after usage is not needed (or allowed), which @@ -339,13 +340,13 @@ Specials: - `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_ssv` - Define key type *cstr* and container i_tag = *ssv*. It binds type convertion from/to *csview*, and its ***cmp***, ***eq***, ***hash***, and ***keydrop*** functions. - `i_key_arcbox TYPE` - Define container key type where TYPE is a smart pointer **carc** or **cbox**. NB: 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: *TYPE_clone*, *TYPE_drop*, *TYPE_cmp*, *TYPE_eq*, *TYPE_hash*. If `i_keyraw` is defined, *TYPE_toraw* func. is bound to `i_keyto`. Only functions required by the particular container need to be defined. E.g., only **cmap** and **cset** and smart pointers uses *TYPE_hash* and *TYPE_eq*. **cstack** does not use *TYPE_cmp*. *TYPE_clone* is not used if *#define i_opt c_no_clone* is specified. Likewise, *TYPE_cmp* is not used if *#define i_opt c_no_cmp* is specified. +- `i_key_bind TYPE` - General version of the three above - will auto-bind to standard named functions: *TYPE_clone*, *TYPE_drop*, *TYPE_cmp*, *TYPE_eq*, *TYPE_hash*. If `i_keyraw` is defined, *TYPE_toraw* function is bound to `i_keyto`. Only functions required by the particular container need to be defined. E.g., only **cmap** and **cset** and smart pointers uses *TYPE_hash* and *TYPE_eq*. **cstack** does not use *TYPE_cmp*. *TYPE_clone* is not used if *#define i_opt c_no_clone* is specified. Likewise, *TYPE_cmp* is not used if *#define i_opt c_no_cmp* is specified. - `i_val_str`, `i_val_bind`, `i_val_arcbox` - Similar rules as for ***key***. **Notes**: -- Instead of defining `i_cmp`, you may define *i_opt c_no_cmp* to disable searching and sorting functions. -- Instead of defining `i_*clone`, you may define *i_opt c_no_clone* to disable emplace and clone-functions. -- `i_keyraw RAWTYPE` - If defined along with *i_key_bind*, the two functions *TYPE TYPE_from(RAWTYPE)* and *RAWTYPE TYPE_toraw(TYPE\*)* are expected in addition to *TYPE TYPE_clone(TYPE)*. Note the signature for ***cmp***, ***eq***, ***hash*** now: *int RAWTYPE_cmp(const RAWTYPE\*, const RAWTYPE\*)*, and similar for the two others. +- Instead of defining `i_cmp`, you may define *i_opt c_no_cmp* to disable *searching and sorting* functions. +- Instead of defining `i_*clone`, you may define *i_opt c_no_clone* to disable *clone* functionality. +- For `i_key_bind`, if *i_keyraw RAWTYPE* is defined along with it, *i_keyfrom* may also be defined to enable the *emplace*-functions. Note: the signature for ***cmp***, ***eq***, and ***hash*** uses *RAWTYPE* as input. The *emplace* versus non-emplace container methods -------------------------------------------------- @@ -380,7 +381,7 @@ and non-emplace methods: #include <stc/cvec.h> // vector of string (cstr) ... 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. +c_with (cstr s = cstr_new("a string literal"), cstr_drop(&s)) // c_with is a more general c_auto. { const char* hello = "Hello"; cvec_str_push_back(&vec, cstr_from(hello); // construct and add string from const char* diff --git a/benchmarks/misc/string_bench_STC.cpp b/benchmarks/misc/string_bench_STC.cpp index 648cb1f3..ae8e4c38 100644 --- a/benchmarks/misc/string_bench_STC.cpp +++ b/benchmarks/misc/string_bench_STC.cpp @@ -38,7 +38,7 @@ cvec_str read_file(const char* name) { cvec_str data = cvec_str_init(); c_auto (cstr, line) - c_autovar (FILE* f = fopen(name, "r"), fclose(f)) + c_with (FILE* f = fopen(name, "r"), fclose(f)) while (cstr_getline(&line, f)) cvec_str_emplace_back(&data, cstr_str(&line)); return data; @@ -101,7 +101,7 @@ void initShortStringVec(cvec_str* vs, cvec_sv* vsv) c_foreach (i, cvec_str, *vs) { cvec_sv_push_back(vsv, cstr_sv(i.ref)); - num += cstr_size(*i.ref); + num += cstr_size(i.ref); } std::cout << "num strings: " << cvec_sv_size(vsv) << std::endl; std::cout << "avg str len: " << num / (float)cvec_sv_size(vsv) << std::endl; @@ -147,7 +147,7 @@ void initLongStringVec(cvec_str* vs, cvec_sv* vsv) c_foreach (i, cvec_str, *vs) { cvec_sv_push_back(vsv, cstr_sv(i.ref)); - num += cstr_size(*i.ref); + num += cstr_size(i.ref); } std::cout << "num strings: " << cvec_sv_size(vsv) << std::endl; std::cout << "avg str len: " << num / (float)cvec_sv_size(vsv) << std::endl; diff --git a/benchmarks/misc/string_bench_STD.cpp b/benchmarks/misc/string_bench_STD.cpp index 5f033ca1..8bb87937 100644 --- a/benchmarks/misc/string_bench_STD.cpp +++ b/benchmarks/misc/string_bench_STD.cpp @@ -17,7 +17,7 @@ std::vector<std::string> read_file(const char* name) { std::vector<std::string> data; c_auto (cstr, line) - c_autovar (FILE* f = fopen(name, "r"), fclose(f)) + c_with (FILE* f = fopen(name, "r"), fclose(f)) while (cstr_getline(&line, f)) data.emplace_back(cstr_str(&line)); return data; diff --git a/docs/carc_api.md b/docs/carc_api.md index 687e9547..d09b1839 100644 --- a/docs/carc_api.md +++ b/docs/carc_api.md @@ -32,25 +32,31 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ## Methods ```c carc_X carc_X_init(); // empty shared pointer -carc_X carc_X_from(i_valraw raw); // construct a new value in an carc from raw type. -carc_X carc_X_make(i_val val); // make a carc from constructed val object. Faster than from_ptr(). -carc_X carc_X_from_ptr(i_val* p); // create a carc from raw pointer. Takes ownership of p. +carc_X carc_X_new(i_valraw raw); // create an carc from raw type (available if i_valraw defined by user). +carc_X carc_X_from(i_val val); // create an carc from constructed val object. Faster than from_ptr(). +carc_X carc_X_from_ptr(i_val* p); // create an 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_assign(carc_X* self, carc_X other); // copy shared (increase use count) +void carc_X_copy(carc_X* self, carc_X other); // shared assign (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); +long carc_X_use_count(const carc_X* self); void carc_X_reset(carc_X* self); void carc_X_reset_to(carc_X* self, i_val* p); // assign new carc from ptr. Takes ownership of p. -uint64_t carc_X_value_hash(const i_val* x); // 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); // carc_X_value_cmp == 0 +uint64_t carc_X_hash(const carc_X* x); // hash value +int carc_X_cmp(const carc_X* x, const carc_X* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default cmp. +bool carc_X_eq(const carc_X* x, const carc_X* y); // carc_X_cmp() == 0 + +// functions on pointed to objects. + +uint64_t carc_X_value_hash(const i_val* x); +int carc_X_value_cmp(const i_val* x, const i_val* y); +bool carc_X_value_eq(const i_val* x, const i_val* y); ``` ## Types and constants @@ -96,18 +102,18 @@ int main() // POPULATE s1 with shared pointers to Map: Map *map; - map = Stack_push(&s1, Arc_make(Map_init()))->get; // push empty map to s1. + map = Stack_push(&s1, Arc_from(Map_init()))->get; // push empty map to s1. c_forarray (Map_raw, v, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992}}) { Map_emplace(map, v->first, v->second); // populate it. } - map = Stack_push(&s1, Arc_make(Map_init()))->get; + map = Stack_push(&s1, Arc_from(Map_init()))->get; c_forarray (Map_raw, v, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }) { Map_emplace(map, v->first, v->second); } // POPULATE s2: - map = Stack_push(&s2, Arc_make(Map_init()))->get; + map = Stack_push(&s2, Arc_from(Map_init()))->get; c_forarray (Map_raw, v, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }) { Map_emplace(map, v->first, v->second); } @@ -118,7 +124,7 @@ int main() // Deep-copy (does not share) a Map from s1 to s2. // s2 will contain two shared and two unshared maps. - map = Stack_push(&s2, Arc_make(Map_clone(*s1.data[1].get)))->get; + map = Stack_push(&s2, Arc_from(Map_clone(*s1.data[1].get)))->get; // Add one more element to the cloned map: Map_emplace_or_assign(map, "Cloned", 2022); diff --git a/docs/carray_api.md b/docs/carray_api.md index 579bf119..cede295e 100644 --- a/docs/carray_api.md +++ b/docs/carray_api.md @@ -91,8 +91,8 @@ int main() // Ex1 int xd = 30, yd = 20, zd = 10; // define arr3[30][20][10], initialized with zeros. - c_autovar (carr3_f arr3 = carr3_f_with_size(xd, yd, zd, 0.0f), - carr3_f_drop(&arr3)) { + c_with (carr3_f arr3 = carr3_f_with_size(xd, yd, zd, 0.0f), + carr3_f_drop(&arr3)) { arr3.data[5][4][3] = 3.14f; float *arr1 = arr3.data[5][4]; @@ -105,7 +105,7 @@ int main() // Ex2 int w = 256, h = 128; - c_autovar (carr2_i image = carr2_i_new_uninit(w, h), carr2_i_drop(&image)) { + c_with (carr2_i image = carr2_i_new_uninit(w, h), carr2_i_drop(&image)) { int n = 0; c_foreach (i, carr2_i, image) { uint32_t t = n++ % 256; diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 1119d930..dc90fa8e 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -31,24 +31,31 @@ compare the pointer addresses when used. Additionally, `c_no_clone` or `i_is_fwd ## Methods ```c cbox_X cbox_X_init(); // return an empty cbox -cbox_X cbox_X_from(i_valraw raw); // construct a new boxed object from raw type, if defined. -cbox_X cbox_X_make(i_val val); // make a cbox from constructed val object. +cbox_X cbox_X_new(i_valraw raw); // create a cbox from raw type. Avail if i_valraw user defined. +cbox_X cbox_X_from(i_val val); // create a cbox from constructed val object. 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_assign(cbox_X* self, cbox_X other); // deep copy to self +void cbox_X_copy(cbox_X* self, cbox_X other); // deep copy to self void cbox_X_drop(cbox_X* self); // destruct the contained object and free's it. void cbox_X_reset(cbox_X* self); void cbox_X_reset_to(cbox_X* self, i_val* p); // assign new cbox from ptr. Takes ownership of p. -uint64_t cbox_X_value_hash(const i_val* p); // hash value -int cbox_X_value_cmp(const i_val* p, 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* p, const i_val* y); // cbox_X_value_cmp == 0 +uint64_t cbox_X_hash(const cbox_X* x); // hash value +int cbox_X_cmp(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default cmp. +bool cbox_X_eq(const cbox_X* x, const cbox_X* y); // cbox_X_cmp() == 0 + +// functions on pointed to objects. + +uint64_t cbox_X_value_hash(const i_val* x); +int cbox_X_value_cmp(const i_val* x, const i_val* y); +bool cbox_X_value_eq(const i_val* x, const i_val* y); ``` + ## Types and constants | Type name | Type definition | Used to represent... | @@ -68,7 +75,7 @@ void int_drop(int* x) { #define i_type IBox #define i_val int #define i_valdrop int_drop // optional func, just to display elements destroyed -#define i_valclone(x) x // must specify because i_valdrop was defined. +#define i_valclone(x) x // must specified when i_valdrop is defined. #include <stc/cbox.h> #define i_type ISet @@ -84,10 +91,8 @@ int main() c_auto (IVec, vec) // declare and init vec, call drop at scope exit c_auto (ISet, set) // similar { - c_forarray (IBox, v, { - IBox_make(2021), IBox_make(2012), - IBox_make(2022), IBox_make(2015), - }) IVec_push(&vec, *v); + c_forarray (int, v, {2021, 2012, 2022, 2015}) + IVec_emplace(&vec, *v); // same as: IVec_push(&vec, IBox_from(*v)); printf("vec:"); c_foreach (i, IVec, vec) diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index b4a90036..d37d4d04 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -2,38 +2,41 @@ The following macros are recommended to use, and they safe/have no side-effects. -### c_auto, c_autovar, c_autoscope, c_autodefer +### c_auto, c_with, c_scope, c_defer General ***defer*** mechanics for resource acquisition. These macros allows you to specify the freeing of the resources at the point where the acquisition takes place. The **checkauto** utility described below, ensures that the `c_auto*` macros are used correctly. -| 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` or `continue` | 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 4 variables. +| Usage | Description | +|:---------------------------------------|:----------------------------------------------------------| +| `c_auto (Type, var...)` | Same as `c_with (Type var=Type_init(), Type_drop(&var))` | +| `c_with (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope | +| `c_with (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed | +| `c_scope (init, drop...)` | Execute `init` and defer `drop...` to end of scope | +| `c_defer (drop...)` | Defer `drop...` to end of scope | +| `continue` | Exit a `c_auto/c_with/c_scope...` without memory leaks | + +For multiple variables, use either multiple **c_with** in sequence, or declare variable outside +scope and use **c_scope**. For convenience, **c_auto** support up to 4 variables. ```c -c_autovar (uint8_t* buf = malloc(BUF_SIZE), free(buf)) -c_autovar (FILE* f = fopen(fname, "rb"), fclose(f)) +// `c_with` is similar to python `with`: it declares and can drop a variable after going out of scope. +c_with (uint8_t* buf = malloc(BUF_SIZE), free(buf)) +c_with (FILE* fp = fopen(fname, "rb"), fclose(fp)) { int n = 0; - if (f && buf) { - n = fread(buf, 1, BUF_SIZE, f); + if (fp && buf) { + n = fread(buf, 1, BUF_SIZE, fp); doSomething(buf, n); } } -c_autovar (cstr s = cstr_new("Hello"), cstr_drop(&s)) +c_with (cstr str = cstr_new("Hello"), cstr_drop(&str)) { - cstr_append(&s, " world"); - printf("%s\n", cstr_str(&s)); + cstr_append(&str, " world"); + printf("%s\n", cstr_str(&str)); } +// `c_auto` automatically initialize and destruct up to 4 variables, like `c_with`. c_auto (cstr, s1, s2) { cstr_append(&s1, "Hello"); @@ -45,14 +48,16 @@ c_auto (cstr, s1, s2) printf("%s %s\n", cstr_str(&s1), cstr_str(&s2)); } -MyData data; -c_autoscope (mydata_init(&data), mydata_destroy(&data)) +// `c_scope` is like `c_with` but works with an already declared variable. +static pthread_mutex_t mut; +c_scope (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut)) { - printf("%s\n", cstr_str(&mydata.name)); + /* Do syncronized work. */ } +// `c_defer` executes the expressions when leaving scope. cstr s1 = cstr_new("Hello"), s2 = cstr_new("world"); -c_autodefer (cstr_drop(&s1), cstr_drop(&s2)) +c_defer (cstr_drop(&s1), cstr_drop(&s2)) { printf("%s %s\n", cstr_str(&s1), cstr_str(&s2)); } @@ -70,16 +75,16 @@ 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_drop(&line)) - while (cstr_getline(&line, fp)) - cvec_str_emplace_back(&vec, cstr_str(&line)); + c_with (FILE* fp = fopen(name, "r"), fclose(fp)) + c_with (cstr line = cstr_null, cstr_drop(&line)) + while (cstr_getline(&line, fp)) + cvec_str_emplace_back(&vec, cstr_str(&line)); return vec; } int main() { - c_autovar (cvec_str x = readFile(__FILE__), cvec_str_drop(&x)) + c_with (cvec_str x = readFile(__FILE__), cvec_str_drop(&x)) c_foreach (i, cvec_str, x) printf("%s\n", cstr_str(i.ref)); } @@ -209,16 +214,15 @@ c_forrange (int, i, 30, 0, -5) printf(" %d", i); ### c_find_if, c_find_in Search linearily in containers using a predicate ``` -// NOTE: it.ref is NULL if not found, not cvec_i_end(&vec).ref -// This makes it easier to test. -cvec_i_iter it; +cvec_i_iter it, it1, it2; // Search vec for first value > 2: -c_find_if(cvec_i, vec, it, *it.ref > 2); +// NOTE: it.ref is NULL if not found +c_find_if(it, cvec_i, vec, *it.ref > 2); if (it.ref) printf("%d\n", *it.ref); // Search within a range: -c_find_in(csmap_str, it1, it2, it, cstr_contains(*it.ref, "hello")); +c_find_in(it, csmap_str, it1, it2, cstr_contains(it.ref, "hello")); if (it.ref) cmap_str_erase_at(&map, it); ``` diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 6826946c..6a47313d 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -29,6 +29,7 @@ cdeq_X cdeq_X_clone(cdeq_X deq); void cdeq_X_clear(cdeq_X* self); void cdeq_X_copy(cdeq_X* self, const cdeq_X* other); +cdeq_X_iter cdeq_X_copy_range(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2); 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); @@ -42,7 +43,7 @@ const cdeq_X_value* cdeq_X_at(const cdeq_X* self, size_t idx); const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get cdeq_X_iter cdeq_X_find(const cdeq_X* self, i_valraw raw); -cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); +cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found cdeq_X_value* cdeq_X_front(const cdeq_X* self); cdeq_X_value* cdeq_X_back(const cdeq_X* self); @@ -57,22 +58,21 @@ cdeq_X_value* cdeq_X_emplace_back(cdeq_X* self, i_valraw raw); cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back() void cdeq_X_pop_back(cdeq_X* self); -cdeq_X_value* cdeq_X_insert(cdeq_X* self, size_t idx, i_val value); // move value -cdeq_X_value* cdeq_X_insert_n(cdeq_X* self, size_t idx, const i_val[] arr, size_t n); // move arr values -cdeq_X_value* cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value -cdeq_X_value* cdeq_X_insert_range_p(cdeq_X* self, i_val* pos, - const i_val* p1, const i_val* p2); +cdeq_X_iter cdeq_X_insert(cdeq_X* self, size_t idx, i_val value); // move value +cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, size_t idx, const i_val[] arr, size_t n); // move arr values +cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value +cdeq_X_iter cdeq_X_insert_range(cdeq_X* self, i_val* pos, + const i_val* p1, const i_val* p2); -cdeq_X_value* cdeq_X_emplace_n(cdeq_X* self, size_t idx, const i_valraw[] arr, size_t n); -cdeq_X_value* cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw); -cdeq_X_value* cdeq_X_emplace_range(cdeq_X* self, cdeq_X_iter it, // will clone - cdeq_X_iter it1, cdeq_X_iter it2); -cdeq_X_value* cdeq_X_emplace_range_p(cdeq_X* self, i_val* pos, - const i_val* p1, const i_val* p2); +cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, size_t idx, const i_valraw[] arr, size_t n); // clone values +cdeq_X_iter cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw); +cdeq_X_iter cdeq_X_emplace_range(cdeq_X* self, i_val* pos, + const i_valraw* p1, const i_valraw* p2); cdeq_X_iter cdeq_X_erase_n(cdeq_X* self, size_t idx, size_t n); cdeq_X_iter cdeq_X_erase_at(cdeq_X* self, cdeq_X_iter it); cdeq_X_iter cdeq_X_erase_range(cdeq_X* self, cdeq_X_iter it1, cdeq_X_iter it2); +cdeq_X_iter cdeq_X_erase_range_p(cdeq_X* self, i_val* p1, i_val* p2); void cdeq_X_sort(cdeq_X* self); void cdeq_X_sort_range(cdeq_X_iter i1, cdeq_X_iter i2, diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 91c36def..792d6c8c 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -211,7 +211,7 @@ typedef struct { int x, y, z; } Vec3i; int main() { // Define map with defered destruct - c_autovar (cmap_vi vecs = cmap_vi_init(), cmap_vi_drop(&vecs)) + c_with (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); @@ -244,7 +244,7 @@ typedef struct { int x, y, z; } Vec3i; int main() { - c_auto (cmap_iv, vecs) // shorthand for c_autovar with _init(), _drop(). + c_auto (cmap_iv, vecs) // shorthand for c_with with _init(), _drop(). { cmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0}); cmap_iv_insert(&vecs, 2, (Vec3i){ 0, 100, 0}); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 3a1a5aa6..91abaae3 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -157,7 +157,7 @@ int main() { uint32_t col = 0xcc7744ff; csmap_id idnames = csmap_id_init(); - c_autodefer (csmap_id_drop(&idnames)) + c_defer (csmap_id_drop(&idnames)) { c_forarray (csmap_id_raw, v, { {100, "Red"}, {110, "Blue"} }) csmap_id_emplace(&idnames, v->first, v->second); @@ -238,7 +238,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_drop(&vecs)) + c_with (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/cstr_api.md b/docs/cstr_api.md index fffec64c..d4e292cd 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -30,16 +30,16 @@ cstr cstr_clone(cstr s); cstr* cstr_take(cstr* self, cstr s); // take ownership of s, i.e. don't drop s. cstr cstr_move(cstr* self); // move string to caller, leave self empty -void cstr_drop(cstr *self); // destructor +void cstr_drop(cstr* self); // destructor const char* cstr_str(const cstr* self); // cast to const char* char* cstr_data(cstr* self); // cast to mutable char* csview cstr_sv(const cstr* self); // cast to string view cstr_buf cstr_buffer(cstr* self); // cast to mutable buffer (with capacity) -size_t cstr_size(cstr s); -size_t cstr_capacity(cstr s); -bool cstr_empty(cstr s); +size_t cstr_size(const cstr* self); +size_t cstr_capacity(const cstr* self); +bool cstr_empty(const cstr* self); char* cstr_reserve(cstr* self, size_t capacity); // return pointer to buffer void cstr_resize(cstr* self, size_t len, char fill); @@ -57,7 +57,7 @@ char* cstr_append(cstr* self, const char* str); char* cstr_append_n(cstr* self, const char* str, size_t n); // append n first bytes of str char* cstr_append_sv(cstr* self, csview str); char* cstr_append_s(cstr* self, cstr str); -char* cstr_append_uninit(cstr *self, size_t len); // append len uninitialized bytes +char* cstr_append_uninit(cstr* self, size_t len); // append len uninitialized bytes void cstr_insert(cstr* self, size_t pos, const char* ins); void cstr_insert_sv(cstr* self, size_t pos, csview ins); @@ -72,19 +72,21 @@ void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* rep void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl); void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl); -bool cstr_equals(cstr s, const char* str); -bool cstr_equals_s(cstr s, cstr s2); -size_t cstr_find(cstr s, const char* search); -size_t cstr_find_at(cstr s, size_t pos, const char* search); // search from pos -bool cstr_contains(cstr s, const char* search); +bool cstr_equals(const cstr* self, const char* str); +bool cstr_equals_s(const cstr* self, cstr s); +bool cstr_equals_sv(const cstr* self, csview sv); -bool cstr_starts_with(cstr s, const char* str); -bool cstr_starts_with_sv(cstr s, csview sv); -bool cstr_starts_with_s(cstr s, cstr s); +size_t cstr_find(const cstr* self, const char* search); +size_t cstr_find_at(const cstr* self, size_t pos, const char* search); // search from pos +bool cstr_contains(const cstr* self, const char* search); -bool cstr_ends_with(cstr s, const char* str); -bool cstr_ends_with_sv(cstr s, csview sv); -bool cstr_ends_with_s(cstr s, cstr s); +bool cstr_starts_with(const cstr* self, const char* str); +bool cstr_starts_with_sv(const cstr* self, csview sv); +bool cstr_starts_with_s(const cstr* self, cstr s); + +bool cstr_ends_with(const cstr* self, const char* str); +bool cstr_ends_with_sv(const cstr* self, csview sv); +bool cstr_ends_with_s(const cstr* self, cstr s); bool cstr_getline(cstr *self, FILE *stream); // cstr_getdelim(self, '\n', stream) bool cstr_getdelim(cstr *self, int delim, FILE *stream); // does not append delim to result @@ -92,12 +94,12 @@ bool cstr_getdelim(cstr *self, int delim, FILE *stream); // does no #### UTF8 methods ```c -size_t cstr_u8_size(cstr s); // number of utf8 codepoints -size_t cstr_u8_size_n(cstr s, size_t nbytes); // utf8 size within n bytes -size_t cstr_u8_to_pos(cstr s, size_t u8idx); // byte pos offset at utf8 codepoint index +size_t cstr_u8_size(const cstr* self); // number of utf8 codepoints +size_t cstr_u8_size_n(const cstr self, size_t nbytes); // utf8 size within n bytes +size_t cstr_u8_to_pos(const cstr* self, size_t u8idx); // byte pos offset at utf8 codepoint index const char* cstr_u8_at(const cstr* self, size_t u8idx); // char* position at utf8 codepoint index csview cstr_u8_chr(const cstr* self, size_t u8idx); // get utf8 character as a csview -void cstr_u8_replace_at(cstr* self, size_t u8pos, size_t u8len, csview repl); // replace at utf8 indices +void cstr_u8_replace(cstr* self, size_t pos, size_t u8len, csview repl); // replace u8len utf8 chars // iterate utf8 codepoints cstr_iter cstr_begin(const cstr* self); @@ -117,18 +119,18 @@ cstr cstr_toupper_sv(csview sv); // returns void cstr_uppercase(cstr* self); // transform cstr to uppercase utf8 int cstr_icmp(const cstr* s1, const cstr* s2); // utf8 case-insensitive comparison -bool cstr_iequals(cstr s, const char* str); // " -bool cstr_istarts_with(cstr s, const char* str); // " -bool cstr_iends_with(cstr s, const char* str); // " +bool cstr_iequals(const cstr* self, const char* str); // " +bool cstr_istarts_with(const cstr* self, const char* str); // " +bool cstr_iends_with(const cstr* self, const char* str); // " ``` Note that all methods with arguments `(..., const char* str, size_t n)`, `n` must be within the range of `str` length. #### Helper methods: ```c -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 cstr_cmp(const cstr* s1, const cstr* s2); +bool cstr_eq(const cstr* s1, const cstr* s2); +bool cstr_hash(const cstr* self); char* c_strnstrn(const char* str, const char* search, size_t slen, size_t nlen); ``` @@ -155,7 +157,7 @@ char* c_strnstrn(const char* str, const char* search, size_t slen, size_t int main() { cstr s0 = cstr_new("Initialization without using strlen()."); - printf("%s\nLength: %" PRIuMAX "\n\n", cstr_str(&s0), cstr_size(s0)); + printf("%s\nLength: %" PRIuMAX "\n\n", cstr_str(&s0), cstr_size(&s0)); cstr s1 = cstr_new("one-nine-three-seven-five."); printf("%s\n", cstr_str(&s1)); diff --git a/docs/csview_api.md b/docs/csview_api.md index 09f377d1..128a1c9d 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -92,11 +92,11 @@ uint64_t csview_hash(const csview* x); ## Types -| Type name | Type definition | Used to represent... | -|:----------------|:------------------------------------------|:-------------------------| -| `csview` | `struct { const char *str; size_t size }` | The string view type | -| `csview_value` | `char` | The string element type | -| `csview_iter` | `struct { csview_value *ref; }` | UTF8 iterator | +| Type name | Type definition | Used to represent... | +|:----------------|:-------------------------------------------|:-------------------------| +| `csview` | `struct { const char *str; size_t size; }` | The string view type | +| `csview_value` | `char` | The string element type | +| `csview_iter` | `struct { csview_value *ref; }` | UTF8 iterator | ## Constants and macros @@ -118,7 +118,7 @@ int main () // (quoting Alfred N. Whitehead) csview sv1 = cstr_substr(&str1, 3, 5); // "think" - size_t pos = cstr_find(str1, "live"); // position of "live" in str1 + size_t pos = cstr_find(&str1, "live"); // position of "live" in str1 csview sv2 = cstr_substr(&str1, pos, 4); // get "live" csview sv3 = cstr_slice(&str1, -8, -1); // get "details" printf("%" c_PRIsv "%" c_PRIsv "%" c_PRIsv "\n", @@ -146,11 +146,11 @@ int main() { c_auto (cstr, s1) { s1 = cstr_new("hell😀 w😀rld"); - cstr_u8_replace_at(&s1, 7, 1, c_sv("ø")); + cstr_u8_replace(&s1, cstr_find(&s1, "😀rld"), 1, c_sv("ø")); printf("%s\n", cstr_str(&s1)); c_foreach (i, cstr, s1) - printf("%.*s,", c_ARGsv(i.chr)); + printf("%.*s,", c_ARGsv(i.u8.chr)); } } ``` @@ -199,7 +199,7 @@ int main() print_split(c_sv("This has no matching separator"), c_sv("xx")); puts(""); - c_autovar (cstack_str s = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cstack_str_drop(&s)) + c_with (cstack_str s = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cstack_str_drop(&s)) c_foreach (i, cstack_str, s) printf("[%s]\n", cstr_str(i.ref)); } diff --git a/docs/cvec_api.md b/docs/cvec_api.md index a907c827..579f6eeb 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -34,9 +34,10 @@ cvec_X cvec_X_clone(cvec_X vec); void cvec_X_clear(cvec_X* self); void cvec_X_copy(cvec_X* self, const cvec_X* other); +cvec_X_iter cvec_X_copy_range(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2); bool cvec_X_reserve(cvec_X* self, size_t cap); bool cvec_X_resize(cvec_X* self, size_t size, i_val null); -cvec_X_value* cvec_X_append_uninit(cvec_X* self, size_t n); // return start of uninit +cvec_X_iter cvec_X_insert_uninit(cvec_X* self, i_val* pos, size_t n); // return pos iter void cvec_X_shrink_to_fit(cvec_X* self); void cvec_X_swap(cvec_X* a, cvec_X* b); void cvec_X_drop(cvec_X* self); // destructor @@ -48,9 +49,9 @@ size_t cvec_X_capacity(const cvec_X* self); 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_at_mut(cvec_X* self, size_t idx); -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); // find mutable value, return value ptr 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_find_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw); // return cvec_X_end() if not found // On sorted vectors: cvec_X_iter cvec_X_binary_search(const cvec_X* self, i_valraw raw); // at elem == raw, else end cvec_X_iter cvec_X_lower_bound(const cvec_X* self, i_valraw raw); // at first elem >= raw, else end @@ -68,22 +69,21 @@ cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); void cvec_X_pop(cvec_X* self); void cvec_X_pop_back(cvec_X* self); // alias for pop -cvec_X_value* cvec_X_insert(cvec_X* self, size_t idx, i_val value); // move value -cvec_X_value* cvec_X_insert_n(cvec_X* self, size_t idx, const i_val[] arr, size_t n); // move n values -cvec_X_value* cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value -cvec_X_value* cvec_X_insert_range_p(cvec_X* self, i_val* pos, - const i_val* p1, const i_val* p2); +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 n 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_insert_range(cvec_X* self, i_val* pos, + const i_val* p1, const i_val* p2); -cvec_X_value* cvec_X_emplace_n(cvec_X* self, size_t idx, const i_valraw[] arr, size_t n); -cvec_X_value* cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw); -cvec_X_value* cvec_X_emplace_range(cvec_X* self, cvec_X_iter it, // will clone - cvec_X_iter it1, cvec_X_iter it2); -cvec_X_value* cvec_X_emplace_range_p(cvec_X* self, i_val* pos, - const i_val* p1, const i_val* p2); +cvec_X_iter cvec_X_emplace_n(cvec_X* self, size_t idx, const i_valraw[] arr, size_t n); // clone values +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, i_val* pos, + const i_valraw* p1, const i_valraw* p2); cvec_X_iter cvec_X_erase_n(cvec_X* self, size_t idx, size_t n); cvec_X_iter cvec_X_erase_at(cvec_X* self, cvec_X_iter it); cvec_X_iter cvec_X_erase_range(cvec_X* self, cvec_X_iter it1, cvec_X_iter it2); +cvec_X_iter cvec_X_erase_range_p(cvec_X* self, i_val* p1, i_val* p2); void cvec_X_sort(cvec_X* self); void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2, diff --git a/examples/arc_containers.c b/examples/arc_containers.c index e8716129..debc6617 100644 --- a/examples/arc_containers.c +++ b/examples/arc_containers.c @@ -53,7 +53,7 @@ int main() // 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_make(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/arc_demo.c b/examples/arc_demo.c index 85e3886f..688fe72f 100644 --- a/examples/arc_demo.c +++ b/examples/arc_demo.c @@ -47,7 +47,7 @@ int main() printf("\nset:"); c_foreach (i, csset_Arc, set) printf(" %d", *i.ref->get); - c_autovar (Arc p = Arc_clone(vec.data[0]), Arc_drop(&p)) { + c_with (Arc p = Arc_clone(vec.data[0]), Arc_drop(&p)) { printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); } diff --git a/examples/arcvec_erase.c b/examples/arcvec_erase.c index eba77f51..b96f4278 100644 --- a/examples/arcvec_erase.c +++ b/examples/arcvec_erase.c @@ -20,13 +20,12 @@ int main() { c_auto (Vec, vec) { - const int v[] = {2012, 1990, 2012, 2019, 2015}; - c_forrange (i, c_arraylen(v)) - Vec_push_back(&vec, Arc_make(v[i])); + c_forarray (int, v, {2012, 1990, 2012, 2019, 2015}) + Vec_emplace(&vec, *v); // clone the second 2012 and push it back. // note: cloning make sure that vec.data[2] has ref count 2. - Vec_push_back(&vec, Arc_clone(vec.data[2])); + Vec_push(&vec, Arc_clone(vec.data[2])); printf("vec before erase :"); c_foreach (i, Vec, vec) diff --git a/examples/astar.c b/examples/astar.c index 7d90bf35..4d9f2469 100644 --- a/examples/astar.c +++ b/examples/astar.c @@ -37,7 +37,7 @@ point_equal(const point* a, const point* b) point point_from(const cstr* maze, const char* c, int width) { - int index = cstr_find(*maze, c); + int index = cstr_find(maze, c); return point_init(index % width, index / width, width); } @@ -131,7 +131,7 @@ astar(cstr* maze, int width) int main(void) { - c_autovar (cstr maze = cstr_new( + c_with (cstr maze = cstr_new( "#########################################################################\n" "# # # # # # #\n" "# # ######### # ##### ######### ##### ##### ##### # ! #\n" @@ -156,8 +156,8 @@ main(void) "# # # # # # #\n" "#########################################################################\n"), cstr_drop(&maze)) { - int width = cstr_find(maze, "\n") + 1; - c_autovar (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path)) + int width = cstr_find(&maze, "\n") + 1; + c_with (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path)) { c_foreach (it, cdeq_point, path) cstr_data(&maze)[point_index(it.ref)] = 'x'; printf("%s", cstr_str(&maze)); diff --git a/examples/bits.c b/examples/bits.c index 8cce573e..c6e70517 100644 --- a/examples/bits.c +++ b/examples/bits.c @@ -3,7 +3,7 @@ int main() { - c_autovar (cbits set = cbits_with_size(23, true), cbits_drop(&set)) { + c_with (cbits set = cbits_with_size(23, true), cbits_drop(&set)) { printf("count %" PRIuMAX ", %" PRIuMAX "\n", cbits_count(&set), cbits_size(&set)); cbits s1 = cbits_from("1110100110111"); char buf[256]; @@ -36,7 +36,7 @@ int main() printf("%d", cbits_test(&set, i)); puts(""); - c_autovar (cbits s2 = cbits_clone(set), cbits_drop(&s2)) { + c_with (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 c7e649bf..b12f1f71 100644 --- a/examples/box.c +++ b/examples/box.c @@ -59,7 +59,7 @@ int main() puts(""); // Look-up Audrey! Create a temporary Person for lookup. - c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { + c_with (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { const PBox *v = Persons_get(&vec, a); // lookup if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last)); } diff --git a/examples/city.c b/examples/city.c index c22693f9..c6a9417f 100644 --- a/examples/city.c +++ b/examples/city.c @@ -32,8 +32,9 @@ static inline void City_drop(City* c) { #define i_type CityArc #define i_key_bind City -#include <stc/cbox.h> -//#include <stc/carc.h> // try instead of cbox.h +#define i_opt c_no_atomic +//#include <stc/cbox.h> +#include <stc/carc.h> // try instead of cbox.h #define i_type Cities #define i_key_arcbox CityArc @@ -50,16 +51,13 @@ int main(void) c_auto (Cities, cities, copy) c_auto (CityMap, map) { - struct City_s { const char *name, *country; float lat, lon; int pop; }; - - c_forarray (struct City_s, c, { - {"New York", "US", 4.3, 23.2, 9000000}, - {"Paris", "France", 4.3, 23.2, 9000000}, - {"Berlin", "Germany", 4.3, 23.2, 9000000}, - {"London", "UK", 4.3, 23.2, 9000000}, + c_forarray (City, c, { + {cstr_new("New York"), cstr_new("US"), 4.3, 23.2, 9000000}, + {cstr_new("Paris"), cstr_new("France"), 4.3, 23.2, 9000000}, + {cstr_new("Berlin"), cstr_new("Germany"), 4.3, 23.2, 9000000}, + {cstr_new("London"), cstr_new("UK"), 4.3, 23.2, 9000000}, }) { - Cities_push(&cities, CityArc_make((City){cstr_from(c->name), cstr_from(c->country), - c->lat, c->lon, c->pop})); + Cities_emplace(&cities, *c); } copy = Cities_clone(cities); // share each element! @@ -73,12 +71,14 @@ int main(void) printf("Vec:\n"); c_foreach (c, Cities, cities) - printf("city:%s, %d, use:%ld\n", cstr_str(&c.ref->get->name), c.ref->get->population, CityArc_use_count(*c.ref)); + printf("city:%s, %d, use:%ld\n", cstr_str(&c.ref->get->name), + c.ref->get->population, + CityArc_use_count(c.ref)); printf("\nMap:\n"); c_forpair (id, city, CityMap, map) printf("id:%d, city:%s, %d, use:%ld\n", *_.id, cstr_str(&_.city->get->name), - _.city->get->population, CityArc_use_count(*_.city)); + _.city->get->population, CityArc_use_count(_.city)); puts(""); } } diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c index 1c533a99..cbcc2607 100644 --- a/examples/csmap_erase.c +++ b/examples/csmap_erase.c @@ -49,6 +49,11 @@ int main() printmap(m2); mymap_iter it1 = mymap_advance(mymap_begin(&m2), 1); mymap_iter it2 = mymap_find(&m2, mymap_back(&m2)->first); + + puts("to remove:"); + c_foreach (i, mymap, it1, it2) + printf(" [%d, %s]", i.ref->first, cstr_str(&i.ref->second)); + puts(""); // The 2nd member function removes elements // in the range [First, Last) mymap_erase_range(&m2, it1, it2); diff --git a/examples/cstr_match.c b/examples/cstr_match.c index 6927ed80..614af490 100644 --- a/examples/cstr_match.c +++ b/examples/cstr_match.c @@ -4,19 +4,19 @@ int main() { - c_autovar (cstr ss = cstr_new("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) { - size_t pos = cstr_find_at(ss, 0, "brown"); + c_with (cstr ss = cstr_new("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) { + size_t pos = cstr_find_at(&ss, 0, "brown"); printf("%" PRIuMAX " [%s]\n", pos, pos == cstr_npos ? "<NULL>" : cstr_str(&ss) + pos); - printf("equals: %d\n", cstr_equals(ss, "The quick brown fox jumps over the lazy dog.JPG")); - printf("contains: %d\n", cstr_contains(ss, "umps ove")); - printf("starts_with: %d\n", cstr_starts_with(ss, "The quick brown")); - printf("ends_with: %d\n", cstr_ends_with(ss, ".jpg")); - printf("ends_with: %d\n", cstr_ends_with(ss, ".JPG")); + printf("equals: %d\n", cstr_equals(&ss, "The quick brown fox jumps over the lazy dog.JPG")); + printf("contains: %d\n", cstr_contains(&ss, "umps ove")); + printf("starts_with: %d\n", cstr_starts_with(&ss, "The quick brown")); + printf("ends_with: %d\n", cstr_ends_with(&ss, ".jpg")); + printf("ends_with: %d\n", cstr_ends_with(&ss, ".JPG")); cstr s1 = cstr_new("hell😀 w😀rl🐨"); csview ch1 = cstr_u8_chr(&s1, 7); csview ch2 = cstr_u8_chr(&s1, 10); - printf("%s\nsize: %" PRIuMAX ", %" PRIuMAX "\n", cstr_str(&s1), cstr_u8_size(s1), cstr_size(s1)); + printf("%s\nsize: %" PRIuMAX ", %" PRIuMAX "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1)); printf("ch1: %.*s\n", c_ARGsv(ch1)); printf("ch2: %.*s\n", c_ARGsv(ch2)); } diff --git a/examples/demos.c b/examples/demos.c index 052c4e32..331ef04f 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_drop(&cs)) + c_with (cstr cs = cstr_new("one-nine-three-seven-five"), cstr_drop(&cs)) { printf("%s.\n", cstr_str(&cs)); @@ -19,7 +19,7 @@ void stringdemo1() cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs))); printf("%s.\n", cstr_str(&cs)); - printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(cs, "four")); + printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(&cs, "four")); // reassign: cstr_assign(&cs, "one two three four five six seven"); @@ -35,7 +35,7 @@ void stringdemo1() void vectordemo1() { printf("\nVECTORDEMO1\n"); - c_autovar (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_drop(&bignums)) + c_with (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) @@ -192,8 +192,8 @@ void mapdemo3() void arraydemo1() { printf("\nARRAYDEMO1\n"); - c_autovar (carr3_f arr3 = carr3_f_with_size(30, 20, 10, 0.0f), - carr3_f_drop(&arr3)) + c_with (carr3_f arr3 = carr3_f_with_size(30, 20, 10, 0.0f), + carr3_f_drop(&arr3)) { arr3.data[5][4][3] = 10.2f; float **arr2 = arr3.data[5]; diff --git a/examples/mmap.c b/examples/mmap.c index 5ca2f92a..ed78d2af 100644 --- a/examples/mmap.c +++ b/examples/mmap.c @@ -4,6 +4,7 @@ // Multimap entries #include <stc/cstr.h> #define i_val_str +//#define i_valdrop(x) (printf("drop %s\n", cstr_str(x)), cstr_drop(x)) #define i_extern // define _clist_mergesort() once #include <stc/clist.h> @@ -34,10 +35,11 @@ int main() { c_auto (Multimap, mmap) { + typedef struct {int a; const char* b;} pair; + // list-initialize - struct { int first; const char* second; } vals[] = - {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}}; - c_forrange (i, c_arraylen(vals)) insert(&mmap, c_pair(&vals[i])); + c_forarray (pair, v, {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}}) + insert(&mmap, v->a, v->b); print("#1", mmap); // insert using value_type @@ -52,24 +54,19 @@ int main() print("#4", mmap); // insert using initialization_list - insert(&mmap, 5, "one"); - insert(&mmap, 5, "two"); + c_forarray (pair, v, {{5, "one"}, {5, "two"}}) + insert(&mmap, v->a, v->b); print("#5", mmap); // FOLLOWING NOT IN ORIGINAL EXAMPLE: - // erase all entries with key 5 Multimap_erase(&mmap, 5); - print("+6", mmap); + print("+5", mmap); + - // find and erase first entry containing "bar" - clist_str_iter pos; - 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; - } - } - print("+7", mmap); + Multimap_clear(&mmap); + c_forarray (pair, v, {{1, "ä"}, {2, "ё"}, {2, "ö"}, {3, "ü"}}) + insert(&mmap, v->a, v->b); + print("#6", mmap); } } diff --git a/examples/music_arc.c b/examples/music_arc.c index ac730bc3..6f9c1c72 100644 --- a/examples/music_arc.c +++ b/examples/music_arc.c @@ -8,7 +8,10 @@ struct Song cstr title; } typedef Song; -Song Song_new(const char* artist, const char* title) +int Song_cmp(const Song* x, const Song* y) + { return cstr_cmp(&x->title, &y->title); } + +Song Song_from(const char* artist, const char* title) { return (Song){cstr_from(artist), cstr_from(title)}; } void Song_drop(Song* s) { @@ -16,40 +19,48 @@ void Song_drop(Song* s) { c_drop(cstr, &s->artist, &s->title); } -#define i_type SongPtr +// Define the reference counted type +#define i_type SongArc #define i_val Song #define i_valdrop Song_drop -#define i_opt c_no_cmp +#define i_cmp Song_cmp #include <stc/carc.h> +// ... and a vector of it #define i_type SongVec -#define i_val_arcbox SongPtr +#define i_val_arcbox SongArc #include <stc/cvec.h> void example3() { c_auto (SongVec, vec, vec2) { - c_forarray (SongPtr, v, { - SongPtr_make(Song_new("Bob Dylan", "The Times They Are A Changing")), - SongPtr_make(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), - SongPtr_make(Song_new("Thalia", "Entre El Mar y Una Estrella")) - }) SongVec_push_back(&vec, *v); + c_forarray (Song, v, { + Song_from("Bob Dylan", "The Times They Are A Changing"), + Song_from("Aretha Franklin", "Bridge Over Troubled Water"), + Song_from("Thalia", "Entre El Mar y Una Estrella") + }) SongVec_emplace(&vec, *v); + // Share all entries in vec with vec2, except Bob Dylan. c_foreach (s, SongVec, vec) - if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) - SongVec_push_back(&vec2, SongPtr_clone(*s.ref)); - - c_forarray (SongPtr, v, { - SongPtr_make(Song_new("Michael Jackson", "Billie Jean")), - SongPtr_make(Song_new("Rihanna", "Stay")), - }) SongVec_push_back(&vec2, *v); - - c_foreach (s, SongVec, vec2) - printf("%s - %s: refs %lu\n", cstr_str(&s.ref->get->artist), - cstr_str(&s.ref->get->title), - *s.ref->use_count); - } + if (!cstr_equals(&s.ref->get->artist, "Bob Dylan")) + SongVec_push(&vec2, SongArc_clone(*s.ref)); + + // Add a few more to vec2. We can use emplace when creating new entries + SongVec_emplace(&vec2, Song_from("Michael Jackson", "Billie Jean")); + SongVec_emplace(&vec2, Song_from("Rihanna", "Stay")); + // If we use push, we would need to construct the Arc explicitly (as in c++, make_shared): + // SongVec_push(&vec2, SongArc_from(Song_from("Rihanna", "Stay"))); + + // We now have two vectors with some shared, some unique entries. + c_forarray (SongVec, v, {vec, vec2}) { + puts("VEC:"); + c_foreach (s, SongVec, *v) + printf(" %s - %s, REFS: %lu\n", cstr_str(&s.ref->get->artist), + cstr_str(&s.ref->get->title), + *s.ref->use_count); + } + } // because the shared elem. are ref. counted, they are only dropped once here. } int main() diff --git a/examples/new_arr.c b/examples/new_arr.c index 17a96062..598e5323 100644 --- a/examples/new_arr.c +++ b/examples/new_arr.c @@ -13,8 +13,8 @@ int main() { int w = 7, h = 5, d = 3; - c_autovar (carr2_int volume = carr2_int_new_uninit(w, h), - carr2_int_drop(&volume)) + c_with (carr2_int volume = carr2_int_new_uninit(w, h), + carr2_int_drop(&volume)) { int *dat = carr2_int_data(&volume); for (size_t i = 0; i < carr2_int_size(&volume); ++i) @@ -30,8 +30,8 @@ int main() puts("\n"); } - c_autovar (carr3_int volume = carr3_int_new_uninit(w, h, d), - carr3_int_drop(&volume)) + c_with (carr3_int volume = carr3_int_new_uninit(w, h, d), + carr3_int_drop(&volume)) { int *dat = carr3_int_data(&volume); for (size_t i = 0; i < carr3_int_size(&volume); ++i) @@ -48,8 +48,8 @@ int main() puts(""); } - c_autovar (carr2_str text2d = carr2_str_with_size(h, d, cstr_init()), - carr2_str_drop(&text2d)) + c_with (carr2_str text2d = carr2_str_with_size(h, d, cstr_init()), + carr2_str_drop(&text2d)) { cstr_assign(&text2d.data[2][1], "hello"); cstr_assign(&text2d.data[4][0], "world"); diff --git a/examples/person_arc.c b/examples/person_arc.c index 272a3f72..bddf7bd6 100644 --- a/examples/person_arc.c +++ b/examples/person_arc.c @@ -62,7 +62,7 @@ int main() puts(""); // Look-up Audrey! - c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { + c_with (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { const PSPtr *v = Persons_get(&vec, a); if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last)); } diff --git a/examples/prime.c b/examples/prime.c index 01a6800b..7af66f33 100644 --- a/examples/prime.c +++ b/examples/prime.c @@ -27,7 +27,7 @@ int main(void) printf("computing prime numbers up to %" PRIuMAX "\n", n); clock_t t1 = clock(); - c_autovar (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { + c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { puts("done"); size_t np = cbits_count(&primes); clock_t t2 = clock(); @@ -37,5 +37,12 @@ int main(void) for (size_t i = 3; i < 1000; i += 2) if (cbits_test(&primes, i>>1)) printf(" %" PRIuMAX "", i); puts(""); + + int k = 20; + c_forrange (intptr_t, i, n-1, 1, -2) { + if (k == 0) break; + else if (cbits_test(&primes, i>>1)) printf("%" PRIdMAX "\n", i), k--; + } + puts(""); } } diff --git a/examples/rawptr_elements.c b/examples/rawptr_elements.c index c3e3188d..bae314fd 100644 --- a/examples/rawptr_elements.c +++ b/examples/rawptr_elements.c @@ -1,67 +1,55 @@ #include <stc/ccommon.h> #include <stdio.h> -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_keydrop(x) c_free(*(x)) -#define i_keyclone(x) c_new(Point, *(x)) -#define i_hash(x) c_default_hash(*(x)) -#define i_cmp(x, y) memcmp(*(x), *(y), sizeof **(x)) // not good! -#define i_tag pnt -#include <stc/cset.h> - #include <stc/cstr.h> -// Map of int64 pointers: Define i_valraw as int64_t for easy emplace calls! +// Map of cstr => int64 pointers typedef int64_t inttype; + +// Do it without cbox: +#define i_type SIPtrMap #define i_key_str #define i_val inttype* #define i_valraw inttype -#define i_valfrom(raw) (puts("from"), c_new(inttype, raw)) -#define i_valto(x) (puts("to"), **(x)) -#define i_valclone c_derived_valclone // enables clone via valto+valfrom -#define i_valdrop(x) c_free(*(x)) +#define i_valfrom(raw) c_new(inttype, raw) +#define i_valto(x) **x +#define i_valclone(x) c_new(inttype, *x) +#define i_valdrop(x) c_free(*x) #include <stc/cmap.h> -int main() -{ - c_auto (cset_pnt, set, cpy) - { - printf("Set with pointer elements:\n"); - // c++: set.insert(new Point{1.2, 3.4}); - cset_pnt_insert(&set, c_new(Point, {1.2, 3.4})); - Point* q = *cset_pnt_insert(&set, c_new(Point, {6.1, 4.7})).ref; - cset_pnt_insert(&set, c_new(Point, {5.7, 2.3})); - - cpy = cset_pnt_clone(set); - cset_pnt_erase(&cpy, q); +// With cbox: +#define i_type IBox +#define i_val int +#include <stc/cbox.h> //<stc/carc.h> - printf("set:"); - c_foreach (i, cset_pnt, set) - printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); - - printf("\ncpy:"); - c_foreach (i, cset_pnt, cpy) - printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); - puts(""); - } +#define i_type SIBoxMap +#define i_key_str +#define i_val_arcbox IBox +#include <stc/cmap.h> - c_auto (cmap_str, map, m2) +int main() +{ + c_auto (SIPtrMap, map, m1) + c_auto (SIBoxMap, m2) { printf("\nMap with pointer elements:\n"); - cmap_str_insert(&map, cstr_new("testing"), c_new(inttype, 999)); - cmap_str_insert(&map, cstr_new("done"), c_new(inttype, 111)); + SIPtrMap_insert(&map, cstr_from("testing"), c_new(inttype, 1)); + SIPtrMap_insert(&map, cstr_from("done"), c_new(inttype, 2)); - // Emplace: implicit key, val construction using i_keyfrom/i_valfrom: - cmap_str_emplace(&map, "hello", 200); - cmap_str_emplace(&map, "goodbye", 400); + // Emplace: implicit key, val construction: + SIPtrMap_emplace(&map, "hello", 3); + SIPtrMap_emplace(&map, "goodbye", 4); - // default uses i_valfrom+i_valto when no i_valclone defined: - m2 = cmap_str_clone(map); + m1 = SIPtrMap_clone(map); - c_forpair (name, number, cmap_str, m2) + c_forpair (name, number, SIPtrMap, m1) printf("%s: %" PRIdMAX "\n", cstr_str(_.name), **_.number); + + + puts("\nIBox map:"); + SIBoxMap_insert(&m2, cstr_from("Hello"), IBox_from(123)); + SIBoxMap_emplace(&m2, "World", 999); + c_forpair (name, number, SIBoxMap, m2) + printf("%s: %d\n", cstr_str(_.name), *_.number->get); + puts(""); } } diff --git a/examples/read.c b/examples/read.c index 26fc46dd..5a9a30d5 100644 --- a/examples/read.c +++ b/examples/read.c @@ -6,8 +6,8 @@ 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_drop(&line)) + c_with (FILE* f = fopen(name, "r"), fclose(f)) + c_with (cstr line = cstr_null, cstr_drop(&line)) while (cstr_getline(&line, f)) cvec_str_push(&vec, cstr_clone(line)); return vec; @@ -16,7 +16,7 @@ cvec_str read_file(const char* name) int main() { int n = 0; - c_autovar (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec)) + c_with (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec)) c_foreach (i, cvec_str, vec) printf("%5d: %s\n", ++n, cstr_str(i.ref)); diff --git a/examples/regex1.c b/examples/regex1.c index 5981e878..c8b3a4f5 100644 --- a/examples/regex1.c +++ b/examples/regex1.c @@ -19,7 +19,7 @@ int main(int argc, char* argv[]) cstr_getline(&input, stdin); // Exit when the user inputs q - if (cstr_equals(input, "q")) + if (cstr_equals(&input, "q")) break; if (cregex_is_match(cstr_str(&input), &float_expr)) diff --git a/examples/regex_replace.c b/examples/regex_replace.c index 1b140676..8640ced1 100644 --- a/examples/regex_replace.c +++ b/examples/regex_replace.c @@ -34,9 +34,9 @@ int main() printf("brack: %s\n", cstr_str(&str)); /* Shows how to compile RE separately */ - c_autovar (cregex re = cregex_from(pattern, 0), cregex_drop(&re)) { + c_with (cregex re = cregex_from(pattern, 0), cregex_drop(&re)) { if (cregex_captures(&re) == 0) - continue; + continue; // break c_with /* European date format. */ cstr_take(&str, cregex_replace(input, &re, "$3.$2.$1", 0)); printf("euros: %s\n", cstr_str(&str)); diff --git a/examples/replace.c b/examples/replace.c index 13b6eaaf..c22c71ff 100644 --- a/examples/replace.c +++ b/examples/replace.c @@ -11,7 +11,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_drop(&s), cstr_drop(&m)) { + c_defer (cstr_drop(&s), cstr_drop(&m)) { cstr_append(&m, cstr_str(&m)); cstr_append(&m, cstr_str(&m)); printf("%s\n", cstr_str(&m)); diff --git a/examples/splitstr.c b/examples/splitstr.c index 68c36291..c483fbe0 100644 --- a/examples/splitstr.c +++ b/examples/splitstr.c @@ -33,7 +33,7 @@ int main() print_split(c_sv("This has no matching separator"), c_sv("xx")); puts(""); - c_autovar (cstack_str s = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cstack_str_drop(&s)) + c_with (cstack_str s = string_split(c_sv("Split,this,,string,now,"), c_sv(",")), cstack_str_drop(&s)) c_foreach (i, cstack_str, s) printf("[%s]\n", cstr_str(i.ref)); } diff --git a/examples/sso_map.c b/examples/sso_map.c index a32a9a3d..43bcb40b 100644 --- a/examples/sso_map.c +++ b/examples/sso_map.c @@ -11,7 +11,7 @@ int main() c_forpair (k, v, cmap_str, m) printf("%s: '%s' Len=%" PRIuMAX ", Is long: %s\n", - cstr_str(_.k), cstr_str(_.v), cstr_size(*_.v), + cstr_str(_.k), cstr_str(_.v), cstr_size(_.v), cstr_is_long(_.v)?"true":"false"); } } diff --git a/examples/sso_substr.c b/examples/sso_substr.c index b47512ea..098d9b4b 100644 --- a/examples/sso_substr.c +++ b/examples/sso_substr.c @@ -6,7 +6,7 @@ int main () { cstr str = cstr_new("We think in generalities, but we live in details."); csview sv1 = cstr_substr_ex(&str, 3, 5); // "think" - size_t pos = cstr_find(str, "live"); // position of "live" + size_t pos = cstr_find(&str, "live"); // position of "live" csview sv2 = cstr_substr_ex(&str, pos, 4); // "live" csview sv3 = cstr_slice_ex(&str, -8, -1); // "details" printf("%.*s, %.*s, %.*s\n", c_ARGsv(sv1), c_ARGsv(sv2), c_ARGsv(sv3)); diff --git a/examples/utf8replace_c.c b/examples/utf8replace_c.c index 792654b6..e7659cfd 100644 --- a/examples/utf8replace_c.c +++ b/examples/utf8replace_c.c @@ -8,7 +8,7 @@ int main() { printf("%s\n", cstr_str(&hello)); /* replace second smiley at utf8 codepoint pos 7 */ - cstr_u8_replace_at(&hello, 7, 1, c_sv("🐨")); + cstr_u8_replace(&hello, cstr_find(&hello, "😀rld"), 1, c_sv("🐨")); printf("%s\n", cstr_str(&hello)); @@ -16,7 +16,7 @@ int main() { printf("%s\n", cstr_str(&hello)); c_foreach (c, cstr, hello) - printf("%.*s,", c_ARGsv(c.chr)); + printf("%.*s,", c_ARGsv(c.u8.chr)); puts(""); } } diff --git a/include/stc/alt/csmap.h b/include/stc/alt/csmap.h index 60a1b72a..4b90fb78 100644 --- a/include/stc/alt/csmap.h +++ b/include/stc/alt/csmap.h @@ -32,7 +32,7 @@ #include <stc/csmap.h> int main(void) { - c_autovar (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) + c_with (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); diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index c669c620..a2233432 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -56,8 +56,8 @@ STC_API cstr* cstr_append_n(cstr* self, const char* str, size_t n); STC_API cstr cstr_replace_sv(csview str, csview find, csview repl, unsigned count); STC_DEF void cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl); STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n); -STC_API size_t cstr_find(cstr s, const char* needle); -STC_API size_t cstr_find_at(cstr s, size_t pos, const char* needle); +STC_API size_t cstr_find(const cstr* self, const char* needle); +STC_API size_t cstr_find_at(const cstr* self, size_t pos, const char* needle); STC_API bool cstr_getdelim(cstr *self, int delim, FILE *stream); STC_INLINE cstr cstr_init() { return cstr_null; } @@ -70,7 +70,7 @@ STC_INLINE csview cstr_sv(const cstr* self) STC_INLINE cstr cstr_from(const char* str) { return cstr_from_n(str, strlen(str)); } STC_INLINE char* cstr_data(cstr* self) { return self->str; } -STC_INLINE size_t cstr_size(cstr s) { return _cstr_p(&s)->size; } +STC_INLINE size_t cstr_size(const cstr* self) { return _cstr_p(self)->size; } STC_INLINE size_t cstr_capacity(cstr s) { return _cstr_p(&s)->cap; } STC_INLINE bool cstr_empty(cstr s) { return _cstr_p(&s)->size == 0; } STC_INLINE void cstr_drop(cstr* self) @@ -106,12 +106,12 @@ STC_INLINE void cstr_erase(cstr* self, const size_t pos) STC_INLINE char* cstr_front(cstr* self) { return self->str; } STC_INLINE char* cstr_back(cstr* self) { return self->str + _cstr_p(self)->size - 1; } -STC_INLINE bool cstr_equals(cstr s, const char* str) - { return strcmp(s.str, str) == 0; } -STC_INLINE bool cstr_equals_s(cstr s1, cstr s2) - { return strcmp(s1.str, s2.str) == 0; } -STC_INLINE bool cstr_contains(cstr s, const char* needle) - { return strstr(s.str, needle) != NULL; } +STC_INLINE bool cstr_equals(const cstr* self, const char* str) + { return strcmp(self->str, str) == 0; } +STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) + { return strcmp(self->str, s.str) == 0; } +STC_INLINE bool cstr_contains(const cstr* self, const char* needle) + { return strstr(self->str, needle) != NULL; } STC_INLINE bool cstr_getline(cstr *self, FILE *stream) { return cstr_getdelim(self, '\n', stream); } @@ -133,7 +133,7 @@ STC_INLINE cstr cstr_with_size(const size_t len, const char fill) { } STC_INLINE char* cstr_append_uninit(cstr *self, size_t n) { - size_t len = cstr_size(*self); char* d; + size_t len = cstr_size(self); char* d; if (!(d = cstr_reserve(self, len + n))) return NULL; _cstr_p(self)->size += n; return d + len; @@ -152,14 +152,15 @@ STC_INLINE cstr cstr_move(cstr* self) { return tmp; } -STC_INLINE bool cstr_starts_with(cstr s, const char* sub) { - while (*sub && *s.str == *sub) ++s.str, ++sub; +STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { + const char* p = self->str; + while (*sub && *p == *sub) ++p, ++sub; return *sub == 0; } -STC_INLINE bool cstr_ends_with(cstr s, const char* sub) { - const size_t n = strlen(sub), sz = _cstr_p(&s)->size; - return n <= sz && !memcmp(s.str + sz - n, sub, n); +STC_INLINE bool cstr_ends_with(const cstr* self, const char* sub) { + const size_t n = strlen(sub), sz = _cstr_p(self)->size; + return n <= sz && !memcmp(self->str + sz - n, sub, n); } STC_INLINE int c_strncasecmp(const char* s1, const char* s2, size_t nmax) { @@ -309,7 +310,7 @@ STC_INLINE void _cstr_internal_move(cstr* self, const size_t pos1, const size_t STC_DEF void cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl) { - const size_t sz = cstr_size(*self); + const size_t sz = cstr_size(self); if (len > sz - pos) len = sz - pos; c_autobuf (xstr, char, repl.size) { memcpy(xstr, repl.str, repl.size); @@ -366,16 +367,16 @@ cstr_getdelim(cstr *self, const int delim, FILE *fp) { } STC_DEF size_t -cstr_find(cstr s, const char* needle) { - char* res = strstr(s.str, needle); - return res ? res - s.str : cstr_npos; +cstr_find(const cstr* self, const char* needle) { + char* res = strstr(self->str, needle); + return res ? res - self->str : cstr_npos; } STC_DEF size_t -cstr_find_at(cstr s, const size_t pos, const char* needle) { - if (pos > _cstr_p(&s)->size) return cstr_npos; - char* res = strstr(s.str + pos, needle); - return res ? res - s.str : cstr_npos; +cstr_find_at(const cstr* self, const size_t pos, const char* needle) { + if (pos > _cstr_p(self)->size) return cstr_npos; + char* res = strstr(self->str + pos, needle); + return res ? res - self->str : cstr_npos; } #endif diff --git a/include/stc/carc.h b/include/stc/carc.h index 57f00899..6e8f7d38 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -34,18 +34,18 @@ void Person_drop(Person* p) { c_drop(cstr, &p->name, &p->last); } -#define i_tag person +#define i_type ArcPers #define i_key Person #define i_keydrop Person_drop #define i_opt c_no_cmp #include <stc/carc.h> int main() { - carc_person p = carc_person_make(Person_new("John", "Smiths")); - carc_person q = carc_person_clone(p); // share the pointer + ArcPers p = ArcPers_from(Person_new("John", "Smiths")); + ArcPers q = ArcPers_clone(p); // share the pointer printf("%s %s. uses: %" PRIuMAX "\n", cstr_str(&q.get->name), cstr_str(&q.get->last), *q.use_count); - c_drop(carc_person, &p, &q); + c_drop(ArcPers, &p, &q); } */ #include "ccommon.h" @@ -56,14 +56,17 @@ int main() { #include <stdlib.h> #if defined(__GNUC__) || defined(__clang__) + typedef long catomic_long; #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) #elif defined(_MSC_VER) #include <intrin.h> + typedef long catomic_long; #define c_atomic_inc(v) (void)_InterlockedIncrement(v) #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) #else #include <stdatomic.h> + typedef _Atomic long catomic_long; #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) #endif @@ -88,23 +91,23 @@ typedef i_keyraw _cx_raw; #if !c_option(c_is_fwd) _cx_deftypes(_c_carc_types, _cx_self, i_key); #endif -_cx_carc_rep { long counter; i_key value; }; +_cx_carc_rep { catomic_long counter; i_key value; }; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } -STC_INLINE long _cx_memb(_use_count)(_cx_self ptr) - { return ptr.use_count ? *ptr.use_count : 0; } +STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) + { return self->use_count ? *self->use_count : 0; } STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { _cx_self ptr = {p}; if (p) - *(ptr.use_count = c_alloc(long)) = 1; + *(ptr.use_count = c_alloc(catomic_long)) = 1; return ptr; } // c++: std::make_shared<_cx_value>(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { +STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) { _cx_self ptr; _cx_carc_rep *rep = c_alloc(_cx_carc_rep); *(ptr.use_count = &rep->counter) = 1; @@ -112,12 +115,12 @@ STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { return ptr; } +STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) // [deprecated] + { return _cx_memb(_from)(val); } + STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } -STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) - { return *self->get; } - STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { _cx_self ptr = *self; self->get = NULL, self->use_count = NULL; @@ -129,7 +132,7 @@ STC_INLINE void _cx_memb(_drop)(_cx_self* self) { i_keydrop(self->get); if ((char *)self->get != (char *)self->use_count + offsetof(_cx_carc_rep, value)) c_free(self->get); - c_free(self->use_count); + c_free((long*)self->use_count); } } @@ -144,8 +147,8 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { } #if !defined _i_no_clone && !defined _i_no_emplace - STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } + STC_INLINE _cx_self _cx_memb(_new)(_cx_raw raw) + { return _cx_memb(_from)(i_keyfrom(raw)); } #endif // !_i_no_clone // does not use i_keyclone, so OK to always define. @@ -155,7 +158,7 @@ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) { return ptr; } -STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) { +STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); _cx_memb(_drop)(self); @@ -194,6 +197,16 @@ STC_INLINE bool _cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { return i_eq((&rx), (&ry)); #endif } + +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) + { return _cx_memb(_value_hash)(x->get); } + +STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_cmp)(x->get, y->get); } + +STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_eq)(x->get, y->get); } + #undef _i_atomic_inc #undef _i_atomic_dec_and_test #include "template.h" diff --git a/include/stc/carr2.h b/include/stc/carr2.h index 66a98f58..ffedb07d 100644 --- a/include/stc/carr2.h +++ b/include/stc/carr2.h @@ -35,7 +35,7 @@ int main() { int w = 7, h = 5; - c_autovar (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image)) + c_with (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image)) { int *dat = carr2_int_data(&image); for (int i = 0; i < carr2_int_size(&image); ++i) @@ -88,14 +88,17 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y) { return self->ydim*x + y; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){*self->data}; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = self->xdim*self->ydim; + return c_make(_cx_iter){n ? *self->data : NULL, *self->data + n}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){*self->data + self->xdim*self->ydim}; } + { return c_make(_cx_iter){NULL, *self->data + self->xdim*self->ydim}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { ++it->ref; } + { if (++it->ref == it->end) it->ref = NULL; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) diff --git a/include/stc/carr3.h b/include/stc/carr3.h index 8ff1670e..07eac2a1 100644 --- a/include/stc/carr3.h +++ b/include/stc/carr3.h @@ -35,7 +35,7 @@ int main() { int w = 7, h = 5, d = 3; - c_autovar (carr3_int image = carr3_int_new_uninit(w, h, d), carr3_int_drop(&image)) + c_with (carr3_int image = carr3_int_new_uninit(w, h, d), carr3_int_drop(&image)) { int *dat = carr3_int_data(&image); for (int i = 0; i < carr3_int_size(&image); ++i) @@ -91,14 +91,17 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y, size_ return self->zdim*(self->ydim*x + y) + z; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){**self->data}; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = _cx_memb(_size)(self); + return c_make(_cx_iter){n ? **self->data : NULL, **self->data + n}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){**self->data + _cx_memb(_size)(self)}; } + { return c_make(_cx_iter){NULL, **self->data + _cx_memb(_size)(self)}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { ++it->ref; } + { if (++it->ref == it->end) it->ref = NULL; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) diff --git a/include/stc/cbits.h b/include/stc/cbits.h index 3f75226d..a1b84acd 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -27,7 +27,7 @@ Similar to boost::dynamic_bitset / std::bitset #include "cbits.h" int main() { - c_autovar (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) + c_with (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) { cbits_reset(&bset, 9); cbits_resize(&bset, 43, false); diff --git a/include/stc/cbox.h b/include/stc/cbox.h index c3a9dd02..02a73fdc 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -48,7 +48,7 @@ void Person_drop(Person* p) { int main() { c_auto (PBox, p, q) { - p = PBox_make(Person_from("John Smiths", "[email protected]")); + p = PBox_from(Person_from("John Smiths", "[email protected]")); q = PBox_clone(p); cstr_assign(&q.get->name, "Joe Smiths"); @@ -82,24 +82,24 @@ _cx_deftypes(_c_cbox_types, _cx_self, i_key); STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } -STC_INLINE long _cx_memb(_use_count)(_cx_self box) - { return (long)(box.get != NULL); } +STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) + { return (long)(self->get != NULL); } STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { return c_make(_cx_self){p}; } // c++: std::make_unique<i_key>(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { +STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) { _cx_self ptr = {c_alloc(_cx_value)}; *ptr.get = val; return ptr; } +// [deprecated] +STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) + { return _cx_memb(_from)(val); } STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } -STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) - { return *self->get; } - // destructor STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->get) { @@ -126,11 +126,11 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { self->get = p; } -#if !defined _i_no_clone #if !defined _i_no_emplace - STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } + STC_INLINE _cx_self _cx_memb(_new)(_cx_raw raw) + { return _cx_memb(_from)(i_keyfrom(raw)); } #endif +#if !defined _i_no_clone STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { if (!other.get) return other; @@ -138,13 +138,6 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { *out.get = i_keyclone(*other.get); return out; } - - STC_INLINE void _cx_memb(_assign)(_cx_self* self, const _cx_self ptr) { - if (self->get == ptr.get) - return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(ptr); - } #endif // !_i_no_clone STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self other) { @@ -179,4 +172,14 @@ STC_INLINE bool _cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { return i_eq((&rx), (&ry)); #endif } + +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) + { return _cx_memb(_value_hash)(x->get); } + +STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_cmp)(x->get, y->get); } + +STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_eq)(x->get, y->get); } + #include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index e2c63b8c..58d74ddf 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -157,16 +157,14 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, #define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__) #define c_foreach3(it, C, cnt) \ - for (C##_iter it = C##_begin(&cnt), it##_end_ = C##_end(&cnt) \ - ; it.ref != it##_end_.ref; C##_next(&it)) + for (C##_iter it = C##_begin(&cnt); it.ref; C##_next(&it)) #define c_foreach4(it, C, start, finish) \ - for (C##_iter it = start, it##_end_ = finish \ - ; it.ref != it##_end_.ref; C##_next(&it)) + for (C##_iter it = start, *_endref = (C##_iter*)(finish).ref \ + ; it.ref != (C##_value*)_endref; C##_next(&it)) #define c_forpair(key, val, C, cnt) /* structured binding */ \ - for (struct {C##_iter _it; C##_value* _endref; const C##_key* key; C##_mapped* val;} \ - _ = {C##_begin(&cnt), C##_end(&cnt).ref} \ - ; _._it.ref != _._endref && (_.key = &_._it.ref->first, _.val = &_._it.ref->second) \ + for (struct {C##_iter _it; const C##_key* key; C##_mapped* val;} _ = {C##_begin(&cnt)} \ + ; _._it.ref && (_.key = &_._it.ref->first, _.val = &_._it.ref->second) \ ; C##_next(&_._it)) #define c_forrange(...) c_MACRO_OVERLOAD(c_forrange, __VA_ARGS__) @@ -178,24 +176,28 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, for (itype i=start, _inc=step, _end=(stop) - (0 < _inc) \ ; (i <= _end) == (0 < _inc); i += _inc) -#define c_autovar(...) c_MACRO_OVERLOAD(c_autovar, __VA_ARGS__) -#define c_autovar2(declvar, drop) for (declvar, **_c_i = NULL; !_c_i; ++_c_i, drop) -#define c_autovar3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop) -#define c_autoscope(init, drop) for (int _c_i = (init, 0); !_c_i; ++_c_i, drop) -#define c_autodefer(...) for (int _c_i = 0; !_c_i; ++_c_i, __VA_ARGS__) +#define c_autovar c_with // [deprecated] +#define c_autoscope c_scope // [deprecated] +#define c_autodefer c_defer // [deprecated] + +#define c_with(...) c_MACRO_OVERLOAD(c_with, __VA_ARGS__) +#define c_with2(declvar, drop) for (declvar, **_c_i = NULL; !_c_i; ++_c_i, drop) +#define c_with3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop) +#define c_scope(init, drop) for (int _c_i = (init, 0); !_c_i; ++_c_i, drop) +#define c_defer(...) for (int _c_i = 0; !_c_i; ++_c_i, __VA_ARGS__) #define c_breakauto continue #define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) #define c_auto2(C, a) \ - c_autovar2(C a = C##_init(), C##_drop(&a)) + c_with2(C a = C##_init(), C##_drop(&a)) #define c_auto3(C, a, b) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init()), \ (C##_drop(&b), C##_drop(&a))) #define c_auto4(C, a, b, c) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init()), \ (C##_drop(&c), C##_drop(&b), C##_drop(&a))) #define c_auto5(C, a, b, c, d) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ (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) @@ -221,16 +223,19 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, #define c_pair(v) (v)->first, (v)->second #define c_drop(C, ...) do { c_forarray_p(C*, _p, {__VA_ARGS__}) C##_drop(*_p); } while(0) -#define c_find_if(C, cnt, it, pred) \ - c_find_in(C, C##_begin(&cnt), C##_end(&cnt), it, pred) +// it.ref == NULL when not found: +#define c_find_if(it, C, cnt, pred) do { \ + size_t index = 0; \ + for (it = C##_begin(&cnt); it.ref && !(pred); C##_next(&it)) \ + ++index; \ +} while (0) -// NB: it.ref == NULL when not found, not end.ref: -#define c_find_in(C, start, end, it, pred) do { \ +#define c_find_in(it, C, start, end, pred) do { \ size_t index = 0; \ - C##_iter _end = end; \ - for (it = start; it.ref != _end.ref && !(pred); C##_next(&it)) \ + const C##_value* _endref = (end).ref; \ + for (it = start; it.ref != _endref && !(pred); C##_next(&it)) \ ++index; \ - if (it.ref == _end.ref) it.ref = NULL; \ + if (it.ref == _endref) it.ref = NULL; \ } while (0) #endif // CCOMMON_H_INCLUDED diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index c5e08393..a8c880f2 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -29,6 +29,8 @@ struct cdeq_rep { size_t size, cap; unsigned base[1]; }; #define cdeq_rep_(self) c_unchecked_container_of((self)->_base, struct cdeq_rep, base) +#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref) +#define _it_ptr(it) (it.ref ? it.ref : it.end) #endif // CDEQ_H_INCLUDED #ifndef _i_prefix @@ -48,15 +50,12 @@ STC_API void _cx_memb(_clear)(_cx_self* self); STC_API void _cx_memb(_drop)(_cx_self* self); STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); + #if !defined _i_queue #if !defined _i_no_emplace -STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); +STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2); #endif // _i_no_emplace -#if !defined _i_no_clone -STC_API _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -#endif // !_i_no_clone #if !c_option(c_no_cmp) STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); @@ -64,23 +63,30 @@ STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value #endif STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); #endif // !_i_queue -#if !defined _i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); #if !defined _i_no_emplace STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } #endif -STC_INLINE i_key _cx_memb(_value_clone)(i_key val) - { return i_keyclone(val); } + +#if !defined _i_no_clone +#if !defined _i_queue +STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); + STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_memb(_clear)(self); + _cx_memb(_copy_range)(self, self->data, other->data, + other->data + cdeq_rep_(other)->size); } +#endif // !_i_queue +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +STC_INLINE i_key _cx_memb(_value_clone)(i_key val) + { return i_keyclone(val); } #endif // !_i_no_clone STC_INLINE size_t _cx_memb(_size)(const _cx_self* cx) { return cdeq_rep_(cx)->size; } STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* cx) { return cdeq_rep_(cx)->cap; } @@ -92,13 +98,6 @@ STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return self->data + cdeq_rep_(self)->size - 1; } STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _i_queue { i_keydrop(self->data); ++self->data; --cdeq_rep_(self)->size; } -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) - { return c_make(_cx_iter){self->data + cdeq_rep_(self)->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } #if !defined _i_queue @@ -117,17 +116,17 @@ STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); + return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); + return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); } STC_INLINE _cx_iter @@ -139,16 +138,25 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { + return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); } -#if !defined _i_no_clone -STC_INLINE _cx_value* -_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); + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = cdeq_rep_(self)->size; + return c_make(_cx_iter){n ? self->data : NULL, self->data + n}; } -#endif // !_i_no_clone + +STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL, self->data + cdeq_rep_(self)->size}; } + +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } + +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } + #if !defined _i_no_emplace STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) { @@ -159,13 +167,13 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); + return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); } #endif // !_i_no_emplace @@ -178,9 +186,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_raw raw) { STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - _cx_iter end = _cx_memb(_end)(self); - _cx_value* val = _cx_memb(_find_in)(_cx_memb(_begin)(self), end, raw).ref; - return val == end.ref ? NULL : val; + return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw).ref; } STC_INLINE _cx_value* @@ -188,9 +194,9 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw) { return (_cx_value *) _cx_memb(_get)(self, raw); } STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, - int(*_cmp_)(const _cx_value*, const _cx_value*)) { - qsort(i1.ref, i2.ref - i1.ref, sizeof *i1.ref, (int(*)(const void*, const void*)) _cmp_); +_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { + qsort(i1.ref, _it2_ptr(i1, i2) - i1.ref, sizeof *i1.ref, + (int(*)(const void*, const void*)) cmp); } STC_INLINE void @@ -222,6 +228,7 @@ _cx_memb(_clear)(_cx_self* self) { --q; i_keydrop(q); } rep->size = 0; + self->data = self->_base; } } @@ -231,7 +238,8 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { struct cdeq_rep* rep = cdeq_rep_(self); const size_t sz = rep->size; memmove(self->_base, self->data, sz*sizeof(i_key)); - rep = (struct cdeq_rep*) c_realloc(rep, offsetof(struct cdeq_rep, base) + sz*sizeof(i_key)); + rep = (struct cdeq_rep*) c_realloc(rep, offsetof(struct cdeq_rep, base) + + sz*sizeof(i_key)); if (rep) { self->_base = self->data = (_cx_value*)rep->base; rep->cap = sz; @@ -316,10 +324,10 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t sz = cdeq_rep_(&cx)->size; _cx_self out = _cx_memb(_with_capacity)(sz); - if (cdeq_rep_(&out)->cap) { - cdeq_rep_(&out)->size = sz; - for (size_t i = 0; i < sz; ++i) - out.data[i] = i_keyclone(cx.data[i]); + struct cdeq_rep* r = cdeq_rep_(&out); + if (r->cap) { + for (size_t i = 0; i < sz; ++i) out.data[i] = i_keyclone(cx.data[i]); + r->size = sz; } return out; } @@ -345,16 +353,21 @@ _cx_memb(_expand_left_half_)(_cx_self* self, const size_t idx, const size_t n) { } } -static _cx_value* -_cx_memb(_insert_uninit_p)(_cx_self* self, const _cx_value* pos, const size_t n) { - const size_t idx = pos - self->data; - if (idx*2 < cdeq_rep_(self)->size) - _cx_memb(_expand_left_half_)(self, idx, n); - else - _cx_memb(_expand_right_half_)(self, idx, n); - if (n) - cdeq_rep_(self)->size += n; /* do only if size > 0 */ - return self->data + idx; +static _cx_iter +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { + struct cdeq_rep* r = cdeq_rep_(self); + if (n) { + if (!pos) pos = self->data + r->size; + const size_t idx = pos - self->data; + if (idx*2 < r->size) + _cx_memb(_expand_left_half_)(self, idx, n); + else + _cx_memb(_expand_right_half_)(self, idx, n); + r = cdeq_rep_(self); + r->size += n; + pos = self->data + idx; + } + return c_make(_cx_iter){pos, self->data + r->size}; } STC_DEF _cx_value* @@ -368,62 +381,63 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { return self->data; } -STC_DEF _cx_value* -_cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, +STC_DEF _cx_iter +_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - if (pos) - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return pos; + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + memcpy(it.ref, p1, (p2 - p1)*sizeof *p1); + return it; } STC_DEF _cx_iter _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_keydrop(p); } - if (p1 == self->data) - self->data += n; - else memmove(p1, p2, (end - p2) * sizeof(i_key)); - cdeq_rep_(self)->size -= n; - } - return c_make(_cx_iter){p1}; + assert(p1 && p2); + intptr_t len = p2 - p1; + struct cdeq_rep* r = cdeq_rep_(self); + _cx_value* p = p1, *end = self->data + r->size; + for (; p != p2; ++p) + { i_keydrop(p); } + memmove(p1, p2, (end - p2) * sizeof *p1); + r->size -= len; + return c_make(_cx_iter){p2 == end ? NULL : p1, end - len}; } -#if !defined _i_no_emplace -STC_DEF _cx_value* -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyfrom((*p1)); +#if !defined _i_no_clone +STC_DEF _cx_iter +_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyclone((*p1)); return it; } -#endif // !_i_no_emplace +#endif // !_i_no_clone -#if !defined _i_no_clone -STC_DEF _cx_value* -_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyclone((*p1)); +#if !defined _i_no_emplace +STC_DEF _cx_iter +_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyfrom((*p1)); return it; } -#endif // !_i_no_clone +#endif // !_i_no_emplace #if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - for (; i1.ref != i2.ref; ++i1.ref) { - _cx_raw r = i_keyto(i1.ref); + const _cx_value* p2 = _it2_ptr(i1, i2); + for (; i1.ref != p2; ++i1.ref) { + const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) return i1; } - return i2; + i2.ref = NULL; return i2; // NB! } STC_DEF int diff --git a/include/stc/clist.h b/include/stc/clist.h index 229db32c..5b9cf0d3 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -159,9 +159,8 @@ _cx_memb(_begin)(const _cx_self* self) { } STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) { - return c_make(_cx_iter){NULL}; -} +_cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) { diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 84957e69..58774fb2 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_drop(&m)) + c_with (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m)) { cmap_ichar_emplace(&m, 5, 'a'); cmap_ichar_emplace(&m, 8, 'b'); @@ -188,12 +188,29 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { return _res; } + +STC_INLINE _cx_iter +_cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL}; } + +STC_INLINE void +_cx_memb(_next)(_cx_iter* it) { + while ((++it->ref, *++it->_hx == 0)) ; + if (it->ref == it->end) it->ref = NULL; +} + +STC_INLINE _cx_iter +_cx_memb(_advance)(_cx_iter it, size_t n) { + while (n-- && it.ref) _cx_memb(_next)(&it); + return it; +} + STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey) { i_size idx; if (!(self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx])) - idx = self->bucket_count; - return c_make(_cx_iter){self->table+idx, self->_hashx+idx}; + return _cx_memb(_end)(self); + return c_make(_cx_iter){self->table+idx, self->table+self->bucket_count, self->_hashx+idx}; } STC_INLINE const _cx_value* @@ -210,25 +227,11 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey) STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->table, self->_hashx}; + _cx_iter it = {self->table, self->table+self->bucket_count, self->_hashx}; if (it._hx) while (*it._hx == 0) ++it.ref, ++it._hx; - return it; -} - -STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){self->table + self->bucket_count}; } - -STC_INLINE void -_cx_memb(_next)(_cx_iter* it) - { while ((++it->ref, *++it->_hx == 0)) ; } - -STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { - // UB if n > elements left - while (n--) _cx_memb(_next)(&it); + if (it.ref == it.end) it.ref = NULL; return it; } diff --git a/include/stc/cpque.h b/include/stc/cpque.h index bb7c207e..79d12b95 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -110,9 +110,9 @@ STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) STC_DEF void _cx_memb(_sift_down_)(_cx_value* arr, const size_t idx, const size_t n) { - for (size_t r = idx, c = idx << 1; c <= n; c <<= 1) { - c += (c < n && (i_cmp((&arr[c]), (&arr[c + 1]))) < 0); - if ((i_cmp((&arr[r]), (&arr[c]))) >= 0) return; + for (size_t r = idx, c = idx*2; c <= n; c *= 2) { + c += (c < n && (i_less((&arr[c]), (&arr[c + 1])))); + if (!(i_less((&arr[r]), (&arr[c])))) return; _cx_value t = arr[r]; arr[r] = arr[c]; arr[r = c] = t; } } @@ -121,7 +121,7 @@ STC_DEF void _cx_memb(_make_heap)(_cx_self* self) { size_t n = self->size; _cx_value *arr = self->data - 1; - for (size_t k = n >> 1; k != 0; --k) + for (size_t k = n/2; k != 0; --k) _cx_memb(_sift_down_)(arr, k, n); } @@ -148,8 +148,8 @@ _cx_memb(_push)(_cx_self* self, _cx_value value) { _cx_memb(_reserve)(self, self->size*3/2 + 4); _cx_value *arr = self->data - 1; /* base 1 */ size_t c = ++self->size; - for (; c > 1 && (i_cmp((&arr[c >> 1]), (&value))) < 0; c >>= 1) - arr[c] = arr[c >> 1]; + for (; c > 1 && (i_less((&arr[c/2]), (&value))); c /= 2) + arr[c] = arr[c/2]; arr[c] = value; } diff --git a/include/stc/cregex.h b/include/stc/cregex.h index d19d518f..4812bff2 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -76,8 +76,9 @@ typedef struct { csview ref[cre_MAXCAPTURES]; } cregex_iter; -#define c_foreach_match(i, _re, _input) \ - for (cregex_iter i = {_re, _input}; cregex_find(i.input, i.re, i.ref, cre_m_next) == cre_success;) +#define c_foreach_match(it, Re, Input) \ + for (cregex_iter it = {Re, Input}; \ + cregex_find(it.input, it.re, it.ref, cre_m_next) == cre_success;) static inline cregex cregex_init(void) { diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 97f1fce1..c773e70f 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_drop(&m)) + c_with (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); diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 46d209ca..e1839d37 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -169,15 +169,18 @@ STC_INLINE i_keyraw _cx_memb(_value_toraw)(const _cx_value* val) { return i_keyto(val); } #endif // !_i_no_clone -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){(_cx_value*)self->data}; } +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + return c_make(_cx_iter){self->size ? (_cx_value*)self->data : NULL, + (_cx_value*)self->data + self->size}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){(_cx_value*)self->data + self->size}; } + { return c_make(_cx_iter){NULL, (_cx_value*)self->data + self->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL ; return it; } #include "template.h" diff --git a/include/stc/cstr.h b/include/stc/cstr.h index aae52ea0..99b60e49 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -80,7 +80,7 @@ STC_API char* _cstr_internal_move(cstr* self, size_t pos1, size_t pos2); STC_API char* cstr_reserve(cstr* self, size_t cap); STC_API void cstr_shrink_to_fit(cstr* self); STC_API void cstr_resize(cstr* self, size_t size, char value); -STC_API size_t cstr_find_at(cstr s, size_t pos, const char* search); +STC_API size_t cstr_find_at(const cstr* self, size_t pos, const char* search); STC_API char* cstr_assign_n(cstr* self, const char* str, size_t len); STC_API char* cstr_append_n(cstr* self, const char* str, size_t len); STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); @@ -161,14 +161,14 @@ STC_INLINE char* cstr_data(cstr* self) STC_INLINE const char* cstr_str(const cstr* self) { return SSO_CALL(self, data(self)); } -STC_INLINE bool cstr_empty(cstr s) - { return s.sml.last == cstr_s_cap; } +STC_INLINE bool cstr_empty(const cstr* self) + { return self->sml.last == cstr_s_cap; } -STC_INLINE size_t cstr_size(cstr s) - { return SSO_CALL(&s, size(&s)); } +STC_INLINE size_t cstr_size(const cstr* self) + { return SSO_CALL(self, size(self)); } -STC_INLINE size_t cstr_capacity(cstr s) - { return cstr_is_long(&s) ? cstr_l_cap(&s) : cstr_s_cap; } +STC_INLINE size_t cstr_capacity(const cstr* self) + { return cstr_is_long(self) ? cstr_l_cap(self) : cstr_s_cap; } // utf8 methods defined in/depending on src/utf8code.c: @@ -200,11 +200,11 @@ STC_INLINE bool cstr_valid_utf8(const cstr* self) // other utf8 -STC_INLINE size_t cstr_u8_size(cstr s) - { return utf8_size(cstr_str(&s)); } +STC_INLINE size_t cstr_u8_size(const cstr* self) + { return utf8_size(cstr_str(self)); } -STC_INLINE size_t cstr_u8_size_n(cstr s, size_t nbytes) - { return utf8_size_n(cstr_str(&s), nbytes); } +STC_INLINE size_t cstr_u8_size_n(const cstr* self, size_t nbytes) + { return utf8_size_n(cstr_str(self), nbytes); } STC_INLINE size_t cstr_u8_to_pos(const cstr* self, size_t u8idx) { return utf8_pos(cstr_str(self), u8idx); } @@ -223,16 +223,18 @@ STC_INLINE csview cstr_u8_chr(const cstr* self, size_t u8idx) { // utf8 iterator STC_INLINE cstr_iter cstr_begin(const cstr* self) { - const char* str = cstr_str(self); - return c_make(cstr_iter){.chr = {str, utf8_chr_size(str)}}; + csview sv = cstr_sv(self); + if (!sv.size) return c_make(cstr_iter){NULL}; + return c_make(cstr_iter){.u8 = {{sv.str, utf8_chr_size(sv.str)}, sv.str + sv.size}}; } STC_INLINE cstr_iter cstr_end(const cstr* self) { csview sv = cstr_sv(self); - return c_make(cstr_iter){sv.str + sv.size}; + return c_make(cstr_iter){.u8 = {{NULL}, sv.str + sv.size}}; } STC_INLINE void cstr_next(cstr_iter* it) { - it->ref += it->chr.size; - it->chr.size = utf8_chr_size(it->ref); + it->ref += it->u8.chr.size; + it->u8.chr.size = utf8_chr_size(it->ref); + if (it->ref == it->u8.end) it->ref = NULL; } @@ -240,7 +242,7 @@ STC_INLINE void cstr_clear(cstr* self) { _cstr_set_size(self, 0); } STC_INLINE char* cstr_append_uninit(cstr *self, size_t len) { - size_t sz = cstr_size(*self); + size_t sz = cstr_size(self); char* d = cstr_reserve(self, sz + len); if (!d) return NULL; _cstr_set_size(self, sz + len); @@ -259,75 +261,75 @@ STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { } -STC_INLINE bool cstr_equals(cstr s1, const char* str) - { return !strcmp(cstr_str(&s1), str); } +STC_INLINE bool cstr_equals(const cstr* self, const char* str) + { return !strcmp(cstr_str(self), str); } -STC_INLINE bool cstr_equals_sv(cstr s, csview sv) - { return sv.size == cstr_size(s) && !memcmp(cstr_str(&s), sv.str, sv.size); } +STC_INLINE bool cstr_equals_sv(const cstr* self, csview sv) + { return sv.size == cstr_size(self) && !memcmp(cstr_str(self), sv.str, sv.size); } -STC_INLINE bool cstr_equals_s(cstr s1, cstr s2) - { return !cstr_cmp(&s1, &s2); } +STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) + { return !cstr_cmp(self, &s); } -STC_INLINE bool cstr_iequals(cstr s1, const char* str) - { return !utf8_icmp(cstr_str(&s1), str); } +STC_INLINE bool cstr_iequals(const cstr* self, const char* str) + { return !utf8_icmp(cstr_str(self), str); } -STC_INLINE size_t cstr_find(cstr s, const char* search) { - const char *str = cstr_str(&s), *res = strstr((char*)str, search); +STC_INLINE size_t cstr_find(const cstr* self, const char* search) { + const char *str = cstr_str(self), *res = strstr((char*)str, search); return res ? res - str : cstr_npos; } -STC_API size_t cstr_find_sv(cstr s, csview search); +STC_API size_t cstr_find_sv(const cstr* self, csview search); -STC_INLINE size_t cstr_find_s(cstr s, cstr search) - { return cstr_find(s, cstr_str(&search)); } +STC_INLINE size_t cstr_find_s(const cstr* self, cstr search) + { return cstr_find(self, cstr_str(&search)); } -STC_INLINE bool cstr_contains(cstr s, const char* search) - { return strstr(cstr_data(&s), search) != NULL; } +STC_INLINE bool cstr_contains(const cstr* self, const char* search) + { return strstr((char*)cstr_str(self), search) != NULL; } -STC_INLINE bool cstr_contains_sv(cstr s, csview search) - { return cstr_find_sv(s, search) != cstr_npos; } +STC_INLINE bool cstr_contains_sv(const cstr* self, csview search) + { return cstr_find_sv(self, search) != cstr_npos; } -STC_INLINE bool cstr_contains_s(cstr s, cstr search) - { return strstr(cstr_data(&s), cstr_str(&search)) != NULL; } +STC_INLINE bool cstr_contains_s(const cstr* self, cstr search) + { return strstr((char*)cstr_str(self), cstr_str(&search)) != NULL; } -STC_INLINE bool cstr_starts_with_sv(cstr s, csview sub) { - if (sub.size > cstr_size(s)) return false; - return !memcmp(cstr_str(&s), sub.str, sub.size); +STC_INLINE bool cstr_starts_with_sv(const cstr* self, csview sub) { + if (sub.size > cstr_size(self)) return false; + return !memcmp(cstr_str(self), sub.str, sub.size); } -STC_INLINE bool cstr_starts_with(cstr s, const char* sub) { - const char* str = cstr_str(&s); +STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { + const char* str = cstr_str(self); while (*sub && *str == *sub) ++str, ++sub; return !*sub; } -STC_INLINE bool cstr_starts_with_s(cstr s, cstr sub) - { return cstr_starts_with_sv(s, cstr_sv(&sub)); } +STC_INLINE bool cstr_starts_with_s(const cstr* self, cstr sub) + { return cstr_starts_with_sv(self, cstr_sv(&sub)); } -STC_INLINE bool cstr_istarts_with(cstr s, const char* sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_istarts_with(const cstr* self, const char* sub) { + csview sv = cstr_sv(self); size_t len = strlen(sub); return len <= sv.size && !utf8_icmp_sv(sv, c_sv(sub, len)); } -STC_INLINE bool cstr_ends_with_sv(cstr s, csview sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_ends_with_sv(const cstr* self, csview sub) { + csview sv = cstr_sv(self); if (sub.size > sv.size) return false; return !memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); } -STC_INLINE bool cstr_ends_with_s(cstr s, cstr sub) - { return cstr_ends_with_sv(s, cstr_sv(&sub)); } +STC_INLINE bool cstr_ends_with_s(const cstr* self, cstr sub) + { return cstr_ends_with_sv(self, cstr_sv(&sub)); } -STC_INLINE bool cstr_ends_with(cstr s, const char* sub) - { return cstr_ends_with_sv(s, c_sv(sub, strlen(sub))); } +STC_INLINE bool cstr_ends_with(const cstr* self, const char* sub) + { return cstr_ends_with_sv(self, c_sv(sub, strlen(sub))); } -STC_INLINE bool cstr_iends_with(cstr s, const char* sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_iends_with(const cstr* self, const char* sub) { + csview sv = cstr_sv(self); size_t n = strlen(sub); return n <= sv.size && !utf8_icmp(sv.str + sv.size - n, sub); } @@ -368,11 +370,8 @@ STC_INLINE void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* STC_INLINE void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl) { cstr_replace_at_sv(self, pos, len, cstr_sv(&repl)); } -STC_INLINE void cstr_u8_replace_at(cstr* self, size_t u8pos, size_t u8len, csview repl) { - csview sv = cstr_sv(self); - const char* p = utf8_at(sv.str, u8pos); - cstr_replace_at_sv(self, p - sv.str, utf8_pos(p, u8len), repl); -} +STC_INLINE void cstr_u8_replace(cstr* self, size_t pos, size_t u8len, csview repl) + { cstr_replace_at_sv(self, pos, utf8_pos(cstr_str(self) + pos, u8len), repl); } STC_INLINE void cstr_insert(cstr* self, size_t pos, const char* str) @@ -400,9 +399,9 @@ STC_DEF uint64_t cstr_hash(const cstr *self) { return c_fasthash(sv.str, sv.size); } -STC_DEF size_t cstr_find_sv(cstr s, csview search) { - char* res = c_strnstrn(cstr_str(&s), search.str, cstr_size(s), search.size); - return res ? res - cstr_str(&s) : cstr_npos; +STC_DEF size_t cstr_find_sv(const cstr* self, csview search) { + char* res = c_strnstrn(cstr_str(self), search.str, cstr_size(self), search.size); + return res ? res - cstr_str(self) : cstr_npos; } STC_DEF char* _cstr_internal_move(cstr* self, const size_t pos1, const size_t pos2) { @@ -472,8 +471,8 @@ STC_DEF void cstr_resize(cstr* self, const size_t size, const char value) { _cstr_set_size(self, size); } -STC_DEF size_t cstr_find_at(cstr s, const size_t pos, const char* search) { - csview sv = cstr_sv(&s); +STC_DEF size_t cstr_find_at(const cstr* self, const size_t pos, const char* search) { + csview sv = cstr_sv(self); if (pos > sv.size) return cstr_npos; const char* res = strstr((char*)sv.str + pos, search); return res ? res - sv.str : cstr_npos; diff --git a/include/stc/csview.h b/include/stc/csview.h index 2efeff5b..dbff8620 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -69,15 +69,22 @@ STC_INLINE csview csview_slice(csview sv, size_t p1, size_t p2) { return sv; } -/* iterator */ -STC_INLINE csview_iter csview_begin(const csview* self) - { return c_make(csview_iter){.chr = {self->str, utf8_chr_size(self->str)}}; } +/* utf8 iterator */ +STC_INLINE csview_iter csview_begin(const csview* self) { + if (!self->size) return c_make(csview_iter){NULL}; + return c_make(csview_iter){.u8 = {{self->str, utf8_chr_size(self->str)}, + self->str + self->size}}; +} + +STC_INLINE csview_iter csview_end(const csview* self) + { return c_make(csview_iter){.u8 = {{NULL}, self->str + self->size}}; } -STC_INLINE csview_iter csview_end(const csview* self) - { return c_make(csview_iter){self->str + self->size}; } +STC_INLINE void csview_next(csview_iter* it) { + it->ref += it->u8.chr.size; + it->u8.chr.size = utf8_chr_size(it->ref); + if (it->ref == it->u8.end) it->ref = NULL; +} -STC_INLINE void csview_next(csview_iter* it) - { it->ref += it->chr.size; it->chr.size = utf8_chr_size(it->ref); } /* utf8 */ STC_INLINE size_t csview_u8_size(csview sv) diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 81678293..6b120ff0 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -66,6 +66,8 @@ int main() { struct cvec_rep { size_t size, cap; unsigned data[1]; }; #define cvec_rep_(self) c_unchecked_container_of((self)->data, struct cvec_rep, data) +#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref) +#define _it_ptr(it) (it.ref ? it.ref : it.end) #endif // CVEC_H_INCLUDED #ifndef _i_prefix @@ -84,9 +86,9 @@ 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_key null); STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_uninit_p)(_cx_self* self, _cx_value* pos, const size_t n); +STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n); #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, _cx_raw raw); @@ -94,37 +96,34 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, #endif #if !defined _i_no_emplace -STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); +STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2); STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); + return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); } #endif // !_i_no_emplace #if !defined _i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_API _cx_value* _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(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) { return i_keyclone(val); } STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_memb(_clear)(self); + _cx_memb(_copy_range)(self, self->data, other->data, + other->data + cvec_rep_(other)->size); } -STC_INLINE _cx_value* -_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 // !_i_no_clone STC_INLINE size_t _cx_memb(_size)(const _cx_self* cx) { return cvec_rep_(cx)->size; } @@ -140,14 +139,6 @@ STC_INLINE void _cx_memb(_pop)(_cx_self* self) STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_memb(_pop)(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) - { return c_make(_cx_iter){self->data + cvec_rep_(self)->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } -STC_INLINE size_t _cx_memb(_index)(const _cx_self* cx, _cx_iter it) { return it.ref - cx->data; } STC_INLINE _cx_self _cx_memb(_with_size)(const size_t size, i_key null) { @@ -168,22 +159,18 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, _cx_memb(_size)(self)); } -STC_INLINE _cx_value* -_cx_memb(_append_uninit)(_cx_self* self, const size_t n) { - return _cx_memb(_insert_uninit_p)(self, self->data + _cx_memb(_size)(self), n); -} -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); + return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); + return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); } STC_INLINE _cx_iter @@ -195,8 +182,8 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { + return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); } STC_INLINE const _cx_value* @@ -208,6 +195,24 @@ _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { assert(idx < cvec_rep_(self)->size); return self->data + idx; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = cvec_rep_(self)->size; + return c_make(_cx_iter){n ? self->data : NULL, self->data + n}; +} + +STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL, self->data + cvec_rep_(self)->size}; } + +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } + +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } + +STC_INLINE size_t _cx_memb(_index)(const _cx_self* cx, _cx_iter it) + { return it.ref - cx->data; } + #if !c_option(c_no_cmp) STC_INLINE _cx_iter @@ -217,9 +222,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_raw raw) { STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - _cx_iter end = _cx_memb(_end)(self); - _cx_value* val = _cx_memb(_find)(self, raw).ref; - return val == end.ref ? NULL : val; + return _cx_memb(_find)(self, raw).ref; } STC_INLINE _cx_value* @@ -240,10 +243,11 @@ _cx_memb(_lower_bound)(const _cx_self* self, _cx_raw raw) { } STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, - int(*_cmp_)(const _cx_value*, const _cx_value*)) { - qsort(i1.ref, i2.ref - i1.ref, sizeof(_cx_value), (int(*)(const void*, const void*)) _cmp_); +_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { + qsort(i1.ref, _it2_ptr(i1, i2) - i1.ref, sizeof(_cx_value), + (int(*)(const void*, const void*)) cmp); } + STC_INLINE void _cx_memb(_sort)(_cx_self* self) { _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); @@ -289,7 +293,8 @@ _cx_memb(_reserve)(_cx_self* self, const size_t cap) { const size_t len = rep->size; 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_key)); + offsetof(struct cvec_rep, data) + + cap*sizeof(i_key)); if (!rep) return false; self->data = (_cx_value*) rep->data; @@ -325,103 +330,106 @@ _cx_memb(_push)(_cx_self* self, i_key value) { *v = value; return v; } -STC_DEF _cx_value* -_cx_memb(_insert_uninit_p)(_cx_self* self, _cx_value* pos, const size_t n) { - const size_t idx = pos - self->data; +STC_DEF _cx_iter +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { struct cvec_rep* r = cvec_rep_(self); - if (!n) - return pos; - if (r->size + n > r->cap) { - if (!_cx_memb(_reserve)(self, r->size*3/2 + n)) - return NULL; - r = cvec_rep_(self); - pos = self->data + idx; + if (n) { + if (!pos) pos = self->data + r->size; + const size_t idx = pos - self->data; + if (r->size + n > r->cap) { + if (!_cx_memb(_reserve)(self, r->size*3/2 + n)) + return _cx_memb(_end)(self); + r = cvec_rep_(self); + pos = self->data + idx; + } + memmove(pos + n, pos, (r->size - idx)*sizeof *pos); + r->size += n; } - memmove(pos + n, pos, (r->size - idx)*sizeof *pos); - r->size += n; - return pos; + return c_make(_cx_iter){pos, self->data + r->size}; } -STC_DEF _cx_value* -_cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - if (pos) - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return pos; +STC_DEF _cx_iter +_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + memcpy(it.ref, p1, (p2 - p1)*sizeof *p1); + return it; } STC_DEF _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { + assert(p1 && 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_keydrop(p); } - memmove(p1, p2, (end - p2) * sizeof(i_key)); - cvec_rep_(self)->size -= len; - } - return c_make(_cx_iter){.ref = p1}; + struct cvec_rep* r = cvec_rep_(self); + _cx_value* p = p1, *end = self->data + r->size; + for (; p != p2; ++p) + { i_keydrop(p); } + memmove(p1, p2, (end - p2) * sizeof *p1); + r->size -= len; + return c_make(_cx_iter){p2 == end ? NULL : p1, end - len}; } #if !defined _i_no_clone STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t len = cvec_rep_(&cx)->size; - _cx_self out = _cx_memb(_with_capacity)(len); - if (cvec_rep_(&out)->cap) - _cx_memb(_clone_range_p)(&out, out.data, cx.data, cx.data + len); + _cx_self out = _cx_memb(_init)(); + _cx_memb(_copy_range)(&out, out.data, cx.data, cx.data + len); return out; } -STC_DEF _cx_value* -_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyclone((*p1)); +STC_DEF _cx_iter +_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyclone((*p1)); return it; } +#endif // !_i_no_clone #if !defined _i_no_emplace -STC_DEF _cx_value* -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyfrom((*p1)); +STC_DEF _cx_iter +_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyfrom((*p1)); return it; } #endif // !_i_no_emplace -#endif // !_i_no_clone #if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - for (; i1.ref != i2.ref; ++i1.ref) { + const _cx_value* p2 = _it2_ptr(i1, i2); + for (; i1.ref != p2; ++i1.ref) { const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) return i1; } - return i2; + i2.ref = NULL; return i2; // NB! } STC_DEF _cx_iter -_cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, _cx_iter* lower_bound) { - _cx_iter mid, last = i2; - while (i1.ref != i2.ref) { - mid.ref = i1.ref + (i2.ref - i1.ref)/2; +_cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, + _cx_iter* lower_bound) { + const _cx_value* p2 = _it2_ptr(i1, i2); + _cx_iter mid = i1; + while (i1.ref != p2) { + mid.ref = i1.ref + (p2 - i1.ref)/2; const _cx_raw m = i_keyto(mid.ref); const int c = i_cmp((&raw), (&m)); if (!c) return *lower_bound = mid; - else if (c < 0) i2.ref = mid.ref; + else if (c < 0) p2 = mid.ref; else i1.ref = mid.ref + 1; } - *lower_bound = i1; - return last; + *lower_bound = i1.ref == i2.end ? i2 : i1; + i2.ref = NULL; return i2; // NB! } STC_DEF int diff --git a/include/stc/forward.h b/include/stc/forward.h index 04566b98..264d6939 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -57,7 +57,7 @@ typedef struct { const char* str; size_t size; } csview; typedef char csview_value; typedef union { const char *ref; - csview chr; + struct { csview chr; const char *end; } u8; } csview_iter, cstr_iter; #define c_true(...) __VA_ARGS__ @@ -68,17 +68,17 @@ typedef union { \ typedef struct { \ SELF##_value* get; \ - long* use_count; \ + catomic_long* use_count; \ } SELF #define _c_carr2_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value **data; size_t xdim, ydim; } SELF #define _c_carr3_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value ***data; size_t xdim, ydim, zdim; } SELF #define _c_cbox_types(SELF, VAL) \ @@ -89,7 +89,7 @@ typedef union { #define _c_cdeq_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct {SELF##_value *ref; } SELF##_iter; \ + typedef struct {SELF##_value *ref, *end; } SELF##_iter; \ typedef struct {SELF##_value *_base, *data;} SELF #define _c_clist_types(SELF, VAL) \ @@ -120,7 +120,7 @@ typedef union { } SELF##_result; \ \ typedef struct { \ - SELF##_value *ref; \ + SELF##_value *ref, *end; \ uint8_t* _hx; \ } SELF##_iter; \ \ @@ -186,7 +186,7 @@ typedef union { #endif #define _c_cstack_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct SELF { \ SELF##_value* data; \ size_t size, capacity; \ @@ -194,7 +194,7 @@ typedef union { #define _c_cstack_fixed(SELF, VAL, CAP) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct SELF { \ SELF##_value data[CAP]; \ size_t size; \ @@ -209,7 +209,7 @@ typedef union { #define _c_cvec_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value *data; } SELF #endif // STC_FORWARD_H_INCLUDED diff --git a/include/stc/template.h b/include/stc/template.h index cb0c7ef2..4597e02c 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -110,7 +110,8 @@ #elif defined i_key_arcbox #define i_key_bind i_key_arcbox #define i_keyraw c_paste(i_key_arcbox, _value) - #define i_keyto c_paste(i_key_arcbox, _toval) + #define i_keyfrom c_paste(i_key_arcbox, _from) + #define i_keyto(x) *(x)->get #define i_eq c_paste(i_key_arcbox, _value_eq) #endif @@ -167,7 +168,7 @@ #define i_keydrop c_default_drop #endif -// i_eq, i_less, i_cmp, i_hash +// i_eq, i_less, i_cmp #if !defined i_eq && (defined i_cmp || defined i_less) #define i_eq(x, y) !(i_cmp(x, y)) #elif !defined i_eq @@ -175,10 +176,13 @@ #endif #if !defined i_less && !defined i_cmp #define i_less c_default_less +#elif !defined i_less + #define i_less(x, y) (i_cmp(x, y)) < 0 #endif #ifndef i_cmp #define i_cmp(x, y) (i_less(y, x)) - (i_less(x, y)) #endif + #ifndef i_hash #define i_hash c_default_hash #endif @@ -197,7 +201,8 @@ #elif defined i_val_arcbox #define i_val_bind i_val_arcbox #define i_valraw c_paste(i_val_arcbox, _value) - #define i_valto c_paste(i_val_arcbox, _toval) + #define i_valfrom c_paste(i_val_arcbox, _from) + #define i_valto(x) *(x)->get #endif #ifdef i_val_bind @@ -213,6 +218,9 @@ #endif #endif +#ifndef i_val + #error "i_val* must be defined for maps" +#endif #if defined i_valraw ^ defined i_valto #error "both i_valto and i_valraw must be defined, if any" #elif defined i_valfrom && !defined i_valraw diff --git a/src/checkauto.l b/src/checkauto.l index 5b4a9c68..384b3855 100644 --- a/src/checkauto.l +++ b/src/checkauto.l @@ -38,6 +38,9 @@ for | while | switch { block_type |= LOOP; state = BRACES; } do { block_type |= LOOP; state = BRACESDONE; } +c_with | +c_scope | +c_defer | c_autovar | c_autoscope | c_autodefer | diff --git a/src/cregex.c b/src/cregex.c index 690c9ad5..46d4d323 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -532,7 +532,7 @@ optimize(Parser *par, Reprog *pp) */ uintptr_t ipp = (uintptr_t)pp; size_t size = sizeof(Reprog) + (par->freep - pp->firstinst)*sizeof(Reinst); - Reprog *npp = (Reprog *)realloc(pp, size); + Reprog *npp = (Reprog *)c_realloc(pp, size); ptrdiff_t diff = (uintptr_t)npp - ipp; if ((npp == NULL) | (diff == 0)) @@ -798,10 +798,10 @@ regcomp1(Reprog *progp, Parser *par, const char *s, int cflags) /* get memory for the program. estimated max usage */ const int instcap = 5 + 6*strlen(s); - Reprog* pp = (Reprog *)realloc(progp, sizeof(Reprog) + instcap*sizeof(Reinst)); + Reprog* pp = (Reprog *)c_realloc(progp, sizeof(Reprog) + instcap*sizeof(Reinst)); if (pp == NULL) { par->error = cre_outofmemory; - free(progp); + c_free(progp); return NULL; } pp->flags.caseless = (cflags & cre_c_caseless) != 0; @@ -861,7 +861,7 @@ regcomp1(Reprog *progp, Parser *par, const char *s, int cflags) #endif out: if (par->error) { - free(pp); + c_free(pp); pp = NULL; } return pp; @@ -1090,7 +1090,7 @@ regexec2(const Reprog *progp, /* program to run */ Relist *relists; /* mark space */ - relists = (Relist *)malloc(2 * BIGLISTSIZE*sizeof(Relist)); + relists = (Relist *)c_malloc(2 * BIGLISTSIZE*sizeof(Relist)); if (relists == NULL) return -1; @@ -1100,7 +1100,7 @@ regexec2(const Reprog *progp, /* program to run */ j->reliste[1] = relists + 2*BIGLISTSIZE - 2; rv = regexec1(progp, bol, mp, ms, j, mflags); - free(relists); + c_free(relists); return rv; } @@ -1265,5 +1265,5 @@ cregex_replace_pe(const char* input, const char* pattern, const char* replace, u void cregex_drop(cregex* self) { - free(self->prog); + c_free(self->prog); } |
