diff options
| author | Tyge Løvset <[email protected]> | 2023-02-04 23:35:56 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-02-04 23:35:56 +0100 |
| commit | adc47cefc2976768c3f0b773bd26bfd1062e8a53 (patch) | |
| tree | 4923f88afb0d091d5d39ae03d65a4998a0517652 | |
| parent | 0c4c4f8bba17562735b67b2923cd23c773aa53a7 (diff) | |
| parent | d2ff84c53aa9bd3857fdf22dcf7cd9398a4780be (diff) | |
| download | STC-modified-adc47cefc2976768c3f0b773bd26bfd1062e8a53.tar.gz STC-modified-adc47cefc2976768c3f0b773bd26bfd1062e8a53.zip | |
Merge pull request #46 from tylov/newinit
Version 4.1 RC2: signed sizes and indices, cspan with numpy slicing.
101 files changed, 3088 insertions, 2731 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f54a7f2..9369a070 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,10 +16,10 @@ if(BUILD_TESTING) foreach(file IN LISTS misc/examples) get_filename_component(name "${file}" NAME_WE) add_executable(${name} ${file}) - target_compile_options(${name} PRIVATE "-pthread") - if(CMAKE_THREAD_LIBS_INIT) - target_link_libraries(${name} PRIVATE "${CMAKE_THREAD_LIBS_INIT}") - endif() + target_compile_options(${name} PRIVATE "-pthread") + if(CMAKE_THREAD_LIBS_INIT) + target_link_libraries(${name} PRIVATE "${CMAKE_THREAD_LIBS_INIT}") + endif() target_link_libraries(${name} PRIVATE stc m) add_test(NAME ${name} COMMAND ${name}) endforeach() @@ -3,17 +3,22 @@ STC - Smart Template Containers for C ===================================== -News: Version 4.1 Beta (Dec 2022) +News: Version 4.1 RC2 (Feb 2023) ------------------------------------------------ -- Major change is uppercase macros in ccommon.h. Lowercase macros are [still supported](include/stc/priv/lowcase.h). +Major changes: +- Signed sizes and indices for all containers (no more mixing unsigned/signed bugs). +- A new exciting [**cspan**](docs/cspan_api.md) single/multi-dimensional array view (with numpy-like slicing). +- Updates on cregex with several new unicode character classes. +- Uppercase flow-control macros (ccommon.h). Lowercase macros are [still supported](include/stc/priv/altnames.h). +- Some API changes in cregex and cstr. - [See detailed changes for version 4](#version-4). 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 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. +The API has similarities with c++ STL, but is more uniform across the containers and takes 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 without the need for boilerplate code. You may specify element-cloning, -comparison, -destruction and @@ -53,30 +58,32 @@ Others Highlights ---------- +- **No boilerplate** - With STC, no boilerplate code is needed to setup containers either with simple built-in types or containers with complex element types, which requires cleanup. Only specify what is needed, e.g. compare-, clone-, drop- functions, and leave the rest as defaults. +- **Fully type safe** - Because of templating, it avoids error-prone casting of container types and elements back and forth from the containers. - **User friendly** - Just include the headers and you are good. The API and functionality is very close to c++ STL, and is fully listed in the docs. - **Templates** - Use `#define i_{arg}` to specify container template arguments. There are templates for element-*type*, -*comparison*, -*destruction*, -*cloning*, -*conversion types*, and more. - **Unparalleled performance** - Some containers are much faster than the c++ STL containers, the rest are about equal in speed. -- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, shared pointers are supported and can be stored in containers, see ***carc***. -- **Fully type safe** - Because of templating, it avoids error-prone casting of container types and elements back and forth from the containers. +- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, smart pointers are supported and can be stored in containers, see ***carc*** and ***cbox***. - **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 -s on linux. +- **No unsigned mess** - Unsigned sizes and indices mixed with signed calculations is asking for trouble. STC now uses only signed numbers in the API. (Small caveat on 32-bit platforms: containers no longer support 2.1 - 4.2 billion elements). +- **Small footprint** - Small source code and generated executables. The executable from the example below using ***six different*** container types is only ***19 Kb in size*** compiled with gcc -O3 -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). -- **Container prefix and forward declaration** - Templated containers may have user defined prefix, e.g. myvec_push_back(). They may also be forward declared without including the full API/implementation. See documentation below. +- **Forward declaration** - Templated containers may be forward declared without including the full API/implementation. See documentation below. Three standout features of STC 1. ***Centralized analysis of template arguments***. Assigns good defaults to non-specified templates. You may specify a number of "standard" template arguments for each container, but as minimum only one is 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. +additional template arguments should be defined. 2. ***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*` 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 -is convenient in C. The alternative lookup type may also be used for adding entries into containers by using -the *emplace*-functions. E.g. `MyCStrVec_emplace_back(&vec, "Hello")`, which further simplifies usage of STC. +is convenient in C. A great ergonomic feature is that the alternative lookup type can also be used for adding +entries into containers through using the *emplace*-functions. E.g. `MyCStrVec_emplace_back(&vec, "Hello")`. 3. ***Standardized container iterators***. All container can be iterated the same way, and uses the same element access syntax. E.g. `c_FOREACH (it, IntContainer, container) printf(" %d", *it.ref);` will work for every type of container defined as `IntContainer` with `int` elements. Also the form `c_FOREACH (it, IntContainer, it1, it2)` @@ -112,7 +119,7 @@ int main(void) FVec_push_back(&vec, 20.f); FVec_push_back(&vec, 30.f); - for (size_t i = 0; i < FVec_size(vec); ++i) + for (intptr_t i = 0; i < FVec_size(vec); ++i) printf(" %g", vec.data[i]); FVec_drop(&vec); // cleanup memory diff --git a/docs/cbits_api.md b/docs/cbits_api.md index b21611df..60586a5b 100644 --- a/docs/cbits_api.md +++ b/docs/cbits_api.md @@ -19,40 +19,40 @@ All cbits definitions and prototypes are available by including a single header ## Methods ```c -cbits cbits_init(void); -cbits cbits_from(const char* str); -cbits cbits_with_size(size_t size, bool value); // size must be <= N if N is defined -cbits cbits_with_pattern(size_t size, uint64_t pattern); -cbits cbits_clone(cbits other); - -void cbits_clear(cbits* self); -cbits* cbits_copy(cbits* self, const cbits* other); -void cbits_resize(cbits* self, size_t size, bool value); // only if i_len is not defined -void cbits_drop(cbits* self); - -cbits* cbits_take(cbits* self, const cbits* other); // give other to self -cbits cbits_move(cbits* self); // transfer self to caller - -size_t cbits_size(const cbits* self); -size_t cbits_count(const cbits* self); // count number of bits set - -bool cbits_test(const cbits* self, size_t i); -bool cbits_at(const cbits* self, size_t i); // same as cbits_test() -bool cbits_subset_of(const cbits* self, const cbits* other); // is set a subset of other? -bool cbits_disjoint(const cbits* self, const cbits* other); // no common bits -char* cbits_to_str(const cbits* self, char* str, size_t start, size_t stop); - -void cbits_set(cbits* self, size_t i); -void cbits_reset(cbits* self, size_t i); -void cbits_set_value(cbits* self, size_t i, bool value); -void cbits_set_all(cbits* self, bool value); -void cbits_set_pattern(cbits* self, uint64_t pattern); -void cbits_flip_all(cbits* self); -void cbits_flip(cbits* self, size_t i); - -void cbits_intersect(cbits* self, const cbits* other); -void cbits_union(cbits* self, const cbits* other); -void cbits_xor(cbits* self, const cbits* other); // set of disjoint bits +cbits cbits_init(void); +cbits cbits_from(const char* str); +cbits cbits_with_size(intptr_t size, bool value); // size must be <= N if N is defined +cbits cbits_with_pattern(intptr_t size, uint64_t pattern); +cbits cbits_clone(cbits other); + +void cbits_clear(cbits* self); +cbits* cbits_copy(cbits* self, const cbits* other); +void cbits_resize(cbits* self, intptr_t size, bool value); // only if i_len is not defined +void cbits_drop(cbits* self); + +cbits* cbits_take(cbits* self, const cbits* other); // give other to self +cbits cbits_move(cbits* self); // transfer self to caller + +intptr_t cbits_size(const cbits* self); +intptr_t cbits_count(const cbits* self); // count number of bits set + +bool cbits_test(const cbits* self, intptr_t i); +bool cbits_at(const cbits* self, intptr_t i); // same as cbits_test() +bool cbits_subset_of(const cbits* self, const cbits* other); // is set a subset of other? +bool cbits_disjoint(const cbits* self, const cbits* other); // no common bits +char* cbits_to_str(const cbits* self, char* str, intptr_t start, intptr_t stop); + +void cbits_set(cbits* self, intptr_t i); +void cbits_reset(cbits* self, intptr_t i); +void cbits_set_value(cbits* self, intptr_t i, bool value); +void cbits_set_all(cbits* self, bool value); +void cbits_set_pattern(cbits* self, uint64_t pattern); +void cbits_flip_all(cbits* self); +void cbits_flip(cbits* self, intptr_t i); + +void cbits_intersect(cbits* self, const cbits* other); +void cbits_union(cbits* self, const cbits* other); +void cbits_xor(cbits* self, const cbits* other); // set of disjoint bits ``` ## Types @@ -70,19 +70,19 @@ void cbits_xor(cbits* self, const cbits* other); // set #include <math.h> #include <time.h> -cbits sieveOfEratosthenes(size_t n) +cbits sieveOfEratosthenes(intptr_t n) { cbits bits = cbits_with_size(n>>1, true); - size_t q = (size_t) sqrt(n); + intptr_t q = (intptr_t) sqrt(n); - for (size_t i = 3; i <= q; i += 2) { - for (size_t j = i; j < n; j += 2) { + for (intptr_t i = 3; i <= q; i += 2) { + for (intptr_t j = i; j < n; j += 2) { if (cbits_test(&bits, j>>1)) { i = j; break; } } - for (size_t j = i*i; j < n; j += i*2) + for (intptr_t j = i*i; j < n; j += i*2) cbits_reset(&bits, j>>1); } return bits; @@ -90,19 +90,19 @@ cbits sieveOfEratosthenes(size_t n) int main(void) { - size_t n = 100000000; - printf("computing prime numbers up to %" c_ZU "\n", n); + intptr_t n = 100000000; + printf("computing prime numbers up to %" c_ZI "\n", n); clock_t t1 = clock(); cbits primes = sieveOfEratosthenes(n + 1); - size_t nprimes = cbits_count(&primes); + intptr_t nprimes = cbits_count(&primes); clock_t t2 = clock(); - printf("number of primes: %" c_ZU ", time: %f\n", nprimes, (float)(t2 - t1)/CLOCKS_PER_SEC); + printf("number of primes: %" c_ZI ", time: %f\n", nprimes, (float)(t2 - t1)/CLOCKS_PER_SEC); printf(" 2"); - for (size_t i = 3; i < 1000; i += 2) - if (cbits_test(&primes, i>>1)) printf(" %" c_ZU, i); + for (intptr_t i = 3; i < 1000; i += 2) + if (cbits_test(&primes, i>>1)) printf(" %" c_ZI, i); puts(""); cbits_drop(&primes); diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 8906f154..4430b9f8 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -48,10 +48,10 @@ void cbox_X_drop(cbox_X* self); // destruct the co 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_hash(const cbox_X* x); // hash value -int cbox_X_cmp(const cbox_X* x, const cbox_X* y); // compares pointer addresses if no `i_cmp` is specified. - // 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 +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 no `i_cmp` is specified. + // 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. diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index b610ff04..54b0312d 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -104,7 +104,7 @@ NOTE: One must always make sure to unwind temporary allocated resources before a - it prevents forgetting to call the destructor at the end. The **checkauto** utility will report any misusages. The following example shows how to correctly break/return -from a `c_AUTO` scope: +from a `c_AUTO` scope: ```c int flag = 0; for (int i = 0; i<n; ++i) { @@ -122,7 +122,7 @@ from a `c_AUTO` scope: if (cond3()) return -1; // checkauto ERROR! return inside c_AUTO - + // CORRECT: if (cond2()) { flag = 1; // flag to break outer for-loop @@ -225,10 +225,10 @@ Iterate containers with stop-criteria and chained range filtering. | Built-in filter | Description | |:----------------------------------|:-------------------------------------| -| `c_FLT_SKIP(it, numItems)` | Skip numItems | -| `c_FLT_TAKE(it, numItems)` | Take numItems | -| `c_FLT_SKIPWHILE(it, predicate)` | Skip items until predicate is false | -| `c_FLT_TAKEWHILE(it, predicate)` | Take items until predicate is false | +| `c_flt_skip(it, numItems)` | Skip numItems | +| `c_flt_take(it, numItems)` | Take numItems | +| `c_flt_skipwhile(it, predicate)` | Skip items until predicate is false | +| `c_flt_takewhile(it, predicate)` | Take items until predicate is false | `it.index` holds the index of the source item, and `it.count` the current number of items taken. ```c @@ -249,20 +249,36 @@ int main() { c_FORFILTER (i, IVec, vec, isOdd(*i.ref) - && c_FLT_SKIP(i, 100) // built-in + && c_flt_skip(i, 100) // built-in && isPrime(*i.ref) - , c_FLT_TAKE(i, 10)) { // breaks loop on false. - printf(" %d", *i.ref); + , c_flt_take(i, 10)) { // breaks loop on false. + printf(" %d", *i.ref); } puts(""); } } -// Out: 1000211 1000213 1000231 1000249 1000253 1000273 1000289 1000291 1000303 1000313 +// Out: 1000211 1000213 1000231 1000249 1000253 1000273 1000289 1000291 1000303 1000313 +``` +Note that `c_flt_take()` is given as an optional argument, which makes the loop stop when it becomes false (for efficiency). Chaining it after `isPrime()` instead will give same result, but the full input is processed. + +### c_make + +Make a container from a literal initializer list. Example: +```c +#define i_val_str // cstr value type +#include <stc/cset.h> + +#define i_key int +#define i_val int +#include <stc/cmap.h> +... +cset_str myset = c_make(cset_str, {"This", "is", "the", "story"}); // note: const char* values given! +int x = 7, y = 8; +cmap_int mymap = c_make(cmap_int, { {1, 2}, {3, 4}, {5, 6}, {x, y} }); ``` -Note that `c_FLT_TAKE()` is given as an optional argument, which makes the loop stop when it becomes false (for efficiency). Chaining it after `isPrime()` instead will give same result, but the full input is processed. ### crange -**crange** is a number sequence generator type. The **crange_value** type is `long long`. Below, *start*, *stop*, *step* are type *crange_value*: +**crange** is a number sequence generator type. The **crange_value** type is `long long`. Below *start*, *stop*, and *step* are of type *crange_value*: ```c crange crange_make(stop); // will generate 0, 1, ..., stop-1 crange crange_make(start, stop); // will generate start, start+1, ... stop-1 @@ -275,57 +291,42 @@ void crange_next(crange_iter* it); // 1. All primes less than 32: crange r1 = crange_make(3, 32, 2); printf("2"); // first prime -c_FORFILTER (i, crange, r1 +c_FORFILTER (i, crange, r1 , isPrime(*i.ref)) printf(" %lld", *i.ref); // 2 3 5 7 11 13 17 19 23 29 31 // 2. The 11 first primes: printf("2"); -c_FORFILTER (i, crange, crange_literal(3, INT64_MAX, 2) +c_FORFILTER (i, crange, crange_literal(3, INT64_MAX, 2) , isPrime(*i.ref) - , c_FLT_TAKE(10)) + , c_flt_take(10)) printf(" %lld", *i.ref); // 2 3 5 7 11 13 17 19 23 29 31 ``` -### c_FIND_IF, c_ERASE_IF +### c_find_if, c_erase_if, c_swap, c_drop Find or erase linearily in containers using a predicate ```c // Search vec for first value > 2: cvec_i_iter i; -c_FIND_IF(i, cvec_i, vec, *i.ref > 2); +c_find_if(i, cvec_i, vec, *i.ref > 2); if (i.ref) printf("%d\n", *i.ref); // Search map for a string containing "hello" and erase it: cmap_str_iter it, it1 = ..., it2 = ...; -c_FIND_IF(it, csmap_str, it1, it2, cstr_contains(it.ref, "hello")); +c_find_if(it, csmap_str, it1, it2, cstr_contains(it.ref, "hello")); if (it.ref) cmap_str_erase_at(&map, it); // Erase all strings containing "hello": // Note 1: iter i need not be declared. // Note 2: variables index and count can be accessed in predicate. -c_ERASE_IF(i, csmap_str, map, cstr_contains(i.ref, "hello")); -``` - -### c_NEW, c_ALLOC, c_ALLOC_N, c_DROP - -| Usage | Meaning | -|:-------------------------------|:----------------------------------------| -| `c_NEW (type, value)` | Move value to a new object on the heap | -| `c_ALLOC (type)` | `(type *) c_MALLOC(sizeof(type))` | -| `c_ALLOC_N (type, N)` | `(type *) c_MALLOC((N)*sizeof(type))` | -| `c_DROP (ctype, &c1, ..., &cN)` | `ctype_drop(&c1); ... ctype_drop(&cN)` | +c_erase_if(i, csmap_str, map, cstr_contains(i.ref, "hello")); -```c -struct Pnt { double x, y, z; }; -struct Pnt *pnt = c_NEW (struct Pnt, {1.2, 3.4, 5.6}); -c_FREE(pnt); - -int* array = c_ALLOC_N (int, 100); -c_FREE(array); +// Safe macro for swapping internals of two objects of same type: +c_swap(cmap_int, &map1, &map2); -cstr a = cstr_lit("Hello"), b = cstr_lit("World"); -c_DROP(cstr, &a, &b); +// Drop multiple containers of same type: +c_drop(cvec_i, &vec1, &vec2, &vec3); ``` ### General predefined template parameter functions @@ -341,17 +342,29 @@ bool crawstr_eq(const crawstr* x, const crawstr* y); uint64_t crawstr_hash(const crawstr* x); ``` -### c_MALLOC, c_CALLOC, c_REALLOC, c_FREE -Memory allocator for the entire library. Macros can be overridden by the user. +### c_NEW, c_ALLOC, c_ALLOC_N + +| Usage | Meaning | +|:----------------------------|:-------------------------------------------| +| `c_NEW (type, value)` | Allocate and init a new object on the heap | +| `c_ALLOC (type)` | `(type *) c_malloc(c_sizeof(type))` | +| `c_ALLOC_N (type, N)` | `(type *) c_malloc((N)*c_sizeof(type))` | -### c_SWAP, c_ARRAYLEN -- **c_SWAP(T, xp, yp)**: Safe macro for swapping internals of two objects of same type. -- **c_ARRAYLEN(array)**: Return number of elements in an array. ```c -cmap_int map1 = {0}, map2 = {0}; -... -c_SWAP(cmap_int, &map1, &map2); +struct Pnt { double x, y, z; }; +struct Pnt *pnt = c_NEW(struct Pnt, {1.2, 3.4, 5.6}); +c_free(pnt); + +int* array = c_ALLOC_N(int, 100); +c_free(array); +``` +### c_malloc, c_calloc, c_realloc, c_free: customizable allocators +Memory allocator for the entire library. Macros can be overridden by the user. + +### c_ARRAYLEN +- **c_ARRAYLEN(array)**: Return number of elements in an array. array must not be a pointer! +```c int array[] = {1, 2, 3, 4}; -size_t n = c_ARRAYLEN(array); +intptr_t n = c_ARRAYLEN(array); ``` diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 584d382f..716a608c 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -27,25 +27,25 @@ See the c++ class [std::deque](https://en.cppreference.com/w/cpp/container/deque ```c cdeq_X cdeq_X_init(void); -cdeq_X cdeq_X_with_capacity(size_t size); +cdeq_X cdeq_X_with_capacity(intptr_t size); 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); +bool cdeq_X_reserve(cdeq_X* self, intptr_t cap); void cdeq_X_shrink_to_fit(cdeq_X* self); -void cdeq_X_drop(cdeq_X* self); // destructor +void cdeq_X_drop(cdeq_X* self); // destructor bool cdeq_X_empty(const cdeq_X* self); -size_t cdeq_X_size(const cdeq_X* self); -size_t cdeq_X_capacity(const cdeq_X* self); +intptr_t cdeq_X_size(const cdeq_X* self); +intptr_t cdeq_X_capacity(const cdeq_X* self); -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 +const cdeq_X_value* cdeq_X_at(const cdeq_X* self, intptr_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); // return cvec_X_end() if not found +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); @@ -55,23 +55,23 @@ cdeq_X_value* cdeq_X_emplace_front(cdeq_X* self, i_valraw raw); void cdeq_X_pop_front(cdeq_X* self); cdeq_X_value* cdeq_X_push_back(cdeq_X* self, i_val value); -cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back() +cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back() 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() +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_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(cdeq_X* self, intptr_t idx, i_val value); // move value +cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_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_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_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_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_n(cdeq_X* self, intptr_t idx, intptr_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); @@ -83,7 +83,7 @@ void cdeq_X_sort_range(cdeq_X_iter i1, cdeq_X_iter i2, cdeq_X_iter cdeq_X_begin(const cdeq_X* self); cdeq_X_iter cdeq_X_end(const cdeq_X* self); void cdeq_X_next(cdeq_X_iter* it); -cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, intptr_t n); +cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, size_t n); cdeq_X_raw cdeq_X_value_toraw(cdeq_X_value* pval); cdeq_X_value cdeq_X_value_clone(cdeq_X_value val); diff --git a/docs/clist_api.md b/docs/clist_api.md index e97d7b5d..29bfd5ff 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -45,33 +45,33 @@ clist_X clist_X_clone(clist_X list); void clist_X_clear(clist_X* self); void clist_X_copy(clist_X* self, const clist_X* other); -void clist_X_drop(clist_X* self); // destructor +void clist_X_drop(clist_X* self); // destructor bool clist_X_empty(const clist_X* list); -size_t clist_X_count(const clist_X* list); // size() in O(n) time +intptr_t clist_X_count(const clist_X* list); // size() in O(n) time clist_X_value* clist_X_back(const clist_X* self); clist_X_value* clist_X_front(const clist_X* self); -void clist_X_push_back(clist_X* self, i_val value); // note: no pop_back() +void clist_X_push_back(clist_X* self, i_val value); // note: no pop_back() void clist_X_push_front(clist_X* self, i_val value); -void clist_X_push(clist_X* self, i_val value); // alias for push_back() +void clist_X_push(clist_X* self, i_val value); // alias for push_back() void clist_X_emplace_back(clist_X* self, i_valraw raw); void clist_X_emplace_front(clist_X* self, i_valraw raw); -void clist_X_emplace(clist_X* self, i_valraw raw); // alias for emplace_back() +void clist_X_emplace(clist_X* self, i_valraw raw); // alias for emplace_back() -clist_X_iter clist_X_insert_at(clist_X* self, clist_X_iter it, i_val value); // return iter to new elem +clist_X_iter clist_X_insert_at(clist_X* self, clist_X_iter it, i_val value); // return iter to new elem clist_X_iter clist_X_emplace_at(clist_X* self, clist_X_iter it, i_valraw raw); void clist_X_pop_front(clist_X* self); -clist_X_iter clist_X_erase_at(clist_X* self, clist_X_iter it); // return iter after it +clist_X_iter clist_X_erase_at(clist_X* self, clist_X_iter it); // return iter after it clist_X_iter clist_X_erase_range(clist_X* self, clist_X_iter it1, clist_X_iter it2); -size_t clist_X_remove(clist_X* self, i_valraw raw); // removes all matches +intptr_t clist_X_remove(clist_X* self, i_valraw raw); // removes all matches -clist_X clist_X_split_off(clist_X* self, clist_X_iter i1, clist_X_iter i2); // split off [i1, i2) -clist_X_iter clist_X_splice(clist_X* self, clist_X_iter it, clist_X* other); // return updated valid it -clist_X_iter clist_X_splice_range(clist_X* self, clist_X_iter it, // return updated valid it +clist_X clist_X_split_off(clist_X* self, clist_X_iter i1, clist_X_iter i2); // split off [i1, i2) +clist_X_iter clist_X_splice(clist_X* self, clist_X_iter it, clist_X* other); // return updated valid it +clist_X_iter clist_X_splice_range(clist_X* self, clist_X_iter it, // return updated valid it clist_X* other, clist_X_iter it1, clist_X_iter it2); clist_X_iter clist_X_find(const clist_X* self, i_valraw raw); @@ -83,10 +83,10 @@ void clist_X_sort(clist_X* self); void clist_X_reverse(clist_X* self); // Node API -clist_X_node* clist_X_get_node(clist_X_value* val); // get the enclosing node +clist_X_node* clist_X_get_node(clist_X_value* val); // get the enclosing node clist_X_value* clist_X_push_node_back(clist_X* self, clist_X_node* node); clist_X_value* clist_X_insert_node_after(clist_X* self, clist_X_node* ref, clist_X_node* node); -clist_X_node* clist_X_unlink_node_after(clist_X* self, clist_X_node* ref); // return the unlinked node +clist_X_node* clist_X_unlink_node_after(clist_X* self, clist_X_node* ref); // return the unlinked node void clist_X_erase_node_after(clist_X* self, clist_X_node* node); clist_X_iter clist_X_begin(const clist_X* self); diff --git a/docs/cmap_api.md b/docs/cmap_api.md index a33715fc..0b91abc7 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -48,56 +48,56 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain ```c cmap_X cmap_X_init(void); -cmap_X cmap_X_with_capacity(size_t cap); +cmap_X cmap_X_with_capacity(int64_t cap); cmap_X cmap_X_clone(cmap_x map); void cmap_X_clear(cmap_X* self); void cmap_X_copy(cmap_X* self, const cmap_X* other); -float cmap_X_max_load_factor(const cmap_X* self); // default: 0.85f -bool cmap_X_reserve(cmap_X* self, size_t size); +float cmap_X_max_load_factor(const cmap_X* self); // default: 0.85f +bool cmap_X_reserve(cmap_X* self, int64_t size); void cmap_X_shrink_to_fit(cmap_X* self); -void cmap_X_drop(cmap_X* self); // destructor +void cmap_X_drop(cmap_X* self); // destructor -size_t cmap_X_size(const cmap_X* self); -size_t cmap_X_capacity(const cmap_X* self); // buckets * max_load_factor bool cmap_X_empty(const cmap_X* self ); -size_t cmap_X_bucket_count(const cmap_X* self); // num. of allocated buckets - -const cmap_X_mapped* cmap_X_at(const cmap_X* self, i_keyraw rkey); // rkey must be in map -cmap_X_mapped* cmap_X_at_mut(cmap_X* self, i_keyraw rkey); // mutable at -const cmap_X_value* cmap_X_get(const cmap_X* self, i_keyraw rkey); // const get -cmap_X_value* cmap_X_get_mut(cmap_X* self, i_keyraw rkey); // mutable get +int64_t cmap_X_size(const cmap_X* self); +int64_t cmap_X_capacity(const cmap_X* self); // buckets * max_load_factor +int64_t cmap_X_bucket_count(const cmap_X* self); // num. of allocated buckets + +const cmap_X_mapped* cmap_X_at(const cmap_X* self, i_keyraw rkey); // rkey must be in map +cmap_X_mapped* cmap_X_at_mut(cmap_X* self, i_keyraw rkey); // mutable at +const cmap_X_value* cmap_X_get(const cmap_X* self, i_keyraw rkey); // const get +cmap_X_value* cmap_X_get_mut(cmap_X* self, i_keyraw rkey); // mutable get bool cmap_X_contains(const cmap_X* self, i_keyraw rkey); -cmap_X_iter cmap_X_find(const cmap_X* self, i_keyraw rkey); // find element +cmap_X_iter cmap_X_find(const cmap_X* self, i_keyraw rkey); // find element -cmap_X_result cmap_X_insert(cmap_X* self, i_key key, i_val mapped); // no change if key in map -cmap_X_result cmap_X_insert_or_assign(cmap_X* self, i_key key, i_val mapped); // always update mapped -cmap_X_result cmap_X_push(cmap_X* self, cmap_X_value entry); // similar to insert +cmap_X_result cmap_X_insert(cmap_X* self, i_key key, i_val mapped); // no change if key in map +cmap_X_result cmap_X_insert_or_assign(cmap_X* self, i_key key, i_val mapped); // always update mapped +cmap_X_result cmap_X_push(cmap_X* self, cmap_X_value entry); // similar to insert -cmap_X_result cmap_X_emplace(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map +cmap_X_result cmap_X_emplace(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map cmap_X_result cmap_X_emplace_or_assign(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update rmapped -size_t cmap_X_erase(cmap_X* self, i_keyraw rkey); // return 0 or 1 -cmap_X_iter cmap_X_erase_at(cmap_X* self, cmap_X_iter it); // return iter after it +int cmap_X_erase(cmap_X* self, i_keyraw rkey); // return 0 or 1 +cmap_X_iter cmap_X_erase_at(cmap_X* self, cmap_X_iter it); // return iter after it void cmap_X_erase_entry(cmap_X* self, cmap_X_value* entry); cmap_X_iter cmap_X_begin(const cmap_X* self); cmap_X_iter cmap_X_end(const cmap_X* self); void cmap_X_next(cmap_X_iter* it); -cmap_X_iter cmap_X_advance(cmap_X_iter it, size_t n); +cmap_X_iter cmap_X_advance(cmap_X_iter it, uint64_t n); cmap_X_value cmap_X_value_clone(cmap_X_value val); cmap_X_raw cmap_X_value_toraw(cmap_X_value* pval); ``` Helpers: ```c -uint64_t c_default_hash(const X *obj); // macro, calls cfasthash(obj, sizeof *obj) -uint64_t cstrhash(const char *str); // string hash funcion, uses strlen() -uint64_t cfasthash(const void *data, size_t len); // base hash function +uint64_t c_default_hash(const X *obj); // macro, calls cfasthash(obj, sizeof *obj) +uint64_t cstrhash(const char *str); // string hash funcion, uses strlen() +uint64_t cfasthash(const void *data, intptr_t len); // base hash function // equalto template parameter functions: -bool c_default_eq(const i_keyraw* a, const i_keyraw* b); // *a == *b -bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !memcmp(a, b, sizeof *a) +bool c_default_eq(const i_keyraw* a, const i_keyraw* b); // *a == *b +bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !memcmp(a, b, sizeof *a) ``` ## Types @@ -353,7 +353,7 @@ typedef struct Viking { } Viking; static inline void Viking_drop(Viking* v) { - c_DROP(cstr, &v->name, &v->country); + c_drop(cstr, &v->name, &v->country); } // Define Viking raw struct with cmp, hash, and convertion functions between Viking and RViking structs: diff --git a/docs/cpque_api.md b/docs/cpque_api.md index 392d3149..48a5b29e 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -28,17 +28,17 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai ```c cpque_X cpque_X_init(void); // create empty pri-queue. -cpque_X cpque_X_with_capacity(size_t cap); -cpque_X cpque_X_with_size(size_t size, i_val null); +cpque_X cpque_X_with_capacity(intptr_t cap); +cpque_X cpque_X_with_size(intptr_t size, i_val null); cpque_X cpque_X_clone(cpque_X pq); void cpque_X_clear(cpque_X* self); -bool cpque_X_reserve(cpque_X* self, size_t n); +bool cpque_X_reserve(cpque_X* self, intptr_t n); void cpque_X_shrink_to_fit(cpque_X* self); void cpque_X_copy(cpque_X* self, const cpque_X* other); void cpque_X_drop(cpque_X* self); // destructor -size_t cpque_X_size(const cpque_X* self); +intptr_t cpque_X_size(const cpque_X* self); bool cpque_X_empty(const cpque_X* self); i_val* cpque_X_top(const cpque_X* self); @@ -47,7 +47,7 @@ void cpque_X_push(cpque_X* self, i_val value); void cpque_X_emplace(cpque_X* self, i_valraw raw); // converts from raw void cpque_X_pop(cpque_X* self); -void cpque_X_erase_at(cpque_X* self, size_t idx); +void cpque_X_erase_at(cpque_X* self, intptr_t idx); i_val cpque_X_value_clone(i_val value); ``` @@ -71,7 +71,7 @@ i_val cpque_X_value_clone(i_val value); int main() { - size_t N = 10000000; + intptr_t N = 10000000; stc64_t rng = stc64_new(1234); stc64_uniform_t dist = stc64_uniform_new(0, N * 10); diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index 977fa855..212cdabe 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -32,7 +32,7 @@ void cqueue_X_clear(cqueue_X* self); void cqueue_X_copy(cqueue_X* self, const cqueue_X* other); void cqueue_X_drop(cqueue_X* self); // destructor -size_t cqueue_X_size(const cqueue_X* self); +intptr_t cqueue_X_size(const cqueue_X* self); bool cqueue_X_empty(const cqueue_X* self); cqueue_X_value* cqueue_X_front(const cqueue_X* self); cqueue_X_value* cqueue_X_back(const cqueue_X* self); diff --git a/docs/crandom_api.md b/docs/crandom_api.md index bd3bf848..391c485f 100644 --- a/docs/crandom_api.md +++ b/docs/crandom_api.md @@ -41,22 +41,22 @@ All crandom definitions and prototypes are available by including a single heade ## Methods ```c -void csrandom(uint64_t seed); // seed global stc64 prng -uint64_t crandom(void); // global stc64_rand(rng) -double crandomf(void); // global stc64_randf(rng) +void csrandom(uint64_t seed); // seed global stc64 prng +uint64_t crandom(void); // global stc64_rand(rng) +double crandomf(void); // global stc64_randf(rng) -stc64_t stc64_new(uint64_t seed); // stc64_init(s) is deprecated -stc64_t stc64_with_seq(uint64_t seed, uint64_t seq); // with unique stream +stc64_t stc64_new(uint64_t seed); // stc64_init(s) is deprecated +stc64_t stc64_with_seq(uint64_t seed, uint64_t seq); // with unique stream -uint64_t stc64_rand(stc64_t* rng); // range [0, 2^64 - 1] -double stc64_randf(stc64_t* rng); // range [0.0, 1.0) +uint64_t stc64_rand(stc64_t* rng); // range [0, 2^64 - 1] +double stc64_randf(stc64_t* rng); // range [0.0, 1.0) -stc64_uniform_t stc64_uniform_new(int64_t low, int64_t high); // uniform-distribution -int64_t stc64_uniform(stc64_t* rng, stc64_uniform_t* dist); // range [low, high] +stc64_uniform_t stc64_uniform_new(int64_t low, int64_t high); // uniform-distribution +int64_t stc64_uniform(stc64_t* rng, stc64_uniform_t* dist); // range [low, high] stc64_uniformf_t stc64_uniformf_new(double lowf, double highf); -double stc64_uniformf(stc64_t* rng, stc64_uniformf_t* dist); // range [lowf, highf) +double stc64_uniformf(stc64_t* rng, stc64_uniformf_t* dist); // range [lowf, highf) -stc64_normalf_t stc64_normalf_new(double mean, double stddev); // normal-distribution +stc64_normalf_t stc64_normalf_new(double mean, double stddev); // normal-distribution double stc64_normalf(stc64_t* rng, stc64_normalf_t* dist); ``` ## Types @@ -76,7 +76,7 @@ double stc64_normalf(stc64_t* rng, stc64_normalf_t* dist); // Declare int -> int sorted map. Uses typetag 'i' for ints. #define i_key int -#define i_val size_t +#define i_val intptr_t #define i_tag i #include <stc/csmap.h> @@ -102,7 +102,7 @@ int main() // Print the gaussian bar chart cstr bar = cstr_init(); c_FOREACH (i, csmap_i, mhist) { - size_t n = (size_t) (i.ref->second * StdDev * Scale * 2.5 / N); + int n = (int)(i.ref->second * StdDev * Scale * 2.5 / N); if (n > 0) { cstr_resize(&bar, n, '*'); printf("%4d %s\n", i.ref->first, cstr_str(&bar)); diff --git a/docs/cregex_api.md b/docs/cregex_api.md index c01f324c..e74040d8 100644 --- a/docs/cregex_api.md +++ b/docs/cregex_api.md @@ -23,35 +23,36 @@ enum { }; cregex cregex_init(void); -cregex cregex_from(const char* pattern, int cflags); - /* return CREG_OK, or negative error code on failure */ -int cregex_compile(cregex *self, const char* pattern, int cflags); +cregex cregex_from(const char* pattern, int cflags = CREG_DEFAULT); + // return CREG_OK, or negative error code on failure +int cregex_compile(cregex *self, const char* pattern, int cflags = CREG_DEFAULT); - /* num. of capture groups in regex. 0 if RE is invalid. First group is the full match */ + // num. of capture groups in regex. 0 if RE is invalid. First group is the full match int cregex_captures(const cregex* self); - /* return CREG_OK, CREG_NOMATCH, or CREG_MATCHERROR */ -int cregex_find(const cregex* re, const char* input, csview match[], int mflags); - /* Search inside input string-view only */ + // return CREG_OK, CREG_NOMATCH, or CREG_MATCHERROR +int cregex_find(const cregex* re, const char* input, csview match[], int mflags = CREG_DEFAULT); + // Search inside input string-view only int cregex_find_sv(const cregex* re, csview input, csview match[]); - /* All-in-one search (compile + find + drop) */ -int cregex_find_pattern(const char* pattern, const char* input, csview match[], int cmflags); + // All-in-one search (compile + find + drop) +int cregex_find_pattern(const char* pattern, const char* input, csview match[], int cmflags = CREG_DEFAULT); - /* Check if there are matches in input */ + // Check if there are matches in input bool cregex_is_match(const cregex* re, const char* input); - /* Replace all matches in input */ -cstr cregex_replace(const cregex* re, const char* input, const char* replace); - /* Replace count matches in input string-view. Optionally transform replacement with mfun. */ -cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, unsigned count, + // Replace all matches in input +cstr cregex_replace(const cregex* re, const char* input, const char* replace, int count = INT_MAX); + // Replace count matches in input string-view. Optionally transform replacement with mfun. +cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count = INT_MAX); +cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count, bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags); - /* All-in-one replacement (compile + find/replace + drop) */ -cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace); -cstr cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count, - bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags); - -void cregex_drop(cregex* self); /* destroy */ + // All-in-one replacement (compile + find/replace + drop) +cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count = INT_MAX); +cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count, + bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags); + // destroy +void cregex_drop(cregex* self); ``` ### Error codes diff --git a/docs/cset_api.md b/docs/cset_api.md index e1d08a87..ef4df63b 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -30,32 +30,32 @@ A **cset** is an associative container that contains a set of unique objects of ```c cset_X cset_X_init(void); -cset_X cset_X_with_capacity(size_t cap); +cset_X cset_X_with_capacity(intptr_t cap); cset_X cset_X_clone(cset_x set); void cset_X_clear(cset_X* self); void cset_X_copy(cset_X* self, const cset_X* other); -float cset_X_max_load_factor(const cset_X* self); // default: 0.85 -bool cset_X_reserve(cset_X* self, size_t size); +float cset_X_max_load_factor(const cset_X* self); // default: 0.85 +bool cset_X_reserve(cset_X* self, intptr_t size); void cset_X_shrink_to_fit(cset_X* self); -void cset_X_drop(cset_X* self); // destructor +void cset_X_drop(cset_X* self); // destructor -size_t cset_X_size(const cset_X* self); // num. of allocated buckets -size_t cset_X_capacity(const cset_X* self); // buckets * max_load_factor +intptr_t cset_X_size(const cset_X* self); // num. of allocated buckets +intptr_t cset_X_capacity(const cset_X* self); // buckets * max_load_factor bool cset_X_empty(const cset_X* self); -size_t cset_X_bucket_count(const cset_X* self); +intptr_t cset_X_bucket_count(const cset_X* self); bool cset_X_contains(const cset_X* self, i_keyraw rkey); -const cset_X_value* cset_X_get(const cset_X* self, i_keyraw rkey); // return NULL if not found -cset_X_value* cset_X_get_mut(cset_X* self, i_keyraw rkey); // mutable get +const cset_X_value* cset_X_get(const cset_X* self, i_keyraw rkey); // return NULL if not found +cset_X_value* cset_X_get_mut(cset_X* self, i_keyraw rkey); // mutable get cset_X_iter cset_X_find(const cset_X* self, i_keyraw rkey); cset_X_result cset_X_insert(cset_X* self, i_key key); -cset_X_result cset_X_push(cset_X* self, i_key key); // alias for insert. +cset_X_result cset_X_push(cset_X* self, i_key key); // alias for insert. cset_X_result cset_X_emplace(cset_X* self, i_keyraw rkey); -size_t cset_X_erase(cset_X* self, i_keyraw rkey); // return 0 or 1 -cset_X_iter cset_X_erase_at(cset_X* self, cset_X_iter it); // return iter after it +intptr_t cset_X_erase(cset_X* self, i_keyraw rkey); // return 0 or 1 +cset_X_iter cset_X_erase_at(cset_X* self, cset_X_iter it); // return iter after it void cset_X_erase_entry(cset_X* self, cset_X_value* entry); cset_X_iter cset_X_begin(const cset_X* self); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 687a6cab..b090f737 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -42,8 +42,8 @@ See the c++ class [std::map](https://en.cppreference.com/w/cpp/container/map) fo ```c csmap_X csmap_X_init(void); -csset_X csmap_X_with_capacity(size_t cap); -bool csmap_X_reserve(csmap_X* self, size_t cap); +csset_X csmap_X_with_capacity(int64_t cap); +bool csmap_X_reserve(csmap_X* self, int64_t cap); void csmap_X_shrink_to_fit(csmap_X* self); csmap_X csmap_X_clone(csmap_x map); @@ -51,9 +51,9 @@ void csmap_X_clear(csmap_X* self); void csmap_X_copy(csmap_X* self, const csmap_X* other); void csmap_X_drop(csmap_X* self); // destructor -size_t csmap_X_size(const csmap_X* self); bool csmap_X_empty(const csmap_X* self); -bool csmap_X_capacity(const csmap_X* self); +int64_t csmap_X_size(const csmap_X* self); +int64_t csmap_X_capacity(const csmap_X* self); const csmap_X_mapped* csmap_X_at(const csmap_X* self, i_keyraw rkey); // rkey must be in map csmap_X_mapped* csmap_X_at_mut(csmap_X* self, i_keyraw rkey); // mutable at @@ -74,14 +74,14 @@ csmap_X_result csmap_X_push(csmap_X* self, csmap_X_value entry); csmap_X_result csmap_X_emplace(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map csmap_X_result csmap_X_emplace_or_assign(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update rmapped -size_t csmap_X_erase(csmap_X* self, i_keyraw rkey); +intptr_t csmap_X_erase(csmap_X* self, i_keyraw rkey); csmap_X_iter csmap_X_erase_at(csmap_X* self, csmap_X_iter it); // returns iter after it csmap_X_iter csmap_X_erase_range(csmap_X* self, csmap_X_iter it1, csmap_X_iter it2); // returns updated it2 csmap_X_iter csmap_X_begin(const csmap_X* self); csmap_X_iter csmap_X_end(const csmap_X* self); void csmap_X_next(csmap_X_iter* iter); -csmap_X_iter csmap_X_advance(csmap_X_iter it, size_t n); +csmap_X_iter csmap_X_advance(csmap_X_iter it, uint64_t n); csmap_X_value csmap_X_value_clone(csmap_X_value val); csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval); diff --git a/docs/cspan_api.md b/docs/cspan_api.md index 2865a1a5..d0463b0a 100644 --- a/docs/cspan_api.md +++ b/docs/cspan_api.md @@ -1,120 +1,199 @@ # STC [cspan](../include/stc/cspan.h): Multi-dimensional Array View  -The **cspan** is templated non-owning multi-dimensional view of an array. - -See the c++ classes [std::span](https://en.cppreference.com/w/cpp/container/span) and +The **cspan** is templated non-owning multi-dimensional view of an array. See the c++ classes +[std::span](https://en.cppreference.com/w/cpp/container/span) and [std::mdspan](https://en.cppreference.com/w/cpp/container/mdspan) for similar functionality. ## Header file and declaration ```c #include <stc/cspan.h> -using_cspan(SpanType, ValueType, Rank); // define SpanType with ValueType elements. - // Rank is number of dimensions (max 4) +using_cspan(SpanType, ValueType); // define a 1-d SpanType with ValueType elements. +using_cspan(SpanTypeN, ValueType, Rank); // define multi-dimensional span with Rank. + // Rank is number of dimensions (max 5) // Shorthands: -using_cspan2(S, ValueType); // define span types S, S2 with ranks 1, 2. -using_cspan3(S, ValueType); // define span types S, S2, S3 with ranks 1, 2, 3. -using_cspan4(S, ValueType); // define span types S, S2, S3, S4 with ranks 1, 2, 3, 4. +using_cspan2(S, ValueType); // define span types S, S2 with ranks 1, 2. +using_cspan3(S, ValueType); // define span types S, S2, S3 with ranks 1, 2, 3. +using_cspan4(S, ValueType); // define span types S, S2, S3, S4 with ranks 1, 2, 3, 4. ``` ## Methods -Note that `cspan_make()`, `cmake_from*()`, `cspan_atN()`, `and cspan_subspanN()` require a (safe) cast to its span-type -on assignment, but not on initialization of a span variable. All functions are type-safe, and arguments are side-effect safe, except for SpanType arg. which must not have side-effects. +All functions are type-safe, and index arguments are side-effect safe. ```c -SpanType{N} cspan_make(ValueType* data, size_t xdim, ...); // make N-dimensional cspan -SpanType cspan_from(STCContainer* cnt); // create a 1D cspan from a compatible STC container -SpanType cspan_from_array(ValueType array[]); // create a 1D cspan from a C array -SpanType cspan_from_list(T ValueType, {val0, val1, ...}); // create a 1D cspan from an initializer list -SpanType& cspan_literal(T SpanType, {val0, val1, ...}); // create a 1D cspan compound literal from init list - -void cspan_resize(SpanType{N}* self, size_t xdim, ...); // change the extent of each dimension +SpanTypeN cspan_md(ValueType* data, intptr_t xdim, ...); // create a multi-dimensional cspan +SpanType cspan_make(T SpanType, {v1, v2, ...}); // make a 1d-dimensional cspan from values +SpanType cspan_from(STCContainer* cnt); // create a 1d cspan from a compatible STC container +SpanType cspan_from_array(ValueType array[]); // create a 1d cspan from a C array + +intptr_t cspan_size(const SpanTypeN* self); // return number of elements +unsigned cspan_rank(const SpanTypeN* self); // return number of dimensions +intptr_t cspan_index(const SpanTypeN* self, intptr_t x, ..); // index of element + +ValueType* cspan_at(const SpanTypeN* self, intptr_t x, ...); // at(): num of args specifies rank of input span. +ValueType* cspan_front(const SpanTypeN* self); +ValueType* cspan_back(const SpanTypeN* self); -size_t cspan_size(const SpanType{N}* self); // return number of elements -unsigned cspan_rank(const SpanType{N}* self); // return number of dimensions -size_t cspan_index(const SpanType{N}* self, size_t x, ...); // index of element + // general index slicing to create a subspan. + // {x} reduces rank. {x,c_END} slice to end. {c_ALL} take the full extent. +SpanTypeN cspan_slice(T SpanTypeN, const SpanTypeM* parent, {x0,x1}, {y0,y1}, ...); -ValueType* cspan_at(SpanType{N}* self, size_t x, ...); // at(): num of args decides input SpanType{N}. -SpanType cspan_at2(SpanType2* self, size_t x); // return a 1D subarray cspan. -SpanType{N} cspan_at3(SpanType3* self, size_t x, ...); // atN(): N decides input SpanType, -SpanType{N} cspan_at4(SpanType4* self, size_t x, ...); // and num of args decides returned SpanType{N}. - -SpanType cspan_subspan(const SpanType* self, size_t offset, size_t count); // return a slice of a 1D cspan -SpanType2 cspan_subspan2(const SpanType2 self, size_t offset, size_t count); // return a slice of a 2D cspan -SpanType3 cspan_subspan3(const SpanType3 self, size_t offset, size_t count); // return a slice of a 3D cspan -SpanType4 cspan_subspan4(const SpanType4 self, size_t offset, size_t count); // return a slice of a 4D cspan - -SpanType{N}_iter SpanType_begin(const SpanType{N}* self); -SpanType{N}_iter SpanType_end(const SpanType{N}* self); -void SpanType_next(SpanType{N}_iter* it); + // create a subspan of lower rank. Like e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL}); +SpanType cspan_submd2(const SpanType2* self, intptr_t x); // return a 1d subspan from a 2d span. +SpanTypeN cspan_submd3(const SpanType3* self, intptr_t x, ...); // return a 1d or 2d subspan from a 3d span. +SpanTypeN cspan_submd4(const SpanType4* self, intptr_t x, ...); // number of args determines rank of output span. + + // create a subspan of same rank. Like e.g. cspan_slice(Span3, &ms3, {off,off+count}, {c_ALL}, {c_ALL}); +SpanType cspan_subspan(const SpanType* self, intptr_t offset, intptr_t count); +SpanType2 cspan_subspan2(const SpanType2 self, intptr_t offset, intptr_t count); +SpanType3 cspan_subspan3(const SpanType3 self, intptr_t offset, intptr_t count); + +SpanTypeN_iter SpanType_begin(const SpanTypeN* self); +SpanTypeN_iter SpanType_end(const SpanTypeN* self); +void SpanType_next(SpanTypeN_iter* it); ``` ## Types -| Type name | Type definition | Used to represent... | -|:--------------------|:-----------------------------------------------|:---------------------| -| SpanType{N} | `struct { ValueType *data; uint32_t dim[N]; }` | SpanType with rank N | -| SpanType{N}`_value` | `ValueType` | The ValueType | -| SpanType{N}`_iter` | `struct { ValueType *ref; ... }` | Iterator type | +| Type name | Type definition | Used to represent... | +|:------------------|:-----------------------------------------------|:---------------------| +| SpanTypeN | `struct { ValueType *data; uint32_t shape[N]; }` | SpanType with rank N | +| SpanTypeN`_value` | `ValueType` | The ValueType | +| `c_ALL` | `0,-1` | Full extent | +| `c_END` | `-1` | End of extent | + +## Example 1 + +The *cspan_slice()* function is similar to pythons numpy multi-dimensional arrays slicing, e.g.: +```py +import numpy as np + +if __name__ == '__main__': + ms3 = np.array((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24), int) + + ms3 = np.reshape(ms3, (2, 3, 4)) + ss3 = ms3[:, 1:3, 2:] + ss2 = ss3[1] + + for i in range(ss2.shape[0]): + for j in range(ss2.shape[1]): + print(" {}".format(ss2[i, j]), end='') + print('') -## Example + for i in ss2.flat: + print(" {}".format(i), end='') + +# 19 20 23 24 +# 19 20 23 24 +``` +... can be done in C with cspan: ```c -#include <stdio.h> -#define i_val float -#include <stc/cstack.h> +#include <c11/fmt.h> +#include <stc/cspan.h> +using_cspan3(myspan, int); // define myspan, myspan2, myspan3. + +int main() { + int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}; + myspan3 ms3 = cspan_md(arr, 2, 3, 4); + myspan3 ss3 = cspan_slice(myspan3, &ms3, {c_ALL}, {1,3}, {2,c_END}); + myspan2 ss2 = cspan_submd3(&ss3, 1); + + c_FORRANGE (i, ss2.shape[0]) + c_FORRANGE (j, ss2.shape[1]) + fmt_print(" {}", *cspan_at(&ss2, i, j)); + puts(""); + + c_FOREACH (i, myspan2, ss2) + fmt_print(" {}", *i.ref); +} +``` +... and (almost) in C++23: +```c++ +#include <print> +#include <mdspan> +#include <tuple> + +int main() { + int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}; + + std::mdspan ms3(arr, 2, 3, 4); + auto ss3 = std::submdspan(ms3, std::full_extent, std::tuple{1,3}, std::tuple{2,4}); + auto ss2 = std::submdspan(ss3, 1, std::full_extent, std::full_extent); + + for (std::size_t i = 0; i < ss2.extent(0); ++i) + for (std::size_t j = 0; j < ss2.extent(1); ++j) + std::print(" {}", ss2[i, j]); + std::println(); + + // std::mdspan can't be iterated as a flat container! +} +``` +## Example 2 +Slicing cspan without and with reducing the rank (like numpy array slicing): +```c +#include <c11/fmt.h> #include <stc/cspan.h> -using_cspan3(FS, float); // Shorthand to define span types FS, FS2, and FS3. + +using_cspan3(Span, int); // Shorthand to define Span, Span2, and Span3 int main() { - int xd = 6, yd = 4, zd = 3; - c_AUTO (cstack_float, vec) { - c_FORRANGE (i, xd*yd*zd) - cstack_float_push(&vec, i); - - // define "span3[xd][yd][zd]" - FS3 span3 = cspan_make(vec.data, xd, yd, zd); - *cspan_at(&span3, 4, 3, 2) = 3.14f; - printf("index: %d", (int)cspan_index(&span3, 4, 3, 2)); - - FS span1 = cspan_at3(&span3, 4, 3); - printf("\niterate span1: "); - c_FOREACH (i, FS, span1) - printf("%g ", *i.ref); - - FS2 span2 = cspan_at3(&span3, 4); - printf("\niterate span2: "); - c_FOREACH (i, FS2, span2) - printf("%g ", *i.ref); - - puts("\niterate span3 by dimensions:"); - c_FORRANGE (i, span3.dim[0]) { - c_FORRANGE (j, span3.dim[1]) { - c_FORRANGE (k, span3.dim[2]) - printf(" %2g", *cspan_at(&span3, i, j, k)); - printf(" |"); - } - puts(""); + // c_make() can create any STC container/span from an initializer list: + Span span = c_make(Span, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}); + // create a 3d cspan: + Span3 span3 = cspan_md(span.data, 2, 4, 3); + + // reduce rank: (i.e. span3[1]) + Span2 span2 = cspan_submd3(&span3, 1); + + puts("\niterate span2 flat:"); + c_FOREACH (i, Span2, span2) + fmt_print(" {}", *i.ref); + puts(""); + + // slice without reducing rank: + Span3 ss3 = cspan_slice(Span3, &span3, {c_ALL}, {3,4}, {c_ALL}); + + puts("\niterate ss3 by dimensions:"); + c_FORRANGE (i, ss3.shape[0]) { + c_FORRANGE (j, ss3.shape[1]) { + c_FORRANGE (k, ss3.shape[2]) + fmt_print(" {:2}", *cspan_at(&ss3, i, j, k)); + fmt_print(" |"); } - - printf("%g\n", *cspan_at(&span3, 4, 3, 2)); - printf("%g\n", *cspan_at(&span2, 3, 2)); - printf("%g\n", *cspan_at(&span1, 2)); + puts(""); + } + // slice and reduce rank: + Span2 ss2 = cspan_slice(Span2, &span3, {c_ALL}, {3}, {c_ALL}); + + puts("\niterate ss2 by dimensions:"); + c_FORRANGE (i, ss2.shape[0]) { + c_FORRANGE (j, ss2.shape[1]) { + fmt_print(" {:2}", *cspan_at(&ss2, i, j)); + fmt_print(" |"); + } + puts(""); } + + puts("\niterate ss2 flat:"); + c_FOREACH (i, Span2, ss2) + fmt_print(" {:2}", *i.ref); + puts(""); } ``` Output: ``` -index: 59 -iterate span1: 57 58 3.14 -iterate span2: 48 49 50 51 52 53 54 55 56 57 58 3.14 -iterate span3 by dimensions: - 0 1 2 | 3 4 5 | 6 7 8 | 9 10 11 | - 12 13 14 | 15 16 17 | 18 19 20 | 21 22 23 | - 24 25 26 | 27 28 29 | 30 31 32 | 33 34 35 | - 36 37 38 | 39 40 41 | 42 43 44 | 45 46 47 | - 48 49 50 | 51 52 53 | 54 55 56 | 57 58 3.14 | - 60 61 62 | 63 64 65 | 66 67 68 | 69 70 71 | -3.14 -3.14 -3.14 +iterate span2 flat: + 13 14 15 16 17 18 19 20 21 22 23 24 + +iterate ss3 by dimensions: + 10 11 12 | + 22 23 24 | + +iterate ss2 by dimensions: + 10 | 11 | 12 | + 22 | 23 | 24 | + +iterate ss2 flat: + 10 11 12 22 23 24 ``` diff --git a/docs/csset_api.md b/docs/csset_api.md index 6276f486..7e068909 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -28,8 +28,8 @@ See the c++ class [std::set](https://en.cppreference.com/w/cpp/container/set) fo ```c csset_X csset_X_init(void); -csset_X csset_X_with_capacity(size_t cap); -bool csset_X_reserve(csset_X* self, size_t cap); +csset_X csset_X_with_capacity(intptr_t cap); +bool csset_X_reserve(csset_X* self, intptr_t cap); void csset_X_shrink_to_fit(csset_X* self); csset_X csset_X_clone(csset_x set); @@ -37,7 +37,7 @@ void csset_X_clear(csset_X* self); void csset_X_copy(csset_X* self, const csset_X* other); void csset_X_drop(csset_X* self); // destructor -size_t csset_X_size(const csset_X* self); +intptr_t csset_X_size(const csset_X* self); bool csset_X_empty(const csset_X* self); const csset_X_value* csset_X_get(const csset_X* self, i_keyraw rkey); // const get @@ -51,7 +51,7 @@ csset_X_result csset_X_insert(csset_X* self, i_key key); csset_X_result csset_X_push(csset_X* self, i_key key); // alias for insert() csset_X_result csset_X_emplace(csset_X* self, i_keyraw rkey); -size_t csset_X_erase(csset_X* self, i_keyraw rkey); +intptr_t csset_X_erase(csset_X* self, i_keyraw rkey); csset_X_iter csset_X_erase_at(csset_X* self, csset_X_iter it); // return iter after it csset_X_iter csset_X_erase_range(csset_X* self, csset_X_iter it1, csset_X_iter it2); // return updated it2 diff --git a/docs/cstack_api.md b/docs/cstack_api.md index e8423385..b1371f4e 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -26,24 +26,24 @@ See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack ```c cstack_X cstack_X_init(void); -cstack_X cstack_X_with_capacity(size_t cap); -cstack_X cstack_X_with_size(size_t size, i_val fill); +cstack_X cstack_X_with_capacity(intptr_t cap); +cstack_X cstack_X_with_size(intptr_t size, i_val fill); cstack_X cstack_X_clone(cstack_X st); void cstack_X_clear(cstack_X* self); -bool cstack_X_reserve(cstack_X* self, size_t n); +bool cstack_X_reserve(cstack_X* self, intptr_t n); void cstack_X_shrink_to_fit(cstack_X* self); -i_val* cstack_X_append_uninit(cstack_X* self, size_t n); +i_val* cstack_X_append_uninit(cstack_X* self, intptr_t n); void cstack_X_copy(cstack_X* self, const cstack_X* other); void cstack_X_drop(cstack_X* self); // destructor -size_t cstack_X_size(const cstack_X* self); -size_t cstack_X_capacity(const cstack_X* self); +intptr_t cstack_X_size(const cstack_X* self); +intptr_t cstack_X_capacity(const cstack_X* self); bool cstack_X_empty(const cstack_X* self); i_val* cstack_X_top(const cstack_X* self); -const i_val* cstack_X_at(const cstack_X* self, size_t idx); -i_val* cstack_X_at_mut(cstack_X* self, size_t idx); +const i_val* cstack_X_at(const cstack_X* self, intptr_t idx); +i_val* cstack_X_at_mut(cstack_X* self, intptr_t idx); i_val* cstack_X_push(cstack_X* self, i_val value); i_val* cstack_X_emplace(cstack_X* self, i_valraw raw); diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 4f895549..37316d4d 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -18,118 +18,117 @@ All cstr definitions and prototypes are available by including a single header f ## Methods ```c -cstr cstr_init(void); // constructor; same as cstr_NULL. -cstr cstr_lit(const char literal_only[]); // cstr from literal; no strlen() call. -cstr cstr_from(const char* str); // constructor using strlen() -cstr cstr_from_n(const char* str, size_t n); // constructor with n first bytes of str -cstr cstr_from_sv(csview sv); // construct cstr from csview -cstr cstr_with_capacity(size_t cap); -cstr cstr_with_size(size_t len, char fill); // repeat fill len times -cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting -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 - -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(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); -void cstr_shrink_to_fit(cstr* self); -void cstr_clear(cstr* self); - -char* cstr_assign(cstr* self, const char* str); -char* cstr_assign_n(cstr* self, const char* str, size_t n); // assign n first bytes of str -char* cstr_assign_sv(cstr* self, csview sv); -char* cstr_copy(cstr* self, cstr s); // copy-assign a cstr -int cstr_printf(cstr* self, const char* fmt, ...); // source and target must not overlap. - -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); -int cstr_append_fmt(cstr* self, const char* fmt, ...); // printf() formatting -char* cstr_append_uninit(cstr* self, size_t len); // return ptr to start of uninited data - -void cstr_push(cstr* self, const char* chr); // append one utf8 char -void cstr_pop(cstr* self); // pop one utf8 char - -void cstr_insert(cstr* self, size_t pos, const char* ins); -void cstr_insert_sv(cstr* self, size_t pos, csview ins); -void cstr_insert_s(cstr* self, size_t pos, cstr ins); - -void cstr_erase(cstr* self, size_t pos, size_t len); // erase len bytes from pos - -void cstr_replace(cstr* self, const char* search, const char* repl); -void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count); -cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count); -void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl); // replace at a position -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(const cstr* self, const char* str); -bool cstr_equals_sv(const cstr* self, csview sv); -bool cstr_equals_s(const cstr* self, 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_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 +cstr cstr_init(void); // constructor; same as cstr_NULL. +cstr cstr_lit(const char literal_only[]); // cstr from literal; no strlen() call. +cstr cstr_from(const char* str); // constructor using strlen() +cstr cstr_from_n(const char* str, intptr_t n); // constructor with n first bytes of str +cstr cstr_from_sv(csview sv); // construct cstr from csview +cstr cstr_with_capacity(intptr_t cap); +cstr cstr_with_size(intptr_t len, char fill); // repeat fill len times +cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting +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 + +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) + +intptr_t cstr_size(const cstr* self); +intptr_t cstr_capacity(const cstr* self); +bool cstr_empty(const cstr* self); + +char* cstr_reserve(cstr* self, intptr_t capacity); // return pointer to buffer +void cstr_resize(cstr* self, intptr_t len, char fill); +void cstr_shrink_to_fit(cstr* self); +void cstr_clear(cstr* self); + +char* cstr_assign(cstr* self, const char* str); +char* cstr_assign_n(cstr* self, const char* str, intptr_t n); // assign n first bytes of str +char* cstr_assign_sv(cstr* self, csview sv); +char* cstr_copy(cstr* self, cstr s); // copy-assign a cstr +int cstr_printf(cstr* self, const char* fmt, ...); // source and target must not overlap. + +char* cstr_append(cstr* self, const char* str); +char* cstr_append_n(cstr* self, const char* str, intptr_t n); // append n first bytes of str +char* cstr_append_sv(cstr* self, csview str); +char* cstr_append_s(cstr* self, cstr str); +int cstr_append_fmt(cstr* self, const char* fmt, ...); // printf() formatting +char* cstr_append_uninit(cstr* self, intptr_t len); // return ptr to start of uninited data + +void cstr_push(cstr* self, const char* chr); // append one utf8 char +void cstr_pop(cstr* self); // pop one utf8 char + +void cstr_insert(cstr* self, intptr_t pos, const char* ins); +void cstr_insert_sv(cstr* self, intptr_t pos, csview ins); +void cstr_insert_s(cstr* self, intptr_t pos, cstr ins); + +void cstr_erase(cstr* self, intptr_t pos, intptr_t len); // erase len bytes from pos + +void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count = MAX_INT); +cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count); +void cstr_replace_at(cstr* self, intptr_t pos, intptr_t len, const char* repl); // replace at a pos +void cstr_replace_at_sv(cstr* self, intptr_t pos, intptr_t len, const csview repl); +void cstr_replace_at_s(cstr* self, intptr_t pos, intptr_t len, cstr repl); + +bool cstr_equals(const cstr* self, const char* str); +bool cstr_equals_sv(const cstr* self, csview sv); +bool cstr_equals_s(const cstr* self, cstr s); + +intptr_t cstr_find(const cstr* self, const char* search); +intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); // search from pos +bool cstr_contains(const cstr* self, const char* search); + +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 ``` #### UTF8 methods ```c -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 bytepos, size_t u8len, csview repl); // replace u8len utf8 chars -void cstr_u8_erase(cstr* self, size_t bytepos, size_t u8len); // erase u8len codepoints from pos +intptr_t cstr_u8_size(const cstr* self); // number of utf8 codepoints +intptr_t cstr_u8_size_n(const cstr self, intptr_t nbytes); // utf8 size within n bytes +intptr_t cstr_u8_to_pos(const cstr* self, intptr_t u8idx); // byte pos offset at utf8 codepoint index +const char* cstr_u8_at(const cstr* self, intptr_t u8idx); // char* position at utf8 codepoint index +csview cstr_u8_chr(const cstr* self, intptr_t u8idx); // get utf8 character as a csview +void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csview repl); // replace u8len utf8 chars +void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); // erase u8len codepoints from pos // iterate utf8 codepoints -cstr_iter cstr_begin(const cstr* self); -cstr_iter cstr_end(const cstr* self); -void cstr_next(cstr_iter* it); -cstr_iter cstr_advance(cstr_iter it, intptr_t n); +cstr_iter cstr_begin(const cstr* self); +cstr_iter cstr_end(const cstr* self); +void cstr_next(cstr_iter* it); +cstr_iter cstr_advance(cstr_iter it, intptr_t n); // utf8 functions requires linking with src/utf8code.c symbols: -bool cstr_valid_utf8(const cstr* self); // check if str is valid utf8 -cstr cstr_casefold_sv(csview sv); // returns new casefolded utf8 cstr - -cstr cstr_tolower(const char* str); // returns new lowercase utf8 cstr -cstr cstr_tolower_sv(csview sv); // returns new lowercase utf8 cstr -void cstr_lowercase(cstr* self); // transform cstr to lowercase utf8 - -cstr cstr_toupper(const char* str); // returns new uppercase utf8 cstr -cstr cstr_toupper_sv(csview sv); // returns new uppercase utf8 cstr -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(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); // " +bool cstr_valid_utf8(const cstr* self); // check if str is valid utf8 +cstr cstr_casefold_sv(csview sv); // returns new casefolded utf8 cstr + +cstr cstr_tolower(const char* str); // returns new lowercase utf8 cstr +cstr cstr_tolower_sv(csview sv); // returns new lowercase utf8 cstr +void cstr_lowercase(cstr* self); // transform cstr to lowercase utf8 + +cstr cstr_toupper(const char* str); // returns new uppercase utf8 cstr +cstr cstr_toupper_sv(csview sv); // returns new uppercase utf8 cstr +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(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. +Note that all methods with arguments `(..., const char* str, intptr_t n)`, `n` must be within the range of `str` length. #### Helper methods: ```c @@ -137,17 +136,17 @@ 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* cstrnstrn(const char* str, const char* search, size_t slen, size_t nlen); +char* cstrnstrn(const char* str, const char* search, intptr_t slen, intptr_t nlen); ``` ## Types -| Type name | Type definition | Used to represent... | -|:----------------|:-------------------------------------------|:---------------------| -| `cstr` | `struct { ... }` | The string type | -| `cstr_value` | `char` | String element type | -| `csview` | `struct { const char *str; size_t size; }` | String view type | -| `cstr_buf` | `struct { char *data; size_t size, cap; }` | String buffer type | +| Type name | Type definition | Used to represent... | +|:----------------|:---------------------------------------------|:---------------------| +| `cstr` | `struct { ... }` | The string type | +| `cstr_value` | `char` | String element type | +| `csview` | `struct { const char *str; intptr_t size; }` | String view type | +| `cstr_buf` | `struct { char *data; intptr_t size, cap; }` | String buffer type | ## Constants and macros @@ -163,7 +162,7 @@ char* cstrnstrn(const char* str, const char* search, size_t slen, size_t int main() { c_AUTO (cstr, s0, s1, full_path) { s0 = cstr_lit("Initialization without using strlen()."); - printf("%s\nLength: %" c_ZU "\n\n", cstr_str(&s0), cstr_size(&s0)); + printf("%s\nLength: %" c_ZI "\n\n", cstr_str(&s0), cstr_size(&s0)); s1 = cstr_lit("one-nine-three-seven-five."); printf("%s\n", cstr_str(&s1)); @@ -174,7 +173,7 @@ int main() { cstr_erase(&s1, 7, 5); // -nine printf("%s\n", cstr_str(&s1)); - cstr_replace_ex(&s1, "seven", "four", 1); + cstr_replace(&s1, "seven", "four", 1); printf("%s\n", cstr_str(&s1)); // reassign: diff --git a/docs/csview_api.md b/docs/csview_api.md index b5508ace..3971c6a6 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -26,61 +26,61 @@ All csview definitions and prototypes are available by including a single header ## Methods ```c -csview c_SV(const char literal_only[]); // construct from literal, no strlen() -csview c_SV(const char* str, size_t n); // construct from str and length n -csview csview_lit(const char literal_only[]); // alias for c_SV(lit) -csview csview_from(const char* str); // construct from const char* -csview csview_from_n(const char* str, size_t n); // alias for c_SV(str, n) +csview c_SV(const char literal_only[]); // construct from literal, no strlen() +csview c_SV(const char* str, intptr_t n); // construct from str and length n +csview csview_lit(const char literal_only[]); // alias for c_SV(lit) +csview csview_from(const char* str); // construct from const char* +csview csview_from_n(const char* str, intptr_t n); // alias for c_SV(str, n) -size_t csview_size(csview sv); +intptr_t csview_size(csview sv); bool csview_empty(csview sv); void csview_clear(csview* self); bool csview_equals(csview sv, csview sv2); -size_t csview_find(csview sv, const char* str); -size_t csview_find_sv(csview sv, csview find); +intptr_t csview_find(csview sv, const char* str); +intptr_t csview_find_sv(csview sv, csview find); bool csview_contains(csview sv, const char* str); bool csview_starts_with(csview sv, const char* str); bool csview_ends_with(csview sv, const char* str); -csview csview_substr_ex(csview sv, intptr_t pos, size_t n); // negative pos count from end -csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); // negative p1, p2 count from end -csview csview_token(csview sv, const char* sep, size_t* start); // *start > sv.size after last token +csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); // negative pos count from end +csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); // negative p1, p2 count from end +csview csview_token(csview sv, const char* sep, intptr_t* start); // *start > sv.size after last token ``` #### UTF8 methods ```c -size_t csview_u8_size(csview sv); -csview csview_u8_substr(csview sv, size_t bytepos, size_t u8len); -bool csview_valid_utf8(csview sv); // requires linking with src/utf8code.c +intptr_t csview_u8_size(csview sv); +csview csview_u8_substr(csview sv, intptr_t bytepos, intptr_t u8len); +bool csview_valid_utf8(csview sv); // requires linking with src/utf8code.c csview_iter csview_begin(const csview* self); csview_iter csview_end(const csview* self); -void csview_next(csview_iter* it); // utf8 codepoint step, not byte! +void csview_next(csview_iter* it); // utf8 codepoint step, not byte! csview_iter csview_advance(csview_iter it, intptr_t n); -// from utf8.h -size_t utf8_size(const char *s); -size_t utf8_size_n(const char *s, size_t nbytes); // number of UTF8 codepoints within n bytes -const char* utf8_at(const char *s, size_t index); // from UTF8 index to char* position -size_t utf8_pos(const char* s, size_t index); // from UTF8 index to byte index position -unsigned utf8_chr_size(const char* s); // UTF8 character size: 1-4 -// implemented in src/utf8code.c: + // from utf8.h +intptr_t utf8_size(const char *s); +intptr_t utf8_size_n(const char *s, intptr_t nbytes); // number of UTF8 codepoints within n bytes +const char* utf8_at(const char *s, intptr_t index); // from UTF8 index to char* position +intptr_t utf8_pos(const char* s, intptr_t index); // from UTF8 index to byte index position +unsigned utf8_chr_size(const char* s); // UTF8 character size: 1-4 + // implemented in src/utf8code.c: bool utf8_valid(const char* s); -bool utf8_valid_n(const char* s, size_t nbytes); -uint32_t utf8_decode(utf8_decode_t *d, uint8_t byte); // decode next byte to utf8, return state. -unsigned utf8_encode(char *out, uint32_t codepoint); // encode unicode cp into out buffer -uint32_t utf8_peek(const char* s); // codepoint value of character at s -uint32_t utf8_peek_off(const char* s, int offset); // codepoint value at utf8 pos (may be negative) +bool utf8_valid_n(const char* s, intptr_t nbytes); +uint32_t utf8_decode(utf8_decode_t *d, uint8_t byte); // decode next byte to utf8, return state. +unsigned utf8_encode(char *out, uint32_t codepoint); // encode unicode cp into out buffer +uint32_t utf8_peek(const char* s); // codepoint value of character at s +uint32_t utf8_peek_off(const char* s, int offset); // codepoint value at utf8 pos (may be negative) ``` #### Extended cstr methods ```c -csview cstr_substr(const cstr* self, size_t pos, size_t n); -csview cstr_substr_ex(const cstr* s, intptr_t pos, size_t n); // negative pos count from end -csview cstr_u8_substr(const cstr* self, size_t bytepos, size_t u8len); +csview cstr_substr(const cstr* self, intptr_t pos, intptr_t n); +csview cstr_substr_ex(const cstr* s, intptr_t pos, intptr_t n); // negative pos count from end +csview cstr_u8_substr(const cstr* self, intptr_t bytepos, intptr_t u8len); -csview cstr_slice(const cstr* self, size_t p1, size_t p2); +csview cstr_slice(const cstr* self, intptr_t p1, intptr_t p2); csview cstr_slice_ex(const cstr* s, intptr_t p, intptr_t q); // negative p or q count from end ``` #### Iterate tokens with *c_FORTOKEN*, *c_FORTOKEN_SV* @@ -103,7 +103,7 @@ uint64_t csview_hash(const csview* x); | Type name | Type definition | Used to represent... | |:----------------|:-------------------------------------------|:-------------------------| -| `csview` | `struct { const char *str; size_t size; }` | The string view type | +| `csview` | `struct { const char *str; intptr_t size; }` | The string view type | | `csview_value` | `char` | The string element type | | `csview_iter` | `struct { csview_value *ref; }` | UTF8 iterator | @@ -125,7 +125,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 + intptr_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("%.*s %.*s %.*s\n", @@ -135,7 +135,7 @@ int main () cstr s3 = cstr_from_sv(cstr_substr(&s1, 0, 6)); // "Apples" printf("%s %s\n", cstr_str(&s2), cstr_str(&s3)); - c_DROP(cstr, &str1, &s1, &s2, &s3); + c_drop(cstr, &str1, &s1, &s2, &s3); } ``` Output: diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 92629c8b..057caa7c 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -31,32 +31,32 @@ See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vect ```c cvec_X cvec_X_init(void); -cvec_X cvec_X_with_size(size_t size, i_val null); -cvec_X cvec_X_with_capacity(size_t size); +cvec_X cvec_X_with_size(intptr_t size, i_val null); +cvec_X cvec_X_with_capacity(intptr_t size); 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_iter cvec_X_insert_uninit(cvec_X* self, i_val* pos, size_t n); // return pos iter +bool cvec_X_reserve(cvec_X* self, intptr_t cap); +bool cvec_X_resize(cvec_X* self, intptr_t size, i_val null); +cvec_X_iter cvec_X_insert_uninit(cvec_X* self, i_val* pos, intptr_t n); // return pos iter void cvec_X_shrink_to_fit(cvec_X* self); -void cvec_X_drop(cvec_X* self); // destructor +void cvec_X_drop(cvec_X* self); // destructor bool cvec_X_empty(const cvec_X* self); -size_t cvec_X_size(const cvec_X* self); -size_t cvec_X_capacity(const cvec_X* self); +intptr_t cvec_X_size(const cvec_X* self); +intptr_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); // find mutable value, return value ptr +const cvec_X_value* cvec_X_at(const cvec_X* self, intptr_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, intptr_t idx); +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); // return cvec_X_end() if not found +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 +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 cvec_X_iter cvec_X_binary_search_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw, cvec_X_iter* lower_bound); @@ -65,24 +65,24 @@ cvec_X_value* cvec_X_back(const cvec_X* self); cvec_X_value* cvec_X_push(cvec_X* self, i_val value); cvec_X_value* cvec_X_emplace(cvec_X* self, i_valraw raw); -cvec_X_value* cvec_X_push_back(cvec_X* self, i_val value); // alias for push -cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); // alias for emplace +cvec_X_value* cvec_X_push_back(cvec_X* self, i_val value); // alias for push +cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); // alias for emplace void cvec_X_pop(cvec_X* self); -void cvec_X_pop_back(cvec_X* self); // alias for pop +void cvec_X_pop_back(cvec_X* self); // alias for pop -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(cvec_X* self, intptr_t idx, i_val value); // move value +cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val[] arr, intptr_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_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_n(cvec_X* self, intptr_t idx, const i_valraw[] arr, intptr_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_n(cvec_X* self, intptr_t idx, intptr_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); @@ -94,7 +94,7 @@ void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2, cvec_X_iter cvec_X_begin(const cvec_X* self); cvec_X_iter cvec_X_end(const cvec_X* self); void cvec_X_next(cvec_X_iter* iter); -cvec_X_iter cvec_X_advance(cvec_X_iter it, intptr_t n); +cvec_X_iter cvec_X_advance(cvec_X_iter it, size_t n); cvec_X_raw cvec_X_value_toraw(cvec_X_value* pval); cvec_X_value cvec_X_value_clone(cvec_X_value val); @@ -222,6 +222,6 @@ int main(void) { c_FOREACH (i, UVec, vec2) printf("%s: %d\n", cstr_str(&i.ref->name), i.ref->id); - c_DROP(UVec, &vec, &vec2); // cleanup + c_drop(UVec, &vec, &vec2); // cleanup } ```
\ No newline at end of file diff --git a/include/c11/fmt.h b/include/c11/fmt.h index ff0cb25c..435193f8 100644 --- a/include/c11/fmt.h +++ b/include/c11/fmt.h @@ -59,6 +59,7 @@ int main() { }
*/
#include <stdio.h>
+#include <stdint.h>
#include <assert.h>
#define fmt_OVERLOAD(name, ...) \
@@ -86,7 +87,7 @@ int main() { typedef struct {
char* data;
- size_t cap, len;
+ intptr_t cap, len;
_Bool stream;
} fmt_buffer;
@@ -202,11 +203,11 @@ FMT_API void _fmt_bprint(fmt_buffer* buf, const char* fmt, ...) { va_copy(args2, args);
const int n = vsnprintf(NULL, 0U, fmt, args);
if (n < 0) goto done2;
- const size_t pos = buf->stream ? buf->len : 0U;
+ const intptr_t pos = buf->stream ? buf->len : 0;
buf->len = pos + n;
if (buf->len > buf->cap) {
buf->cap = buf->len + buf->cap/2;
- buf->data = (char*)realloc(buf->data, buf->cap + 1);
+ buf->data = (char*)realloc(buf->data, (size_t)buf->cap + 1U);
}
vsprintf(buf->data + pos, fmt, args2);
done2: va_end(args2);
@@ -252,7 +253,7 @@ FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...) { if (!strchr("csdioxXufFeEaAgGnp", fmt[-1]))
while (*arg) *p++ = *arg++;
if (p0 && (p[-1] == 's' || p[-1] == 'c')) /* left-align str */
- memmove(p0 + 1, p0, p++ - p0), *p0 = '-';
+ memmove(p0 + 1, p0, (size_t)(p++ - p0)), *p0 = '-';
fmt += *fmt == '}';
continue;
}
diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index 63242a54..39236ae0 100644 --- a/include/stc/algo/crange.h +++ b/include/stc/algo/crange.h @@ -36,7 +36,7 @@ int main() int a = 100, b = INT32_MAX; c_FORFILTER (i, crange, crange_literal(a, b, 8) , i.index > 10 - , c_FLT_TAKE(i, 3)) + , c_flt_take(i, 3)) printf(" %lld", *i.ref); puts(""); } @@ -54,10 +54,10 @@ typedef struct { crange_value start, end, step, value; } crange; typedef struct { crange_value *ref, end, step; } crange_iter; #define crange_make(...) c_MACRO_OVERLOAD(crange_make, __VA_ARGS__) -#define crange_make1(stop) crange_make3(0, stop, 1) -#define crange_make2(start, stop) crange_make3(start, stop, 1) +#define crange_make_1(stop) crange_make_3(0, stop, 1) +#define crange_make_2(start, stop) crange_make_3(start, stop, 1) -STC_INLINE crange crange_make3(crange_value start, crange_value stop, crange_value step) +STC_INLINE crange crange_make_3(crange_value start, crange_value stop, crange_value step) { crange r = {start, stop - (step > 0), step}; return r; } STC_INLINE crange_iter crange_begin(crange* self) diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h index 2cd7b548..c8c41257 100644 --- a/include/stc/algo/csort.h +++ b/include/stc/algo/csort.h @@ -84,13 +84,13 @@ static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi while (i_less((&arr[i]), (&pivot))) ++i; while (i_less((&pivot), (&arr[j]))) --j; if (i <= j) { - c_SWAP(i_val, arr+i, arr+j); + c_swap(i_val, arr+i, arr+j); ++i; --j; } } if (j - lo > hi - i) { - c_SWAP(intptr_t, &lo, &i); - c_SWAP(intptr_t, &hi, &j); + c_swap(intptr_t, &lo, &i); + c_swap(intptr_t, &hi, &j); } if (j - lo > 64) c_PASTE(cqsort_, i_tag)(arr, lo, j); @@ -99,7 +99,7 @@ static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi } } -static inline void c_PASTE(csort_, i_tag)(i_val arr[], size_t n) - { c_PASTE(cqsort_, i_tag)(arr, 0, (intptr_t)n - 1); } +static inline void c_PASTE(csort_, i_tag)(i_val arr[], intptr_t n) + { c_PASTE(cqsort_, i_tag)(arr, 0, n - 1); } #include <stc/priv/template.h> diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index e941be2e..9037c984 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -37,9 +37,9 @@ int main() puts(""); c_FORFILTER (i, cstack_int, stk - , c_FLT_SKIPWHILE(i, *i.ref < 3) + , c_flt_skipwhile(i, *i.ref < 3) && (*i.ref & 1) == 0 // even only - , c_FLT_TAKE(i, 2)) // break after 2 + , c_flt_take(i, 2)) // break after 2 printf(" %d", *i.ref); puts(""); } @@ -54,17 +54,17 @@ int main() #define c_NFILTERS 14 /* 22, 30, .. */ #endif -#define c_FLT_TAKE(i, n) (++(i).s1[(i).s1top++] <= (n)) -#define c_FLT_SKIP(i, n) (++(i).s1[(i).s1top++] > (n)) -#define c_FLT_SKIPWHILE(i, pred) ((i).s2[(i).s2top++] |= !(pred)) -#define c_FLT_TAKEWHILE(i, pred) !c_FLT_SKIPWHILE(i, pred) +#define c_flt_take(i, n) (++(i).s1[(i).s1top++] <= (n)) +#define c_flt_skip(i, n) (++(i).s1[(i).s1top++] > (n)) +#define c_flt_skipwhile(i, pred) ((i).s2[(i).s2top++] |= !(pred)) +#define c_flt_takewhile(i, pred) !c_flt_skipwhile(i, pred) #define c_FORFILTER(...) c_MACRO_OVERLOAD(c_FORFILTER, __VA_ARGS__) -#define c_FORFILTER4(i, C, cnt, filter) \ +#define c_FORFILTER_4(i, C, cnt, filter) \ c_FORFILTER_B(i, C, C##_begin(&cnt), filter) -#define c_FORFILTER5(i, C, cnt, filter, cond) \ +#define c_FORFILTER_5(i, C, cnt, filter, cond) \ c_FORFILTER_B(i, C, C##_begin(&cnt), filter) if (!(cond)) break; else #define c_FORFILTER_B(i, C, start, filter) \ diff --git a/include/stc/carc.h b/include/stc/carc.h index 614af18e..5bf4ebc2 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -45,7 +45,7 @@ int main() { ArcPers q = ArcPers_clone(p); // share the pointer printf("%s %s. uses: %ld\n", cstr_str(&q.get->name), cstr_str(&q.get->last), *q.use_count); - c_DROP(ArcPers, &p, &q); + c_drop(ArcPers, &p, &q); } */ #include "ccommon.h" @@ -93,7 +93,7 @@ _cx_deftypes(_c_carc_types, _cx_self, i_key); struct _cx_memb(_rep_) { catomic_long counter; i_key value; }; STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_INIT(_cx_self){NULL, NULL}; } + { return c_LITERAL(_cx_self){NULL, NULL}; } STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) { return self->use_count ? *self->use_count : 0; } @@ -127,8 +127,8 @@ STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { i_keydrop(self->get); if ((char *)self->get != (char *)self->use_count + offsetof(struct _cx_memb(_rep_), value)) - c_FREE(self->get); - c_FREE((long*)self->use_count); + c_free(self->get); + c_free((long*)self->use_count); } } diff --git a/include/stc/cbits.h b/include/stc/cbits.h index 6a71487f..577ecb13 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -56,40 +56,40 @@ int main() { #include <string.h> #define _cbits_bit(i) ((uint64_t)1 << ((i) & 63)) -#define _cbits_words(n) (((n) + 63)>>6) -#define _cbits_bytes(n) (_cbits_words(n) * sizeof(uint64_t)) +#define _cbits_words(n) (intptr_t)(((n) + 63)>>6) +#define _cbits_bytes(n) (_cbits_words(n) * c_sizeof(uint64_t)) #if defined(__GNUC__) || defined(__clang__) - STC_INLINE uint64_t cpopcount64(uint64_t x) {return (uint64_t)__builtin_popcountll(x);} + STC_INLINE int cpopcount64(uint64_t x) {return __builtin_popcountll(x);} #elif defined(_MSC_VER) && defined(_WIN64) #include <intrin.h> - STC_INLINE uint64_t cpopcount64(uint64_t x) {return __popcnt64(x);} + STC_INLINE int cpopcount64(uint64_t x) {return (int)__popcnt64(x);} #else - STC_INLINE uint64_t cpopcount64(uint64_t x) { /* http://en.wikipedia.org/wiki/Hamming_weight */ + STC_INLINE int cpopcount64(uint64_t x) { /* http://en.wikipedia.org/wiki/Hamming_weight */ x -= (x >> 1) & 0x5555555555555555; x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f; - return (x * 0x0101010101010101) >> 56; + return (int)((x * 0x0101010101010101) >> 56); } #endif -STC_INLINE size_t _cbits_count(const uint64_t* set, const size_t sz) { - const size_t n = sz>>6; - size_t count = 0; - for (size_t i = 0; i < n; ++i) +STC_INLINE intptr_t _cbits_count(const uint64_t* set, const intptr_t sz) { + const intptr_t n = sz>>6; + intptr_t count = 0; + for (intptr_t i = 0; i < n; ++i) count += cpopcount64(set[i]); if (sz & 63) count += cpopcount64(set[n] & (_cbits_bit(sz) - 1)); return count; } -STC_INLINE char* _cbits_to_str(const uint64_t* set, const size_t sz, - char* out, size_t start, size_t stop) { +STC_INLINE char* _cbits_to_str(const uint64_t* set, const intptr_t sz, + char* out, intptr_t start, intptr_t stop) { if (stop > sz) stop = sz; assert(start <= stop); - memset(out, '0', stop - start); - for (size_t i = start; i < stop; ++i) + c_memset(out, '0', stop - start); + for (intptr_t i = start; i < stop; ++i) if ((set[i>>6] & _cbits_bit(i)) != 0) out[i - start] = '1'; out[stop - start] = '\0'; @@ -97,8 +97,8 @@ STC_INLINE char* _cbits_to_str(const uint64_t* set, const size_t sz, } #define _cbits_OPR(OPR, VAL) \ - const size_t n = sz>>6; \ - for (size_t i = 0; i < n; ++i) \ + const uint64_t n = (uint64_t)sz>>6; \ + for (uint64_t i = 0; i < n; ++i) \ if ((set[i] OPR other[i]) != VAL) \ return false; \ if (!(sz & 63)) \ @@ -106,10 +106,10 @@ STC_INLINE char* _cbits_to_str(const uint64_t* set, const size_t sz, const uint64_t i = n, m = _cbits_bit(sz) - 1; \ return ((set[i] OPR other[i]) & m) == (VAL & m) -STC_INLINE bool _cbits_subset_of(const uint64_t* set, const uint64_t* other, const size_t sz) +STC_INLINE bool _cbits_subset_of(const uint64_t* set, const uint64_t* other, const intptr_t sz) { _cbits_OPR(|, set[i]); } -STC_INLINE bool _cbits_disjoint(const uint64_t* set, const uint64_t* other, const size_t sz) +STC_INLINE bool _cbits_disjoint(const uint64_t* set, const uint64_t* other, const intptr_t sz) { _cbits_OPR(&, 0); } #endif // CBITS_H_INCLUDED @@ -121,12 +121,12 @@ STC_INLINE bool _cbits_disjoint(const uint64_t* set, const uint64_t* other, cons #define _i_assert(x) assert(x) #define i_type cbits -struct { uint64_t *data64; size_t _size; } typedef i_type; +struct { uint64_t *data64; intptr_t _size; } typedef i_type; -STC_INLINE cbits cbits_init(void) { return c_INIT(cbits){NULL}; } +STC_INLINE cbits cbits_init(void) { return c_LITERAL(cbits){NULL}; } STC_INLINE void cbits_create(cbits* self) { self->data64 = NULL; self->_size = 0; } -STC_INLINE void cbits_drop(cbits* self) { c_FREE(self->data64); } -STC_INLINE size_t cbits_size(const cbits* self) { return self->_size; } +STC_INLINE void cbits_drop(cbits* self) { c_free(self->data64); } +STC_INLINE intptr_t cbits_size(const cbits* self) { return self->_size; } STC_INLINE cbits* cbits_take(cbits* self, cbits other) { if (self->data64 != other.data64) { @@ -137,8 +137,8 @@ STC_INLINE cbits* cbits_take(cbits* self, cbits other) { } STC_INLINE cbits cbits_clone(cbits other) { - const size_t bytes = _cbits_bytes(other._size); - cbits set = {(uint64_t *)memcpy(c_MALLOC(bytes), other.data64, bytes), other._size}; + const intptr_t bytes = _cbits_bytes(other._size); + cbits set = {(uint64_t *)c_memcpy(c_malloc(bytes), other.data64, bytes), other._size}; return set; } @@ -147,16 +147,16 @@ STC_INLINE cbits* cbits_copy(cbits* self, const cbits* other) { return self; if (self->_size != other->_size) return cbits_take(self, cbits_clone(*other)); - memcpy(self->data64, other->data64, _cbits_bytes(other->_size)); + c_memcpy(self->data64, other->data64, _cbits_bytes(other->_size)); return self; } -STC_INLINE void cbits_resize(cbits* self, const size_t size, const bool value) { - const size_t new_n = _cbits_words(size), osize = self->_size, old_n = _cbits_words(osize); - self->data64 = (uint64_t *)c_REALLOC(self->data64, new_n*8); +STC_INLINE void cbits_resize(cbits* self, const intptr_t size, const bool value) { + const intptr_t new_n = _cbits_words(size), osize = self->_size, old_n = _cbits_words(osize); + self->data64 = (uint64_t *)c_realloc(self->data64, new_n*8); self->_size = size; if (new_n >= old_n) { - memset(self->data64 + old_n, -(int)value, (new_n - old_n)*8); + c_memset(self->data64 + old_n, -(int)value, (new_n - old_n)*8); if (old_n > 0) { uint64_t m = _cbits_bit(osize) - 1; /* mask */ value ? (self->data64[old_n - 1] |= ~m) @@ -174,14 +174,14 @@ STC_INLINE cbits cbits_move(cbits* self) { return tmp; } -STC_INLINE cbits cbits_with_size(const size_t size, const bool value) { - cbits set = {(uint64_t *)c_MALLOC(_cbits_bytes(size)), size}; +STC_INLINE cbits cbits_with_size(const intptr_t size, const bool value) { + cbits set = {(uint64_t *)c_malloc(_cbits_bytes(size)), size}; cbits_set_all(&set, value); return set; } -STC_INLINE cbits cbits_with_pattern(const size_t size, const uint64_t pattern) { - cbits set = {(uint64_t *)c_MALLOC(_cbits_bytes(size)), size}; +STC_INLINE cbits cbits_with_pattern(const intptr_t size, const uint64_t pattern) { + cbits set = {(uint64_t *)c_malloc(_cbits_bytes(size)), size}; cbits_set_pattern(&set, pattern); return set; } @@ -195,10 +195,10 @@ STC_INLINE cbits cbits_with_pattern(const size_t size, const uint64_t pattern) { struct { uint64_t data64[(i_capacity - 1)/64 + 1]; } typedef i_type; -STC_INLINE i_type _i_memb(_init)(void) { return c_INIT(i_type){0}; } +STC_INLINE i_type _i_memb(_init)(void) { return c_LITERAL(i_type){0}; } STC_INLINE void _i_memb(_create)(i_type* self) {} STC_INLINE void _i_memb(_drop)(i_type* self) {} -STC_INLINE size_t _i_memb(_size)(const i_type* self) { return i_capacity; } +STC_INLINE intptr_t _i_memb(_size)(const i_type* self) { return i_capacity; } STC_INLINE i_type _i_memb(_move)(i_type* self) { return *self; } STC_INLINE i_type* _i_memb(_take)(i_type* self, i_type other) @@ -213,13 +213,13 @@ STC_INLINE i_type* _i_memb(_copy)(i_type* self, const i_type* other) STC_INLINE void _i_memb(_set_all)(i_type *self, const bool value); STC_INLINE void _i_memb(_set_pattern)(i_type *self, const uint64_t pattern); -STC_INLINE i_type _i_memb(_with_size)(const size_t size, const bool value) { +STC_INLINE i_type _i_memb(_with_size)(const intptr_t size, const bool value) { assert(size <= i_capacity); i_type set; _i_memb(_set_all)(&set, value); return set; } -STC_INLINE i_type _i_memb(_with_pattern)(const size_t size, const uint64_t pattern) { +STC_INLINE i_type _i_memb(_with_pattern)(const intptr_t size, const uint64_t pattern) { assert(size <= i_capacity); i_type set; _i_memb(_set_pattern)(&set, pattern); return set; @@ -229,39 +229,39 @@ STC_INLINE i_type _i_memb(_with_pattern)(const size_t size, const uint64_t patte // COMMON: STC_INLINE void _i_memb(_set_all)(i_type *self, const bool value) - { memset(self->data64, value? ~0 : 0, _cbits_bytes(_i_memb(_size)(self))); } + { c_memset(self->data64, value? ~0 : 0, _cbits_bytes(_i_memb(_size)(self))); } STC_INLINE void _i_memb(_set_pattern)(i_type *self, const uint64_t pattern) { - size_t n = _cbits_words(_i_memb(_size)(self)); + intptr_t n = _cbits_words(_i_memb(_size)(self)); while (n--) self->data64[n] = pattern; } -STC_INLINE bool _i_memb(_test)(const i_type* self, const size_t i) +STC_INLINE bool _i_memb(_test)(const i_type* self, const intptr_t i) { return (self->data64[i>>6] & _cbits_bit(i)) != 0; } -STC_INLINE bool _i_memb(_at)(const i_type* self, const size_t i) +STC_INLINE bool _i_memb(_at)(const i_type* self, const intptr_t i) { return (self->data64[i>>6] & _cbits_bit(i)) != 0; } -STC_INLINE void _i_memb(_set)(i_type *self, const size_t i) +STC_INLINE void _i_memb(_set)(i_type *self, const intptr_t i) { self->data64[i>>6] |= _cbits_bit(i); } -STC_INLINE void _i_memb(_reset)(i_type *self, const size_t i) +STC_INLINE void _i_memb(_reset)(i_type *self, const intptr_t i) { self->data64[i>>6] &= ~_cbits_bit(i); } -STC_INLINE void _i_memb(_set_value)(i_type *self, const size_t i, const bool b) { +STC_INLINE void _i_memb(_set_value)(i_type *self, const intptr_t i, const bool b) { self->data64[i>>6] ^= ((uint64_t)-(int)b ^ self->data64[i>>6]) & _cbits_bit(i); } -STC_INLINE void _i_memb(_flip)(i_type *self, const size_t i) +STC_INLINE void _i_memb(_flip)(i_type *self, const intptr_t i) { self->data64[i>>6] ^= _cbits_bit(i); } STC_INLINE void _i_memb(_flip_all)(i_type *self) { - size_t n = _cbits_words(_i_memb(_size)(self)); + intptr_t n = _cbits_words(_i_memb(_size)(self)); while (n--) self->data64[n] ^= ~(uint64_t)0; } STC_INLINE i_type _i_memb(_from)(const char* str) { - size_t n = strlen(str); + intptr_t n = c_strlen(str); i_type set = _i_memb(_with_size)(n, false); while (n--) if (str[n] == '1') _i_memb(_set)(&set, n); return set; @@ -270,26 +270,26 @@ STC_INLINE i_type _i_memb(_from)(const char* str) { /* Intersection */ STC_INLINE void _i_memb(_intersect)(i_type *self, const i_type* other) { _i_assert(self->_size == other->_size); - size_t n = _cbits_words(_i_memb(_size)(self)); + intptr_t n = _cbits_words(_i_memb(_size)(self)); while (n--) self->data64[n] &= other->data64[n]; } /* Union */ STC_INLINE void _i_memb(_union)(i_type *self, const i_type* other) { _i_assert(self->_size == other->_size); - size_t n = _cbits_words(_i_memb(_size)(self)); + intptr_t n = _cbits_words(_i_memb(_size)(self)); while (n--) self->data64[n] |= other->data64[n]; } /* Exclusive disjunction */ STC_INLINE void _i_memb(_xor)(i_type *self, const i_type* other) { _i_assert(self->_size == other->_size); - size_t n = _cbits_words(_i_memb(_size)(self)); + intptr_t n = _cbits_words(_i_memb(_size)(self)); while (n--) self->data64[n] ^= other->data64[n]; } -STC_INLINE size_t _i_memb(_count)(const i_type* self) +STC_INLINE intptr_t _i_memb(_count)(const i_type* self) { return _cbits_count(self->data64, _i_memb(_size)(self)); } -STC_INLINE char* _i_memb(_to_str)(const i_type* self, char* out, size_t start, size_t stop) +STC_INLINE char* _i_memb(_to_str)(const i_type* self, char* out, intptr_t start, intptr_t stop) { return _cbits_to_str(self->data64, _i_memb(_size)(self), out, start, stop); } STC_INLINE bool _i_memb(_subset_of)(const i_type* self, const i_type* other) { diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 95dfdf8f..4f0a2976 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -37,7 +37,7 @@ Person Person_clone(Person p) { } void Person_drop(Person* p) { printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->email)); - c_DROP(cstr, &p->name, &p->email); + c_drop(cstr, &p->name, &p->email); } #define i_keyclass Person // bind Person clone+drop fn's @@ -79,13 +79,13 @@ _cx_deftypes(_c_cbox_types, _cx_self, i_key); // constructors (take ownership) STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_INIT(_cx_self){NULL}; } + { return c_LITERAL(_cx_self){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_INIT(_cx_self){p}; } + { return c_LITERAL(_cx_self){p}; } // c++: std::make_unique<i_key>(val) STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { @@ -100,7 +100,7 @@ STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->get) { i_keydrop(self->get); - c_FREE(self->get); + c_free(self->get); } } diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index edf4b2cb..b8ea6316 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -29,17 +29,13 @@ #include <stdbool.h> #include <string.h> #include <assert.h> -#include "priv/lowcase.h" +#include "priv/altnames.h" -#if SIZE_MAX == UINT32_MAX - #define c_ZU PRIu32 - #define c_NPOS INT32_MAX -#elif SIZE_MAX == UINT64_MAX - #define c_ZU PRIu64 - #define c_NPOS INT64_MAX -#endif +#define c_NPOS INTPTR_MAX +#define c_ZI PRIiPTR +#define c_ZU PRIuPTR #if defined STC_NDEBUG || defined NDEBUG - #define c_ASSERT(expr) (void)(expr) + #define c_ASSERT(expr) (void)(0) #else #define c_ASSERT(expr) assert(expr) #endif @@ -56,7 +52,7 @@ /* Macro overloading feature support based on: https://rextester.com/ONP80107 */ #define c_MACRO_OVERLOAD(name, ...) \ - c_PASTE(name, c_NUMARGS(__VA_ARGS__))(__VA_ARGS__) + c_PASTE(c_CONCAT(name,_), c_NUMARGS(__VA_ARGS__))(__VA_ARGS__) #define c_CONCAT(a, b) a ## b #define c_PASTE(a, b) c_CONCAT(a, b) #define c_EXPAND(...) __VA_ARGS__ @@ -68,36 +64,46 @@ #ifdef __cplusplus #include <new> - #define c_ALLOC(T) static_cast<T*>(c_MALLOC(sizeof(T))) - #define c_ALLOC_N(T, n) static_cast<T*>(c_MALLOC(sizeof(T)*(n))) + #define c_ALLOC(T) static_cast<T*>(c_malloc(c_sizeof(T))) + #define c_ALLOC_N(T, n) static_cast<T*>(c_malloc(c_sizeof(T)*(n))) #define c_NEW(T, ...) new (c_ALLOC(T)) T(__VA_ARGS__) - #define c_INIT(T) T + #define c_LITERAL(T) T #else - #define c_ALLOC(T) ((T*)c_MALLOC(sizeof(T))) - #define c_ALLOC_N(T, n) ((T*)c_MALLOC(sizeof(T)*(n))) + #define c_ALLOC(T) ((T*)c_malloc(c_sizeof(T))) + #define c_ALLOC_N(T, n) ((T*)c_malloc(c_sizeof(T)*(n))) #define c_NEW(T, ...) ((T*)memcpy(c_ALLOC(T), (T[]){__VA_ARGS__}, sizeof(T))) - #define c_INIT(T) (T) -#endif -#ifndef c_MALLOC - #define c_MALLOC(sz) malloc(sz) - #define c_CALLOC(n, sz) calloc(n, sz) - #define c_REALLOC(p, sz) realloc(p, sz) - #define c_FREE(p) free(p) + #define c_LITERAL(T) (T) #endif -#define c_STATIC_ASSERT(b) ((int)(0*sizeof(int[(b) ? 1 : -1]))) -#define c_CONTAINER_OF(p, T, m) ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m))) -#define c_DELETE(T, ptr) do { T *_tp = ptr; T##_drop(_tp); c_FREE(_tp); } while (0) -#define c_SWAP(T, xp, yp) do { T *_xp = xp, *_yp = yp, \ +#ifndef c_malloc + #define c_malloc(sz) malloc(c_i2u(sz)) + #define c_calloc(n, sz) calloc(c_i2u(n), c_i2u(sz)) + #define c_realloc(p, sz) realloc(p, c_i2u(sz)) + #define c_free(p) free(p) +#endif +#define c_static_assert(b) ((int)(0*sizeof(int[(b) ? 1 : -1]))) +#define c_container_of(p, T, m) ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m))) +#define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); c_free(_tp); } while (0) +#define c_swap(T, xp, yp) do { T *_xp = xp, *_yp = yp, \ _tv = *_xp; *_xp = *_yp; *_yp = _tv; } while (0) -#define c_ARRAYLEN(a) (sizeof(a)/sizeof 0[a]) +#define c_sizeof (intptr_t)sizeof +#define c_strlen(s) (intptr_t)strlen(s) +#define c_strncmp(a, b, ilen) strncmp(a, b, c_i2u(ilen)) +#define c_memcpy(d, s, ilen) memcpy(d, s, c_i2u(ilen)) +#define c_memmove(d, s, ilen) memmove(d, s, c_i2u(ilen)) +#define c_memset(d, val, ilen) memset(d, val, c_i2u(ilen)) +#define c_memcmp(a, b, ilen) memcmp(a, b, c_i2u(ilen)) + +#define c_u2i(u) ((intptr_t)((u) + 0*sizeof((u) == 1U))) +#define c_i2u(i) ((size_t)(i) + 0*sizeof((i) == 1)) +#define c_LTu(a, b) ((size_t)(a) < (size_t)(b)) // x and y are i_keyraw* type, defaults to i_key*: #define c_default_cmp(x, y) (c_default_less(y, x) - c_default_less(x, y)) #define c_default_less(x, y) (*(x) < *(y)) #define c_default_eq(x, y) (*(x) == *(y)) #define c_memcmp_eq(x, y) (memcmp(x, y, sizeof *(x)) == 0) -#define c_default_hash(x) cfasthash(x, sizeof *(x)) +#define c_default_hash(x) cfasthash(x, c_sizeof(*(x))) #define c_default_clone(v) (v) #define c_default_toraw(vp) (*(vp)) @@ -113,24 +119,28 @@ #define c_no_hash (1<<6) #define c_no_lookup (c_no_cmp|c_no_eq|c_no_hash) -/* Generic algorithms */ +/* Function macros and others */ + +#define c_make(C, ...) \ + C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw)) typedef const char* crawstr; #define crawstr_cmp(xp, yp) strcmp(*(xp), *(yp)) #define crawstr_hash(p) cstrhash(*(p)) -#define crawstr_len(literal) (sizeof("" literal) - 1U) +#define crawstr_len(literal) (c_sizeof("" literal) - 1) +#define c_ARRAYLEN(a) (intptr_t)(sizeof(a)/sizeof 0[a]) #define c_SV(...) c_MACRO_OVERLOAD(c_SV, __VA_ARGS__) -#define c_SV1(lit) c_SV2(lit, crawstr_len(lit)) -#define c_SV2(str, n) (c_INIT(csview){str, n}) +#define c_SV_1(lit) c_SV_2(lit, crawstr_len(lit)) +#define c_SV_2(str, n) (c_LITERAL(csview){str, n}) #define c_ARGSV(sv) (int)(sv).size, (sv).str /* use with "%.*s" */ #define c_PAIR(ref) (ref)->first, (ref)->second #define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) -STC_INLINE uint64_t cfasthash(const void* key, size_t len) { +STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) { const uint8_t *x = (const uint8_t*) key; - uint64_t u8, h = 1; size_t n = len >> 3; + uint64_t u8, h = 1; intptr_t n = len >> 3; uint32_t u4; while (n--) { memcpy(&u8, x, 8), x += 8; @@ -147,30 +157,32 @@ STC_INLINE uint64_t cfasthash(const void* key, size_t len) { } STC_INLINE uint64_t cstrhash(const char *str) - { return cfasthash(str, strlen(str)); } + { return cfasthash(str, c_strlen(str)); } STC_INLINE char* cstrnstrn(const char *str, const char *needle, - size_t slen, const size_t nlen) { + intptr_t slen, const intptr_t nlen) { if (!nlen) return (char *)str; if (nlen > slen) return NULL; slen -= nlen; do { - if (*str == *needle && !memcmp(str, needle, nlen)) + if (*str == *needle && !c_memcmp(str, needle, nlen)) return (char *)str; ++str; } while (slen--); return NULL; } +/* Control block macros */ + #define c_FOREACH(...) c_MACRO_OVERLOAD(c_FOREACH, __VA_ARGS__) -#define c_FOREACH3(it, C, cnt) \ +#define c_FOREACH_3(it, C, cnt) \ for (C##_iter it = C##_begin(&cnt); it.ref; C##_next(&it)) -#define c_FOREACH4(it, C, start, finish) \ +#define c_FOREACH_4(it, C, start, finish) \ for (C##_iter it = start, *_endref = (C##_iter*)(finish).ref \ ; it.ref != (C##_value*)_endref; C##_next(&it)) #define c_FORWHILE(i, C, start, cond) \ - for (struct {C##_iter it; C##_value *ref; size_t index;} \ + for (struct {C##_iter it; C##_value *ref; intptr_t index;} \ i = {.it=start, .ref=i.it.ref}; i.it.ref && (cond) \ ; C##_next(&i.it), i.ref = i.it.ref, ++i.index) @@ -180,17 +192,17 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, ; C##_next(&_.it)) #define c_FORRANGE(...) c_MACRO_OVERLOAD(c_FORRANGE, __VA_ARGS__) -#define c_FORRANGE1(stop) c_FORRANGE3(_c_i, 0, stop) -#define c_FORRANGE2(i, stop) c_FORRANGE3(i, 0, stop) -#define c_FORRANGE3(i, start, stop) \ +#define c_FORRANGE_1(stop) c_FORRANGE_3(_c_i, 0, stop) +#define c_FORRANGE_2(i, stop) c_FORRANGE_3(i, 0, stop) +#define c_FORRANGE_3(i, start, stop) \ for (long long i=start, _end=(long long)(stop); i < _end; ++i) -#define c_FORRANGE4(i, start, stop, step) \ +#define c_FORRANGE_4(i, start, stop, step) \ for (long long i=start, _inc=step, _end=(long long)(stop) - (_inc > 0) \ ; (_inc > 0) ^ (i > _end); i += _inc) #ifndef __cplusplus #define c_FORLIST(it, T, ...) \ for (struct {T* data; T* ref; int size, index;} \ - it = {.data=(T[])__VA_ARGS__, .ref=it.data, .size=sizeof((T[])__VA_ARGS__)/sizeof(T)} \ + it = {.data=(T[])__VA_ARGS__, .ref=it.data, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \ ; it.index < it.size; ++it.ref, ++it.index) #else #include <initializer_list> @@ -200,42 +212,44 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, ; it.index < it.size; ++it.ref, ++it.index) #endif #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_WITH_2(declvar, drop) for (declvar, **_c_i = NULL; !_c_i; ++_c_i, drop) +#define c_WITH_3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop) #define c_SCOPE(init, drop) for (int _c_i = (init, 1); _c_i; --_c_i, drop) #define c_DEFER(...) for (int _c_i = 1; _c_i; --_c_i, __VA_ARGS__) -#define c_DROP(C, ...) do { c_FORLIST (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0) #define c_AUTO(...) c_MACRO_OVERLOAD(c_AUTO, __VA_ARGS__) -#define c_AUTO2(C, a) \ - c_WITH2(C a = C##_init(), C##_drop(&a)) -#define c_AUTO3(C, a, b) \ - c_WITH2(c_EXPAND(C a = C##_init(), b = C##_init()), \ +#define c_AUTO_2(C, a) \ + c_WITH_2(C a = C##_init(), C##_drop(&a)) +#define c_AUTO_3(C, a, b) \ + c_WITH_2(c_EXPAND(C a = C##_init(), b = C##_init()), \ (C##_drop(&b), C##_drop(&a))) -#define c_AUTO4(C, a, b, c) \ - c_WITH2(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init()), \ +#define c_AUTO_4(C, a, b, c) \ + c_WITH_2(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_WITH2(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ +#define c_AUTO_5(C, a, b, c, d) \ + c_WITH_2(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_FIND_IF(...) c_MACRO_OVERLOAD(c_FIND_IF, __VA_ARGS__) -#define c_FIND_IF4(it, C, cnt, pred) do { \ - size_t index = 0; \ +/* Generic functions */ + +#define c_drop(C, ...) do { c_FORLIST (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0) +#define c_find_if(...) c_MACRO_OVERLOAD(c_find_if, __VA_ARGS__) +#define c_find_if_4(it, C, cnt, pred) do { \ + intptr_t index = 0; \ for (it = C##_begin(&cnt); it.ref && !(pred); C##_next(&it)) \ ++index; \ } while (0) -#define c_FIND_IF5(it, C, start, end, pred) do { \ - size_t index = 0; \ +#define c_find_if_5(it, C, start, end, pred) do { \ + intptr_t index = 0; \ const C##_value* _endref = (end).ref; \ for (it = start; it.ref != _endref && !(pred); C##_next(&it)) \ ++index; \ if (it.ref == _endref) it.ref = NULL; \ } while (0) -#define c_ERASE_IF(it, C, cnt, pred) do { \ +#define c_erase_if(it, C, cnt, pred) do { \ C##_iter it = C##_begin(&cnt); \ - for (size_t index = 0; it.ref; ++index) { \ + for (intptr_t index = 0; it.ref; ++index) { \ if (pred) it = C##_erase_at(&cnt, it); \ else C##_next(&it); \ } \ diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index 1fe52548..56c0e867 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -42,13 +42,16 @@ _cx_deftypes(_c_cdeq_types, _cx_self, i_key); typedef i_keyraw _cx_raw; STC_API _cx_self _cx_memb(_init)(void); -STC_API _cx_self _cx_memb(_with_capacity)(const size_t n); -STC_API bool _cx_memb(_reserve)(_cx_self* self, const size_t n); +STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n); +STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n); 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); - +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } #if !defined _i_queue #if !defined i_no_emplace STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, @@ -86,8 +89,8 @@ 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* self) { return self->_len; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; } STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } @@ -97,30 +100,30 @@ STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _ { i_keydrop(self->data); ++self->data; --self->_len; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - size_t n = self->_len; - return c_INIT(_cx_iter){n ? self->data : NULL, self->data + n}; + intptr_t n = self->_len; + return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n}; } STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL, self->data + self->_len}; } + { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; } 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 n) +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_queue -STC_INLINE size_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) - { return (size_t)(it.ref - self->data); } +STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) + { return (it.ref - self->data); } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } -STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const size_t idx) { +STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } -STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { +STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } @@ -128,11 +131,11 @@ STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } STC_INLINE _cx_iter -_cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { +_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) { return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } STC_INLINE _cx_iter -_cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { +_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -141,7 +144,7 @@ _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { } STC_INLINE _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const size_t idx, const size_t n) { +_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); } STC_INLINE _cx_iter @@ -164,7 +167,7 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { } STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { +_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) { return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -204,7 +207,7 @@ _cx_memb(_sort)(_cx_self* self) { /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) -#define _cdeq_nfront(self) (size_t)((self)->data - (self)->_base) +#define _cdeq_nfront(self) ((self)->data - (self)->_base) STC_DEF _cx_self _cx_memb(_init)(void) { @@ -225,8 +228,8 @@ _cx_memb(_clear)(_cx_self* self) { STC_DEF void _cx_memb(_shrink_to_fit)(_cx_self *self) { if (self->_len != self->_cap) { - memmove(self->_base, self->data, self->_len*sizeof(i_key)); - _cx_value* d = (_cx_value*)c_REALLOC(self->_base, self->_len*sizeof(i_key)); + c_memmove(self->_base, self->data, self->_len*c_sizeof(i_key)); + _cx_value* d = (_cx_value*)c_realloc(self->_base, self->_len*c_sizeof(i_key)); if (d) { self->_base = d; self->_cap = self->_len; @@ -239,15 +242,15 @@ STC_DEF void _cx_memb(_drop)(_cx_self* self) { if (self->_base) { _cx_memb(_clear)(self); - c_FREE(self->_base); + c_free(self->_base); } } -static size_t -_cx_memb(_realloc_)(_cx_self* self, const size_t n) { - const size_t cap = (size_t)((float)self->_len*1.7f) + n + 7U; - const size_t nfront = _cdeq_nfront(self); - _cx_value* d = (_cx_value*)c_REALLOC(self->_base, cap*sizeof(i_key)); +static intptr_t +_cx_memb(_realloc_)(_cx_self* self, const intptr_t n) { + const intptr_t cap = (intptr_t)((float)self->_len*1.7f) + n + 7; + const intptr_t nfront = _cdeq_nfront(self); + _cx_value* d = (_cx_value*)c_realloc(self->_base, cap*c_sizeof(i_key)); if (!d) return 0; self->_cap = cap; @@ -257,37 +260,37 @@ _cx_memb(_realloc_)(_cx_self* self, const size_t n) { } static bool -_cx_memb(_expand_right_half_)(_cx_self* self, const size_t idx, const size_t n) { - const size_t sz = self->_len, cap = self->_cap; - const size_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; - if (nback >= n || (size_t)((float)sz*1.3f) + n > cap) { +_cx_memb(_expand_right_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) { + const intptr_t sz = self->_len, cap = self->_cap; + const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; + if (nback >= n || (intptr_t)((float)sz*1.3f) + n > cap) { if (!_cx_memb(_realloc_)(self, n)) return false; - memmove(self->data + idx + n, self->data + idx, (sz - idx)*sizeof(i_key)); + c_memmove(self->data + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); } else { #if !defined _i_queue - const size_t unused = cap - (sz + n); - const size_t pos = (nfront*2 < unused) ? nfront : unused/2; + const intptr_t unused = cap - (sz + n); + const intptr_t pos = (nfront*2 < unused) ? nfront : unused/2; #else - const size_t pos = 0; + const intptr_t pos = 0; #endif - memmove(self->_base + pos, self->data, idx*sizeof(i_key)); - memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*sizeof(i_key)); + c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key)); + c_memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); self->data = self->_base + pos; } return true; } STC_DEF _cx_self -_cx_memb(_with_capacity)(const size_t n) { +_cx_memb(_with_capacity)(const intptr_t n) { _cx_self cx = _cx_memb(_init)(); _cx_memb(_expand_right_half_)(&cx, 0, n); return cx; } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const size_t n) { - const size_t sz = self->_len; +_cx_memb(_reserve)(_cx_self* self, const intptr_t n) { + const intptr_t sz = self->_len; return n <= sz || _cx_memb(_expand_right_half_)(self, sz, n - sz); } @@ -305,7 +308,7 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { _cx_self out = _cx_memb(_with_capacity)(cx._len); if (out._base) - for (size_t i = 0; i < cx._len; ++i) + for (intptr_t i = 0; i < cx._len; ++i) out.data[i] = i_keyclone(cx.data[i]); return out; } @@ -314,27 +317,27 @@ _cx_memb(_clone)(_cx_self cx) { #if !defined _i_queue static void -_cx_memb(_expand_left_half_)(_cx_self* self, const size_t idx, const size_t n) { - size_t cap = self->_cap; - const size_t sz = self->_len; - const size_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; +_cx_memb(_expand_left_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) { + intptr_t cap = self->_cap; + const intptr_t sz = self->_len; + const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; if (nfront >= n) { - self->data = (_cx_value *)memmove(self->data - n, self->data, idx*sizeof(i_key)); + self->data = (_cx_value *)c_memmove(self->data - n, self->data, idx*c_sizeof(i_key)); } else { - if ((size_t)((float)sz*1.3f) + n > cap) + if ((intptr_t)((float)sz*1.3f) + n > cap) cap = _cx_memb(_realloc_)(self, n); - const size_t unused = cap - (sz + n); - const size_t pos = (nback*2 < unused) ? unused - nback : unused/2; - memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*sizeof(i_key)); - self->data = (_cx_value *)memmove(self->_base + pos, self->data, idx*sizeof(i_key)); + const intptr_t unused = cap - (sz + n); + const intptr_t pos = (nback*2 < unused) ? unused - nback : unused/2; + c_memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); + self->data = (_cx_value *)c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key)); } } static _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) { if (n) { if (!pos) pos = self->data + self->_len; - const size_t idx = (size_t)(pos - self->data); + const intptr_t idx = (pos - self->data); if (idx*2 < self->_len) _cx_memb(_expand_left_half_)(self, idx, n); else @@ -342,7 +345,7 @@ _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { self->_len += n; pos = self->data + idx; } - return c_INIT(_cx_iter){pos, self->data + self->_len}; + return c_LITERAL(_cx_iter){pos, self->data + self->_len}; } STC_DEF _cx_value* @@ -359,9 +362,9 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { 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, (size_t)(p2 - p1)); + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); if (it.ref) - memcpy(it.ref, p1, (size_t)(p2 - p1)*sizeof *p1); + c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1); return it; } @@ -372,16 +375,16 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { _cx_value* p = p1, *end = self->data + self->_len; for (; p != p2; ++p) { i_keydrop(p); } - memmove(p1, p2, (size_t)(end - p2)*sizeof *p1); - self->_len -= (size_t)len; - return c_INIT(_cx_iter){p2 == end ? NULL : p1, end - len}; + c_memmove(p1, p2, (end - p2)*c_sizeof *p1); + self->_len -= len; + return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len}; } #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, (size_t)(p2 - p1)); + _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)); @@ -393,7 +396,7 @@ _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, 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, (size_t)(p2 - p1)); + _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)); diff --git a/include/stc/clist.h b/include/stc/clist.h index 37fa447a..283c8774 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -64,7 +64,7 @@ SELF##_value value; \ } -#define _clist_tonode(vp) c_CONTAINER_OF(vp, _cx_node, value) +#define _clist_tonode(vp) c_container_of(vp, _cx_node, value) _c_clist_types(clist_VOID, int); _c_clist_complete_types(clist_VOID, dummy); @@ -98,7 +98,7 @@ STC_API _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); #if !defined i_no_cmp -STC_API size_t _cx_memb(_remove)(_cx_self* self, _cx_raw val); +STC_API intptr_t _cx_memb(_remove)(_cx_self* self, _cx_raw val); STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val); STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); STC_API int _cx_memb(_sort_cmp_)(const clist_VOID_node* x, const clist_VOID_node* y); @@ -133,8 +133,12 @@ STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push_back)(self, i_keyfrom(raw)); } #endif // !i_no_emplace -STC_INLINE _cx_self _cx_memb(_init)(void) { return c_INIT(_cx_self){NULL}; } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { return true; } +STC_INLINE _cx_self _cx_memb(_init)(void) { return c_LITERAL(_cx_self){NULL}; } +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push_back)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) { return true; } STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return self->last == NULL; } STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); } STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, i_key value) @@ -146,9 +150,9 @@ STC_INLINE _cx_node* _cx_memb(_unlink_node_front)(_cx_self* self) STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; } STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; } -STC_INLINE size_t +STC_INLINE intptr_t _cx_memb(_count)(const _cx_self* self) { - size_t n = 1; const _cx_node *node = self->last; + intptr_t n = 1; const _cx_node *node = self->last; if (!node) return 0; while ((node = node->next) != self->last) ++n; return n; @@ -157,12 +161,12 @@ _cx_memb(_count)(const _cx_self* self) { STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { _cx_value* head = self->last ? &self->last->next->value : NULL; - return c_INIT(_cx_iter){head, &self->last, self->last}; + return c_LITERAL(_cx_iter){head, &self->last, self->last}; } STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL}; } + { return c_LITERAL(_cx_iter){NULL}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) { @@ -344,7 +348,7 @@ STC_DEF void _cx_memb(_erase_node_after)(_cx_self* self, _cx_node* ref) { _cx_node* node = _cx_memb(_unlink_node_after)(self, ref); i_keydrop((&node->value)); - c_FREE(node); + c_free(node); } STC_DEF _cx_node* @@ -410,9 +414,9 @@ _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val) { it2.ref = NULL; return it2; } -STC_DEF size_t +STC_DEF intptr_t _cx_memb(_remove)(_cx_self* self, _cx_raw val) { - size_t n = 0; + intptr_t n = 0; _cx_node *prev = self->last, *node; if (prev) do { node = prev->next; diff --git a/include/stc/cmap.h b/include/stc/cmap.h index df3ce6fc..393df53f 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -53,7 +53,7 @@ int main(void) { #include "forward.h" #include <stdlib.h> #include <string.h> -typedef struct { size_t idx; uint8_t hx; } chash_bucket_t; +typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -73,6 +73,12 @@ typedef struct { size_t idx; uint8_t hx; } chash_bucket_t; #ifndef i_max_load_factor #define i_max_load_factor 0.85f #endif +#ifndef i_size + #define i_size int32_t + #define _i_expandby 1 +#else + #define _i_expandby 2 +#endif #include "priv/template.h" #ifndef i_hash_functor #define i_hash_functor(self, x) i_hash(x) @@ -96,25 +102,25 @@ typedef _i_SET_ONLY( i_keyraw ) i_valraw second; } ) _cx_raw; -STC_API _cx_self _cx_memb(_with_capacity)(size_t cap); +STC_API _cx_self _cx_memb(_with_capacity)(int64_t cap); #if !defined i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self map); #endif STC_API void _cx_memb(_drop)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t capacity); +STC_API bool _cx_memb(_reserve)(_cx_self* self, int64_t capacity); STC_API chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr); STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_rawkey rkey); STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val); -STC_INLINE _cx_self _cx_memb(_init)(void) { return c_INIT(_cx_self){0}; } +STC_INLINE _cx_self _cx_memb(_init)(void) { return c_LITERAL(_cx_self){0}; } STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, self->size); } STC_INLINE float _cx_memb(_max_load_factor)(const _cx_self* self) { return (float)(i_max_load_factor); } STC_INLINE bool _cx_memb(_empty)(const _cx_self* map) { return !map->size; } -STC_INLINE size_t _cx_memb(_size)(const _cx_self* map) { return map->size; } -STC_INLINE size_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* map) - { return (size_t)((float)map->bucket_count * (i_max_load_factor)); } +STC_INLINE int64_t _cx_memb(_size)(const _cx_self* map) { return map->size; } +STC_INLINE int64_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } +STC_INLINE int64_t _cx_memb(_capacity)(const _cx_self* map) + { return (int64_t)((float)map->bucket_count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_rawkey rkey) { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } @@ -166,7 +172,7 @@ _cx_memb(_emplace)(_cx_self* self, _cx_rawkey rkey _i_MAP_ONLY(, i_valraw rmappe STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { return _i_SET_ONLY( i_keyto(val) ) - _i_MAP_ONLY( c_INIT(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); + _i_MAP_ONLY( c_LITERAL(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); } STC_INLINE void @@ -195,8 +201,23 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { return _res; } -STC_INLINE _cx_iter -_cx_memb(_begin)(const _cx_self* self) { +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, int64_t n) { + while (n--) +#if defined _i_isset && defined i_no_emplace + _cx_memb(_insert)(self, *raw++); +#elif defined _i_isset + _cx_memb(_emplace)(self, *raw++); +#elif defined i_no_emplace + _cx_memb(_insert_or_assign)(self, raw->first, raw->second), ++raw; +#else + _cx_memb(_emplace_or_assign)(self, raw->first, raw->second), ++raw; +#endif +} + +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, int64_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { _cx_iter it = {self->table, self->table+self->bucket_count, self->_hashx}; if (it._hx) while (*it._hx == 0) @@ -207,7 +228,7 @@ _cx_memb(_begin)(const _cx_self* self) { STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL}; } + { return c_LITERAL(_cx_iter){NULL}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) { @@ -216,16 +237,16 @@ _cx_memb(_next)(_cx_iter* it) { } STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { +_cx_memb(_advance)(_cx_iter it, uint64_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) { - size_t idx; + int64_t idx; if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx]) - return c_INIT(_cx_iter){self->table + idx, + return c_LITERAL(_cx_iter){self->table + idx, self->table + self->bucket_count, self->_hashx + idx}; return _cx_memb(_end)(self); @@ -233,7 +254,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey) { STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_rawkey rkey) { - size_t idx; + int64_t idx; if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx]) return self->table + idx; return NULL; @@ -243,12 +264,12 @@ STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey) { return (_cx_value*)_cx_memb(_get)(self, rkey); } -STC_INLINE size_t +STC_INLINE int _cx_memb(_erase)(_cx_self* self, _cx_rawkey rkey) { if (self->size == 0) return 0; chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); - return self->_hashx[b.idx] ? _cx_memb(_erase_entry)(self, self->table + b.idx), 1U : 0U; + return self->_hashx[b.idx] ? _cx_memb(_erase_entry)(self, self->table + b.idx), 1 : 0; } STC_INLINE _cx_iter @@ -263,11 +284,11 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { #if defined(i_implement) #ifndef CMAP_H_INCLUDED -STC_INLINE size_t fastrange_1(uint64_t x, uint64_t n) - { return (size_t)((uint32_t)x*n >> 32); } // n < 2^32 +STC_INLINE int64_t fastrange_1(uint64_t x, uint64_t n) + { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^32 -STC_INLINE size_t fastrange_2(uint64_t x, uint64_t n) - { return x & (n - 1); } // n power of 2. +STC_INLINE int64_t fastrange_2(uint64_t x, uint64_t n) + { return (int64_t)(x & (n - 1)); } // n power of 2. STC_INLINE uint64_t next_power_of_2(uint64_t n) { n--; @@ -279,7 +300,7 @@ STC_INLINE uint64_t next_power_of_2(uint64_t n) { #endif // CMAP_H_INCLUDED STC_DEF _cx_self -_cx_memb(_with_capacity)(const size_t cap) { +_cx_memb(_with_capacity)(const int64_t cap) { _cx_self h = {0}; _cx_memb(_reserve)(&h, cap); return h; @@ -297,14 +318,14 @@ STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { STC_DEF void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_wipe_)(self); - c_FREE(self->_hashx); - c_FREE((void *) self->table); + c_free(self->_hashx); + c_free((void *) self->table); } STC_DEF void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_wipe_)(self); self->size = 0; - memset(self->_hashx, 0, self->bucket_count); + c_memset(self->_hashx, 0, self->bucket_count); } #ifndef _i_isset @@ -339,8 +360,8 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { STC_DEF chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { const uint64_t _hash = i_hash_functor(self, rkeyptr); - i_size _cap = self->bucket_count; - chash_bucket_t b = {c_PASTE(fastrange_,_i_expandby)(_hash, _cap), (uint8_t)(_hash | 0x80)}; + int64_t _cap = self->bucket_count; + chash_bucket_t b = {c_PASTE(fastrange_,_i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; const uint8_t* _hx = self->_hashx; while (_hx[b.idx]) { if (_hx[b.idx] == b.hx) { @@ -375,9 +396,9 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self m) { if (m.table) { _cx_value *t = c_ALLOC_N(_cx_value, m.bucket_count), *dst = t, *m_end = m.table + m.bucket_count; - uint8_t *h = (uint8_t *)memcpy(c_MALLOC(m.bucket_count + 1), m._hashx, m.bucket_count + 1); + uint8_t *h = (uint8_t *)c_memcpy(c_malloc(m.bucket_count + 1), m._hashx, m.bucket_count + 1); if (!(t && h)) - { c_FREE(t), c_FREE(h), t = 0, h = 0, m.bucket_count = 0; } + { c_free(t), c_free(h), t = 0, h = 0, m.bucket_count = 0; } else for (; m.table != m_end; ++m.table, ++m._hashx, ++dst) if (*m._hashx) @@ -389,8 +410,8 @@ _cx_memb(_clone)(_cx_self m) { #endif STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const size_t _newcap) { - const i_size _oldbuckets = self->bucket_count; +_cx_memb(_reserve)(_cx_self* self, const int64_t newcap) { + const i_size _oldbuckets = self->bucket_count, _newcap = (i_size)newcap; if (_newcap != self->size && _newcap <= _oldbuckets) return true; i_size _nbuckets = (i_size)((float)_newcap / (i_max_load_factor)) + 4; @@ -401,24 +422,24 @@ _cx_memb(_reserve)(_cx_self* self, const size_t _newcap) { #endif _cx_self m = { c_ALLOC_N(_cx_value, _nbuckets), - (uint8_t *) c_CALLOC(_nbuckets + 1, 1), - self->size, (i_size)_nbuckets, + (uint8_t *) c_calloc(_nbuckets + 1, 1), + self->size, _nbuckets, }; bool ok = m.table && m._hashx; if (ok) { /* Rehash: */ m._hashx[_nbuckets] = 0xff; const _cx_value* e = self->table; const uint8_t* h = self->_hashx; - for (size_t i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { + for (i_size i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { _cx_rawkey r = i_keyto(_i_keyref(e)); chash_bucket_t b = _cx_memb(_bucket_)(&m, &r); m.table[b.idx] = *e; - m._hashx[b.idx] = (uint8_t)b.hx; + m._hashx[b.idx] = b.hx; } - c_SWAP(_cx_self, self, &m); + c_swap(_cx_self, self, &m); } - c_FREE(m._hashx); - c_FREE(m.table); + c_free(m._hashx); + c_free(m.table); return ok; } @@ -435,7 +456,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! _hashx[j]) break; const _cx_rawkey _raw = i_keyto(_i_keyref(_slot + j)); - k = (i_size)c_PASTE(fastrange_,_i_expandby)(i_hash_functor(self, (&_raw)), _cap); + k = (i_size)c_PASTE(fastrange_,_i_expandby)(i_hash_functor(self, (&_raw)), (uint64_t)_cap); if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ _slot[i] = _slot[j], _hashx[i] = _hashx[j], i = j; } diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 28b5eb86..55df70ef 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -41,47 +41,53 @@ typedef i_keyraw _cx_raw; STC_API void _cx_memb(_make_heap)(_cx_self* self); -STC_API void _cx_memb(_erase_at)(_cx_self* self, size_t idx); +STC_API void _cx_memb(_erase_at)(_cx_self* self, intptr_t idx); STC_API void _cx_memb(_push)(_cx_self* self, _cx_value value); STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_INIT(_cx_self){NULL}; } + { return c_LITERAL(_cx_self){NULL}; } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, const size_t cap) { +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } + +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } + +STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { if (cap != self->_len && cap <= self->_cap) return true; - _cx_value *d = (_cx_value *)c_REALLOC(self->data, cap*sizeof *d); + _cx_value *d = (_cx_value *)c_realloc(self->data, cap*c_sizeof *d); return d ? (self->data = d, self->_cap = cap, true) : false; } STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, self->_len); } -STC_INLINE _cx_self _cx_memb(_with_capacity)(const size_t cap) { +STC_INLINE _cx_self _cx_memb(_with_capacity)(const intptr_t cap) { _cx_self out = {NULL}; _cx_memb(_reserve)(&out, cap); return out; } -STC_INLINE _cx_self _cx_memb(_with_size)(const size_t size, i_key null) { +STC_INLINE _cx_self _cx_memb(_with_size)(const intptr_t size, i_key null) { _cx_self out = {NULL}; _cx_memb(_reserve)(&out, size); while (out._len < size) out.data[out._len++] = null; return out; } STC_INLINE void _cx_memb(_clear)(_cx_self* self) { - size_t i = self->_len; self->_len = 0; + intptr_t i = self->_len; self->_len = 0; while (i--) { i_keydrop((self->data + i)); } } STC_INLINE void _cx_memb(_drop)(_cx_self* self) - { _cx_memb(_clear)(self); c_FREE(self->data); } + { _cx_memb(_clear)(self); c_free(self->data); } -STC_INLINE size_t _cx_memb(_size)(const _cx_self* q) +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* q) { return q->_len; } STC_INLINE bool _cx_memb(_empty)(const _cx_self* q) { return !q->_len; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* q) +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* q) { return q->_cap; } STC_INLINE const _cx_value* _cx_memb(_top)(const _cx_self* self) @@ -111,9 +117,9 @@ STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) #if defined(i_implement) STC_DEF void -_cx_memb(_sift_down_)(_cx_self* self, const size_t idx, const size_t n) { +_cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) { _cx_value t, *arr = self->data - 1; - for (size_t r = idx, c = idx*2; c <= n; c *= 2) { + for (intptr_t r = idx, c = idx*2; c <= n; c *= 2) { c += i_less_functor(self, (&arr[c]), (&arr[c + (c < n)])); if (!(i_less_functor(self, (&arr[r]), (&arr[c])))) return; t = arr[r], arr[r] = arr[c], arr[r = c] = t; @@ -122,8 +128,8 @@ _cx_memb(_sift_down_)(_cx_self* self, const size_t idx, const size_t n) { STC_DEF void _cx_memb(_make_heap)(_cx_self* self) { - size_t n = self->_len; - for (size_t k = n/2; k != 0; --k) + intptr_t n = self->_len; + for (intptr_t k = n/2; k != 0; --k) _cx_memb(_sift_down_)(self, k, n); } @@ -137,9 +143,9 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self q) { #endif STC_DEF void -_cx_memb(_erase_at)(_cx_self* self, const size_t idx) { +_cx_memb(_erase_at)(_cx_self* self, const intptr_t idx) { i_keydrop((self->data + idx)); - const size_t n = --self->_len; + const intptr_t n = --self->_len; self->data[idx] = self->data[n]; _cx_memb(_sift_down_)(self, idx + 1, n); } @@ -149,7 +155,7 @@ _cx_memb(_push)(_cx_self* self, _cx_value value) { if (self->_len == self->_cap) _cx_memb(_reserve)(self, self->_len*3/2 + 4); _cx_value *arr = self->data - 1; /* base 1 */ - size_t c = ++self->_len; + intptr_t c = ++self->_len; for (; c > 1 && (i_less_functor(self, (&arr[c/2]), (&value))); c /= 2) arr[c] = arr[c/2]; arr[c] = value; diff --git a/include/stc/crandom.h b/include/stc/crandom.h index 733c3ec5..32e541ff 100644 --- a/include/stc/crandom.h +++ b/include/stc/crandom.h @@ -46,7 +46,7 @@ int main() { typedef struct stc64 { uint64_t state[5]; } stc64_t; typedef struct stc64_uniform { int64_t lower; uint64_t range, threshold; } stc64_uniform_t; typedef struct stc64_uniformf { double lower, range; } stc64_uniformf_t; -typedef struct stc64_normalf { double mean, stddev, next; unsigned has_next; } stc64_normalf_t; +typedef struct stc64_normalf { double mean, stddev, next; int has_next; } stc64_normalf_t; /* PRNG stc64. * Very fast PRNG suited for parallel usage with Weyl-sequence parameter. @@ -100,12 +100,12 @@ STC_INLINE double stc64_uniformf(stc64_t* rng, stc64_uniformf_t* dist) { /* Init uniform distributed float64 RNG, range [low, high). */ STC_INLINE stc64_uniformf_t stc64_uniformf_new(double low, double high) { - return c_INIT(stc64_uniformf_t){low, high - low}; + return c_LITERAL(stc64_uniformf_t){low, high - low}; } /* Marsaglia polar method for gaussian/normal distribution, float64. */ STC_INLINE stc64_normalf_t stc64_normalf_new(double mean, double stddev) { - return c_INIT(stc64_normalf_t){mean, stddev, 0.0, 0}; + return c_LITERAL(stc64_normalf_t){mean, stddev, 0.0, 0}; } /* -------------------------- IMPLEMENTATION ------------------------- */ diff --git a/include/stc/cregex.h b/include/stc/cregex.h index 4bb17938..564fe157 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -33,6 +33,7 @@ THE SOFTWARE. #include <stdbool.h> #include <string.h> #include "forward.h" // csview +#include "ccommon.h" enum { CREG_DEFAULT = 0, @@ -81,69 +82,87 @@ typedef struct { #define c_FORMATCH(it, Re, Input) \ for (cregex_iter it = {Re, Input}; \ - cregex_find(it.re, it.input, it.match, CREG_M_NEXT) == CREG_OK; ) + cregex_find_4(it.re, it.input, it.match, CREG_M_NEXT) == CREG_OK; ) -static inline -cregex cregex_init(void) { +STC_INLINE cregex cregex_init(void) { cregex re = {0}; return re; } /* return CREG_OK, or negative error code on failure. */ -int cregex_compile(cregex *self, const char* pattern, int cflags); +#define cregex_compile(...) c_MACRO_OVERLOAD(cregex_compile, __VA_ARGS__) +#define cregex_compile_2(re, pattern) cregex_compile_3(re, pattern, CREG_DEFAULT) +int cregex_compile_3(cregex *re, const char* pattern, int cflags); -static inline -cregex cregex_from(const char* pattern, int cflags) { +/* construct and return a regex from a pattern. */ +#define cregex_from(...) c_MACRO_OVERLOAD(cregex_from, __VA_ARGS__) +#define cregex_from_1(pattern) cregex_from_2(pattern, CREG_DEFAULT) + +STC_INLINE cregex cregex_from_2(const char* pattern, int cflags) { cregex re = {0}; - cregex_compile(&re, pattern, cflags); + cregex_compile_3(&re, pattern, cflags); return re; } -/* number of capture groups in a regex pattern, 0 if regex is invalid */ -unsigned cregex_captures(const cregex* self); +/* number of capture groups in a regex pattern including full the match capture, 0 if regex is invalid */ +int cregex_captures(const cregex* re); /* return CREG_OK, CREG_NOMATCH or CREG_MATCHERROR. */ -int cregex_find(const cregex* re, const char* input, - csview match[], int mflags); -static inline -int cregex_find_sv(const cregex* re, csview input, csview match[]) { +#define cregex_find(...) c_MACRO_OVERLOAD(cregex_find, __VA_ARGS__) +#define cregex_find_3(re, input, match) cregex_find_4(re, input, match, CREG_DEFAULT) +int cregex_find_4(const cregex* re, const char* input, csview match[], int mflags); + +/* find with csview as input. */ +STC_INLINE int cregex_find_sv(const cregex* re, csview input, csview match[]) { csview *mp = NULL; if (match) { match[0] = input; mp = match; } return cregex_find(re, input.str, mp, CREG_M_STARTEND); } /* match + compile RE pattern */ -int cregex_find_pattern(const char* pattern, const char* input, - csview match[], int cmflags); - -static inline -bool cregex_is_match(const cregex* re, const char* input) - { return cregex_find(re, input, NULL, CREG_DEFAULT) == CREG_OK; } - -/* replace regular expression */ -cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, unsigned count, +#define cregex_find_pattern(...) c_MACRO_OVERLOAD(cregex_find_pattern, __VA_ARGS__) +#define cregex_find_pattern_3(pattern, input, match) \ + cregex_find_pattern_4(pattern, input, match, CREG_DEFAULT) +int cregex_find_pattern_4(const char* pattern, const char* input, + csview match[], int cmflags); + +STC_INLINE bool cregex_is_match(const cregex* re, const char* input) + { return cregex_find_4(re, input, NULL, CREG_DEFAULT) == CREG_OK; } + +/* replace csview input with replace using regular expression pattern */ +#define cregex_replace_sv(...) c_MACRO_OVERLOAD(cregex_replace_sv, __VA_ARGS__) +#define cregex_replace_sv_3(pattern, input, replace) \ + cregex_replace_sv_4(pattern, input, replace, INT32_MAX) +#define cregex_replace_sv_4(pattern, input, replace, count) \ + cregex_replace_sv_6(pattern, input, replace, count, NULL, CREG_DEFAULT) +cstr cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, bool (*mfun)(int i, csview match, cstr* mstr), int rflags); -static inline -cstr cregex_replace(const cregex* re, const char* input, const char* replace) { - csview sv = {input, strlen(input)}; - return cregex_replace_sv(re, sv, replace, ~0U, NULL, CREG_DEFAULT); +/* replace input with replace using regular expression */ +#define cregex_replace(...) c_MACRO_OVERLOAD(cregex_replace, __VA_ARGS__) +#define cregex_replace_3(re, input, replace) cregex_replace_4(re, input, replace, INT32_MAX) + +STC_INLINE cstr cregex_replace_4(const cregex* re, const char* input, const char* replace, int count) { + csview sv = {input, c_strlen(input)}; + return cregex_replace_sv_4(re, sv, replace, count); } /* replace + compile RE pattern, and extra arguments */ -cstr cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count, - bool (*mfun)(int i, csview match, cstr* mstr), int crflags); -static inline -cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace) - { return cregex_replace_pattern_ex(pattern, input, replace, ~0U, NULL, CREG_DEFAULT); } +#define cregex_replace_pattern(...) c_MACRO_OVERLOAD(cregex_replace_pattern, __VA_ARGS__) +#define cregex_replace_pattern_3(pattern, input, replace) \ + cregex_replace_pattern_4(pattern, input, replace, INT32_MAX) +#define cregex_replace_pattern_4(pattern, input, replace, count) \ + cregex_replace_pattern_6(pattern, input, replace, count, NULL, CREG_DEFAULT) +cstr cregex_replace_pattern_6(const char* pattern, const char* input, const char* replace, int count, + bool (*mfun)(int i, csview match, cstr* mstr), int crflags); /* destroy regex */ -void cregex_drop(cregex* self); +void cregex_drop(cregex* re); #endif // CREGEX_H_INCLUDED #if defined i_extern || defined STC_EXTERN -# include "../src/cregex.c" -# include "../src/utf8code.c" +# include "../../src/cregex.c" +# include "../../src/utf8code.c" #endif #undef i_opt #undef i_header diff --git a/include/stc/csmap.h b/include/stc/csmap.h index e5df0fe2..0f21f954 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -73,6 +73,9 @@ int main(void) { #define _i_SET_ONLY c_false #define _i_keyref(vp) (&(vp)->first) #endif +#ifndef i_size + #define i_size int32_t +#endif #include "priv/template.h" #ifndef i_cmp_functor #define i_cmp_functor(self, x, y) i_cmp(x, y) @@ -107,7 +110,7 @@ STC_API _cx_self _cx_memb(_init)(void); STC_API _cx_result _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)); STC_API _cx_result _cx_memb(_push)(_cx_self* self, _cx_value _val); STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t cap); +STC_API bool _cx_memb(_reserve)(_cx_self* self, int64_t cap); STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out); STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, _cx_rawkey rkey); STC_API _cx_value* _cx_memb(_front)(const _cx_self* self); @@ -118,8 +121,8 @@ STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx STC_API void _cx_memb(_next)(_cx_iter* it); STC_INLINE bool _cx_memb(_empty)(const _cx_self* cx) { return cx->size == 0; } -STC_INLINE size_t _cx_memb(_size)(const _cx_self* cx) { return cx->size; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* cx) { return cx->cap; } +STC_INLINE int64_t _cx_memb(_size)(const _cx_self* cx) { return cx->size; } +STC_INLINE int64_t _cx_memb(_capacity)(const _cx_self* cx) { return cx->cap; } STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey) { _cx_iter it; _cx_memb(_find_it)(self, rkey, &it); return it; } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_rawkey rkey) @@ -130,7 +133,7 @@ STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey) { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } STC_INLINE _cx_self -_cx_memb(_with_capacity)(const size_t cap) { +_cx_memb(_with_capacity)(const int64_t cap) { _cx_self tree = _cx_memb(_init)(); _cx_memb(_reserve)(&tree, cap); return tree; @@ -143,7 +146,7 @@ _cx_memb(_clear)(_cx_self* self) STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { return _i_SET_ONLY( i_keyto(val) ) - _i_MAP_ONLY( c_INIT(_cx_raw){i_keyto((&val->first)), + _i_MAP_ONLY( c_LITERAL(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); } @@ -209,7 +212,7 @@ _cx_memb(_end)(const _cx_self* self) { } STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { +_cx_memb(_advance)(_cx_iter it, uint64_t n) { while (n-- && it.ref) _cx_memb(_next)(&it); return it; @@ -225,13 +228,13 @@ _cx_memb(_init)(void) { } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const size_t cap) { - if (cap <= self->cap) +_cx_memb(_reserve)(_cx_self* self, const int64_t cap) { + if ((i_size)cap <= self->cap) return false; - _cx_node* nodes = (_cx_node*)c_REALLOC(self->nodes, (cap + 1)*sizeof(_cx_node)); + _cx_node* nodes = (_cx_node*)c_realloc(self->nodes, (cap + 1)*c_sizeof(_cx_node)); if (!nodes) return false; - nodes[0] = c_INIT(_cx_node){{0, 0}, 0}; + nodes[0] = c_LITERAL(_cx_node){{0, 0}, 0}; self->nodes = nodes; self->cap = (i_size)cap; return true; @@ -294,6 +297,22 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { return _res; } +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, int64_t n) { + while (n--) +#if defined _i_isset && defined i_no_emplace + _cx_memb(_insert)(self, *raw++); +#elif defined _i_isset + _cx_memb(_emplace)(self, *raw++); +#elif defined i_no_emplace + _cx_memb(_insert_or_assign)(self, raw->first, raw->second), ++raw; +#else + _cx_memb(_emplace_or_assign)(self, raw->first, raw->second), ++raw; +#endif +} + +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, int64_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } + #ifndef _i_isset STC_DEF _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped) { @@ -562,7 +581,7 @@ STC_DEF void _cx_memb(_drop)(_cx_self* self) { if (self->cap) { _cx_memb(_drop_r_)(self->nodes, self->root); - c_FREE(self->nodes); + c_free(self->nodes); } } diff --git a/include/stc/cspan.h b/include/stc/cspan.h index a4c8f5cb..68a13522 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -30,28 +30,27 @@ using_cspan(Intspan, int, 1); int demo1() { float raw[4*5]; - Span2f ms = cspan_make(raw, 4, 5); + Span2f ms = cspan_md(raw, 4, 5); - for (size_t i=0; i<ms.dim[0]; i++) - for (size_t j=0; j<ms.dim[1]; j++) + for (int i=0; i<ms.shape[0]; i++) + for (int j=0; j<ms.shape[1]; j++) *cspan_at(&ms, i, j) = i*1000 + j; printf("%f\n", *cspan_at(&ms, 3, 4)); } int demo2() { - int array[] = {1, 2, 3, 4, 5}; + int array[] = {10, 20, 30, 23, 22, 21}; Intspan span = cspan_from_array(array); c_FOREACH (i, Intspan, span) printf(" %d", *i.ref); puts(""); - // use a temporary Intspan object. - c_FORFILTER (i, Intspan, cspan_literal(Intspan, {10, 20, 30, 23, 22, 21}) - , c_FLT_SKIPWHILE(i, *i.ref < 25) + c_FORFILTER (i, Intspan, span, + , c_flt_skipwhile(i, *i.ref < 25) && (*i.ref & 1) == 0 // even only - , c_FLT_TAKE(i, 2)) // break after 2 + , c_flt_take(i, 2)) // break after 2 printf(" %d", *i.ref); puts(""); } @@ -61,102 +60,190 @@ int demo2() { #include "ccommon.h" -#define using_cspan(Self, T, RANK) \ - typedef T Self##_value, Self##_raw; \ - typedef struct { Self##_value *ref, *end; } Self##_iter; \ - typedef struct { Self##_value *data; uint32_t dim[RANK]; } Self; \ +#define using_cspan(...) c_MACRO_OVERLOAD(using_cspan, __VA_ARGS__) +#define using_cspan_2(Self, T) using_cspan_3(Self, T, 1) +#define using_cspan_3(Self, T, RANK) \ + typedef T Self##_value; typedef T Self##_raw; \ + typedef struct { \ + Self##_value *data; \ + int32_t shape[RANK]; \ + cspan_idx##RANK stride; \ + } Self; \ + typedef struct { Self##_value *ref; int32_t pos[RANK]; const Self *_s; } Self##_iter; \ \ + STC_INLINE Self Self##_from_n(Self##_raw* raw, const intptr_t n) { \ + return (Self){.data=raw, .shape={(int32_t)n}}; \ + } \ + STC_INLINE Self Self##_slice_(Self##_value* v, const int32_t shape[], const int32_t stri[], \ + const int rank, const int32_t a[][2]) { \ + Self s = {.data=v}; int outrank; \ + s.data += _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \ + c_ASSERT(outrank == RANK); \ + return s; \ + } \ STC_INLINE Self##_iter Self##_begin(const Self* self) { \ - size_t n = cspan_size(self); \ - Self##_iter it = {n ? self->data : NULL, self->data + n}; \ + Self##_iter it = {.ref=self->data, .pos={0}, ._s=self}; \ return it; \ } \ STC_INLINE Self##_iter Self##_end(const Self* self) { \ - Self##_iter it = {NULL, self->data + cspan_size(self)}; \ + Self##_iter it = {.ref=NULL}; \ return it; \ } \ - STC_INLINE void Self##_next(Self##_iter* it) \ - { if (++it->ref == it->end) it->ref = NULL; } \ + STC_INLINE void Self##_next(Self##_iter* it) { \ + it->ref += _cspan_next##RANK(RANK, it->pos, it->_s->shape, it->_s->stride.d); \ + if (it->pos[0] == it->_s->shape[0]) it->ref = NULL; \ + } \ struct stc_nostruct -#define using_cspan2(Self, T) using_cspan(Self, T, 1); using_cspan(Self##2, T, 2) -#define using_cspan3(Self, T) using_cspan2(Self, T); using_cspan(Self##3, T, 3) -#define using_cspan4(Self, T) using_cspan3(Self, T); using_cspan(Self##4, T, 4) - -#define cspan_rank_ok(self, rank) c_STATIC_ASSERT(cspan_rank(self) == rank) - -#define cspan_make(array, ...) \ - {.data=array, .dim={__VA_ARGS__}} - +#define using_cspan2(Self, T) using_cspan_3(Self, T, 1); using_cspan_3(Self##2, T, 2) +#define using_cspan3(Self, T) using_cspan2(Self, T); using_cspan_3(Self##3, T, 3) +#define using_cspan4(Self, T) using_cspan3(Self, T); using_cspan_3(Self##4, T, 4) +typedef struct { int32_t d[1]; } cspan_idx1; +typedef struct { int32_t d[2]; } cspan_idx2; +typedef struct { int32_t d[3]; } cspan_idx3; +typedef struct { int32_t d[4]; } cspan_idx4; +typedef struct { int32_t d[5]; } cspan_idx5; +typedef struct { int32_t d[6]; } cspan_idx6; +#define c_END -1 +#define c_ALL 0,-1 + +#define cspan_md(array, ...) \ + {.data=array, .shape={__VA_ARGS__}, .stride={.d={__VA_ARGS__}}} + +/* For static initialization, use cspan_make(). c_make() for non-static only. */ +#define cspan_make(SpanType, ...) \ + {.data=(SpanType##_value[])__VA_ARGS__, .shape={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}} + +#define cspan_slice(OutSpan, parent, ...) \ + OutSpan##_slice_((parent)->data, (parent)->shape, (parent)->stride.d, cspan_rank(parent) + \ + c_static_assert(cspan_rank(parent) == sizeof((int32_t[][2]){__VA_ARGS__})/sizeof(int32_t[2])), \ + (const int32_t[][2]){__VA_ARGS__}) + /* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */ #define cspan_from(container) \ - {.data=(container)->data, .dim={(container)->_len}} + {.data=(container)->data, .shape={(int32_t)(container)->_len}} #define cspan_from_array(array) \ - {.data=(array) + c_STATIC_ASSERT(sizeof(array) != sizeof(void*)), .dim={c_ARRAYLEN(array)}} - -#define cspan_from_list(ValueType, ...) \ - {.data=(ValueType[])__VA_ARGS__, .dim={sizeof((ValueType[])__VA_ARGS__)/sizeof(ValueType)}} - -#define cspan_literal(SpanType, ...) \ - (c_INIT(SpanType)cspan_from_list(SpanType##_value, __VA_ARGS__)) - -#define cspan_size(self) _cspan_size((self)->dim, cspan_rank(self)) -#define cspan_rank(self) c_ARRAYLEN((self)->dim) -#define cspan_index(self, ...) \ - c_PASTE(_cspan_i, c_NUMARGS(__VA_ARGS__))((self)->dim, __VA_ARGS__) + \ - cspan_rank_ok(self, c_NUMARGS(__VA_ARGS__)) - -#define cspan_resize(self, ...) \ - (void)memcpy((self)->dim, (uint32_t[]){__VA_ARGS__}, \ - sizeof((self)->dim) + cspan_rank_ok(self, c_NUMARGS(__VA_ARGS__))) + {.data=(array) + c_static_assert(sizeof(array) != sizeof(void*)), .shape={c_ARRAYLEN(array)}} + +#define cspan_size(self) _cspan_size((self)->shape, cspan_rank(self)) +#define cspan_rank(self) c_ARRAYLEN((self)->shape) + +#define cspan_index(self, ...) c_PASTE(cspan_idx_, c_NUMARGS(__VA_ARGS__))(self, __VA_ARGS__) +#define cspan_idx_1 cspan_idx_4 +#define cspan_idx_2 cspan_idx_4 +#define cspan_idx_3 cspan_idx_4 +#define cspan_idx_4(self, ...) \ + c_PASTE(_cspan_idx, c_NUMARGS(__VA_ARGS__))((self)->shape, (self)->stride, __VA_ARGS__) // small/fast +#define cspan_idx_5(self, ...) \ + (_cspan_idxN(c_NUMARGS(__VA_ARGS__), (self)->shape, (self)->stride.d, (int32_t[]){__VA_ARGS__}) + \ + c_static_assert(cspan_rank(self) == c_NUMARGS(__VA_ARGS__))) // general +#define cspan_idx_6 cspan_idx_5 #define cspan_at(self, ...) ((self)->data + cspan_index(self, __VA_ARGS__)) #define cspan_front(self) ((self)->data) #define cspan_back(self) ((self)->data + cspan_size(self) - 1) +// cspan_subspanN. (N<4) Optimized, same as e.g. cspan_slice(Span3, &ms3, {off,off+count}, {c_ALL}, {c_ALL}); #define cspan_subspan(self, offset, count) \ - {.data=cspan_at(self, offset), .dim={count}} + {.data=cspan_at(self, offset), .shape={count}} #define cspan_subspan2(self, offset, count) \ - {.data=cspan_at(self, offset, 0), .dim={count, (self)->dim[1]}} + {.data=cspan_at(self, offset, 0), .shape={count, (self)->shape[1]}, .stride={(self)->stride}} #define cspan_subspan3(self, offset, count) \ - {.data=cspan_at(self, offset, 0, 0), .dim={count, (self)->dim[1], (self)->dim[2]}} -#define cspan_subspan4(self, offset, count) \ - {.data=cspan_at(self, offset, 0, 0, 0), .dim={count, (self)->dim[1], (self)->dim[2], (self)->dim[3]}} - -#define cspan_at4(...) c_MACRO_OVERLOAD(cspan_at4, __VA_ARGS__) -#define cspan_at3(...) c_MACRO_OVERLOAD(cspan_at3, __VA_ARGS__) -#define cspan_at2(self, x) \ - {.data=cspan_at(self, x, 0), .dim={(self)->dim[1]}} -#define cspan_at32(self, x) \ - {.data=cspan_at(self, x, 0, 0), .dim={(self)->dim[1], (self)->dim[2]}} -#define cspan_at33(self, x, y) \ - {.data=cspan_at(self, x, y, 0), .dim={(self)->dim[2]}} -#define cspan_at42(self, x) \ - {.data=cspan_at(self, x, 0, 0, 0), .dim={(self)->dim[1], (self)->dim[2], (self)->dim[3]}} -#define cspan_at43(self, x, y) \ - {.data=cspan_at(self, x, y, 0, 0), .dim={(self)->dim[2], (self)->dim[3]}} -#define cspan_at44(self, x, y, z) \ - {.data=cspan_at(self, x, y, z, 0), .dim={(self)->dim[3]}} - -STC_INLINE size_t _cspan_i1(const uint32_t dim[1], uint32_t x) - { c_ASSERT(x < dim[0]); return x; } - -STC_INLINE size_t _cspan_i2(const uint32_t dim[2], uint32_t x, uint32_t y) - { c_ASSERT(x < dim[0] && y < dim[1]); return dim[1]*x + y; } - -STC_INLINE size_t _cspan_i3(const uint32_t dim[3], uint32_t x, uint32_t y, uint32_t z) { - c_ASSERT(x < dim[0] && y < dim[1] && z < dim[2]); - return dim[2]*(dim[1]*x + y) + z; + {.data=cspan_at(self, offset, 0, 0), .shape={count, (self)->shape[1], (self)->shape[2]}, .stride={(self)->stride}} + +// cspan_submdN: reduce rank (N<5) Optimized, same as e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL}); +#define cspan_submd4(...) c_MACRO_OVERLOAD(cspan_submd4, __VA_ARGS__) +#define cspan_submd3(...) c_MACRO_OVERLOAD(cspan_submd3, __VA_ARGS__) +#define cspan_submd2(self, x) \ + {.data=cspan_at(self, x, 0), .shape={(self)->shape[1]}} +#define cspan_submd3_2(self, x) \ + {.data=cspan_at(self, x, 0, 0), .shape={(self)->shape[1], (self)->shape[2]}, \ + .stride={.d={0, (self)->stride.d[2]}}} +#define cspan_submd3_3(self, x, y) \ + {.data=cspan_at(self, x, y, 0), .shape={(self)->shape[2]}} +#define cspan_submd4_2(self, x) \ + {.data=cspan_at(self, x, 0, 0, 0), .shape={(self)->shape[1], (self)->shape[2], (self)->shape[3]}, \ + .stride={.d={0, (self)->stride.d[2], (self)->stride.d[3]}}} +#define cspan_submd4_3(self, x, y) \ + {.data=cspan_at(self, x, y, 0, 0), .shape={(self)->shape[2], (self)->shape[3]}, .stride={.d={0, (self)->stride.d[3]}}} +#define cspan_submd4_4(self, x, y, z) \ + {.data=cspan_at(self, x, y, z, 0), .shape={(self)->shape[3]}} + +// FUNCTIONS + +STC_INLINE intptr_t _cspan_idx1(const int32_t shape[1], const cspan_idx1 stri, int32_t x) + { c_ASSERT(c_LTu(x, shape[0])); return x; } + +STC_INLINE intptr_t _cspan_idx2(const int32_t shape[2], const cspan_idx2 stri, int32_t x, int32_t y) + { c_ASSERT(c_LTu(x, shape[0]) && c_LTu(y, shape[1])); return (intptr_t)stri.d[1]*x + y; } + +STC_INLINE intptr_t _cspan_idx3(const int32_t shape[3], const cspan_idx3 stri, int32_t x, int32_t y, int32_t z) { + c_ASSERT(c_LTu(x, shape[0]) && c_LTu(y, shape[1]) && c_LTu(z, shape[2])); + return (intptr_t)stri.d[2]*(stri.d[1]*x + y) + z; } -STC_INLINE size_t _cspan_i4(const uint32_t dim[4], uint32_t x, uint32_t y, uint32_t z, uint32_t w) { - c_ASSERT(x < dim[0] && y < dim[1] && z < dim[3] && w < dim[3]); - return dim[3]*(dim[2]*(dim[1]*x + y) + z) + w; +STC_INLINE intptr_t _cspan_idx4(const int32_t shape[4], const cspan_idx4 stri, int32_t x, int32_t y, + int32_t z, int32_t w) { + c_ASSERT(c_LTu(x, shape[0]) && c_LTu(y, shape[1]) && c_LTu(z, shape[2]) && c_LTu(w, shape[3])); + return (intptr_t)stri.d[3]*(stri.d[2]*(stri.d[1]*x + y) + z) + w; } -STC_INLINE size_t _cspan_size(const uint32_t dim[], unsigned rank) { - size_t sz = dim[0]; - while (rank-- > 1) sz *= dim[rank]; +STC_INLINE intptr_t _cspan_idxN(int rank, const int32_t shape[], const int32_t stri[], const int32_t a[]) { + intptr_t off = a[0]; + bool ok = c_LTu(a[0], shape[0]); + for (int i = 1; i < rank; ++i) { + off *= stri[i]; + off += a[i]; + ok &= c_LTu(a[i], shape[i]); + } + c_ASSERT(ok); + return off; +} + +STC_INLINE intptr_t _cspan_size(const int32_t shape[], int rank) { + intptr_t sz = shape[0]; + while (rank-- > 1) sz *= shape[rank]; return sz; } +#define _cspan_next1(r, pos, d, s) (++pos[0], 1) +#define _cspan_next3 _cspan_next2 +#define _cspan_next4 _cspan_next2 +#define _cspan_next5 _cspan_next2 +#define _cspan_next6 _cspan_next2 + +STC_INLINE intptr_t _cspan_next2(int rank, int32_t pos[], const int32_t shape[], const int32_t stride[]) { + intptr_t off = 1, rs = 1; + ++pos[rank - 1]; + while (--rank && pos[rank] == shape[rank]) { + pos[rank] = 0, ++pos[rank - 1]; + const intptr_t ds = rs*shape[rank]; + rs *= stride[rank]; + off += rs - ds; + } + return off; +} + +STC_INLINE intptr_t _cspan_slice(int32_t odim[], int32_t ostri[], int* orank, + const int32_t shape[], const int32_t stri[], + int rank, const int32_t a[][2]) { + intptr_t off = 0; + int i = 0, j = 0, ok = true; + int32_t t, s = 1; + for (; i < rank; ++i) { + off *= stri[i]; + off += a[i][0]; + switch (a[i][1]) { + case 0: s *= stri[i]; ok &= c_LTu(a[i][0], shape[i]); continue; + case -1: t = shape[i]; break; + default: t = a[i][1]; break; + } + odim[j] = t - a[i][0]; + ostri[j] = s*stri[i]; + ok &= c_LTu(0, odim[j]) & !c_LTu(shape[i], t); + s = 1; ++j; + } + *orank = j; + c_ASSERT(ok); + return off; +} #endif diff --git a/include/stc/cstack.h b/include/stc/cstack.h index f4a86156..dd4686e9 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -44,11 +44,11 @@ typedef i_keyraw _cx_raw; STC_INLINE _cx_self _cx_memb(_init)(void) { - _cx_self s; s._len = 0; + _cx_self cx; cx._len = 0; #ifndef i_capacity - s._cap = 0; s.data = NULL; + cx._cap = 0; cx.data = NULL; #endif - return s; + return cx; } #ifdef i_capacity @@ -58,13 +58,13 @@ STC_INLINE void _cx_memb(_create)(_cx_self* self) STC_INLINE void _cx_memb(_create)(_cx_self* self) { self->_len = 0; self->_cap = 0; self->data = NULL; } -STC_INLINE _cx_self _cx_memb(_with_capacity)(size_t cap) { - _cx_self out = {(_cx_value *) c_MALLOC(cap*sizeof(i_key)), 0, cap}; +STC_INLINE _cx_self _cx_memb(_with_capacity)(intptr_t cap) { + _cx_self out = {(_cx_value *) c_malloc(cap*c_sizeof(i_key)), 0, cap}; return out; } -STC_INLINE _cx_self _cx_memb(_with_size)(size_t size, i_key null) { - _cx_self out = {(_cx_value *) c_MALLOC(size*sizeof null), size, size}; +STC_INLINE _cx_self _cx_memb(_with_size)(intptr_t size, i_key null) { + _cx_self out = {(_cx_value *) c_malloc(size*c_sizeof null), size, size}; while (size) out.data[--size] = null; return out; } @@ -79,17 +79,17 @@ STC_INLINE void _cx_memb(_clear)(_cx_self* self) { STC_INLINE void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_clear)(self); #ifndef i_capacity - c_FREE(self->data); + c_free(self->data); #endif } -STC_INLINE size_t _cx_memb(_size)(const _cx_self* self) +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* self) { +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { #ifndef i_capacity return self->_cap; #else @@ -97,18 +97,17 @@ STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* self) { #endif } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { +STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) { if (n < self->_len) return true; #ifndef i_capacity - _cx_value *t = (_cx_value *)c_REALLOC(self->data, n*sizeof *t); + _cx_value *t = (_cx_value *)c_realloc(self->data, n*c_sizeof *t); if (t) { self->_cap = n, self->data = t; return true; } #endif return false; } -STC_INLINE _cx_value* -_cx_memb(_append_uninit)(_cx_self *self, size_t n) { - size_t len = self->_len; +STC_INLINE _cx_value* _cx_memb(_append_uninit)(_cx_self *self, intptr_t n) { + intptr_t len = self->_len; if (!_cx_memb(_reserve)(self, len + n)) return NULL; self->_len += n; return self->data + len; @@ -137,9 +136,15 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { STC_INLINE void _cx_memb(_pop)(_cx_self* self) { assert(!_cx_memb(_empty)(self)); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } -STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, size_t idx) +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } + +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } + +STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, intptr_t idx) { assert(idx < self->_len); return self->data + idx; } -STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, size_t idx) +STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, intptr_t idx) { assert(idx < self->_len); return self->data + idx; } #if !defined i_no_emplace @@ -149,9 +154,9 @@ STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) #if !defined i_no_clone STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { - _cx_self out = {(_cx_value *)c_MALLOC(v._len*sizeof(_cx_value)), v._len, v._len}; + _cx_self out = {(_cx_value *)c_malloc(v._len*c_sizeof(_cx_value)), v._len, v._len}; if (!out.data) out._cap = 0; - else for (size_t i = 0; i < v._len; ++v.data) + else for (intptr_t i = 0; i < v._len; ++v.data) out.data[i++] = i_keyclone((*v.data)); return out; } @@ -170,17 +175,17 @@ STC_INLINE i_keyraw _cx_memb(_value_toraw)(const _cx_value* val) #endif // !i_no_clone STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - return c_INIT(_cx_iter){self->_len ? (_cx_value*)self->data : NULL, + return c_LITERAL(_cx_iter){self->_len ? (_cx_value*)self->data : NULL, (_cx_value*)self->data + self->_len}; } STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL, (_cx_value*)self->data + self->_len}; } + { return c_LITERAL(_cx_iter){NULL, (_cx_value*)self->data + self->_len}; } 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 n) +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 "priv/template.h" diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 46ad2fcd..2966db81 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -47,79 +47,79 @@ #endif enum { cstr_s_cap = sizeof(cstr_buf) - 2 }; -#define cstr_s_size(s) ((size_t)(s)->sml.size) +#define cstr_s_size(s) ((intptr_t)(s)->sml.size) #define cstr_s_set_size(s, len) ((s)->sml.size = (uint8_t)(len), (s)->sml.data[len] = 0) #define cstr_s_data(s) (s)->sml.data #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) - #define cstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) - #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) + #define cstr_l_cap(s) (intptr_t)(~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_((size_t)(cap), 1)) #else - #define cstr_l_cap(s) (~(s)->lon.ncap) - #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) + #define cstr_l_cap(s) (intptr_t)(~(s)->lon.ncap) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(size_t)(cap)) #endif -#define cstr_l_size(s) ((s)->lon.size) -#define cstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (len)] = 0) +#define cstr_l_size(s) (intptr_t)((s)->lon.size) +#define cstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (size_t)(len)] = 0) #define cstr_l_data(s) (s)->lon.data -#define cstr_l_drop(s) c_FREE((s)->lon.data) +#define cstr_l_drop(s) c_free((s)->lon.data) #define cstr_is_long(s) ((s)->sml.size > 127) -STC_API char* _cstr_init(cstr* self, size_t len, size_t cap); -STC_API char* _cstr_internal_move(cstr* self, size_t pos1, size_t pos2); +STC_API char* _cstr_init(cstr* self, intptr_t len, intptr_t cap); +STC_API char* _cstr_internal_move(cstr* self, intptr_t pos1, intptr_t pos2); /**************************** PUBLIC API **********************************/ #define cstr_lit(literal) cstr_from_n(literal, crawstr_len(literal)) -#define cstr_NULL (c_INIT(cstr){{{0}, 0}}) +#define cstr_NULL (c_LITERAL(cstr){{{0}, 0}}) #define cstr_toraw(self) cstr_str(self) -STC_API char* cstr_reserve(cstr* self, size_t cap); -STC_API void cstr_shrink_to_fit(cstr* self); -STC_API void cstr_resize(cstr* self, size_t size, char value); -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); -STC_API void cstr_erase(cstr* self, size_t pos, size_t len); -STC_API void cstr_u8_erase(cstr* self, size_t bytepos, size_t u8len); -STC_API cstr cstr_from_fmt(const char* fmt, ...); -STC_API size_t cstr_append_fmt(cstr* self, const char* fmt, ...); -STC_API size_t cstr_printf(cstr* self, const char* fmt, ...); -STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, unsigned count); +STC_API char* cstr_reserve(cstr* self, intptr_t cap); +STC_API void cstr_shrink_to_fit(cstr* self); +STC_API void cstr_resize(cstr* self, intptr_t size, char value); +STC_API intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); +STC_API char* cstr_assign_n(cstr* self, const char* str, intptr_t len); +STC_API char* cstr_append_n(cstr* self, const char* str, intptr_t len); +STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); +STC_API void cstr_erase(cstr* self, intptr_t pos, intptr_t len); +STC_API void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); +STC_API cstr cstr_from_fmt(const char* fmt, ...); +STC_API intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...); +STC_API intptr_t cstr_printf(cstr* self, const char* fmt, ...); +STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, int32_t count); STC_INLINE cstr_buf cstr_buffer(cstr* s) { return cstr_is_long(s) - ? c_INIT(cstr_buf){s->lon.data, cstr_l_size(s), cstr_l_cap(s)} - : c_INIT(cstr_buf){s->sml.data, cstr_s_size(s), cstr_s_cap}; + ? c_LITERAL(cstr_buf){s->lon.data, cstr_l_size(s), cstr_l_cap(s)} + : c_LITERAL(cstr_buf){s->sml.data, cstr_s_size(s), cstr_s_cap}; } STC_INLINE csview cstr_sv(const cstr* s) { - return cstr_is_long(s) ? c_INIT(csview){s->lon.data, cstr_l_size(s)} - : c_INIT(csview){s->sml.data, cstr_s_size(s)}; + return cstr_is_long(s) ? c_LITERAL(csview){s->lon.data, cstr_l_size(s)} + : c_LITERAL(csview){s->sml.data, cstr_s_size(s)}; } STC_INLINE cstr cstr_init(void) { return cstr_NULL; } -STC_INLINE cstr cstr_from_n(const char* str, const size_t len) { +STC_INLINE cstr cstr_from_n(const char* str, const intptr_t len) { cstr s; - memcpy(_cstr_init(&s, len, len), str, len); + c_memcpy(_cstr_init(&s, len, len), str, len); return s; } STC_INLINE cstr cstr_from(const char* str) - { return cstr_from_n(str, strlen(str)); } + { return cstr_from_n(str, c_strlen(str)); } STC_INLINE cstr cstr_from_sv(csview sv) { return cstr_from_n(sv.str, sv.size); } -STC_INLINE cstr cstr_with_size(const size_t size, const char value) { +STC_INLINE cstr cstr_with_size(const intptr_t size, const char value) { cstr s; - memset(_cstr_init(&s, size, size), value, size); + c_memset(_cstr_init(&s, size, size), value, size); return s; } -STC_INLINE cstr cstr_with_capacity(const size_t cap) { +STC_INLINE cstr cstr_with_capacity(const intptr_t cap) { cstr s; _cstr_init(&s, 0, cap); return s; @@ -150,7 +150,7 @@ STC_INLINE void cstr_drop(cstr* self) { #define SSO_CALL(s, call) (cstr_is_long(s) ? cstr_l_##call : cstr_s_##call) -STC_INLINE void _cstr_set_size(cstr* self, size_t len) +STC_INLINE void _cstr_set_size(cstr* self, intptr_t len) { SSO_CALL(self, set_size(self, len)); } STC_INLINE char* cstr_data(cstr* self) @@ -162,10 +162,10 @@ STC_INLINE const char* cstr_str(const cstr* self) STC_INLINE bool cstr_empty(const cstr* self) { return self->sml.size == 0; } -STC_INLINE size_t cstr_size(const cstr* self) +STC_INLINE intptr_t cstr_size(const cstr* self) { return SSO_CALL(self, size(self)); } -STC_INLINE size_t cstr_capacity(const cstr* self) +STC_INLINE intptr_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: @@ -182,10 +182,10 @@ STC_INLINE cstr cstr_toupper_sv(csview sv) { return cstr_tocase(sv, 2); } STC_INLINE cstr cstr_tolower(const char* str) - { return cstr_tolower_sv(c_SV(str, strlen(str))); } + { return cstr_tolower_sv(c_SV(str, c_strlen(str))); } STC_INLINE cstr cstr_toupper(const char* str) - { return cstr_toupper_sv(c_SV(str, strlen(str))); } + { return cstr_toupper_sv(c_SV(str, c_strlen(str))); } STC_INLINE void cstr_lowercase(cstr* self) { cstr_take(self, cstr_tolower_sv(cstr_sv(self))); } @@ -198,19 +198,19 @@ STC_INLINE bool cstr_valid_utf8(const cstr* self) // other utf8 -STC_INLINE size_t cstr_u8_size(const cstr* self) +STC_INLINE intptr_t cstr_u8_size(const cstr* self) { return utf8_size(cstr_str(self)); } -STC_INLINE size_t cstr_u8_size_n(const cstr* self, size_t nbytes) +STC_INLINE intptr_t cstr_u8_size_n(const cstr* self, intptr_t nbytes) { return utf8_size_n(cstr_str(self), nbytes); } -STC_INLINE size_t cstr_u8_to_pos(const cstr* self, size_t u8idx) +STC_INLINE intptr_t cstr_u8_to_pos(const cstr* self, intptr_t u8idx) { return utf8_pos(cstr_str(self), u8idx); } -STC_INLINE const char* cstr_u8_at(const cstr* self, size_t u8idx) +STC_INLINE const char* cstr_u8_at(const cstr* self, intptr_t u8idx) { return utf8_at(cstr_str(self), u8idx); } -STC_INLINE csview cstr_u8_chr(const cstr* self, size_t u8idx) { +STC_INLINE csview cstr_u8_chr(const cstr* self, intptr_t u8idx) { const char* str = cstr_str(self); csview sv; sv.str = utf8_at(str, u8idx); @@ -222,11 +222,11 @@ STC_INLINE csview cstr_u8_chr(const cstr* self, size_t u8idx) { STC_INLINE cstr_iter cstr_begin(const cstr* self) { csview sv = cstr_sv(self); - if (!sv.size) return c_INIT(cstr_iter){NULL}; - return c_INIT(cstr_iter){.u8 = {{sv.str, utf8_chr_size(sv.str)}}}; + if (!sv.size) return c_LITERAL(cstr_iter){NULL}; + return c_LITERAL(cstr_iter){.u8 = {{sv.str, utf8_chr_size(sv.str)}}}; } STC_INLINE cstr_iter cstr_end(const cstr* self) { - (void)self; return c_INIT(cstr_iter){NULL}; + (void)self; return c_LITERAL(cstr_iter){NULL}; } STC_INLINE void cstr_next(cstr_iter* it) { it->ref += it->u8.chr.size; @@ -246,8 +246,8 @@ STC_INLINE cstr_iter cstr_advance(cstr_iter it, intptr_t pos) { 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); +STC_INLINE char* cstr_append_uninit(cstr *self, intptr_t len) { + intptr_t sz = cstr_size(self); char* d = cstr_reserve(self, sz + len); if (!d) return NULL; _cstr_set_size(self, sz + len); @@ -262,7 +262,7 @@ STC_INLINE int cstr_icmp(const cstr* s1, const cstr* s2) STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { csview x = cstr_sv(s1), y = cstr_sv(s2); - return x.size == y.size && !memcmp(x.str, y.str, x.size); + return x.size == y.size && !c_memcmp(x.str, y.str, x.size); } @@ -270,7 +270,7 @@ STC_INLINE bool cstr_equals(const cstr* self, const char* str) { return !strcmp(cstr_str(self), str); } 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); } + { return sv.size == cstr_size(self) && !c_memcmp(cstr_str(self), sv.str, sv.size); } STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) { return !cstr_cmp(self, &s); } @@ -279,14 +279,14 @@ STC_INLINE bool cstr_iequals(const cstr* self, const char* str) { return !utf8_icmp(cstr_str(self), str); } -STC_INLINE size_t cstr_find(const cstr* self, const char* search) { +STC_INLINE intptr_t cstr_find(const cstr* self, const char* search) { const char *str = cstr_str(self), *res = strstr((char*)str, search); - return res ? (size_t)(res - str) : c_NPOS; + return res ? (res - str) : c_NPOS; } -STC_API size_t cstr_find_sv(const cstr* self, csview search); +STC_API intptr_t cstr_find_sv(const cstr* self, csview search); -STC_INLINE size_t cstr_find_s(const cstr* self, cstr search) +STC_INLINE intptr_t cstr_find_s(const cstr* self, cstr search) { return cstr_find(self, cstr_str(&search)); } @@ -302,7 +302,7 @@ STC_INLINE bool cstr_contains_s(const cstr* self, cstr search) 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); + return !c_memcmp(cstr_str(self), sub.str, sub.size); } STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { @@ -316,7 +316,7 @@ STC_INLINE bool cstr_starts_with_s(const cstr* self, cstr sub) STC_INLINE bool cstr_istarts_with(const cstr* self, const char* sub) { csview sv = cstr_sv(self); - size_t len = strlen(sub); + intptr_t len = c_strlen(sub); return len <= sv.size && !utf8_icmp_sv(sv, c_SV(sub, len)); } @@ -324,24 +324,24 @@ STC_INLINE bool cstr_istarts_with(const cstr* self, const char* sub) { 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); + return !c_memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); } 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(const cstr* self, const char* sub) - { return cstr_ends_with_sv(self, c_SV(sub, strlen(sub))); } + { return cstr_ends_with_sv(self, c_SV(sub, c_strlen(sub))); } STC_INLINE bool cstr_iends_with(const cstr* self, const char* sub) { csview sv = cstr_sv(self); - size_t n = strlen(sub); + intptr_t n = c_strlen(sub); return n <= sv.size && !utf8_icmp(sv.str + sv.size - n, sub); } STC_INLINE char* cstr_assign(cstr* self, const char* str) - { return cstr_assign_n(self, str, strlen(str)); } + { return cstr_assign_n(self, str, c_strlen(str)); } STC_INLINE char* cstr_assign_sv(cstr* self, csview sv) { return cstr_assign_n(self, sv.str, sv.size); } @@ -359,11 +359,11 @@ STC_INLINE void cstr_pop(cstr* self) { csview sv = cstr_sv(self); const char* s = sv.str + sv.size; while ((*--s & 0xC0) == 0x80) ; - _cstr_set_size(self, (size_t)(s - sv.str)); + _cstr_set_size(self, (s - sv.str)); } STC_INLINE char* cstr_append(cstr* self, const char* str) - { return cstr_append_n(self, str, strlen(str)); } + { return cstr_append_n(self, str, c_strlen(str)); } STC_INLINE void cstr_append_sv(cstr* self, csview sv) { cstr_append_n(self, sv.str, sv.size); } @@ -373,35 +373,35 @@ STC_INLINE char* cstr_append_s(cstr* self, cstr s) { return cstr_append_n(self, sv.str, sv.size); } -STC_INLINE void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count) { - cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(search, strlen(search)), - c_SV(repl, strlen(repl)), count)); +#define cstr_replace(...) c_MACRO_OVERLOAD(cstr_replace, __VA_ARGS__) +#define cstr_replace_3(self, search, repl) cstr_replace_4(self, search, repl, INT32_MAX) +STC_INLINE void cstr_replace_4(cstr* self, const char* search, const char* repl, int32_t count) { + cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(search, c_strlen(search)), + c_SV(repl, c_strlen(repl)), count)); } -STC_INLINE void cstr_replace(cstr* self, const char* search, const char* repl) - { cstr_replace_ex(self, search, repl, ~0U); } -STC_INLINE void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl) { +STC_INLINE void cstr_replace_at_sv(cstr* self, intptr_t pos, intptr_t len, const csview repl) { char* d = _cstr_internal_move(self, pos + len, pos + repl.size); - memcpy(d + pos, repl.str, repl.size); + c_memcpy(d + pos, repl.str, repl.size); } -STC_INLINE void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl) - { cstr_replace_at_sv(self, pos, len, c_SV(repl, strlen(repl))); } +STC_INLINE void cstr_replace_at(cstr* self, intptr_t pos, intptr_t len, const char* repl) + { cstr_replace_at_sv(self, pos, len, c_SV(repl, c_strlen(repl))); } -STC_INLINE void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl) +STC_INLINE void cstr_replace_at_s(cstr* self, intptr_t pos, intptr_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 bytepos, size_t u8len, csview repl) +STC_INLINE void cstr_u8_replace_at(cstr* self, intptr_t bytepos, intptr_t u8len, csview repl) { cstr_replace_at_sv(self, bytepos, utf8_pos(cstr_str(self) + bytepos, u8len), repl); } -STC_INLINE void cstr_insert(cstr* self, size_t pos, const char* str) - { cstr_replace_at_sv(self, pos, 0, c_SV(str, strlen(str))); } +STC_INLINE void cstr_insert(cstr* self, intptr_t pos, const char* str) + { cstr_replace_at_sv(self, pos, 0, c_SV(str, c_strlen(str))); } -STC_INLINE void cstr_insert_sv(cstr* self, size_t pos, csview sv) +STC_INLINE void cstr_insert_sv(cstr* self, intptr_t pos, csview sv) { cstr_replace_at_sv(self, pos, 0, sv); } -STC_INLINE void cstr_insert_s(cstr* self, size_t pos, cstr s) { +STC_INLINE void cstr_insert_s(cstr* self, intptr_t pos, cstr s) { csview sv = cstr_sv(&s); cstr_replace_at_sv(self, pos, 0, sv); } @@ -425,7 +425,7 @@ cstr cstr_tocase(csview sv, int k) { cstr out = cstr_init(); char *buf = cstr_reserve(&out, sv.size*3/2); const char *end = sv.str + sv.size; - uint32_t cp; size_t sz = 0; + uint32_t cp; intptr_t sz = 0; utf8_decode_t d = {.state=0}; while (sv.str < end) { @@ -451,27 +451,27 @@ STC_DEF uint64_t cstr_hash(const cstr *self) { return cfasthash(sv.str, sv.size); } -STC_DEF size_t cstr_find_sv(const cstr* self, csview search) { +STC_DEF intptr_t cstr_find_sv(const cstr* self, csview search) { csview sv = cstr_sv(self); char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); - return res ? (size_t)(res - sv.str) : c_NPOS; + return res ? (res - sv.str) : c_NPOS; } -STC_DEF char* _cstr_internal_move(cstr* self, const size_t pos1, const size_t pos2) { +STC_DEF char* _cstr_internal_move(cstr* self, const intptr_t pos1, const intptr_t pos2) { cstr_buf r = cstr_buffer(self); if (pos1 != pos2) { - const intptr_t newlen = (intptr_t)(r.size + pos2 - pos1); - if (newlen > (intptr_t)r.cap) + const intptr_t newlen = (r.size + pos2 - pos1); + if (newlen > r.cap) r.data = cstr_reserve(self, r.size*3/2 + pos2 - pos1); - memmove(&r.data[pos2], &r.data[pos1], r.size - pos1); - _cstr_set_size(self, (size_t)newlen); + c_memmove(&r.data[pos2], &r.data[pos1], r.size - pos1); + _cstr_set_size(self, newlen); } return r.data; } -STC_DEF char* _cstr_init(cstr* self, const size_t len, const size_t cap) { +STC_DEF char* _cstr_init(cstr* self, const intptr_t len, const intptr_t cap) { if (cap > cstr_s_cap) { - self->lon.data = (char *)c_MALLOC(cap + 1); + self->lon.data = (char *)c_malloc(cap + 1); cstr_l_set_size(self, len); cstr_l_set_cap(self, cap); return self->lon.data; @@ -485,67 +485,67 @@ STC_DEF void cstr_shrink_to_fit(cstr* self) { if (r.size == r.cap) return; if (r.size > cstr_s_cap) { - self->lon.data = (char *)c_REALLOC(self->lon.data, r.size + 1); + self->lon.data = (char *)c_realloc(self->lon.data, r.size + 1); cstr_l_set_cap(self, r.size); } else if (r.cap > cstr_s_cap) { - memcpy(self->sml.data, r.data, r.size + 1); + c_memcpy(self->sml.data, r.data, r.size + 1); cstr_s_set_size(self, r.size); - c_FREE(r.data); + c_free(r.data); } } -STC_DEF char* cstr_reserve(cstr* self, const size_t cap) { +STC_DEF char* cstr_reserve(cstr* self, const intptr_t cap) { if (cstr_is_long(self)) { if (cap > cstr_l_cap(self)) { - self->lon.data = (char *)c_REALLOC(self->lon.data, cap + 1); + self->lon.data = (char *)c_realloc(self->lon.data, cap + 1); cstr_l_set_cap(self, cap); } return self->lon.data; } /* from short to long: */ if (cap > cstr_s_cap) { - char* data = (char *)c_MALLOC(cap + 1); - const size_t len = cstr_s_size(self); - memcpy(data, self->sml.data, cstr_s_cap + 1); + char* data = (char *)c_malloc(cap + 1); + const intptr_t len = cstr_s_size(self); + c_memcpy(data, self->sml.data, cstr_s_cap + 1); self->lon.data = data; - self->lon.size = len; + self->lon.size = (size_t)len; cstr_l_set_cap(self, cap); return data; } return self->sml.data; } -STC_DEF void cstr_resize(cstr* self, const size_t size, const char value) { +STC_DEF void cstr_resize(cstr* self, const intptr_t size, const char value) { cstr_buf r = cstr_buffer(self); if (size > r.size) { if (size > r.cap) r.data = cstr_reserve(self, size); - memset(r.data + r.size, value, size - r.size); + c_memset(r.data + r.size, value, size - r.size); } _cstr_set_size(self, size); } -STC_DEF size_t cstr_find_at(const cstr* self, const size_t pos, const char* search) { +STC_DEF intptr_t cstr_find_at(const cstr* self, const intptr_t pos, const char* search) { csview sv = cstr_sv(self); if (pos > sv.size) return c_NPOS; const char* res = strstr((char*)sv.str + pos, search); - return res ? (size_t)(res - sv.str) : c_NPOS; + return res ? (res - sv.str) : c_NPOS; } -STC_DEF char* cstr_assign_n(cstr* self, const char* str, const size_t len) { +STC_DEF char* cstr_assign_n(cstr* self, const char* str, const intptr_t len) { char* d = cstr_reserve(self, len); - memmove(d, str, len); + c_memmove(d, str, len); _cstr_set_size(self, len); return d; } -STC_DEF char* cstr_append_n(cstr* self, const char* str, const size_t len) { +STC_DEF char* cstr_append_n(cstr* self, const char* str, const intptr_t len) { cstr_buf r = cstr_buffer(self); if (r.size + len > r.cap) { const size_t off = (size_t)(str - r.data); r.data = cstr_reserve(self, r.size*3/2 + len); - if (off <= r.size) str = r.data + off; /* handle self append */ + if (off <= (size_t)r.size) str = r.data + off; /* handle self append */ } - memcpy(r.data + r.size, str, len); + c_memcpy(r.data + r.size, str, len); _cstr_set_size(self, r.size + len); return r.data; } @@ -554,7 +554,7 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { int c = fgetc(fp); if (c == EOF) return false; - size_t pos = 0; + intptr_t pos = 0; cstr_buf r = cstr_buffer(self); for (;;) { if (c == delim || c == EOF) { @@ -571,13 +571,13 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { } STC_DEF cstr -cstr_replace_sv(csview in, csview search, csview repl, unsigned count) { +cstr_replace_sv(csview in, csview search, csview repl, int32_t count) { cstr out = cstr_NULL; - size_t from = 0; char* res; - if (!count) count = ~0U; + intptr_t from = 0; char* res; + if (!count) count = INT32_MAX; if (search.size) while (count-- && (res = cstrnstrn(in.str + from, search.str, in.size - from, search.size))) { - const size_t pos = (size_t)(res - in.str); + const intptr_t pos = (res - in.str); cstr_append_n(&out, in.str + from, pos - from); cstr_append_n(&out, repl.str, repl.size); from = pos + search.size; @@ -586,17 +586,17 @@ cstr_replace_sv(csview in, csview search, csview repl, unsigned count) { return out; } -STC_DEF void cstr_erase(cstr* self, const size_t pos, size_t len) { +STC_DEF void cstr_erase(cstr* self, const intptr_t pos, intptr_t len) { cstr_buf r = cstr_buffer(self); if (len > r.size - pos) len = r.size - pos; - memmove(&r.data[pos], &r.data[pos + len], r.size - (pos + len)); + c_memmove(&r.data[pos], &r.data[pos + len], r.size - (pos + len)); _cstr_set_size(self, r.size - len); } -STC_DEF void cstr_u8_erase(cstr* self, const size_t bytepos, const size_t u8len) { +STC_DEF void cstr_u8_erase(cstr* self, const intptr_t bytepos, const intptr_t u8len) { cstr_buf r = cstr_buffer(self); - size_t len = utf8_pos(r.data + bytepos, u8len); - memmove(&r.data[bytepos], &r.data[bytepos + len], r.size - (bytepos + len)); + intptr_t len = utf8_pos(r.data + bytepos, u8len); + c_memmove(&r.data[bytepos], &r.data[bytepos + len], r.size - (bytepos + len)); _cstr_set_size(self, r.size - len); } @@ -608,10 +608,10 @@ STC_DEF void cstr_u8_erase(cstr* self, const size_t bytepos, const size_t u8len) # pragma warning(disable: 4996) #endif -STC_DEF size_t cstr_vfmt(cstr* self, size_t start, const char* fmt, va_list args) { +STC_DEF intptr_t cstr_vfmt(cstr* self, intptr_t start, const char* fmt, va_list args) { va_list args2; va_copy(args2, args); - const size_t n = (size_t)vsnprintf(NULL, (size_t)0, fmt, args); + const int n = vsnprintf(NULL, 0ULL, fmt, args); vsprintf(cstr_reserve(self, start + n) + start, fmt, args2); va_end(args2); _cstr_set_size(self, start + n); @@ -632,19 +632,19 @@ STC_DEF cstr cstr_from_fmt(const char* fmt, ...) { return s; } -STC_DEF size_t cstr_append_fmt(cstr* self, const char* fmt, ...) { +STC_DEF intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...) { va_list args; va_start(args, fmt); - const size_t n = cstr_vfmt(self, cstr_size(self), fmt, args); + const intptr_t n = cstr_vfmt(self, cstr_size(self), fmt, args); va_end(args); return n; } /* NB! self-data in args is UB */ -STC_DEF size_t cstr_printf(cstr* self, const char* fmt, ...) { +STC_DEF intptr_t cstr_printf(cstr* self, const char* fmt, ...) { va_list args; va_start(args, fmt); - const size_t n = cstr_vfmt(self, 0, fmt, args); + const intptr_t n = cstr_vfmt(self, 0, fmt, args); va_end(args); return n; } diff --git a/include/stc/csview.h b/include/stc/csview.h index 1ab34d9a..a30672cd 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -27,48 +27,48 @@ #include "forward.h" #include "utf8.h" -#define csview_NULL c_SV1("") +#define csview_NULL c_SV_1("") #define csview_init() csview_NULL #define csview_drop(p) c_default_drop(p) #define csview_clone(sv) c_default_clone(sv) -#define csview_lit(literal) c_SV1(literal) -#define csview_from_n(str, n) c_SV2(str, n) +#define csview_lit(literal) c_SV_1(literal) +#define csview_from_n(str, n) c_SV_2(str, n) -STC_API size_t csview_find_sv(csview sv, csview search); +STC_API intptr_t csview_find_sv(csview sv, csview search); STC_INLINE csview csview_from(const char* str) - { return c_INIT(csview){str, strlen(str)}; } + { return c_LITERAL(csview){str, c_strlen(str)}; } STC_INLINE void csview_clear(csview* self) { *self = csview_NULL; } -STC_INLINE size_t csview_size(csview sv) { return sv.size; } +STC_INLINE intptr_t csview_size(csview sv) { return sv.size; } STC_INLINE bool csview_empty(csview sv) { return sv.size == 0; } STC_INLINE bool csview_equals(csview sv, const char* str) - { size_t n = strlen(str); return sv.size == n && !memcmp(sv.str, str, n); } + { intptr_t n = c_strlen(str); return sv.size == n && !c_memcmp(sv.str, str, n); } -STC_INLINE size_t csview_find(csview sv, const char* str) - { return csview_find_sv(sv, c_SV(str, strlen(str))); } +STC_INLINE intptr_t csview_find(csview sv, const char* str) + { return csview_find_sv(sv, c_SV(str, c_strlen(str))); } STC_INLINE bool csview_contains(csview sv, const char* str) { return csview_find(sv, str) != c_NPOS; } STC_INLINE bool csview_starts_with(csview sv, const char* str) { - size_t n = strlen(str); - return n > sv.size ? false : !memcmp(sv.str, str, n); + intptr_t n = c_strlen(str); + return n > sv.size ? false : !c_memcmp(sv.str, str, n); } STC_INLINE bool csview_ends_with(csview sv, const char* str) { - size_t n = strlen(str); - return n > sv.size ? false : !memcmp(sv.str + sv.size - n, str, n); + intptr_t n = c_strlen(str); + return n > sv.size ? false : !c_memcmp(sv.str + sv.size - n, str, n); } -STC_INLINE csview csview_substr(csview sv, size_t pos, size_t n) { +STC_INLINE csview csview_substr(csview sv, intptr_t pos, intptr_t n) { if (pos + n > sv.size) n = sv.size - pos; sv.str += pos, sv.size = n; return sv; } -STC_INLINE csview csview_slice(csview sv, size_t p1, size_t p2) { +STC_INLINE csview csview_slice(csview sv, intptr_t p1, intptr_t p2) { if (p2 > sv.size) p2 = sv.size; sv.str += p1, sv.size = p2 > p1 ? p2 - p1 : 0; return sv; @@ -76,12 +76,12 @@ STC_INLINE csview csview_slice(csview sv, size_t p1, size_t p2) { /* utf8 iterator */ STC_INLINE csview_iter csview_begin(const csview* self) { - if (!self->size) return c_INIT(csview_iter){NULL}; - return c_INIT(csview_iter){.u8 = {{self->str, utf8_chr_size(self->str)}, - self->str + self->size}}; + if (!self->size) return c_LITERAL(csview_iter){NULL}; + return c_LITERAL(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_INIT(csview_iter){.u8 = {{NULL}, self->str + self->size}}; + return c_LITERAL(csview_iter){.u8 = {{NULL}, self->str + self->size}}; } STC_INLINE void csview_next(csview_iter* it) { it->ref += it->u8.chr.size; @@ -99,10 +99,10 @@ STC_INLINE csview_iter csview_advance(csview_iter it, intptr_t pos) { /* utf8 */ -STC_INLINE size_t csview_u8_size(csview sv) +STC_INLINE intptr_t csview_u8_size(csview sv) { return utf8_size_n(sv.str, sv.size); } -STC_INLINE csview csview_u8_substr(csview sv, size_t bytepos, size_t u8len) { +STC_INLINE csview csview_u8_substr(csview sv, intptr_t bytepos, intptr_t u8len) { sv.str += bytepos; sv.size = utf8_pos(sv.str, u8len); return sv; @@ -111,12 +111,12 @@ STC_INLINE csview csview_u8_substr(csview sv, size_t bytepos, size_t u8len) { STC_INLINE bool csview_valid_utf8(csview sv) // depends on src/utf8code.c { return utf8_valid_n(sv.str, sv.size); } -STC_API csview csview_substr_ex(csview sv, intptr_t pos, size_t n); +STC_API csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); STC_API csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); -STC_API csview csview_token(csview sv, const char* sep, size_t* start); +STC_API csview csview_token(csview sv, const char* sep, intptr_t* start); #define c_FORTOKEN_SV(it, inputsv, sep) \ - for (struct { csview _inp, token, *ref; const char *_sep; size_t pos; } \ + for (struct { csview _inp, token, *ref; const char *_sep; intptr_t pos; } \ it = {._inp=inputsv, .token=it._inp, .ref=&it.token, ._sep=sep} \ ; it.pos <= it._inp.size && (it.token = csview_token(it._inp, it._sep, &it.pos)).str ; ) @@ -126,27 +126,27 @@ STC_API csview csview_token(csview sv, const char* sep, size_t* start); /* csview interaction with cstr: */ #ifdef CSTR_H_INCLUDED -STC_INLINE csview cstr_substr(const cstr* self, size_t pos, size_t n) +STC_INLINE csview cstr_substr(const cstr* self, intptr_t pos, intptr_t n) { return csview_substr(cstr_sv(self), pos, n); } -STC_INLINE csview cstr_slice(const cstr* self, size_t p1, size_t p2) +STC_INLINE csview cstr_slice(const cstr* self, intptr_t p1, intptr_t p2) { return csview_slice(cstr_sv(self), p1, p2); } -STC_INLINE csview cstr_substr_ex(const cstr* self, intptr_t pos, size_t n) +STC_INLINE csview cstr_substr_ex(const cstr* self, intptr_t pos, intptr_t n) { return csview_substr_ex(cstr_sv(self), pos, n); } STC_INLINE csview cstr_slice_ex(const cstr* self, intptr_t p1, intptr_t p2) { return csview_slice_ex(cstr_sv(self), p1, p2); } -STC_INLINE csview cstr_u8_substr(const cstr* self , size_t bytepos, size_t u8len) +STC_INLINE csview cstr_u8_substr(const cstr* self , intptr_t bytepos, intptr_t u8len) { return csview_u8_substr(cstr_sv(self), bytepos, u8len); } #endif /* ---- Container helper functions ---- */ STC_INLINE int csview_cmp(const csview* x, const csview* y) { - size_t n = x->size < y->size ? x->size : y->size; - int c = memcmp(x->str, y->str, n); + intptr_t n = x->size < y->size ? x->size : y->size; + int c = c_memcmp(x->str, y->str, n); return c ? c : (int)(x->size - y->size); } @@ -154,48 +154,48 @@ STC_INLINE int csview_icmp(const csview* x, const csview* y) { return utf8_icmp_sv(*x, *y); } STC_INLINE bool csview_eq(const csview* x, const csview* y) - { return x->size == y->size && !memcmp(x->str, y->str, x->size); } + { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } STC_API uint64_t csview_hash(const csview *self); /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) -STC_DEF size_t csview_find_sv(csview sv, csview search) { +STC_DEF intptr_t csview_find_sv(csview sv, csview search) { char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); - return res ? (size_t)(res - sv.str) : c_NPOS; + return res ? (res - sv.str) : c_NPOS; } STC_DEF uint64_t csview_hash(const csview *self) { return cfasthash(self->str, self->size); } -STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, size_t n) { +STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { if (pos < 0) { - pos += (intptr_t)sv.size; + pos += sv.size; if (pos < 0) pos = 0; } - if ((size_t)pos > sv.size) pos = (intptr_t)sv.size; - if ((size_t)pos + n > sv.size) n = sv.size - (size_t)pos; + if (pos > sv.size) pos = sv.size; + if (pos + n > sv.size) n = sv.size - pos; sv.str += pos, sv.size = n; return sv; } STC_DEF csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { if (p1 < 0) { - p1 += (intptr_t)sv.size; + p1 += sv.size; if (p1 < 0) p1 = 0; } - if (p2 < 0) p2 += (intptr_t)sv.size; - if (p2 > (intptr_t)sv.size) p2 = (intptr_t)sv.size; - sv.str += p1, sv.size = (size_t)(p2 > p1 ? p2 - p1 : 0); + if (p2 < 0) p2 += sv.size; + if (p2 > sv.size) p2 = sv.size; + sv.str += p1, sv.size = (p2 > p1 ? p2 - p1 : 0); return sv; } -STC_DEF csview csview_token(csview sv, const char* sep, size_t* start) { - size_t sep_size = strlen(sep); +STC_DEF csview csview_token(csview sv, const char* sep, intptr_t* start) { + intptr_t sep_size = c_strlen(sep); csview slice = {sv.str + *start, sv.size - *start}; const char* res = cstrnstrn(slice.str, sep, slice.size, sep_size); - csview tok = {slice.str, res ? (size_t)(res - slice.str) : slice.size}; + csview tok = {slice.str, res ? (res - slice.str) : slice.size}; *start += tok.size + sep_size; return tok; } diff --git a/include/stc/cvec.h b/include/stc/cvec.h index fbacd305..06664b4d 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -80,13 +80,13 @@ typedef i_keyraw _cx_raw; STC_API _cx_self _cx_memb(_init)(void); STC_API void _cx_memb(_drop)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t cap); -STC_API bool _cx_memb(_resize)(_cx_self* self, size_t size, i_key null); +STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap); +STC_API bool _cx_memb(_resize)(_cx_self* self, intptr_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_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); +STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n); #if !defined i_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); @@ -101,7 +101,7 @@ STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw 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_iter -_cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { +_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) { return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -114,6 +114,10 @@ _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { STC_API _cx_self _cx_memb(_clone)(_cx_self cx); 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(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } 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) { @@ -124,8 +128,8 @@ STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { } #endif // !i_no_clone -STC_INLINE size_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } -STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; } STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { return i_keyto(val); } STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } @@ -138,14 +142,14 @@ STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_memb(_pop)(self); } STC_INLINE _cx_self -_cx_memb(_with_size)(const size_t size, i_key null) { +_cx_memb(_with_size)(const intptr_t size, i_key null) { _cx_self cx = _cx_memb(_init)(); _cx_memb(_resize)(&cx, size, null); return cx; } STC_INLINE _cx_self -_cx_memb(_with_capacity)(const size_t cap) { +_cx_memb(_with_capacity)(const intptr_t cap) { _cx_self cx = _cx_memb(_init)(); _cx_memb(_reserve)(&cx, cap); return cx; @@ -158,11 +162,11 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) { STC_INLINE _cx_iter -_cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { +_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) { return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } STC_INLINE _cx_iter -_cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { +_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } STC_INLINE _cx_iter @@ -171,7 +175,7 @@ _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { } STC_INLINE _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const size_t idx, const size_t n) { +_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); } STC_INLINE _cx_iter @@ -184,31 +188,31 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { } STC_INLINE const _cx_value* -_cx_memb(_at)(const _cx_self* self, const size_t idx) { +_cx_memb(_at)(const _cx_self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } STC_INLINE _cx_value* -_cx_memb(_at_mut)(_cx_self* self, const size_t idx) { +_cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - size_t n = self->_len; - return c_INIT(_cx_iter){n ? self->data : NULL, self->data + n}; + intptr_t n = self->_len; + return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n}; } STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL, self->data + self->_len}; } + { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; } 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 n) +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* self, _cx_iter it) - { return (size_t)(it.ref - self->data); } +STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) + { return (it.ref - self->data); } #if !defined i_no_cmp @@ -255,7 +259,7 @@ _cx_memb(_sort)(_cx_self* self) { STC_DEF _cx_self _cx_memb(_init)(void) { - return c_INIT(_cx_self){NULL}; + return c_LITERAL(_cx_self){NULL}; } STC_DEF void @@ -273,13 +277,13 @@ _cx_memb(_drop)(_cx_self* self) { if (self->_cap == 0) return; _cx_memb(_clear)(self); - c_FREE(self->data); + c_free(self->data); } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const size_t cap) { +_cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { if (cap > self->_cap || (cap && cap == self->_len)) { - _cx_value* d = (_cx_value*)c_REALLOC(self->data, cap*sizeof(i_key)); + _cx_value* d = (_cx_value*)c_realloc(self->data, cap*c_sizeof(i_key)); if (!d) return false; self->data = d; @@ -289,13 +293,13 @@ _cx_memb(_reserve)(_cx_self* self, const size_t cap) { } STC_DEF bool -_cx_memb(_resize)(_cx_self* self, const size_t len, i_key null) { +_cx_memb(_resize)(_cx_self* self, const intptr_t len, i_key null) { if (!_cx_memb(_reserve)(self, len)) return false; - const size_t n = self->_len; - for (size_t i = len; i < n; ++i) + const intptr_t n = self->_len; + for (intptr_t i = len; i < n; ++i) { i_keydrop((self->data + i)); } - for (size_t i = n; i < len; ++i) + for (intptr_t i = n; i < len; ++i) self->data[i] = null; self->_len = len; return true; @@ -312,39 +316,39 @@ _cx_memb(_push)(_cx_self* self, i_key value) { } STC_DEF _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) { if (n) { if (!pos) pos = self->data + self->_len; - const size_t idx = (size_t)(pos - self->data); + const intptr_t idx = (pos - self->data); if (self->_len + n > self->_cap) { if (!_cx_memb(_reserve)(self, self->_len*3/2 + n)) return _cx_memb(_end)(self); pos = self->data + idx; } - memmove(pos + n, pos, (self->_len - idx)*sizeof *pos); + c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos); self->_len += n; } - return c_INIT(_cx_iter){pos, self->data + self->_len}; + return c_LITERAL(_cx_iter){pos, self->data + self->_len}; } 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, (size_t)(p2 - p1)); + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); if (it.ref) - memcpy(it.ref, p1, (size_t)(p2 - p1)*sizeof *p1); + c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1); return it; } STC_DEF _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { - size_t len = (size_t)(p2 - p1); + intptr_t len = (p2 - p1); _cx_value* p = p1, *end = self->data + self->_len; for (; p != p2; ++p) { i_keydrop(p); } - memmove(p1, p2, (size_t)(end - p2)*sizeof *p1); + c_memmove(p1, p2, (end - p2)*c_sizeof *p1); self->_len -= len; - return c_INIT(_cx_iter){p2 == end ? NULL : p1, end - len}; + return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len}; } #if !defined i_no_clone @@ -358,7 +362,7 @@ _cx_memb(_clone)(_cx_self cx) { 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, (size_t)(p2 - p1)); + _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)); @@ -370,7 +374,7 @@ _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, 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, (size_t)(p2 - p1)); + _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)); @@ -394,20 +398,19 @@ _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { STC_DEF _cx_iter _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_value* w[2] = {i1.ref, _it2_ptr(i1, i2)}; _cx_iter mid = i1; - while (i1.ref != p2) { - mid.ref = i1.ref + (p2 - i1.ref)/2; + while (w[0] != w[1]) { + mid.ref = w[0] + (w[1] - w[0])/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) p2 = mid.ref; - else i1.ref = mid.ref + 1; + w[c < 0] = mid.ref + (c > 0); } - i2.ref = NULL; - *lower_bound = i1.ref == i2.end ? i2 : i1; - return i2; + i1.ref = w[0] == i2.end ? NULL : w[0]; + *lower_bound = i1; + i1.ref = NULL; return i1; } STC_DEF int diff --git a/include/stc/forward.h b/include/stc/forward.h index 60c18c37..d08b71b4 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -23,34 +23,34 @@ #ifndef STC_FORWARD_H_INCLUDED #define STC_FORWARD_H_INCLUDED -#include <stddef.h> +#include <stdint.h> #define forward_carc(CX, VAL) _c_carc_types(CX, VAL) -#define forward_carr2(CX, VAL) _c_carr2_types(CX, VAL) -#define forward_carr3(CX, VAL) _c_carr3_types(CX, VAL) #define forward_cbox(CX, VAL) _c_cbox_types(CX, VAL) #define forward_cdeq(CX, VAL) _c_cdeq_types(CX, VAL) #define forward_clist(CX, VAL) _c_clist_types(CX, VAL) -#define forward_cmap(CX, KEY, VAL) _c_chash_types(CX, KEY, VAL, uint32_t, c_true, c_false) -#define forward_cmap_huge(CX, KEY, VAL) _c_chash_types(CX, KEY, VAL, size_t, c_true, c_false) -#define forward_cset(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, uint32_t, c_false, c_true) -#define forward_cset_huge(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, size_t, c_false, c_true) -#define forward_csmap(CX, KEY, VAL) _c_aatree_types(CX, KEY, VAL, uint32_t, c_true, c_false) -#define forward_csset(CX, KEY) _c_aatree_types(CX, KEY, KEY, uint32_t, c_false, c_true) +#define forward_cmap(CX, KEY, VAL) _c_chash_types(CX, KEY, VAL, int32_t, c_true, c_false) +#define forward_cmap64(CX, KEY, VAL) _c_chash_types(CX, KEY, VAL, int64_t, c_true, c_false) +#define forward_cset(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, int32_t, c_false, c_true) +#define forward_cset64(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, int64_t, c_false, c_true) +#define forward_csmap(CX, KEY, VAL) _c_aatree_types(CX, KEY, VAL, int32_t, c_true, c_false) +#define forward_csset(CX, KEY) _c_aatree_types(CX, KEY, KEY, int32_t, c_false, c_true) #define forward_cstack(CX, VAL) _c_cstack_types(CX, VAL) #define forward_cpque(CX, VAL) _c_cpque_types(CX, VAL) #define forward_cqueue(CX, VAL) _c_cdeq_types(CX, VAL) #define forward_cvec(CX, VAL) _c_cvec_types(CX, VAL) +// csview typedef const char csview_value; -typedef struct { csview_value* str; size_t size; } csview; +typedef struct { csview_value* str; intptr_t size; } csview; typedef union { csview_value* ref; struct { csview chr; csview_value* end; } u8; } csview_iter; +// cstr typedef char cstr_value; -typedef struct { cstr_value* data; size_t size, cap; } cstr_buf; +typedef struct { cstr_value* data; intptr_t size, cap; } cstr_buf; typedef union { struct { cstr_value data[sizeof(cstr_buf) - 1]; unsigned char size; } sml; struct { cstr_value* data; size_t size, ncap; } lon; @@ -71,16 +71,6 @@ typedef union { catomic_long* use_count; \ } SELF -#define _c_carr2_types(SELF, VAL) \ - typedef VAL SELF##_value; \ - 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, *end; } SELF##_iter; \ - typedef struct { SELF##_value ***data; size_t xdim, ydim, zdim; } SELF - #define _c_cbox_types(SELF, VAL) \ typedef VAL SELF##_value; \ typedef struct { \ @@ -90,7 +80,7 @@ typedef union { #define _c_cdeq_types(SELF, VAL) \ typedef VAL SELF##_value; \ typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ - typedef struct { SELF##_value *_base, *data; size_t _len, _cap; } SELF + typedef struct { SELF##_value *_base, *data; intptr_t _len, _cap; } SELF #define _c_clist_types(SELF, VAL) \ typedef VAL SELF##_value; \ @@ -108,7 +98,7 @@ typedef union { #define _c_chash_types(SELF, KEY, VAL, SZ, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ typedef VAL SELF##_mapped; \ - typedef SZ SELF##_size_t; \ + typedef SZ SELF##_sizet; \ \ typedef SET_ONLY( SELF##_key ) \ MAP_ONLY( struct SELF##_value ) \ @@ -127,40 +117,13 @@ typedef union { typedef struct { \ SELF##_value* table; \ uint8_t* _hashx; \ - SELF##_size_t size, bucket_count; \ + SELF##_sizet size, bucket_count; \ } SELF -#if defined STC_CSMAP_V1 -#define _c_aatree_types(SELF, KEY, VAL, SZ, MAP_ONLY, SET_ONLY) \ - typedef KEY SELF##_key; \ - typedef VAL SELF##_mapped; \ - typedef SZ SELF##_size_t; \ - typedef struct SELF##_node SELF##_node; \ -\ - typedef SET_ONLY( SELF##_key ) \ - MAP_ONLY( struct SELF##_value ) \ - SELF##_value; \ -\ - typedef struct { \ - SELF##_value *ref; \ - bool inserted, nomem_error; \ - } SELF##_result; \ -\ - typedef struct { \ - SELF##_value *ref; \ - int _top; \ - SELF##_node *_tn, *_st[36]; \ - } SELF##_iter; \ -\ - typedef struct { \ - SELF##_node *root; \ - SELF##_size_t size; \ - } SELF -#else #define _c_aatree_types(SELF, KEY, VAL, SZ, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ typedef VAL SELF##_mapped; \ - typedef SZ SELF##_size_t; \ + typedef SZ SELF##_sizet; \ typedef struct SELF##_node SELF##_node; \ \ typedef SET_ONLY( SELF##_key ) \ @@ -176,32 +139,31 @@ typedef union { SELF##_value *ref; \ SELF##_node *_d; \ int _top; \ - SELF##_size_t _tn, _st[36]; \ + SELF##_sizet _tn, _st[36]; \ } SELF##_iter; \ \ typedef struct { \ SELF##_node *nodes; \ - SELF##_size_t root, disp, head, size, cap; \ + SELF##_sizet root, disp, head, size, cap; \ } SELF -#endif #define _c_cstack_fixed(SELF, VAL, CAP) \ typedef VAL SELF##_value; \ typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ - typedef struct { SELF##_value data[CAP]; size_t _len; } SELF + typedef struct { SELF##_value data[CAP]; intptr_t _len; } SELF #define _c_cstack_types(SELF, VAL) \ typedef VAL SELF##_value; \ typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ - typedef struct { SELF##_value* data; size_t _len, _cap; } SELF + typedef struct { SELF##_value* data; intptr_t _len, _cap; } SELF #define _c_cvec_types(SELF, VAL) \ typedef VAL SELF##_value; \ typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ - typedef struct { SELF##_value *data; size_t _len, _cap; } SELF + typedef struct { SELF##_value *data; intptr_t _len, _cap; } SELF #define _c_cpque_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value* data; size_t _len, _cap; } SELF + typedef struct { SELF##_value* data; intptr_t _len, _cap; } SELF #endif // STC_FORWARD_H_INCLUDED diff --git a/include/stc/priv/lowcase.h b/include/stc/priv/altnames.h index 8fdadd75..024868c2 100644 --- a/include/stc/priv/lowcase.h +++ b/include/stc/priv/altnames.h @@ -23,14 +23,6 @@ #define c_alloc c_ALLOC #define c_alloc_n c_ALLOC_N #define c_new c_NEW -#define c_malloc c_MALLOC -#define c_calloc c_CALLOC -#define c_realloc c_REALLOC -#define c_free c_FREE -#define c_delete c_DELETE -#define c_swap c_SWAP -#define c_container_of c_CONTAINER_OF -#define c_static_assert c_STATIC_ASSERT #define c_arraylen c_ARRAYLEN #define c_forlist c_FORLIST #define c_forrange c_FORRANGE @@ -45,14 +37,4 @@ #define c_with c_WITH #define c_scope c_SCOPE #define c_defer c_DEFER -#define c_drop c_DROP #define c_sv c_SV -#define c_ARGsv c_ARGSV -#define c_find_if c_FIND_IF -#define c_erase_if c_ERASE_IF -#define c_flt_take c_FLT_TAKE -#define c_flt_skip c_FLT_SKIP -#define c_flt_skipwhile c_FLT_SKIPWHILE -#define c_flt_takewhile c_FLT_TAKEWHILE -#define cstr_new(lit) cstr_lit(lit) -#define cstr_null cstr_NULL diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index 9634fe2c..6eb82bcb 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -44,11 +44,8 @@ #define _i_prefix #endif -#ifdef i_size - #define _i_expandby 2 -#else - #define i_size uint32_t - #define _i_expandby 1 +#ifndef i_size + #define i_size intptr_t #endif #if !(defined i_key || defined i_key_str || defined i_key_ssv || \ diff --git a/include/stc/utf8.h b/include/stc/utf8.h index f30e76ac..da738fc6 100644 --- a/include/stc/utf8.h +++ b/include/stc/utf8.h @@ -23,9 +23,9 @@ extern uint32_t utf8_tolower(uint32_t c); extern uint32_t utf8_toupper(uint32_t c); extern bool utf8_iscased(uint32_t c); extern bool utf8_isword(uint32_t c); -extern bool utf8_valid_n(const char* s, size_t nbytes); +extern bool utf8_valid_n(const char* s, intptr_t nbytes); extern int utf8_icmp_sv(csview s1, csview s2); -extern unsigned utf8_encode(char *out, uint32_t c); +extern int utf8_encode(char *out, uint32_t c); extern uint32_t utf8_peek_off(const char *s, int offset); STC_INLINE bool utf8_isupper(uint32_t c) @@ -35,7 +35,7 @@ STC_INLINE bool utf8_islower(uint32_t c) { return utf8_toupper(c) != c; } STC_INLINE bool utf8_isalnum(uint32_t c) { - if (c < 128) return isalnum(c) != 0; + if (c < 128) return isalnum((int)c) != 0; return utf8_isalpha(c) || utf8_isgroup(U8G_Nd, c); } @@ -45,7 +45,7 @@ STC_INLINE bool utf8_isblank(uint32_t c) { } STC_INLINE bool utf8_isspace(uint32_t c) { - if (c < 128) return isspace(c) != 0; + if (c < 128) return isspace((int)c) != 0; return ((c == 8232) | (c == 8233)) || utf8_isgroup(U8G_Zs, c); } @@ -68,17 +68,17 @@ STC_INLINE uint32_t utf8_peek(const char* s) { /* case-insensitive utf8 string comparison */ STC_INLINE int utf8_icmp(const char* s1, const char* s2) { - return utf8_icmp_sv(c_SV(s1, ~(size_t)0), c_SV(s2, ~(size_t)0)); + return utf8_icmp_sv(c_SV(s1, INTPTR_MAX), c_SV(s2, INTPTR_MAX)); } STC_INLINE bool utf8_valid(const char* s) { - return utf8_valid_n(s, ~(size_t)0); + return utf8_valid_n(s, INTPTR_MAX); } /* following functions are independent but assume valid utf8 strings: */ /* number of bytes in the utf8 codepoint from s */ -STC_INLINE unsigned utf8_chr_size(const char *s) { +STC_INLINE int utf8_chr_size(const char *s) { unsigned b = (uint8_t)*s; if (b < 0x80) return 1; /*if (b < 0xC2) return 0;*/ @@ -89,32 +89,32 @@ STC_INLINE unsigned utf8_chr_size(const char *s) { } /* number of codepoints in the utf8 string s */ -STC_INLINE size_t utf8_size(const char *s) { - size_t size = 0; +STC_INLINE intptr_t utf8_size(const char *s) { + intptr_t size = 0; while (*s) size += (*++s & 0xC0) != 0x80; return size; } -STC_INLINE size_t utf8_size_n(const char *s, size_t nbytes) { - size_t size = 0; +STC_INLINE intptr_t utf8_size_n(const char *s, intptr_t nbytes) { + intptr_t size = 0; while ((nbytes-- != 0) & (*s != 0)) { size += (*++s & 0xC0) != 0x80; } return size; } -STC_INLINE const char* utf8_at(const char *s, size_t index) { +STC_INLINE const char* utf8_at(const char *s, intptr_t index) { while ((index > 0) & (*s != 0)) index -= (*++s & 0xC0) != 0x80; return s; } -STC_INLINE size_t utf8_pos(const char* s, size_t index) - { return (size_t)(utf8_at(s, index) - s); } +STC_INLINE intptr_t utf8_pos(const char* s, intptr_t index) + { return (intptr_t)(utf8_at(s, index) - s); } #endif // UTF8_H_INCLUDED #if defined i_extern || defined STC_EXTERN -# include "../src/utf8code.c" +# include "../../src/utf8code.c" # undef i_extern #endif diff --git a/misc/archived/csmap.h b/misc/archived/csmap.h deleted file mode 100644 index 5c9fba6b..00000000 --- a/misc/archived/csmap.h +++ /dev/null @@ -1,511 +0,0 @@ -/* MIT License - * - * Copyright (c) 2023 Tyge Løvset - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -// Sorted/Ordered set and map - implemented as an AA-tree. -/* -#include <stdio.h> -#include <stc/cstr.h> - -#define i_tag sx // Sorted map<cstr, double> -#define i_key_str -#define i_val double -#include <stc/csmap.h> - -int main(void) { - 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); - csmap_sx_emplace(&m, "Testing three", 123.4); - - csmap_sx_value *v = csmap_sx_get(&m, "Testing five"); // NULL - double num = *csmap_sx_at(&m, "Testing one"); - csmap_sx_emplace_or_assign(&m, "Testing three", 1000.0); // update - csmap_sx_erase(&m, "Testing two"); - - c_FOREACH (i, csmap_sx, m) - printf("map %s: %g\n", cstr_str(&i.ref->first), i.ref->second); - } -} -*/ -#include <stc/ccommon.h> - -#ifndef CSMAP_H_INCLUDED -#define STC_CSMAP_V1 1 -#include <stc/forward.h> -#include <stdlib.h> -#include <string.h> -#endif // CSMAP_H_INCLUDED - -#ifndef _i_prefix -#define _i_prefix csmap_ -#endif -#ifdef _i_isset - #define _i_MAP_ONLY c_false - #define _i_SET_ONLY c_true - #define _i_keyref(vp) (vp) -#else - #define _i_ismap - #define _i_MAP_ONLY c_true - #define _i_SET_ONLY c_false - #define _i_keyref(vp) (&(vp)->first) -#endif -#include <stc/priv/template.h> - -#if !c_option(c_is_forward) -_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, i_size, _i_MAP_ONLY, _i_SET_ONLY); -#endif - -_i_MAP_ONLY( struct _cx_value { - _cx_key first; - _cx_mapped second; -}; ) -struct _cx_node { - struct _cx_node *link[2]; - uint8_t level; - _cx_value value; -}; - -typedef i_keyraw _cx_rawkey; -typedef i_valraw _cx_memb(_rawmapped); -typedef _i_SET_ONLY( i_keyraw ) - _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) - _cx_raw; - -#if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -#if !defined i_no_emplace -STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)); -#endif // !i_no_emplace -#endif // !i_no_clone -STC_API _cx_self _cx_memb(_init)(void); -STC_API _cx_result _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)); -STC_API _cx_result _cx_memb(_push)(_cx_self* self, _cx_value _val); -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out); -STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, i_keyraw rkey); -STC_API _cx_value* _cx_memb(_front)(const _cx_self* self); -STC_API _cx_value* _cx_memb(_back)(const _cx_self* self); -STC_API int _cx_memb(_erase)(_cx_self* self, i_keyraw rkey); -STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); -STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); -STC_API void _cx_memb(_next)(_cx_iter* it); - -STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.size == 0; } -STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cx.size; } -STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) - { _cx_iter it; _cx_memb(_find_it)(self, rkey, &it); return it; } -STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it) != NULL; } -STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, i_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } -STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, i_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } - -STC_INLINE void -_cx_memb(_clear)(_cx_self* self) - { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); } - -STC_INLINE _cx_raw -_cx_memb(_value_toraw)(_cx_value* val) { - return _i_SET_ONLY( i_keyto(val) ) - _i_MAP_ONLY( c_INIT(_cx_raw){i_keyto((&val->first)), - i_valto((&val->second))} ); -} - -STC_INLINE int -_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { - _cx_rawkey rx = i_keyto(_i_keyref(x)), ry = i_keyto(_i_keyref(y)); - return i_cmp((&rx), (&ry)); -} - -STC_INLINE void -_cx_memb(_value_drop)(_cx_value* val) { - i_keydrop(_i_keyref(val)); - _i_MAP_ONLY( i_valdrop((&val->second)); ) -} - -#if !defined i_no_clone -STC_INLINE _cx_value -_cx_memb(_value_clone)(_cx_value _val) { - *_i_keyref(&_val) = i_keyclone((*_i_keyref(&_val))); - _i_MAP_ONLY( _val.second = i_valclone(_val.second); ) - return _val; -} - -STC_INLINE void -_cx_memb(_copy)(_cx_self *self, const _cx_self* other) { - if (self->root == other->root) - return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); -} -#endif // !i_no_clone - -#ifndef _i_isset - #if !defined i_no_clone && !defined i_no_emplace - STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped); - #endif - STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); - - STC_INLINE const _cx_mapped* - _cx_memb(_at)(const _cx_self* self, i_keyraw rkey) - { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } - STC_INLINE _cx_mapped* - _cx_memb(_at_mut)(_cx_self* self, i_keyraw rkey) - { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } -#endif // !_i_isset - -STC_INLINE _cx_iter -_cx_memb(_begin)(const _cx_self* self) { - _cx_iter it; - it.ref = NULL, it._top = 0, it._tn = self->root; - _cx_memb(_next)(&it); - return it; -} - -STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) { - (void)self; - _cx_iter it; it.ref = NULL, it._top = 0, it._tn = NULL; - return it; -} - -STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { - while (n-- && it.ref) - _cx_memb(_next)(&it); - return it; -} - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) - -#ifndef CSMAP_H_INCLUDED -static struct { void *link[2]; uint8_t level; } -_csmap_sentinel = {{&_csmap_sentinel, &_csmap_sentinel}, 0}; -#endif - -static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey); - -STC_DEF _cx_self -_cx_memb(_init)(void) { - _cx_self cx = {(_cx_node *)&_csmap_sentinel, 0}; - return cx; -} - -STC_DEF _cx_value* -_cx_memb(_front)(const _cx_self* self) { - _cx_node *tn = self->root; - while (tn->link[0]->level) - tn = tn->link[0]; - return &tn->value; -} - -STC_DEF _cx_value* -_cx_memb(_back)(const _cx_self* self) { - _cx_node *tn = self->root; - while (tn->link[1]->level) - tn = tn->link[1]; - return &tn->value; -} - -STC_DEF _cx_result -_cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)) { - _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto((&key))); - if (res.inserted) - { *_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} - else - { i_keydrop((&key)); _i_MAP_ONLY( i_valdrop((&mapped)); )} - return res; -} - -STC_DEF _cx_result -_cx_memb(_push)(_cx_self* self, _cx_value _val) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); - if (_res.inserted) - *_res.ref = _val; - else - _cx_memb(_value_drop)(&_val); - return _res; -} - -#ifndef _i_isset - STC_DEF _cx_result - _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped) { - _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto((&key))); - if (res.inserted) - res.ref->first = key; - else - { i_keydrop((&key)); i_valdrop((&res.ref->second)); } - res.ref->second = mapped; - return res; - } - #if !defined i_no_clone && !defined i_no_emplace - STC_DEF _cx_result - _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { - _cx_result res = _cx_memb(_insert_entry_)(self, rkey); - if (res.inserted) - res.ref->first = i_keyfrom(rkey); - else - { i_valdrop((&res.ref->second)); } - res.ref->second = i_valfrom(rmapped); - return res; - } - #endif // !i_no_clone && !i_no_emplace -#endif // !_i_isset - -STC_DEF _cx_value* -_cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out) { - _cx_node *tn = self->root; - out->_top = 0; - while (tn->level) { - int c; _cx_rawkey raw = i_keyto(_i_keyref(&tn->value)); - if ((c = i_cmp((&raw), (&rkey))) < 0) - tn = tn->link[1]; - else if (c > 0) - { out->_st[out->_top++] = tn; tn = tn->link[0]; } - else - { out->_tn = tn->link[1]; return (out->ref = &tn->value); } - } - return (out->ref = NULL); -} - -STC_DEF _cx_iter -_cx_memb(_lower_bound)(const _cx_self* self, i_keyraw rkey) { - _cx_iter it; - _cx_memb(_find_it)(self, rkey, &it); - if (!it.ref && it._top) { - _cx_node *tn = it._st[--it._top]; - it._tn = tn->link[1]; - it.ref = &tn->value; - } - return it; -} - -STC_DEF void -_cx_memb(_next)(_cx_iter *it) { - _cx_node *tn = it->_tn; - if (it->_top || tn->level) { - while (tn->level) { - it->_st[it->_top++] = tn; - tn = tn->link[0]; - } - tn = it->_st[--it->_top]; - it->_tn = tn->link[1]; - it->ref = &tn->value; - } else - it->ref = NULL; -} - -static _cx_node * -_cx_memb(_skew_)(_cx_node *tn) { - if (tn && tn->link[0]->level == tn->level && tn->level) { - _cx_node *tmp = tn->link[0]; - tn->link[0] = tmp->link[1]; - tmp->link[1] = tn; - tn = tmp; - } - return tn; -} - -static _cx_node * -_cx_memb(_split_)(_cx_node *tn) { - if (tn->link[1]->link[1]->level == tn->level && tn->level) { - _cx_node *tmp = tn->link[1]; - tn->link[1] = tmp->link[0]; - tmp->link[0] = tn; - tn = tmp; - ++tn->level; - } - return tn; -} - -static _cx_node* -_cx_memb(_insert_entry_i_)(_cx_node* tn, const _cx_rawkey* rkey, _cx_result* res) { - _cx_node *up[64], *tx = tn; - int c, top = 0, dir = 0; - while (tx->level) { - up[top++] = tx; - _cx_rawkey r = i_keyto(_i_keyref(&tx->value)); - if (!(c = (i_cmp((&r), rkey)))) - { res->ref = &tx->value; return tn; } - dir = (c < 0); - tx = tx->link[dir]; - } - tn = c_ALLOC(_cx_node); - tn->link[0] = tn->link[1] = (_cx_node*)&_csmap_sentinel; - tn->level = 1; - res->ref = &tn->value, res->inserted = true; - if (top == 0) - return tn; - up[top - 1]->link[dir] = tn; - while (top--) { - if (top) - dir = (up[top - 1]->link[1] == up[top]); - up[top] = _cx_memb(_skew_)(up[top]); - up[top] = _cx_memb(_split_)(up[top]); - if (top) - up[top - 1]->link[dir] = up[top]; - } - return up[0]; -} - -STC_DEF _cx_result -_cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey) { - _cx_result res = {NULL}; - self->root = _cx_memb(_insert_entry_i_)(self->root, &rkey, &res); - self->size += res.inserted; - return res; -} - -static _cx_node* -_cx_memb(_erase_r_)(_cx_node *tn, const _cx_rawkey* rkey, int *erased) { - if (tn->level == 0) - return tn; - _cx_rawkey raw = i_keyto(_i_keyref(&tn->value)); - _cx_node *tx; int c = (i_cmp((&raw), rkey)); - if (c != 0) - tn->link[c < 0] = _cx_memb(_erase_r_)(tn->link[c < 0], rkey, erased); - else { - if (!*erased) - { _cx_memb(_value_drop)(&tn->value); *erased = 1; } - if (tn->link[0]->level && tn->link[1]->level) { - tx = tn->link[0]; - while (tx->link[1]->level) - tx = tx->link[1]; - tn->value = tx->value; - raw = i_keyto(_i_keyref(&tn->value)); - tn->link[0] = _cx_memb(_erase_r_)(tn->link[0], &raw, erased); - } else { /* unlink node */ - tx = tn; - tn = tn->link[tn->link[0]->level == 0]; - c_FREE(tx); - } - } - if (tn->link[0]->level < tn->level - 1 || tn->link[1]->level < tn->level - 1) { - if (tn->link[1]->level > --tn->level) - tn->link[1]->level = tn->level; - tn = _cx_memb(_skew_)(tn); - tx = tn->link[0] = _cx_memb(_skew_)(tn->link[0]); - tx->link[0] = _cx_memb(_skew_)(tx->link[0]); - tn = _cx_memb(_split_)(tn); - tn->link[0] = _cx_memb(_split_)(tn->link[0]); - } - return tn; -} - -STC_DEF int -_cx_memb(_erase)(_cx_self* self, i_keyraw rkey) { - int erased = 0; - self->root = _cx_memb(_erase_r_)(self->root, &rkey, &erased); - self->size -= erased; - return erased; -} - -STC_DEF _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - _cx_rawkey raw = i_keyto(_i_keyref(it.ref)), nxt; - _cx_memb(_next)(&it); - if (it.ref) - nxt = i_keyto(_i_keyref(it.ref)); - _cx_memb(_erase)(self, raw); - if (it.ref) - _cx_memb(_find_it)(self, nxt, &it); - return it; -} - -STC_DEF _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - if (!it2.ref) { - while (it1.ref) - it1 = _cx_memb(_erase_at)(self, it1); - return it1; - } - _cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref); - _cx_rawkey r1 = i_keyto((&k1)); - for (;;) { - if (memcmp(&k1, &k2, sizeof k1) == 0) - return it1; - _cx_memb(_next)(&it1); - k1 = *_i_keyref(it1.ref); - _cx_memb(_erase)(self, r1); - r1 = i_keyto((&k1)); - _cx_memb(_find_it)(self, r1, &it1); - } -} - -#if !defined i_no_clone -static _cx_node* -_cx_memb(_clone_r_)(_cx_node *tn) { - if (! tn->level) - return tn; - _cx_node *cn = c_ALLOC(_cx_node); - cn->level = tn->level; - cn->value = _cx_memb(_value_clone)(tn->value); - cn->link[0] = _cx_memb(_clone_r_)(tn->link[0]); - cn->link[1] = _cx_memb(_clone_r_)(tn->link[1]); - return cn; -} - -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - return c_INIT(_cx_self){_cx_memb(_clone_r_)(cx.root), cx.size}; -} -#endif // !i_no_clone - -#if !defined i_no_emplace -STC_DEF _cx_result -_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { - _cx_result res = _cx_memb(_insert_entry_)(self, rkey); - if (res.inserted) { - *_i_keyref(res.ref) = i_keyfrom(rkey); - _i_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) - } - return res; -} -#endif // i_no_emplace - -static void -_cx_memb(_drop_r_)(_cx_node* tn) { - if (tn->level != 0) { - _cx_memb(_drop_r_)(tn->link[0]); - _cx_memb(_drop_r_)(tn->link[1]); - _cx_memb(_value_drop)(&tn->value); - c_FREE(tn); - } -} - -STC_DEF void -_cx_memb(_drop)(_cx_self* self) { - _cx_memb(_drop_r_)(self->root); -} - -#endif // i_implement -#undef _i_isset -#undef _i_ismap -#undef _i_keyref -#undef _i_MAP_ONLY -#undef _i_SET_ONLY -#define CSMAP_H_INCLUDED -#include <stc/priv/template.h> diff --git a/misc/archived/cstr.h b/misc/archived/cstr.h deleted file mode 100644 index e074b6e4..00000000 --- a/misc/archived/cstr.h +++ /dev/null @@ -1,384 +0,0 @@ -/* MIT License - * - * Copyright (c) 2023 Tyge Løvset - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef CSTR_H_INCLUDED -#define CSTR_H_INCLUDED - -#include <stc/ccommon.h> -#include <stc/forward.h> -#include <stdlib.h> /* malloc */ -#include <string.h> -#include <stdarg.h> -#include <stdio.h> /* vsnprintf */ -#include <ctype.h> - -#define c_unchecked_container_of(ptr, type, member) \ - ((type*)((char*)(ptr) - offsetof(type, member))) - -typedef char cstr_value; -typedef struct { cstr_value* str; } cstr; -typedef struct { size_t size, cap; char chr[1]; } cstr_priv; -#define _cstr_p(self) c_unchecked_container_of((self)->str, cstr_priv, chr) -#ifdef i_static - static cstr_priv _cstr_nullrep = {0, 0, {0}}; - static const cstr cstr_NULL = {_cstr_nullrep.chr}; -#else - extern const cstr cstr_NULL; -#endif -/* optimal memory: based on malloc_usable_size() sequence: 24, 40, 56, ... */ -#define _cstr_opt_mem(cap) ((((offsetof(cstr_priv, chr) + (cap) + 8)>>4)<<4) + 8) -/* optimal string capacity: 7, 23, 39, ... */ -#define _cstr_opt_cap(cap) (_cstr_opt_mem(cap) - offsetof(cstr_priv, chr) - 1) - -STC_API cstr cstr_from_n(const char* str, size_t n); -STC_API cstr cstr_from_fmt(const char* fmt, ...); -STC_API char* cstr_reserve(cstr* self, size_t cap); -STC_API void cstr_resize(cstr* self, size_t len, char fill); -STC_API cstr* cstr_assign_n(cstr* self, const char* str, size_t n); -STC_API int cstr_printf(cstr* self, const char* fmt, ...); -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(cstr* self, size_t pos, size_t n); -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; } -STC_INLINE const char* cstr_str(const cstr* self) { return self->str; } -#define cstr_toraw(self) (self)->str -STC_INLINE csview cstr_sv(const cstr* self) - { return c_INIT(csview){self->str, _cstr_p(self)->size}; } -#define cstr_lit(literal) \ - cstr_from_n(literal, crawstr_len(literal)) -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(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) - { if (_cstr_p(self)->cap) c_FREE(_cstr_p(self)); } -STC_INLINE cstr cstr_clone(cstr s) - { return cstr_from_n(s.str, _cstr_p(&s)->size); } -STC_INLINE void cstr_clear(cstr* self) - { self->str[_cstr_p(self)->size = 0] = '\0'; } -STC_INLINE cstr* cstr_assign(cstr* self, const char* str) - { return cstr_assign_n(self, str, strlen(str)); } -STC_INLINE cstr* cstr_copy(cstr* self, cstr s) - { return cstr_assign_n(self, s.str, _cstr_p(&s)->size); } -STC_INLINE cstr* cstr_append(cstr* self, const char* str) - { return cstr_append_n(self, str, strlen(str)); } -STC_INLINE cstr* cstr_append_s(cstr* self, cstr s) - { return cstr_append_n(self, s.str, _cstr_p(&s)->size); } -STC_INLINE void cstr_push_back(cstr* self, char value) - { cstr_append_n(self, &value, 1); } -STC_INLINE void cstr_pop_back(cstr* self) - { self->str[ --_cstr_p(self)->size ] = '\0'; } -STC_INLINE void cstr_insert_n(cstr* self, const size_t pos, const char* str, const size_t n) - { cstr_replace_at_sv(self, pos, 0, c_SV(str, n)); } -STC_INLINE void cstr_insert(cstr* self, const size_t pos, const char* str) - { cstr_replace_at_sv(self, pos, 0, c_SV(str, strlen(str))); } -STC_INLINE void cstr_insert_s(cstr* self, const size_t pos, cstr s) - { cstr_replace_at_sv(self, pos, 0, c_SV(s.str, _cstr_p(&s)->size)); } -STC_INLINE void cstr_replace_at(cstr* self, const size_t pos, const size_t len, const char* str) - { cstr_replace_at_sv(self, pos, len, c_SV(str, strlen(str))); } -STC_INLINE void cstr_replace_s(cstr* self, const size_t pos, const size_t len, cstr s) - { cstr_replace_at_sv(self, pos, len, c_SV(s.str, _cstr_p(&s)->size)); } -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(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); } - -STC_INLINE cstr_buf cstr_buffer(cstr* s) { - cstr_priv* p = _cstr_p(s); - return c_INIT(cstr_buf){s->str, p->size, p->cap}; -} - -STC_INLINE cstr cstr_with_capacity(const size_t cap) { - cstr s = cstr_NULL; - cstr_reserve(&s, cap); - return s; -} - -STC_INLINE cstr cstr_with_size(const size_t len, const char fill) { - cstr s = cstr_NULL; - cstr_resize(&s, len, fill); - return s; -} - -STC_INLINE char* cstr_append_uninit(cstr *self, size_t n) { - 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; -} - -STC_INLINE cstr* cstr_take(cstr* self, cstr s) { - if (self->str != s.str && _cstr_p(self)->cap) - c_FREE(_cstr_p(self)); - self->str = s.str; - return self; -} - -STC_INLINE cstr cstr_move(cstr* self) { - cstr tmp = *self; - *self = cstr_NULL; - return tmp; -} - -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(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) { - int ret = 0; - while (nmax-- && (ret = tolower(*s1++) - tolower(*s2)) == 0 && *s2++) - ; - return ret; -} - -/* container adaptor functions: */ -#define cstr_cmp(xp, yp) strcmp((xp)->str, (yp)->str) - -STC_INLINE bool cstr_eq(const cstr* x, const cstr* y) { - size_t xs = _cstr_p(x)->size, ys = _cstr_p(y)->size; - return xs == ys && !memcmp(x->str, y->str, xs); -} -STC_INLINE uint64_t cstr_hash(const cstr *self) { - return cfasthash(self->str, _cstr_p(self)->size); -} - -STC_INLINE void cstr_replace_ex(cstr* self, const char* find, const char* repl, unsigned count) { - cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(find, strlen(find)), - c_SV(repl, strlen(repl)), count)); -} -STC_INLINE void cstr_replace(cstr* self, const char* search, const char* repl) - { cstr_replace_ex(self, search, repl, ~0U); } - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) - -#ifndef i_static -static cstr_priv _cstr_nullrep = {0, 0, {0}}; -const cstr cstr_NULL = {_cstr_nullrep.chr}; -#endif - -STC_DEF char* -cstr_reserve(cstr* self, const size_t cap) { - cstr_priv *p = _cstr_p(self); - const size_t oldcap = p->cap; - if (cap > oldcap) { - p = (cstr_priv*) c_REALLOC(((oldcap != 0) & (p != &_cstr_nullrep)) ? p : NULL, _cstr_opt_mem(cap)); - if (!p) return NULL; - self->str = p->chr; - if (oldcap == 0) self->str[p->size = 0] = '\0'; - p->cap = _cstr_opt_cap(cap); - } - return self->str; -} - -STC_DEF void -cstr_resize(cstr* self, const size_t len, const char fill) { - const size_t n = _cstr_p(self)->size; - cstr_reserve(self, len); - if (len > n) memset(self->str + n, fill, len - n); - if (len | n) self->str[_cstr_p(self)->size = len] = '\0'; -} - -STC_DEF cstr -cstr_from_n(const char* str, const size_t n) { - if (n == 0) return cstr_NULL; - cstr_priv* prv = (cstr_priv*) c_MALLOC(_cstr_opt_mem(n)); - cstr s = {(char *) memcpy(prv->chr, str, n)}; - s.str[prv->size = n] = '\0'; - prv->cap = _cstr_opt_cap(n); - return s; -} - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4996) -#endif - -STC_DEF int -cstr_vfmt(cstr* self, const char* fmt, va_list args) { - va_list args2; - va_copy(args2, args); - int len = vsnprintf(NULL, (size_t)0, fmt, args); - cstr_reserve(self, len); - vsprintf(self->str, fmt, args2); - va_end(args2); - return _cstr_p(self)->size = len; -} - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - -STC_DEF cstr -cstr_from_fmt(const char* fmt, ...) { - cstr ret = cstr_NULL; - va_list args; va_start(args, fmt); - cstr_vfmt(&ret, fmt, args); - va_end(args); - return ret; -} - -STC_DEF int -cstr_printf(cstr* self, const char* fmt, ...) { - cstr ret = cstr_NULL; - va_list args; - va_start(args, fmt); - int n = cstr_vfmt(&ret, fmt, args); - va_end(args); - cstr_drop(self); - *self = ret; - return n; -} - -STC_DEF cstr* -cstr_assign_n(cstr* self, const char* str, const size_t n) { - if (n || _cstr_p(self)->cap) { - cstr_reserve(self, n); - memmove(self->str, str, n); - self->str[_cstr_p(self)->size = n] = '\0'; - } - return self; -} - -STC_DEF cstr* -cstr_append_n(cstr* self, const char* str, const size_t n) { - if (n == 0) return self; - const size_t oldlen = _cstr_p(self)->size, newlen = oldlen + n; - if (newlen > _cstr_p(self)->cap) { - const size_t off = (size_t) (str - self->str); /* handle self append */ - cstr_reserve(self, (oldlen*3 >> 1) + n); - if (off <= oldlen) str = self->str + off; - } - memcpy(&self->str[oldlen], str, n); - self->str[_cstr_p(self)->size = newlen] = '\0'; - return self; -} - -STC_INLINE void _cstr_internal_move(cstr* self, const size_t pos1, const size_t pos2) { - if (pos1 == pos2) - return; - const size_t len = _cstr_p(self)->size, newlen = len + pos2 - pos1; - if (newlen > _cstr_p(self)->cap) - cstr_reserve(self, (len*3 >> 1) + pos2 - pos1); - memmove(&self->str[pos2], &self->str[pos1], len - pos1); - self->str[_cstr_p(self)->size = newlen] = '\0'; -} - -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); - if (len > sz - pos) len = sz - pos; - char buf[256], *xstr = repl.size > 256 ? c_MALLOC(repl.size) : buf; - memcpy(xstr, repl.str, repl.size); - _cstr_internal_move(self, pos + len, pos + repl.size); - memcpy(&self->str[pos], xstr, repl.size); - if (repl.size > 256) c_FREE(xstr); -} - -STC_DEF cstr -cstr_replace_sv(csview str, csview find, csview repl, unsigned count) { - cstr out = cstr_NULL; - size_t from = 0; char* res; - if (find.size) - while (count-- && (res = cstrnstrn(str.str + from, find.str, str.size - from, find.size))) { - const size_t pos = res - str.str; - cstr_append_n(&out, str.str + from, pos - from); - cstr_append_n(&out, repl.str, repl.size); - from = pos + find.size; - } - cstr_append_n(&out, str.str + from, str.size - from); - return out; -} - -STC_DEF void -cstr_erase(cstr* self, const size_t pos, size_t n) { - const size_t len = _cstr_p(self)->size; - if (n > len - pos) n = len - pos; - if (len) { - memmove(&self->str[pos], &self->str[pos + n], len - (pos + n)); - self->str[_cstr_p(self)->size -= n] = '\0'; - } -} - -STC_DEF bool -cstr_getdelim(cstr *self, const int delim, FILE *fp) { - size_t pos = 0, cap = _cstr_p(self)->cap; - char* d = self->str; - int c = fgetc(fp); - if (c == EOF) - return false; - for (;;) { - if (c == delim || c == EOF) { - if (cap) d[_cstr_p(self)->size = pos] = '\0'; - return true; - } - if (pos == cap) { - d = cstr_reserve(self, (cap*3 >> 1) + 16); - cap = cstr_capacity(*self); - } - d[pos++] = (char) c; - c = fgetc(fp); - } -} - -STC_DEF size_t -cstr_find(const cstr* self, const char* needle) { - char* res = strstr(self->str, needle); - return res ? res - self->str : c_NPOS; -} - -STC_DEF size_t -cstr_find_at(const cstr* self, const size_t pos, const char* needle) { - if (pos > _cstr_p(self)->size) return c_NPOS; - char* res = strstr(self->str + pos, needle); - return res ? res - self->str : c_NPOS; -} - -#endif -#endif // CSTR_H_INCLUDED -#undef i_opt diff --git a/misc/archived/new_arr.c b/misc/archived/new_arr.c deleted file mode 100644 index 1006439d..00000000 --- a/misc/archived/new_arr.c +++ /dev/null @@ -1,57 +0,0 @@ -#include <stc/cstr.h> - -#define i_val int -#include "carr2.h" - -#define i_val int -#include "carr3.h" - -#define i_val_str -#include "carr2.h" - -int main() -{ - int w = 7, h = 5, d = 3; - - 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) - dat[i] = i; - - for (size_t x = 0; x < volume.xdim; ++x) - for (size_t y = 0; y < volume.ydim; ++y) - printf(" %d", volume.data[x][y]); - puts(""); - - c_FOREACH (i, carr2_int, volume) - printf(" %d", *i.ref); - puts("\n"); - } - - 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) - dat[i] = i; - - for (size_t x = 0; x < volume.xdim; ++x) - for (size_t y = 0; y < volume.ydim; ++y) - for (size_t z = 0; z < volume.zdim; ++z) - printf(" %d", volume.data[x][y][z]); - puts(""); - - c_FOREACH (i, carr3_int, volume) - printf(" %d", *i.ref); - puts(""); - } - - c_WITH (carr2_str text2d = carr2_str_with_size(h, d, cstr_NULL), carr2_str_drop(&text2d)) - { - cstr_assign(&text2d.data[2][1], "hello"); - cstr_assign(&text2d.data[4][0], "world"); - - c_FOREACH (i, carr2_str, text2d) - printf("line: %s\n", cstr_str(i.ref)); - } -} diff --git a/misc/benchmarks/build_all.sh b/misc/benchmarks/build_all.sh index 54340998..869559ba 100644 --- a/misc/benchmarks/build_all.sh +++ b/misc/benchmarks/build_all.sh @@ -1,5 +1,5 @@ #!/bin/bash -cc='g++ -I../../include -s -O3 -Wall -pedantic -x c++ -std=c++20' +cc='g++ -I../../include -s -O3 -Wall -pedantic -x c++ -std=c++2a' #cc='clang++ -I../include -s -O3 -Wall -pedantic -x c++ -std=c++20' #cc='cl -nologo -I../include -O2 -TP -EHsc -std:c++20' run=0 diff --git a/misc/examples/astar.c b/misc/examples/astar.c index 828de8ce..ddc9de3a 100644 --- a/misc/examples/astar.c +++ b/misc/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 = (int)cstr_find(maze, c); return point_init(index % width, index / width, width); } @@ -156,7 +156,7 @@ main(void) "# # # # # # #\n" "#########################################################################\n"), cstr_drop(&maze)) { - int width = cstr_find(&maze, "\n") + 1; + int width = (int)cstr_find(&maze, "\n") + 1; c_WITH (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path)) { c_FOREACH (it, cdeq_point, path) diff --git a/misc/examples/birthday.c b/misc/examples/birthday.c index be7f0457..fb887cd7 100644 --- a/misc/examples/birthday.c +++ b/misc/examples/birthday.c @@ -50,19 +50,19 @@ void test_distribution(void) uint64_t sum = 0; c_FOREACH (i, cmap_x, map) sum += i.ref->second; - sum /= map.size; + sum /= (uint64_t)map.size; c_FOREACH (i, cmap_x, map) { printf("%4" PRIu32 ": %" PRIu64 " - %" PRIu64 ": %11.8f\n", i.ref->first, i.ref->second, sum, - (1 - (double)i.ref->second / sum)); + (1.0 - (double)i.ref->second / (double)sum)); } } } int main() { - seed = time(NULL); + seed = (uint64_t)time(NULL); test_distribution(); test_repeats(); } diff --git a/misc/examples/bits.c b/misc/examples/bits.c index c50eac6e..03b74881 100644 --- a/misc/examples/bits.c +++ b/misc/examples/bits.c @@ -4,18 +4,18 @@ int main() { c_WITH (cbits set = cbits_with_size(23, true), cbits_drop(&set)) { - printf("count %" c_ZU ", %" c_ZU "\n", cbits_count(&set), cbits_size(&set)); + printf("count %" c_ZI ", %" c_ZI "\n", cbits_count(&set), cbits_size(&set)); cbits s1 = cbits_from("1110100110111"); char buf[256]; cbits_to_str(&s1, buf, 0, 255); - printf("buf: %s: %" c_ZU "\n", buf, cbits_count(&s1)); + printf("buf: %s: %" c_ZI "\n", buf, cbits_count(&s1)); cbits_drop(&s1); cbits_reset(&set, 9); cbits_resize(&set, 43, false); printf(" str: %s\n", cbits_to_str(&set, buf, 0, 255)); - printf("%4" c_ZU ": ", cbits_size(&set)); + printf("%4" c_ZI ": ", cbits_size(&set)); c_FORRANGE (i, cbits_size(&set)) printf("%d", cbits_test(&set, i)); puts(""); @@ -25,12 +25,12 @@ int main() cbits_resize(&set, 93, false); cbits_resize(&set, 102, true); cbits_set_value(&set, 99, false); - printf("%4" c_ZU ": ", cbits_size(&set)); + printf("%4" c_ZI ": ", cbits_size(&set)); c_FORRANGE (i, cbits_size(&set)) printf("%d", cbits_test(&set, i)); puts("\nIterate:"); - printf("%4" c_ZU ": ", cbits_size(&set)); + printf("%4" c_ZI ": ", cbits_size(&set)); c_FORRANGE (i, cbits_size(&set)) printf("%d", cbits_test(&set, i)); puts(""); @@ -52,7 +52,7 @@ int main() puts(""); cbits_set_all(&set, false); - printf("%4" c_ZU ": ", cbits_size(&set)); + printf("%4" c_ZI ": ", cbits_size(&set)); c_FORRANGE (i, cbits_size(&set)) printf("%d", cbits_test(&set, i)); puts(""); diff --git a/misc/examples/bits2.c b/misc/examples/bits2.c index 502e7268..9b1d1af7 100644 --- a/misc/examples/bits2.c +++ b/misc/examples/bits2.c @@ -9,10 +9,10 @@ int main() { Bits s1 = Bits_from("1110100110111"); - printf("size %" c_ZU "\n", Bits_size(&s1)); + printf("size %" c_ZI "\n", Bits_size(&s1)); char buf[256]; Bits_to_str(&s1, buf, 0, 256); - printf("buf: %s: count=%" c_ZU "\n", buf, Bits_count(&s1)); + printf("buf: %s: count=%" c_ZI "\n", buf, Bits_count(&s1)); Bits_reset(&s1, 8); printf(" s1: %s\n", Bits_to_str(&s1, buf, 0, 256)); diff --git a/misc/examples/books.c b/misc/examples/books.c index 96c7ff6e..4695941a 100644 --- a/misc/examples/books.c +++ b/misc/examples/books.c @@ -32,7 +32,7 @@ int main() // When collections store owned values (String), they can still be // queried using references (&str). if (cmap_str_contains(&book_reviews, "Les Misérables")) { - printf("We've got %" c_ZU " reviews, but Les Misérables ain't one.", + printf("We've got %" c_ZI " reviews, but Les Misérables ain't one.", cmap_str_size(&book_reviews)); } diff --git a/misc/examples/box.c b/misc/examples/box.c index 446a7603..3a7a8139 100644 --- a/misc/examples/box.c +++ b/misc/examples/box.c @@ -24,7 +24,7 @@ Person Person_clone(Person p) { void Person_drop(Person* p) { printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); - c_DROP(cstr, &p->name, &p->last); + c_drop(cstr, &p->name, &p->last); } #define i_type PBox diff --git a/misc/examples/city.c b/misc/examples/city.c index 7f355bdf..e24c90de 100644 --- a/misc/examples/city.c +++ b/misc/examples/city.c @@ -44,7 +44,7 @@ City City_clone(City c) { void City_drop(City* c) { printf("drop %s\n", cstr_str(&c->name)); - c_DROP(cstr, &c->name, &c->country); + c_drop(cstr, &c->name, &c->country); } diff --git a/misc/examples/complex.c b/misc/examples/complex.c index 6fed1d4d..5c212554 100644 --- a/misc/examples/complex.c +++ b/misc/examples/complex.c @@ -37,7 +37,7 @@ int main() // Put in some data in the structures stack.data[3] = 3.1415927f; - printf("stack size: %" c_ZU "\n", FloatStack_size(&stack)); + printf("stack size: %" c_ZI "\n", FloatStack_size(&stack)); StackList list = StackList_init(); StackList_push_back(&list, stack); diff --git a/misc/examples/csmap_erase.c b/misc/examples/csmap_erase.c index bef00a17..a41a1ad1 100644 --- a/misc/examples/csmap_erase.c +++ b/misc/examples/csmap_erase.c @@ -12,7 +12,7 @@ void printmap(mymap m) { c_FOREACH (elem, mymap, m) printf(" [%d, %s]", elem.ref->first, cstr_str(&elem.ref->second)); - printf("\nsize() == %" c_ZU "\n\n", mymap_size(&m)); + printf("\nsize() == %" c_ZI "\n\n", mymap_size(&m)); } int main() @@ -75,9 +75,9 @@ int main() puts("Starting data of map m3 is:"); printmap(m3); // The 3rd member function removes elements with a given Key - size_t count = mymap_erase(&m3, 2); + int count = mymap_erase(&m3, 2); // The 3rd member function also returns the number of elements removed - printf("The number of elements removed from m3 is: %" c_ZU "\n", count); + printf("The number of elements removed from m3 is: %d\n", count); puts("After the element with a key of 2 is deleted, the map m3 is:"); printmap(m3); } diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c index a61a47be..201c94e9 100644 --- a/misc/examples/csmap_find.c +++ b/misc/examples/csmap_find.c @@ -18,7 +18,7 @@ void print_elem(csmap_istr_raw p) { #define using_print_collection(CX) \ void print_collection_##CX(const CX* t) { \ - printf("%" c_ZU " elements: ", CX##_size(t)); \ + printf("%" c_ZI " elements: ", CX##_size(t)); \ \ c_FOREACH (p, CX, *t) { \ print_elem(CX##_value_toraw(p.ref)); \ diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c index 116e5dd4..bfb0df6b 100644 --- a/misc/examples/cstr_match.c +++ b/misc/examples/cstr_match.c @@ -5,8 +5,8 @@ int main() { c_WITH (cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) { - size_t pos = cstr_find_at(&ss, 0, "brown"); - printf("%" c_ZU " [%s]\n", pos, pos == c_NPOS ? "<NULL>" : cstr_str(&ss) + pos); + intptr_t pos = cstr_find_at(&ss, 0, "brown"); + printf("%" c_ZI " [%s]\n", pos, pos == c_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")); @@ -16,7 +16,7 @@ int main() cstr s1 = cstr_lit("hell😀 w😀rl🐨"); csview ch1 = cstr_u8_chr(&s1, 7); csview ch2 = cstr_u8_chr(&s1, 10); - printf("%s\nsize: %" c_ZU ", %" c_ZU "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1)); + printf("%s\nsize: %" c_ZI ", %" c_ZI "\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/misc/examples/demos.c b/misc/examples/demos.c index 4455b840..7070d860 100644 --- a/misc/examples/demos.c +++ b/misc/examples/demos.c @@ -13,7 +13,7 @@ void stringdemo1() cstr_erase(&cs, 7, 5); // -nine printf("%s.\n", cstr_str(&cs)); - cstr_replace_ex(&cs, "seven", "four", 1); + cstr_replace(&cs, "seven", "four", 1); printf("%s.\n", cstr_str(&cs)); cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs))); @@ -38,7 +38,7 @@ void vectordemo1() 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) + for (int i = 10; i <= 100; i += 10) cvec_ix_push(&bignums, i * i); printf("erase - %d: %" PRIu64 "\n", 3, bignums.data[3]); @@ -47,8 +47,8 @@ void vectordemo1() cvec_ix_pop(&bignums); // erase the last cvec_ix_erase_n(&bignums, 0, 1); // erase the first - for (size_t i = 0; i < cvec_ix_size(&bignums); ++i) { - printf("%" c_ZU ": %" PRIu64 "\n", i, bignums.data[i]); + for (int i = 0; i < cvec_ix_size(&bignums); ++i) { + printf("%d: %" PRIu64 "\n", i, bignums.data[i]); } } } @@ -175,11 +175,11 @@ void mapdemo3() cmap_str_iter it = cmap_str_find(&table, "Make"); c_FOREACH (i, cmap_str, table) printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); - printf("size %" c_ZU ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second)); + printf("size %" c_ZI ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second)); //cmap_str_erase(&table, "Make"); cmap_str_erase_at(&table, it); - printf("size %" c_ZU "\n", cmap_str_size(&table)); + printf("size %" c_ZI "\n", cmap_str_size(&table)); c_FOREACH (i, cmap_str, table) printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); cmap_str_drop(&table); // frees key and value cstrs, and hash table. diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 05d0bc28..1c64c9e0 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -33,12 +33,12 @@ void demo1(void) int res, sum = 0; c_FORFILTER (i, IVec, vec - , c_FLT_SKIPWHILE(i, *i.ref != 80) - && c_FLT_SKIP(i, 1) - && c_FLT_SKIPWHILE(i, *i.ref != 80) + , c_flt_skipwhile(i, *i.ref != 80) + && c_flt_skip(i, 1) + && c_flt_skipwhile(i, *i.ref != 80) && flt_isEven(i) && flt_skipValue(i, 80) - , c_FLT_TAKE(i, 5) // short-circuit + , c_flt_take(i, 5) // short-circuit ){ sum += res = flt_square(i); printf(" %d", res); @@ -64,12 +64,12 @@ void demo2(void) { c_AUTO (IVec, vector) { puts("demo2:"); - - c_FORFILTER (x, crange, crange_literal(INT64_MAX) - , c_FLT_SKIPWHILE(x, *x.ref != 11) + crange R = crange_make(INT64_MAX); + c_FORFILTER (x, crange, R + , c_flt_skipwhile(x, *x.ref != 11) && *x.ref % 2 != 0 - , c_FLT_TAKE(x, 5)) - IVec_push(&vector, *x.ref * *x.ref); + , c_flt_take(x, 5)) + IVec_push(&vector, (int)(*x.ref * *x.ref)); c_FOREACH (x, IVec, vector) printf(" %d", *x.ref); puts(""); @@ -126,13 +126,13 @@ void demo5(void) #define flt_even(i) ((*i.ref & 1) == 0) #define flt_mid_decade(i) ((*i.ref % 10) != 0) puts("demo5:"); - crange r1 = crange_make(1963, INT32_MAX); - c_FORFILTER (i, crange, r1 - , c_FLT_SKIP(i,15) - && c_FLT_SKIPWHILE(i, flt_mid_decade(i)) - && c_FLT_SKIP(i,30) + crange R = crange_make(1963, INT32_MAX); + c_FORFILTER (i, crange, R + , c_flt_skip(i,15) + && c_flt_skipwhile(i, flt_mid_decade(i)) + && c_flt_skip(i,30) && flt_even(i) - , c_FLT_TAKE(i,10)) + , c_flt_take(i,10)) printf(" %lld", *i.ref); puts(""); } diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 69c1c193..cd3c4d9e 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -68,12 +68,12 @@ int main() puts("\n\nc_forfilter:");
c_FORFILTER (i, IVec, vec
- , c_FLT_SKIPWHILE(i, *i.ref != 65)
- && c_FLT_TAKEWHILE(i, *i.ref != 280)
- && c_FLT_SKIPWHILE(i, isOdd(i))
+ , c_flt_skipwhile(i, *i.ref != 65)
+ && c_flt_takewhile(i, *i.ref != 280)
+ && c_flt_skipwhile(i, isOdd(i))
&& isOdd(i)
- && c_FLT_SKIP(i, 2)
- , c_FLT_TAKE(i, 1))
+ && c_flt_skip(i, 2)
+ , c_flt_take(i, 1))
printf(" %d", *i.ref);
puts("");
// 189
diff --git a/misc/examples/functor.c b/misc/examples/functor.c index 54e2702d..f1db3644 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -23,7 +23,7 @@ struct { #define i_type ipque #define i_val int #define i_opt c_is_forward // needed to avoid re-type-define container type -#define i_less_functor(self, x, y) c_CONTAINER_OF(self, IPQueue, Q)->less(x, y) +#define i_less_functor(self, x, y) c_container_of(self, IPQueue, Q)->less(x, y) #include <stc/cpque.h> void print_queue(const char* name, IPQueue q) { diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c index 519a7895..6b06b4e8 100644 --- a/misc/examples/gauss1.c +++ b/misc/examples/gauss1.c @@ -24,7 +24,7 @@ int main() printf("Demo of gaussian / normal distribution of %d random samples\n", N); // Setup random engine with normal distribution. - uint64_t seed = time(NULL); + uint64_t seed = (uint64_t)time(NULL); stc64_t rng = stc64_new(seed); stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); @@ -45,7 +45,7 @@ int main() // Print the gaussian bar chart c_FOREACH (i, cvec_ii, histvec) { - int n = (int)(i.ref->second * StdDev * Scale * 2.5 / N); + int n = (int)(i.ref->second * StdDev * Scale * 2.5 / (double)N); if (n > 0) { printf("%4d ", i.ref->first); c_FORRANGE (n) printf("*"); diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c index c2ed2e00..c627fc91 100644 --- a/misc/examples/gauss2.c +++ b/misc/examples/gauss2.c @@ -18,7 +18,7 @@ int main() printf("Demo of gaussian / normal distribution of %d random samples\n", N); // Setup random engine with normal distribution. - uint64_t seed = time(NULL); + uint64_t seed = (uint64_t)time(NULL); stc64_t rng = stc64_new(seed); stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); @@ -33,7 +33,7 @@ int main() // Print the gaussian bar chart c_AUTO (cstr, bar) c_FORPAIR (index, count, csmap_int, mhist) { - size_t n = (size_t) (*_.count * StdDev * Scale * 2.5 / (float)N); + int n = (int)((float)*_.count * StdDev * Scale * 2.5f / (float)N); if (n > 0) { cstr_resize(&bar, n, '*'); printf("%4d %s\n", *_.index, cstr_str(&bar)); diff --git a/misc/examples/make.sh b/misc/examples/make.sh index bd1392fc..19a53880 100755 --- a/misc/examples/make.sh +++ b/misc/examples/make.sh @@ -6,14 +6,14 @@ if [ "$(uname)" = 'Linux' ]; then oflag='-o ' fi +cc=gcc; cflags="-s -O2 -std=c99 -Wconversion -Wpedantic -Wall -Wsign-compare -Wwrite-strings" #cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall $sanitize" -cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings" # -Wconversion #cc=tcc; cflags="-Wall -std=c99" #cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings" #cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -DSTC_CSTR_V1 -DSTC_CSMAP_V1" #cc=gcc; cflags="-x c++ -s -O2 -Wall -std=c++20" #cc=g++; cflags="-x c++ -s -O2 -Wall" -#cc=cl; cflags="-O2 -nologo -W2 -MD" +#cc=cl; cflags="-O2 -nologo -W3 -MD" #cc=cl; cflags="-nologo -TP" #cc=cl; cflags="-nologo -std:c11" @@ -40,13 +40,13 @@ fi if [ $run = 0 ] ; then for i in *.c ; do - echo $comp -I../include $i $clibs $oflag$(basename $i .c).exe - $comp -I../include $i $clibs $oflag$(basename $i .c).exe + echo $comp -I../../include $i $clibs $oflag$(basename $i .c).exe + $comp -I../../include $i $clibs $oflag$(basename $i .c).exe done else for i in *.c ; do - echo $comp -I../include $i $clibs - $comp -I../include $i $clibs + echo $comp -I../../include $i $clibs + $comp -I../../include $i $clibs if [ -f $(basename -s .c $i).exe ]; then ./$(basename -s .c $i).exe; fi if [ -f ./a.exe ]; then ./a.exe; fi if [ -f ./a.out ]; then ./a.out; fi diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c index 945741b1..e61959ca 100644 --- a/misc/examples/multidim.c +++ b/misc/examples/multidim.c @@ -5,53 +5,66 @@ #include <stdio.h> using_cspan3(ispan, int); -/* -using_cspan(ispan, int, 1); -using_cspan(ispan2, int, 2); -using_cspan(ispan3, int, 3); -*/ int main() { - cstack_int v = {0}; - c_FORLIST (i, unsigned, {1,2,3,4,5,6,7,8,9,10,11,12}) - cstack_int_push(&v, *i.ref); - - // View data as contiguous memory representing 12 ints - ispan ms1 = cspan_from(&v); - // View data as contiguous memory representing 2 rows of 6 ints each - ispan2 ms2 = cspan_make(v.data, 2, 6); - // View the same data as a 3D array 2 x 3 x 2 - ispan3 ms3 = cspan_make(v.data, 2, 3, 2); - - // write data using 2D view - for (unsigned i=0; i != ms2.dim[0]; i++) - for (unsigned j=0; j != ms2.dim[1]; j++) - *cspan_at(&ms2, i, j) = i*1000 + j; - - // print all items using 1D view - printf("all: "); - for (unsigned i=0; i != cspan_size(&ms1); i++) - printf(" %d", *cspan_at(&ms1, i)); - puts(""); - - // or iterate a subspan... - ispan2 sub = cspan_at3(&ms3, 1); - printf("sub: "); - c_FOREACH (i, ispan2, sub) - printf(" %d", *i.ref); - puts(""); - - // read back using 3D view - for (unsigned i=0; i != ms3.dim[0]; i++) - { - printf("slice @ i = %u\n", i); - for (unsigned j=0; j != ms3.dim[1]; j++) - { - for (unsigned k=0; k != ms3.dim[2]; k++) - printf("%d ", *cspan_at(&ms3, i, j, k)); - puts(""); + cstack_int v = {0}; + c_FORLIST (i, int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}) + cstack_int_push(&v, *i.ref); + + // View data as contiguous memory representing 24 ints + ispan ms1 = cspan_from(&v); + + // View the same data as a 3D array 2 x 3 x 4 + ispan3 ms3 = cspan_md(v.data, 2, 3, 4); + + puts("ms3:"); + for (int i=0; i != ms3.shape[0]; i++) { + for (int j=0; j != ms3.shape[1]; j++) { + for (int k=0; k != ms3.shape[2]; k++) { + printf(" %2d", *cspan_at(&ms3, i, j, k)); + } + puts(""); + } + puts(""); } - } - cstack_int_drop(&v); + puts("ss3 = ms3[:, 1:3, 1:3]"); + ispan3 ss3 = ms3; + //cspan_slice(&ss3, {c_ALL}, {1,3}, {1,3}); + ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); + + for (int i=0; i != ss3.shape[0]; i++) { + for (int j=0; j != ss3.shape[1]; j++) { + for (int k=0; k != ss3.shape[2]; k++) { + printf(" %2d", *cspan_at(&ss3, i, j, k)); + } + puts(""); + } + puts(""); + } + + puts("Iterate ss3 flat:"); + c_FOREACH (i, ispan3, ss3) + printf(" %d", *i.ref); + puts(""); + + ispan2 ms2 = cspan_submd3(&ms3, 0); + + // write data using 2D view + for (int i=0; i != ms2.shape[0]; i++) + for (int j=0; j != ms2.shape[1]; j++) + *cspan_at(&ms2, i, j) = i*1000 + j; + + puts("\nview data as 1D view:"); + for (int i=0; i != cspan_size(&ms1); i++) + printf(" %d", *cspan_at(&ms1, i)); + puts(""); + + puts("iterate subspan ms3[1]:"); + ispan2 sub = cspan_submd3(&ms3, 1); + c_FOREACH (i, ispan2, sub) + printf(" %d", *i.ref); + puts(""); + + cstack_int_drop(&v); } diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c index 9896c591..fad7ddcf 100644 --- a/misc/examples/music_arc.c +++ b/misc/examples/music_arc.c @@ -16,7 +16,7 @@ Song Song_make(const char* artist, const char* title) void Song_drop(Song* s) { printf("drop: %s\n", cstr_str(&s->title)); - c_DROP(cstr, &s->artist, &s->title); + c_drop(cstr, &s->artist, &s->title); } // Define the reference counted type diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c index 72705eb2..9cee987d 100644 --- a/misc/examples/new_map.c +++ b/misc/examples/new_map.c @@ -48,24 +48,25 @@ int main() c_AUTO (cset_str, sset) { cmap_int_insert(&map, 123, 321); + cmap_int_insert(&map, 456, 654); + cmap_int_insert(&map, 789, 987); - c_FORLIST (i, cmap_pnt_raw, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}}) - cmap_pnt_insert(&pmap, c_PAIR(i.ref)); + pmap = c_make(cmap_pnt, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}}); c_FOREACH (i, cmap_pnt, pmap) printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); puts(""); - c_FORLIST (i, cmap_str_raw, { + smap = c_make(cmap_str, { {"Hello, friend", "long time no see"}, - {"So long, friend", "see you around"}, - }) cmap_str_emplace(&smap, c_PAIR(i.ref)); + {"So long", "see you around"}, + }); - c_FORLIST (i, const char*, { + sset = c_make(cset_str, { "Hello, friend", "Nice to see you again", - "So long, friend", - }) cset_str_emplace(&sset, *i.ref); + "So long", + }); c_FOREACH (i, cset_str, sset) printf(" %s\n", cstr_str(i.ref)); diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c index d127b592..b3d94c2f 100644 --- a/misc/examples/new_pque.c +++ b/misc/examples/new_pque.c @@ -48,7 +48,7 @@ int main() cpque_int_push(&ique, 123); cpque_int_push(&ique, 321); // print - for (size_t i=0; i<cpque_int_size(&ique); ++i) + for (int i=0; i<cpque_int_size(&ique); ++i) printf(" %d", ique.data[i]); puts(""); } diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c index 828387b5..5c25a229 100644 --- a/misc/examples/new_queue.c +++ b/misc/examples/new_queue.c @@ -22,25 +22,25 @@ int point_cmp(const Point* a, const Point* b) { int main() { int n = 50000000; - stc64_t rng = stc64_new(time(NULL)); + stc64_t rng = stc64_new((uint64_t)time(NULL)); stc64_uniform_t dist = stc64_uniform_new(0, n); c_AUTO (IQ, Q) { // Push 50'000'000 random numbers onto the queue. c_FORRANGE (n) - IQ_push(&Q, stc64_uniform(&rng, &dist)); + IQ_push(&Q, (int)stc64_uniform(&rng, &dist)); // Push or pop on the queue 50 million times - printf("befor: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q)); + printf("befor: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q)); c_FORRANGE (n) { - int r = stc64_uniform(&rng, &dist); + int r = (int)stc64_uniform(&rng, &dist); if (r & 3) IQ_push(&Q, r); else IQ_pop(&Q); } - printf("after: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q)); + printf("after: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q)); } } diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c index 5441ae01..116827a4 100644 --- a/misc/examples/new_sptr.c +++ b/misc/examples/new_sptr.c @@ -43,7 +43,7 @@ Person Person_clone(Person p) { } void Person_drop(Person* p) { printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); - c_DROP(cstr, &p->name, &p->last); + c_drop(cstr, &p->name, &p->last); } diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c index f782c9da..4d9c2a51 100644 --- a/misc/examples/person_arc.c +++ b/misc/examples/person_arc.c @@ -24,7 +24,7 @@ Person Person_clone(Person p) { void Person_drop(Person* p) { printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); - c_DROP(cstr, &p->name, &p->last); + c_drop(cstr, &p->name, &p->last); } #define i_type PSPtr diff --git a/misc/examples/prime.c b/misc/examples/prime.c index 40ccc299..11c1f1c7 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -6,19 +6,19 @@ #include <stc/algo/crange.h> -cbits sieveOfEratosthenes(size_t n) +cbits sieveOfEratosthenes(intptr_t n) { cbits bits = cbits_with_size(n/2 + 1, true); - size_t q = (size_t) sqrt((double) n) + 1; - for (size_t i = 3; i < q; i += 2) { - size_t j = i; + intptr_t q = (intptr_t)sqrt((double) n) + 1; + for (intptr_t i = 3; i < q; i += 2) { + intptr_t j = i; for (; j < n; j += 2) { if (cbits_test(&bits, j>>1)) { i = j; break; } } - for (size_t j = i*i; j < n; j += i*2) + for (intptr_t j = i*i; j < n; j += i*2) cbits_reset(&bits, j>>1); } return bits; @@ -26,16 +26,16 @@ cbits sieveOfEratosthenes(size_t n) int main(void) { - size_t n = 1000000000; - printf("computing prime numbers up to %" c_ZU "\n", n); + intptr_t n = 1000000000; + printf("computing prime numbers up to %" c_ZI "\n", n); clock_t t1 = clock(); c_WITH (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { puts("done"); - size_t np = cbits_count(&primes); + intptr_t np = cbits_count(&primes); clock_t t2 = clock(); - printf("number of primes: %" c_ZU ", time: %f\n", np, (t2 - t1) / (float)CLOCKS_PER_SEC); + printf("number of primes: %" c_ZI ", time: %f\n", np, (float)(t2 - t1) / (float)CLOCKS_PER_SEC); puts("Show all the primes in the range [2, 1000):"); printf("2"); c_FORRANGE (i, 3, 1000, 2) @@ -43,9 +43,10 @@ int main(void) puts(""); puts("Show the last 50 primes using a temporary crange generator:"); - c_FORFILTER (i, crange, crange_literal(n - 1, 0, -2) + crange R = crange_make(n - 1, 0, -2); + c_FORFILTER (i, crange, R , cbits_test(&primes, *i.ref>>1) - , c_FLT_TAKE(i, 50)) { + , c_flt_take(i, 50)) { printf("%lld ", *i.ref); if (i.count % 10 == 0) puts(""); } diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index a897e669..82b54367 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -1,42 +1,57 @@ // printspan.c #include <stdio.h> +#include <stc/cstr.h> #define i_val int #include <stc/cvec.h> #define i_val int #include <stc/cstack.h> #define i_val int #include <stc/cdeq.h> +#define i_val_str +#include <stc/cset.h> #include <stc/cspan.h> -using_cspan(ispan, int, 1); +using_cspan(intspan, int, 1); -void printMe(ispan container) { - printf("%d\n", (int)cspan_size(&container)); - c_FOREACH (e, ispan, container) printf("%d ", *e.ref); +void printMe(intspan container) { + printf("%d:", (int)cspan_size(&container)); + c_FOREACH (e, intspan, container) printf(" %d", *e.ref); puts(""); } -int main() { +int main() +{ c_AUTO (cvec_int, vec) c_AUTO (cstack_int, stk) c_AUTO (cdeq_int, deq) + c_AUTO (cset_str, set) { - int arr[] = {1, 2, 3, 4, 5}; - ispan sp = cspan_from_array(arr); - printMe((ispan)cspan_subspan(&sp, 1, 3)); + intspan sp1 = cspan_make(intspan, {1, 2}); + printMe( sp1 ); + + printMe( c_make(intspan, {1, 2, 3}) ); - printMe((ispan)cspan_from_list(int, {1, 2, 3, 4})); + int arr[] = {1, 2, 3, 4, 5, 6}; + intspan sp2 = cspan_from_array(arr); + printMe( (intspan)cspan_subspan(&sp2, 1, 4) ); - printMe((ispan)cspan_from_array(arr)); + c_FORLIST (i, int, {1, 2, 3, 4, 5}) + cvec_int_push(&vec, *i.ref); + printMe( (intspan)cspan_from(&vec) ); - c_FORLIST (i, int, {1, 2, 3, 4, 5, 6}) cvec_int_push(&vec, *i.ref); - printMe((ispan)cspan_from(&vec)); + printMe( sp2 ); - c_FORLIST (i, int, {1, 2, 3, 4, 5, 6, 7}) cstack_int_push(&stk, *i.ref); - printMe((ispan)cspan_from(&stk)); + stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7}); + printMe( (intspan)cspan_from(&stk) ); - c_FORLIST (i, int, {1, 2, 3, 4, 5, 6, 7, 8}) cdeq_int_push_front(&deq, *i.ref); - printMe((ispan)cspan_from(&deq)); + deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8}); + printMe( (intspan)cspan_from(&deq) ); + + set = c_make(cset_str, {"1", "2", "3", "4", "5", "6", "7", "8", "9"}); + printf("%d:", (int)cset_str_size(&set)); + c_FOREACH (e, cset_str, set) + printf(" %s", cstr_str(e.ref)); + puts(""); } } diff --git a/misc/examples/priority.c b/misc/examples/priority.c index 22da6f60..f39c0634 100644 --- a/misc/examples/priority.c +++ b/misc/examples/priority.c @@ -9,13 +9,13 @@ #include <stc/cpque.h> int main() { - size_t N = 10000000; - stc64_t rng = stc64_new(time(NULL)); + intptr_t N = 10000000; + stc64_t rng = stc64_new((uint64_t)time(NULL)); stc64_uniform_t dist = stc64_uniform_new(0, N * 10); c_AUTO (cpque_i, heap) { // Push ten million random numbers to priority queue - printf("Push %" c_ZU " numbers\n", N); + printf("Push %" c_ZI " numbers\n", N); c_FORRANGE (N) cpque_i_push(&heap, stc64_uniform(&rng, &dist)); diff --git a/misc/examples/queue.c b/misc/examples/queue.c index 1d325fc6..ee537b58 100644 --- a/misc/examples/queue.c +++ b/misc/examples/queue.c @@ -15,17 +15,17 @@ int main() { { // Push ten million random numbers onto the queue. c_FORRANGE (n) - cqueue_i_push(&queue, stc64_uniform(&rng, &dist)); + cqueue_i_push(&queue, (int)stc64_uniform(&rng, &dist)); // Push or pop on the queue ten million times printf("%d\n", n); c_FORRANGE (n) { // forrange uses initial n only. - int r = stc64_uniform(&rng, &dist); + int r = (int)stc64_uniform(&rng, &dist); if (r & 1) ++n, cqueue_i_push(&queue, r); else --n, cqueue_i_pop(&queue); } - printf("%d, %" c_ZU "\n", n, cqueue_i_size(&queue)); + printf("%d, %" c_ZI "\n", n, cqueue_i_size(&queue)); } } diff --git a/misc/examples/random.c b/misc/examples/random.c index 82214924..fc4576dd 100644 --- a/misc/examples/random.c +++ b/misc/examples/random.c @@ -5,10 +5,10 @@ int main() { const size_t N = 1000000000; - const uint64_t seed = time(NULL), range = 1000000; + const uint64_t seed = (uint64_t)time(NULL), range = 1000000; stc64_t rng = stc64_new(seed); - uint64_t sum; + int64_t sum; clock_t diff, before; printf("Compare speed of full and unbiased ranged random numbers...\n"); @@ -18,8 +18,8 @@ int main() sum += (uint32_t)stc64_rand(&rng); } diff = clock() - before; - printf("full range\t\t: %f secs, %" c_ZU ", avg: %f\n", - (float)diff / CLOCKS_PER_SEC, N, (double)sum / N); + printf("full range\t\t: %f secs, %" c_ZI ", avg: %f\n", + (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N); stc64_uniform_t dist1 = stc64_uniform_new(0, range); rng = stc64_new(seed); @@ -29,17 +29,17 @@ int main() sum += stc64_uniform(&rng, &dist1); // unbiased } diff = clock() - before; - printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZU ", avg: %f\n", - range, (float)diff/CLOCKS_PER_SEC, N, (double)sum / N); + printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZI ", avg: %f\n", + range, (float)diff/CLOCKS_PER_SEC, N, (float)sum / (float)N); sum = 0; rng = stc64_new(seed); before = clock(); c_FORRANGE (N) { - sum += stc64_rand(&rng) % (range + 1); // biased + sum += (int64_t)(stc64_rand(&rng) % (range + 1)); // biased } diff = clock() - before; - printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZU ", avg: %f\n", - range, (float)diff / CLOCKS_PER_SEC, N, (double)sum / N); + printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZI ", avg: %f\n", + range, (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N); } diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c index 05910c77..96a9ba86 100644 --- a/misc/examples/rawptr_elements.c +++ b/misc/examples/rawptr_elements.c @@ -13,7 +13,7 @@ typedef int64_t inttype; #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) +#define i_valdrop(x) c_free(*x) #include <stc/cmap.h> // With cbox: diff --git a/misc/examples/regex1.c b/misc/examples/regex1.c index 9552db62..ae00b71c 100644 --- a/misc/examples/regex1.c +++ b/misc/examples/regex1.c @@ -10,7 +10,7 @@ int main(int argc, char* argv[]) c_AUTO (cstr, input) c_AUTO (cregex, float_expr) { - int res = cregex_compile(&float_expr, "^[+-]?[0-9]+((\\.[0-9]*)?|\\.[0-9]+)$", CREG_DEFAULT); + int res = cregex_compile(&float_expr, "^[+-]?[0-9]+((\\.[0-9]*)?|\\.[0-9]+)$"); // Until "q" is given, ask for another number if (res > 0) while (true) { diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c index e24cce51..2b742529 100644 --- a/misc/examples/regex2.c +++ b/misc/examples/regex2.c @@ -18,7 +18,7 @@ int main() c_AUTO (cregex, re) c_FORRANGE (i, c_ARRAYLEN(s)) { - int res = cregex_compile(&re, s[i].pattern, CREG_DEFAULT); + int res = cregex_compile(&re, s[i].pattern); if (res < 0) { printf("error in regex pattern: %d\n", res); continue; diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c index b6bd6521..b7d6ed3a 100644 --- a/misc/examples/regex_match.c +++ b/misc/examples/regex_match.c @@ -1,6 +1,7 @@ #define i_extern #include <stc/cregex.h> #include <stc/csview.h> + #define i_val float #include <stc/cstack.h> @@ -17,12 +18,12 @@ int main() c_AUTO (cstr, nums) { const char* pattern = "[+-]?([0-9]*\\.)?\\d+([Ee][+-]?\\d+)?"; - int res = cregex_compile(&re, pattern, CREG_DEFAULT); + int res = cregex_compile(&re, pattern); printf("%d: %s\n", res, pattern); // extract and convert all numbers in str to floats c_FORMATCH (i, &re, str) - cstack_float_push(&vec, atof(i.match[0].str)); + cstack_float_push(&vec, (float)atof(i.match[0].str)); c_FOREACH (i, cstack_float, vec) printf(" %g\n", *i.ref); diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c index a170856b..ec38ca56 100644 --- a/misc/examples/regex_replace.c +++ b/misc/examples/regex_replace.c @@ -26,15 +26,15 @@ int main() printf("fixed: %s\n", cstr_str(&str)); /* US date format, and add 10 years to dates: */ - cstr_take(&str, cregex_replace_pattern_ex(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT)); + cstr_take(&str, cregex_replace_pattern(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT)); printf("us+10: %s\n", cstr_str(&str)); /* Wrap first date inside []: */ - cstr_take(&str, cregex_replace_pattern_ex(pattern, input, "[$0]", 1, NULL, CREG_DEFAULT)); + cstr_take(&str, cregex_replace_pattern(pattern, input, "[$0]")); printf("brack: %s\n", cstr_str(&str)); /* Shows how to compile RE separately */ - c_WITH (cregex re = cregex_from(pattern, CREG_DEFAULT), cregex_drop(&re)) { + c_WITH (cregex re = cregex_from(pattern), cregex_drop(&re)) { if (cregex_captures(&re) == 0) continue; /* break c_WITH */ /* European date format. */ diff --git a/misc/examples/shape.c b/misc/examples/shape.c index ed0c3fe1..9ce0b946 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -38,7 +38,7 @@ void Shape_delete(Shape* shape) { if (shape) { shape->api->drop(shape); - c_FREE(shape); + c_free(shape); } } @@ -50,12 +50,12 @@ typedef struct { Point p[3]; } Triangle; -static struct ShapeAPI Triangle_api; +extern struct ShapeAPI Triangle_api; Triangle Triangle_from(Point a, Point b, Point c) { - Triangle t = {{.api=&Triangle_api}, .p={a, b, c}}; + Triangle t = {.shape={.api=&Triangle_api}, .p={a, b, c}}; return t; } @@ -68,7 +68,7 @@ static void Triangle_draw(const Shape* shape) self->p[2].x, self->p[2].y); } -static struct ShapeAPI Triangle_api = { +struct ShapeAPI Triangle_api = { .drop = Shape_drop, .draw = Triangle_draw, }; @@ -85,12 +85,12 @@ typedef struct { PointVec points; } Polygon; -static struct ShapeAPI Polygon_api; +extern struct ShapeAPI Polygon_api; Polygon Polygon_init(void) { - Polygon p = {{.api=&Polygon_api}, .points=PointVec_init()}; + Polygon p = {.shape={.api=&Polygon_api}, .points=PointVec_init()}; return p; } @@ -116,7 +116,7 @@ static void Polygon_draw(const Shape* shape) puts(""); } -static struct ShapeAPI Polygon_api = { +struct ShapeAPI Polygon_api = { .drop = Polygon_drop, .draw = Polygon_draw, }; diff --git a/misc/examples/sort.c b/misc/examples/sort.c index de94cede..65077143 100644 --- a/misc/examples/sort.c +++ b/misc/examples/sort.c @@ -14,7 +14,7 @@ #define fmt_Elem "%lld" -int testsort(csort_elm_value *a, size_t size, const char *desc) { +int testsort(csort_elm_value *a, long size, const char *desc) { clock_t t = clock(); #ifdef __cplusplus printf("std::sort: "); @@ -26,13 +26,13 @@ int testsort(csort_elm_value *a, size_t size, const char *desc) { t = clock() - t; printf("%s: %d elements sorted in %.2f ms\n", - desc, (int)size, t*1000.0/CLOCKS_PER_SEC); + desc, (int)size, (float)t*1000.0f/CLOCKS_PER_SEC); return 0; } int main(int argc, char *argv[]) { - size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000; - csort_elm_value *a = (csort_elm_value*)malloc(sizeof(*a) * size); + long i, size = argc > 1 ? strtol(argv[1], NULL, 0) : 10000000; + csort_elm_value *a = (csort_elm_value*)c_malloc(c_sizeof(*a) * size); if (a == NULL) return -1; for (i = 0; i < size; i++) diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c index 70d1935e..ba927412 100644 --- a/misc/examples/splitstr.c +++ b/misc/examples/splitstr.c @@ -13,7 +13,7 @@ int main() puts("\nSplit with c_FORMATCH (regex):"); - c_WITH (cregex re = cregex_from("[^ ]+", CREG_DEFAULT), cregex_drop(&re)) + c_WITH (cregex re = cregex_from("[^ ]+"), cregex_drop(&re)) c_FORMATCH (i, &re, " Hello World C99! ") printf("'%.*s'\n", c_ARGSV(i.match[0])); } diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c index f88e5f79..0841a316 100644 --- a/misc/examples/sso_map.c +++ b/misc/examples/sso_map.c @@ -10,7 +10,7 @@ int main() cmap_str_emplace(&m, "Test long ", "This is a longer string"); c_FORPAIR (k, v, cmap_str, m) - printf("%s: '%s' Len=%" c_ZU ", Is long: %s\n", + printf("%s: '%s' Len=%" c_ZI ", Is long: %s\n", cstr_str(_.k), cstr_str(_.v), cstr_size(_.v), cstr_is_long(_.v) ? "true" : "false"); } diff --git a/misc/examples/sso_substr.c b/misc/examples/sso_substr.c index 8e7450ba..7e858ec4 100644 --- a/misc/examples/sso_substr.c +++ b/misc/examples/sso_substr.c @@ -6,7 +6,7 @@ int main () { cstr str = cstr_lit("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" + intptr_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)); @@ -16,5 +16,5 @@ int main () cstr s3 = cstr_from_sv(cstr_substr_ex(&str, 0, 6)); // "apples" printf("%s %s: %d, %d\n", cstr_str(&s2), cstr_str(&s3), cstr_is_long(&str), cstr_is_long(&s2)); - c_DROP (cstr, &str, &s2, &s3); + c_drop (cstr, &str, &s2, &s3); } diff --git a/misc/examples/stack.c b/misc/examples/stack.c index 370577b9..86099607 100644 --- a/misc/examples/stack.c +++ b/misc/examples/stack.c @@ -15,7 +15,7 @@ int main() { c_AUTO (cstack_c, chars) { c_FORRANGE (i, 101) - cstack_i_push(&stack, i*i); + cstack_i_push(&stack, (int)(i*i)); printf("%d\n", *cstack_i_top(&stack)); diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c index 5658924e..2d4b5324 100644 --- a/misc/examples/sview_split.c +++ b/misc/examples/sview_split.c @@ -6,7 +6,7 @@ int main() { // No memory allocations or string length calculations! const csview date = c_SV("2021/03/12"); - size_t pos = 0; + intptr_t pos = 0; const csview year = csview_token(date, "/", &pos); const csview month = csview_token(date, "/", &pos); const csview day = csview_token(date, "/", &pos); diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c index 2d8d1921..3f98a2a6 100644 --- a/misc/examples/utf8replace_c.c +++ b/misc/examples/utf8replace_c.c @@ -16,11 +16,8 @@ int main() { c_FOREACH (c, cstr, hello) printf("%.*s,", c_ARGSV(c.u8.chr)); - //csview sv = c_SV("If you find the time, you will find the winner"); - //str = cstr_replace_sv(sv, c_SV("find"), c_SV("match"), 0); - - str = cstr_lit("If you find the time, you will find the winner"); - cstr_replace(&str, "find", "match"); + str = cstr_lit("scooby, dooby doo"); + cstr_replace(&str, "oo", "00"); printf("\n%s\n", cstr_str(&str)); } } diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c index c65a9caa..86d60519 100644 --- a/misc/examples/vikings.c +++ b/misc/examples/vikings.c @@ -23,11 +23,11 @@ static inline int RViking_cmp(const RViking* rx, const RViking* ry) { } static inline Viking Viking_from(RViking raw) { // note: parameter is by value - return c_INIT(Viking){cstr_from(raw.name), cstr_from(raw.country)}; + return c_LITERAL(Viking){cstr_from(raw.name), cstr_from(raw.country)}; } static inline RViking Viking_toraw(const Viking* vp) { - return c_INIT(RViking){cstr_str(&vp->name), cstr_str(&vp->country)}; + return c_LITERAL(RViking){cstr_str(&vp->name), cstr_str(&vp->country)}; } // With this in place, we define the Viking => int hash map type: diff --git a/misc/tests/cregex_test.c b/misc/tests/cregex_test.c index cd812aa2..24c39950 100644 --- a/misc/tests/cregex_test.c +++ b/misc/tests/cregex_test.c @@ -1,260 +1,282 @@ -#if 0 -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <stc/csview.h> -#include <stc/stctest.h> +#define i_extern #include <stc/cregex.h> +#include <stc/csview.h> +#include "ctest.h" -#define START_TEST(f) void f(void) -#define END_TEST +#define M_START(m) ((m).str - inp) +#define M_END(m) (M_START(m) + (m).size) -#define M_START(re, m) ((m).str - (re).input) -#define M_END(re, m) (M_START(re, m) + (m).size) -START_TEST(compile_match_char) +CTEST(cregex, compile_match_char) { - cregex re = cregex_from("äsdf", 0); - EXPECT_EQ(re.error, 0); + const char* inp; + cregex re = cregex_from("äsdf"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_TRUE(cregex_find("äsdf", &re, &match, 0)); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 5); // ä is two bytes wide + ASSERT_EQ(cregex_find(&re, inp="äsdf", &match, CREG_M_FULLMATCH), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 5); // ä is two bytes wide - EXPECT_EQ(cregex_find("zäsdf", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 1); - EXPECT_EQ(M_END(re, match), 6); + ASSERT_EQ(cregex_find(&re, inp="zäsdf", &match), CREG_OK); + ASSERT_EQ(M_START(match), 1); + ASSERT_EQ(M_END(match), 6); cregex_drop(&re); } -END_TEST -START_TEST(compile_match_anchors) +CTEST(cregex, compile_match_anchors) { - cregex re = cregex_from("^äs.f$", 0); - EXPECT_EQ(re.error, 0); + const char* inp; + cregex re = cregex_from(inp="^äs.f$"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_TRUE(cregex_find("äsdf", &re, &match, 0)); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 5); + ASSERT_EQ(cregex_find(&re, inp="äsdf", &match), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 5); - EXPECT_TRUE(cregex_is_match("äs♥f", &re)); - EXPECT_TRUE(cregex_is_match("äsöf", &re)); + ASSERT_TRUE(cregex_is_match(&re, "äs♥f")); + ASSERT_TRUE(cregex_is_match(&re, "äsöf")); - cregex_drop(re); + cregex_drop(&re); } -END_TEST -START_TEST(compile_match_quantifiers) +CTEST(cregex, compile_match_quantifiers1) { + const char* inp; c_AUTO (cregex, re) { - re = cregex_from("ä+", 0); - EXPECT_EQ(re.error, 0); + re = cregex_from("ä+"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_EQ(cregex_find("ääb", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 4); + ASSERT_EQ(cregex_find(&re, inp="ääb", &match), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 4); - EXPECT_EQ(cregex_find("bäbb", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 1); - EXPECT_EQ(M_END(re, match), 3); + ASSERT_EQ(cregex_find(&re, inp="bäbb", &match), CREG_OK); + ASSERT_EQ(M_START(match), 1); + ASSERT_EQ(M_END(match), 3); - EXPECT_FALSE(cregex_find("bbb", &re, &match, 0)); + ASSERT_EQ(cregex_find(&re, "bbb", &match), CREG_NOMATCH); } +} + +CTEST(cregex, compile_match_quantifiers2) +{ + const char* inp; c_AUTO (cregex, re) { - re = cregex_from("bä*", 0); - EXPECT_EQ(re.error, 0); + re = cregex_from("bä*"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_EQ(cregex_find("bääb", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 5); + ASSERT_EQ(cregex_find(&re, inp="bääb", &match), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 5); - EXPECT_EQ(cregex_find("bäbb", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 3); + ASSERT_EQ(cregex_find(&re, inp="bäbb", &match), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 3); - EXPECT_EQ(cregex_find("bbb", &re, &match, 0), 1); - EXPECT_EQ(M_START(re, match), 0); - EXPECT_EQ(M_END(re, match), 1); + ASSERT_EQ(cregex_find(&re, inp="bbb", &match), CREG_OK); + ASSERT_EQ(M_START(match), 0); + ASSERT_EQ(M_END(match), 1); } } -END_TEST -START_TEST(compile_match_escaped_chars) +CTEST(cregex, compile_match_escaped_chars) { - cregex re = cregex_from("\\n\\r\\t\\{", 0); - EXPECT_EQ(re.error, 0); + cregex re = cregex_from("\\n\\r\\t\\{"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_EQ(cregex_find("\n\r\t{", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("\n\r\t", &re, &match, 0), 0); + ASSERT_EQ(cregex_find(&re, "\n\r\t{", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "\n\r\t", &match), CREG_NOMATCH); cregex_drop(&re); } -END_TEST -START_TEST(compile_match_class_simple) +CTEST(cregex, compile_match_class_simple) { c_AUTO (cregex, re1, re2, re3) { - re1 = cregex_from("\\s", 0); - EXPECT_EQ(re1.error, 0); - re2 = cregex_from("\\w", 0); - EXPECT_EQ(re2.error, 0); - re3 = cregex_from("\\D", 0); - EXPECT_EQ(re3.error, 0); + re1 = cregex_from("\\s"); + ASSERT_EQ(re1.error, 0); + re2 = cregex_from("\\w"); + ASSERT_EQ(re2.error, 0); + re3 = cregex_from("\\D"); + ASSERT_EQ(re3.error, 0); csview match; - EXPECT_EQ(cregex_find(" ", &re1, &match, 0), 1); - EXPECT_EQ(cregex_find("\r", &re1, &match, 0), 1); - EXPECT_EQ(cregex_find("\n", &re1, &match, 0), 1); + ASSERT_EQ(cregex_find(&re1, " " , &match), CREG_OK); + ASSERT_EQ(cregex_find(&re1, "\r", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re1, "\n", &match), CREG_OK); - EXPECT_EQ(cregex_find("a", &re2, &match, 0), 1); - EXPECT_EQ(cregex_find("0", &re2, &match, 0), 1); - EXPECT_EQ(cregex_find("_", &re2, &match, 0), 1); + ASSERT_EQ(cregex_find(&re2, "a", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re2, "0", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re2, "_", &match), CREG_OK); - EXPECT_EQ( cregex_find("k", &re3, &match, 0), 1); - EXPECT_EQ(cregex_find("0", &re3, &match, 0), 0); + ASSERT_EQ(cregex_find(&re3, "k", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re3, "0", &match), CREG_NOMATCH); } } -END_TEST -START_TEST(compile_match_or) +CTEST(cregex, compile_match_or) { c_AUTO (cregex, re, re2) { - re = cregex_from("as|df", 0); - EXPECT_EQ(re.error, 0); + re = cregex_from("as|df"); + ASSERT_EQ(re.error, 0); - csview match; - EXPECT_EQ(cregex_find("as", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("df", &re, &match, 0), 1); + csview match[4]; + ASSERT_EQ(cregex_find(&re, "as", match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "df", match), CREG_OK); - re2 = cregex_from("(as|df)", 0); - EXPECT_EQ(re2.error, 0); + re2 = cregex_from("(as|df)"); + ASSERT_EQ(re2.error, 0); - EXPECT_EQ(cregex_find(&re2, "as", &re, &match, 0), 1); - EXPECT_EQ(cregex_find(&re2, "df", &re, &match, 0), 1); + ASSERT_EQ(cregex_find(&re2, "as", match), CREG_OK); + ASSERT_EQ(cregex_find(&re2, "df", match), CREG_OK); } } -END_TEST -START_TEST(compile_match_class_complex_0) +CTEST(cregex, compile_match_class_complex_0) { - cregex re = cregex_from("[asdf]", 0); - EXPECT_EQ(re.error, 0); + cregex re = cregex_from("[asdf]"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_EQ(cregex_find("a", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("s", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("d", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("f", &re, &match, 0), 1); + ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "s", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "d", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "f", &match), CREG_OK); cregex_drop(&re); } -END_TEST -START_TEST(compile_match_class_complex_1) +CTEST(cregex, compile_match_class_complex_1) { - cregex re = cregex_from("[a-zä0-9öA-Z]", 0); - EXPECT_EQ(re.error, 0); + cregex re = cregex_from("[a-zä0-9öA-Z]"); + ASSERT_EQ(re.error, 0); csview match; - EXPECT_EQ(cregex_find("a", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("5", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("A", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("ä", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("ö", &re, &match, 0), 1); + ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "5", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "A", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "ä", &match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "ö", &match), CREG_OK); cregex_drop(&re); } -END_TEST -START_TEST(compile_match_cap) +CTEST(cregex, compile_match_cap) { - cregex re = cregex_from("(abc)d", 0); - EXPECT_EQ(re.error, 0); + cregex re = cregex_from("(abc)d"); + ASSERT_EQ(re.error, 0); - csview match; - EXPECT_EQ(cregex_find("abcd", &re, &match, 0)), 1; - EXPECT_EQ(cregex_find("llljabcdkk", &re, &match, 0), 1); - EXPECT_EQ(cregex_find("abc", &re, &match, 0), 0); + csview match[4]; + ASSERT_EQ(cregex_find(&re, "abcd", match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "llljabcdkk", match), CREG_OK); + ASSERT_EQ(cregex_find(&re, "abc", match), CREG_NOMATCH); cregex_drop(&re); } -END_TEST -START_TEST(search_all) +CTEST(cregex, search_all) { + const char* inp; c_AUTO (cregex, re) { - re = cregex_from("ab", 0); + re = cregex_from("ab"); csview m = {0}; int res; - - res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT); - EXPECT_TRUE(res==1 && M_START(re, m) == 0); - res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT); - EXPECT_TRUE(res==1 && M_START(re, m) == 3); - res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT); - EXPECT_TRUE(res==1 && M_START(re, m) == 6); - res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT); - EXPECT_NE(res, 1); + ASSERT_EQ(re.error, CREG_OK); + inp="ab,ab,ab"; + res = cregex_find(&re, inp, &m, CREG_M_NEXT); + ASSERT_EQ(M_START(m), 0); + res = cregex_find(&re, inp, &m, CREG_M_NEXT); + ASSERT_EQ(res, CREG_OK); + ASSERT_EQ(M_START(m), 3); + res = cregex_find(&re, inp, &m, CREG_M_NEXT); + ASSERT_EQ(M_START(m), 6); + res = cregex_find(&re, inp, &m, CREG_M_NEXT); + ASSERT_NE(res, CREG_OK); } } -END_TEST -START_TEST(captures_len) +CTEST(cregex, captures_len) { c_AUTO (cregex, re) { - cregex re = cregex_from("(ab(cd))(ef)", 0); - EXPECT_EQ(cregex_captures(&re), 3); + cregex re = cregex_from("(ab(cd))(ef)"); + ASSERT_EQ(cregex_captures(&re), 4); } } -END_TEST -START_TEST(captures_cap) +CTEST(cregex, captures_cap) { + const char* inp; c_AUTO (cregex, re) { - re = cregex_from("(ab)((cd)+)", 0); - EXPECT_EQ(cregex_captures(&re), 3); + re = cregex_from("(ab)((cd)+)"); + ASSERT_EQ(cregex_captures(&re), 4); csview cap[5]; - EXPECT_EQ(cregex_find("xxabcdcde", &re, cap, 0), 1); - EXPECT_TRUE(csview_equals(cap.match[0], c_SV("abcdcd"))); - /* - EXPECT_EQ(cap0.end, 8); - EXPECT_EQ(cap1.start, 2); - EXPECT_EQ(cap1.end, 4); - EXPECT_EQ(cap2.start, 4); - EXPECT_EQ(cap2.end, 8); - */ - EXPECT_FALSE(cregex_is_match("abcdcde", &re)); - EXPECT_TRUE(cregex_is_match("abcdcdcd", &re)); + ASSERT_EQ(cregex_find(&re, inp="xxabcdcde", cap), CREG_OK); + ASSERT_TRUE(csview_equals(cap[0], "abcdcd")); + + ASSERT_EQ(M_END(cap[0]), 8); + ASSERT_EQ(M_START(cap[1]), 2); + ASSERT_EQ(M_END(cap[1]), 4); + ASSERT_EQ(M_START(cap[2]), 4); + ASSERT_EQ(M_END(cap[2]), 8); + + ASSERT_TRUE(cregex_is_match(&re, "abcdcde")); + ASSERT_TRUE(cregex_is_match(&re, "abcdcdcd")); } } -END_TEST +static bool add_10_years(int i, csview match, cstr* out) { + if (i == 1) { // group 1 matches year + int year; + sscanf(match.str, "%4d", &year); // scan 4 chars only + cstr_printf(out, "%04d", year + 10); + return true; + } + return false; +} -int main() +CTEST(cregex, replace) { - RUN_TEST(compile_match_char); - RUN_TEST(compile_match_anchors); - RUN_TEST(compile_match_quantifiers); - RUN_TEST(compile_match_escaped_chars); - RUN_TEST(compile_match_class_simple); - RUN_TEST(compile_match_class_complex_0); - RUN_TEST(compile_match_class_complex_1); - RUN_TEST(compile_match_cap); - RUN_TEST(search_all); - RUN_TEST(captures_len); - RUN_TEST(captures_cap); - RUN_TEST(compile_match_or); - return REPORT_TESTS(); + const char* pattern = "\\b(\\d\\d\\d\\d)-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])\\b"; + const char* input = "start date: 2015-12-31, end date: 2022-02-28"; + + c_AUTO (cstr, str) { + /* replace with a fixed string, extended all-in-one call: */ + cstr_take(&str, cregex_replace_pattern(pattern, input, "YYYY-MM-DD")); + ASSERT_TRUE(cstr_equals(&str, "start date: YYYY-MM-DD, end date: YYYY-MM-DD")); + + /* US date format, and add 10 years to dates: */ + cstr_take(&str, cregex_replace_pattern(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT)); + ASSERT_TRUE(cstr_equals(&str, "start date: 2025/31/12, end date: 2032/28/02")); + + /* Wrap first date inside []: */ + cstr_take(&str, cregex_replace_pattern(pattern, input, "[$0]", 1)); + ASSERT_TRUE(cstr_equals(&str, "start date: [2015-12-31], end date: 2022-02-28")); + + /* Wrap all words in ${} */ + cstr_take(&str, cregex_replace_pattern("[a-z]+", "52 apples and 31 mangoes", "$${$0}")); + ASSERT_TRUE(cstr_equals(&str, "52 ${apples} ${and} 31 ${mangoes}")); + + /* Compile RE separately */ + c_WITH (cregex re = cregex_from(pattern), cregex_drop(&re)) { + ASSERT_EQ(cregex_captures(&re), 4); + + /* European date format. */ + cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1")); + ASSERT_TRUE(cstr_equals(&str, "start date: 31.12.2015, end date: 28.02.2022")); + + /* Strip out everything but the matches */ + cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP)); + ASSERT_TRUE(cstr_equals(&str, "31.12.2015;28.02.2022;")); + } + } } -#endif - diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c new file mode 100644 index 00000000..9e33467c --- /dev/null +++ b/misc/tests/cspan_test.c @@ -0,0 +1,125 @@ +#include <stdio.h> +#include <stc/cspan.h> +#include "ctest.h" + +using_cspan3(intspan, int); + + +CTEST(cspan, subdim) { + int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + intspan3 m = cspan_md(array, 2, 2, 3); + + for (size_t i = 0; i < m.shape[0]; ++i) { + intspan2 sub_i = cspan_submd3(&m, i); + for (size_t j = 0; j < m.shape[1]; ++j) { + intspan sub_i_j = cspan_submd2(&sub_i, j); + for (size_t k = 0; k < m.shape[2]; ++k) { + ASSERT_EQ(*cspan_at(&sub_i_j, k), *cspan_at(&m, i, j, k)); + } + } + } +} + +CTEST(cspan, slice) { + int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + intspan2 m1 = cspan_md(array, 3, 4); + + size_t sum1 = 0; + for (size_t i = 0; i < m1.shape[0]; ++i) { + for (size_t j = 0; j < m1.shape[1]; ++j) { + sum1 += *cspan_at(&m1, i, j); + } + } + + intspan2 m2 = cspan_slice(intspan2, &m1, {c_ALL}, {2,4}); + + size_t sum2 = 0; + for (size_t i = 0; i < m2.shape[0]; ++i) { + for (size_t j = 0; j < m2.shape[1]; ++j) { + sum2 += *cspan_at(&m2, i, j); + } + } + ASSERT_EQ(78, sum1); + ASSERT_EQ(45, sum2); +} + +#define i_val int +#include <stc/cstack.h> + +CTEST(cspan, slice2) { + c_AUTO (cstack_int, stack) + { + c_FORRANGE (i, 10*20*30) + cstack_int_push(&stack, i); + + intspan3 ms3 = cspan_md(stack.data, 10, 20, 30); + ms3 = cspan_slice(intspan3, &ms3, {1,4}, {3,7}, {20,24}); + + size_t sum = 0; + for (size_t i = 0; i < ms3.shape[0]; ++i) { + for (size_t j = 0; j < ms3.shape[1]; ++j) { + for (size_t k = 0; k < ms3.shape[2]; ++k) { + sum += *cspan_at(&ms3, i, j, k); + } + } + } + ASSERT_EQ(65112, sum); + + sum = 0; + c_FOREACH (i, intspan3, ms3) + sum += *i.ref; + ASSERT_EQ(65112, sum); + } +} + + +#define i_type Tiles +#define i_val intspan3 +#include <stc/cstack.h> + +CTEST_FIXTURE(cspan_cube) { + cstack_int stack; + Tiles tiles; +}; + +CTEST_SETUP(cspan_cube) { + enum {TSIZE=4, CUBE=64, N=CUBE*CUBE*CUBE}; + + _self->stack = cstack_int_init(); + _self->tiles = Tiles_init(); + + cstack_int_reserve(&_self->stack, N); + c_FORRANGE (i, N) + cstack_int_push(&_self->stack, i+1); + + intspan3 ms3 = cspan_md(_self->stack.data, CUBE, CUBE, CUBE); + + c_FORRANGE (i, 0, ms3.shape[0], TSIZE) { + c_FORRANGE (j, 0, ms3.shape[1], TSIZE) { + c_FORRANGE (k, 0, ms3.shape[2], TSIZE) { + intspan3 tile = cspan_slice(intspan3, &ms3, {i, i + TSIZE}, {j, j + TSIZE}, {k, k + TSIZE}); + Tiles_push(&_self->tiles, tile); + } + } + } +} + +// Optional teardown function for suite, called after every test in suite +CTEST_TEARDOWN(cspan_cube) { + cstack_int_drop(&_self->stack); + Tiles_drop(&_self->tiles); +} + + +CTEST_F(cspan_cube, slice3) { + intptr_t n = cstack_int_size(&_self->stack); + //printf("\ntiles: %zi, cells: %zi\n", Tiles_size(&_self->tiles), n); + + int64_t sum = 0; + // iterate each 3d tile in sequence + c_FOREACH (i, Tiles, _self->tiles) + c_FOREACH (t, intspan3, *i.ref) + sum += *t.ref; + + ASSERT_EQ(n*(n + 1)/2, sum); +} diff --git a/misc/tests/ctest.h b/misc/tests/ctest.h new file mode 100644 index 00000000..373cda0e --- /dev/null +++ b/misc/tests/ctest.h @@ -0,0 +1,575 @@ +/* Copyright 2011-2023 Bas van den Berg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CTEST_H +#define CTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ +#define CTEST_IMPL_FORMAT_PRINTF(a, b) __attribute__ ((format(printf, a, b))) +#else +#define CTEST_IMPL_FORMAT_PRINTF(a, b) +#endif + +#include <inttypes.h> /* intmax_t, uintmax_t, PRI* */ +#include <stdbool.h> /* bool, true, false */ +#include <stddef.h> /* size_t */ + +typedef void (*ctest_nullary_run_func)(void); +typedef void (*ctest_unary_run_func)(void*); +typedef void (*ctest_setup_func)(void*); +typedef void (*ctest_teardown_func)(void*); + +union ctest_run_func_union { + ctest_nullary_run_func nullary; + ctest_unary_run_func unary; +}; + +#define CTEST_IMPL_PRAGMA(x) _Pragma (#x) +#define CTEST_CONTAINER_OF(p, T, m) \ + ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m))) + +#if defined(__GNUC__) +#if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +/* the GCC argument will work for both gcc and clang */ +#define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \ + CTEST_IMPL_PRAGMA(GCC diagnostic push) \ + CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w) +#define CTEST_IMPL_DIAG_POP() \ + CTEST_IMPL_PRAGMA(GCC diagnostic pop) +#else +/* the push/pop functionality wasn't in gcc until 4.6, fallback to "ignored" */ +#define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \ + CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w) +#define CTEST_IMPL_DIAG_POP() +#endif +#else +/* leave them out entirely for non-GNUC compilers */ +#define CTEST_IMPL_DIAG_PUSH_IGNORED(w) +#define CTEST_IMPL_DIAG_POP() +#endif + +struct ctest { + uint32_t magic0, padding; + + const char* ssname; // suite name + const char* ttname; // test name + union ctest_run_func_union run; + + void* data; + ctest_setup_func* setup; + ctest_teardown_func* teardown; + + int32_t skip; + uint32_t magic1; +}; + +#define CTEST_IMPL_NAME(name) ctest_##name +#define CTEST_IMPL_FNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_run) +#define CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname) +#define CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_NAME(sname##_data) +#define CTEST_IMPL_DATA_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_data) +#define CTEST_IMPL_SETUP_FNAME(sname) CTEST_IMPL_NAME(sname##_setup) +#define CTEST_IMPL_SETUP_FPNAME(sname) CTEST_IMPL_NAME(sname##_setup_ptr) +#define CTEST_IMPL_SETUP_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_setup_ptr) +#define CTEST_IMPL_TEARDOWN_FNAME(sname) CTEST_IMPL_NAME(sname##_teardown) +#define CTEST_IMPL_TEARDOWN_FPNAME(sname) CTEST_IMPL_NAME(sname##_teardown_ptr) +#define CTEST_IMPL_TEARDOWN_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_teardown_ptr) + +#ifdef __APPLE__ +#define CTEST_IMPL_SECTION __attribute__ ((used, section ("__DATA, .ctest"), aligned(1))) +#elif !defined _MSC_VER +#define CTEST_IMPL_SECTION __attribute__ ((used, section (".ctest"), aligned(1))) +#else +#define CTEST_IMPL_SECTION +#endif + +#define CTEST_IMPL_STRUCT(sname, tname, tskip, tdata, tsetup, tteardown) \ + static struct ctest CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_SECTION = { \ + 0xBADCAFE0, 0, \ + #sname, \ + #tname, \ + { (ctest_nullary_run_func) CTEST_IMPL_FNAME(sname, tname) }, \ + tdata, \ + (ctest_setup_func*) tsetup, \ + (ctest_teardown_func*) tteardown, \ + tskip, \ + 0xBADCAFE1, \ + } + +#ifdef __cplusplus + +#define CTEST_SETUP(sname) \ + template <> void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#define CTEST_TEARDOWN(sname) \ + template <> void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#define CTEST_FIXTURE(sname) \ + template <typename T> void CTEST_IMPL_SETUP_FNAME(sname)(T* _self) { } \ + template <typename T> void CTEST_IMPL_TEARDOWN_FNAME(sname)(T* _self) { } \ + struct CTEST_IMPL_DATA_SNAME(sname) + +#define CTEST_IMPL_CTEST(sname, tname, tskip) \ + static void CTEST_IMPL_FNAME(sname, tname)(void); \ + CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \ + static void CTEST_IMPL_FNAME(sname, tname)(void) + +#define CTEST_IMPL_CTEST_F(sname, tname, tskip) \ + static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \ + static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \ + static void (*CTEST_IMPL_SETUP_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \ + static void (*CTEST_IMPL_TEARDOWN_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \ + CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_TPNAME(sname, tname), &CTEST_IMPL_TEARDOWN_TPNAME(sname, tname)); \ + static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#else + +#define CTEST_SETUP(sname) \ + static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \ + static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname); \ + static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#define CTEST_TEARDOWN(sname) \ + static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \ + static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname); \ + static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#define CTEST_FIXTURE(sname) \ + struct CTEST_IMPL_DATA_SNAME(sname); \ + static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \ + static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \ + struct CTEST_IMPL_DATA_SNAME(sname) + +#define CTEST_IMPL_CTEST(sname, tname, tskip) \ + static void CTEST_IMPL_FNAME(sname, tname)(void); \ + CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \ + static void CTEST_IMPL_FNAME(sname, tname)(void) + +#define CTEST_IMPL_CTEST_F(sname, tname, tskip) \ + static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \ + static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \ + CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_FPNAME(sname), &CTEST_IMPL_TEARDOWN_FPNAME(sname)); \ + static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self) + +#endif + +void CTEST_LOG(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); +void CTEST_ERR(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); // doesn't return + +#define CTEST(sname, tname) CTEST_IMPL_CTEST(sname, tname, 0) +#define CTEST_SKIP(sname, tname) CTEST_IMPL_CTEST(sname, tname, 1) + +#define CTEST_F(sname, tname) CTEST_IMPL_CTEST_F(sname, tname, 0) +#define CTEST_F_SKIP(sname, tname) CTEST_IMPL_CTEST_F(sname, tname, 1) + +void assert_str(const char* cmp, const char* exp, const char* real, const char* caller, int line); +#define ASSERT_STREQ(exp, real) assert_str("==", exp, real, __FILE__, __LINE__) +#define ASSERT_STRNE(exp, real) assert_str("!=", exp, real, __FILE__, __LINE__) +#define ASSERT_SUBSTR(substr, real) assert_str("=~", substr, real, __FILE__, __LINE__) +#define ASSERT_NOT_SUBSTR(substr, real) assert_str("!~", substr, real, __FILE__, __LINE__) + +void assert_wstr(const char* cmp, const wchar_t *exp, const wchar_t *real, const char* caller, int line); +#define ASSERT_WSTREQ(exp, real) assert_wstr("==", exp, real, __FILE__, __LINE__) +#define ASSERT_WSTRNE(exp, real) assert_wstr("!=", exp, real, __FILE__, __LINE__) + +#define CTEST_FLT_EPSILON 1e-5 +#define CTEST_DBL_EPSILON 1e-12 + +void assert_compare(const char* cmp, intmax_t exp, intmax_t real, const char* caller, int line); +#define ASSERT_EQ(v1, v2) assert_compare("==", v1, v2, __FILE__, __LINE__) +#define ASSERT_NE(v1, v2) assert_compare("!=", v1, v2, __FILE__, __LINE__) +#define ASSERT_LT(v1, v2) assert_compare("<", v1, v2, __FILE__, __LINE__) +#define ASSERT_LE(v1, v2) assert_compare("<=", v1, v2, __FILE__, __LINE__) +#define ASSERT_GT(v1, v2) assert_compare(">", v1, v2, __FILE__, __LINE__) +#define ASSERT_GE(v1, v2) assert_compare(">=", v1, v2, __FILE__, __LINE__) + +void assert_interval(intmax_t low, intmax_t high, intmax_t real, const char* caller, int line); +#define ASSERT_INTERVAL(low, high, real) assert_interval(low, high, real, __FILE__, __LINE__) + +void assert_pointers(const char* cmp, const void* exp, const void* real, const char* caller, int line); +#define ASSERT_PTR_EQ(exp, real) ((void)sizeof((exp) == (real)), assert_pointers("==", exp, real, __FILE__, __LINE__)) +#define ASSERT_PTR_NE(exp, real) ((void)sizeof((exp) != (real)), assert_pointers("!=", exp, real, __FILE__, __LINE__)) +#define ASSERT_NULL(real) ASSERT_PTR_EQ(NULL, real) +#define ASSERT_NOT_NULL(real) ASSERT_PTR_NE(NULL, real) + +void assert_bool(bool exp, bool real, const char* caller, int line); +#define ASSERT_TRUE(real) assert_bool(true, real, __FILE__, __LINE__) +#define ASSERT_FALSE(real) assert_bool(false, real, __FILE__, __LINE__) + +void assert_fail(const char* caller, int line); +#define ASSERT_FAIL() assert_fail(__FILE__, __LINE__) + +void assert_dbl_compare(const char* cmp, double exp, double real, double tol, const char* caller, int line); +#define ASSERT_NEAR(exp, real, tol) assert_dbl_compare("==", exp, real, tol, __FILE__, __LINE__) +#define ASSERT_NOT_NEAR(exp, real, tol) assert_dbl_compare("!=", exp, real, tol, __FILE__, __LINE__) +#define ASSERT_DOUBLE_EQ(exp, real) assert_dbl_compare("==", exp, real, -CTEST_DBL_EPSILON, __FILE__, __LINE__) +#define ASSERT_DOUBLE_NE(exp, real) assert_dbl_compare("!=", exp, real, -CTEST_DBL_EPSILON, __FILE__, __LINE__) +#define ASSERT_DOUBLE_LT(v1, v2) assert_dbl_compare("<", v1, v2, 0.0, __FILE__, __LINE__) +#define ASSERT_DOUBLE_GT(v1, v2) assert_dbl_compare(">", v1, v2, 0.0, __FILE__, __LINE__) + +#define ASSERT_FLOAT_EQ(v1, v2) assert_dbl_compare("==", v1, v2, -CTEST_FLT_EPSILON, __FILE__, __LINE__) +#define ASSERT_FLOAT_NE(v1, v2) assert_dbl_compare("!=", v1, v2, -CTEST_FLT_EPSILON, __FILE__, __LINE__) +#define ASSERT_FLOAT_LT(v1, v2) assert_dbl_compare("<", (float)(v1), (float)(v2), 0.0, __FILE__, __LINE__) +#define ASSERT_FLOAT_GT(v1, v2) assert_dbl_compare(">", (float)(v1), (float)(v2), 0.0, __FILE__, __LINE__) + +#ifdef CTEST_MAIN + +#include <setjmp.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#if !defined(_WIN32) || defined(__GNUC__) +#include <unistd.h> +#elif defined(_WIN32) +#include <io.h> +#endif +#include <stdint.h> +#include <stdlib.h> +#include <wchar.h> + +static size_t ctest_errorsize; +static char* ctest_errormsg; +#define MSG_SIZE 4096 +static char ctest_errorbuffer[MSG_SIZE]; +static jmp_buf ctest_err; +static int color_output = 1; +static const char* suite_name; + +typedef int (*ctest_filter_func)(struct ctest*); + +#define ANSI_BLACK "\033[0;30m" +#define ANSI_RED "\033[0;31m" +#define ANSI_GREEN "\033[0;32m" +#define ANSI_YELLOW "\033[0;33m" +#define ANSI_BLUE "\033[0;34m" +#define ANSI_MAGENTA "\033[0;35m" +#define ANSI_CYAN "\033[0;36m" +#define ANSI_GREY "\033[0;37m" +#define ANSI_DARKGREY "\033[01;30m" +#define ANSI_BRED "\033[01;31m" +#define ANSI_BGREEN "\033[01;32m" +#define ANSI_BYELLOW "\033[01;33m" +#define ANSI_BBLUE "\033[01;34m" +#define ANSI_BMAGENTA "\033[01;35m" +#define ANSI_BCYAN "\033[01;36m" +#define ANSI_WHITE "\033[01;37m" +#define ANSI_NORMAL "\033[0m" + +CTEST(suite, test) { } + +static void vprint_errormsg(const char* const fmt, va_list ap) CTEST_IMPL_FORMAT_PRINTF(1, 0); +static void print_errormsg(const char* const fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); + +static void vprint_errormsg(const char* const fmt, va_list ap) { + // (v)snprintf returns the number that would have been written + const int ret = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, ap); + if (ret < 0) { + ctest_errormsg[0] = 0x00; + } else { + const size_t size = (size_t) ret; + const size_t s = (ctest_errorsize <= size ? size -ctest_errorsize : size); + // ctest_errorsize may overflow at this point + ctest_errorsize -= s; + ctest_errormsg += s; + } +} + +static void print_errormsg(const char* const fmt, ...) { + va_list argp; + va_start(argp, fmt); + vprint_errormsg(fmt, argp); + va_end(argp); +} + +static void msg_start(const char* color, const char* title) { + if (color_output) { + print_errormsg("%s", color); + } + print_errormsg(" %s: ", title); +} + +static void msg_end(void) { + if (color_output) { + print_errormsg(ANSI_NORMAL); + } + print_errormsg("\n"); +} + +void CTEST_LOG(const char* fmt, ...) +{ + va_list argp; + msg_start(ANSI_BLUE, "LOG"); + + va_start(argp, fmt); + vprint_errormsg(fmt, argp); + va_end(argp); + + msg_end(); +} + +CTEST_IMPL_DIAG_PUSH_IGNORED(missing-noreturn) + +void CTEST_ERR(const char* fmt, ...) +{ + va_list argp; + msg_start(ANSI_YELLOW, "ERR"); + + va_start(argp, fmt); + vprint_errormsg(fmt, argp); + va_end(argp); + + msg_end(); + longjmp(ctest_err, 1); +} + +CTEST_IMPL_DIAG_POP() + +void assert_str(const char* cmp, const char* exp, const char* real, const char* caller, int line) { + if ((!exp ^ !real) || (exp && ( + (cmp[1] == '=' && ((cmp[0] == '=') ^ (strcmp(real, exp) == 0))) || + (cmp[1] == '~' && ((cmp[0] == '=') ^ (strstr(real, exp) != NULL))) + ))) { + CTEST_ERR("%s:%d assertion failed, '%s' %s '%s'", caller, line, exp, cmp, real); + } +} + +void assert_wstr(const char* cmp, const wchar_t *exp, const wchar_t *real, const char* caller, int line) { + if ((!exp ^ !real) || (exp && ( + (cmp[1] == '=' && ((cmp[0] == '=') ^ (wcscmp(real, exp) == 0))) || + (cmp[1] == '~' && ((cmp[0] == '=') ^ (wcsstr(real, exp) != NULL))) + ))) { + CTEST_ERR("%s:%d assertion failed, '%ls' %s '%ls'", caller, line, exp, cmp, real); + } +} + +static bool get_compare_result(const char* cmp, int c3, bool eq) { + if (cmp[0] == '<') + return c3 < 0 || ((cmp[1] == '=') & eq); + if (cmp[0] == '>') + return c3 > 0 || ((cmp[1] == '=') & eq); + return (cmp[0] == '=') == eq; +} + +void assert_compare(const char* cmp, intmax_t exp, intmax_t real, const char* caller, int line) { + int c3 = (real < exp) - (exp < real); + + if (!get_compare_result(cmp, c3, c3 == 0)) { + CTEST_ERR("%s:%d assertion failed, %" PRIdMAX " %s %" PRIdMAX "", caller, line, exp, cmp, real); + } +} + +void assert_interval(intmax_t low, intmax_t high, intmax_t real, const char* caller, int line) { + if (real < low || real > high) { + CTEST_ERR("%s:%d expected %" PRIdMAX "-%" PRIdMAX ", got %" PRIdMAX, caller, line, low, high, real); + } +} + +static bool approximately_equal(double a, double b, double epsilon) { + double d = a - b; + if (d < 0) d = -d; + if (a < 0) a = -a; + if (b < 0) b = -b; + return d <= (a > b ? a : b)*epsilon; /* D.Knuth */ +} + +/* tol < 0 means it is an epsilon, else absolute error */ +void assert_dbl_compare(const char* cmp, double exp, double real, double tol, const char* caller, int line) { + double diff = exp - real; + double absdiff = diff < 0 ? -diff : diff; + int c3 = (real < exp) - (exp < real); + bool eq = tol < 0 ? approximately_equal(exp, real, -tol) : absdiff <= tol; + + if (!get_compare_result(cmp, c3, eq)) { + const char* tolstr = "tol"; + if (tol < 0) { + tolstr = "eps"; + tol = -tol; + } + CTEST_ERR("%s:%d assertion failed, %.8g %s %.8g (diff %.4g, %s %.4g)", caller, line, exp, cmp, real, diff, tolstr, tol); + } +} + +void assert_pointers(const char* cmp, const void* exp, const void* real, const char* caller, int line) { + if ((exp == real) != (cmp[0] == '=')) { + CTEST_ERR("%s:%d assertion failed (0x%02llx) %s (0x%02llx)", caller, line, (unsigned long long)exp , cmp, (unsigned long long)real); + } +} + +void assert_bool(bool exp, bool real, const char* caller, int line) { + if (exp != real) { + CTEST_ERR("%s:%d should be %s", caller, line, exp ? "true" : "false"); + } +} + +void assert_fail(const char* caller, int line) { + CTEST_ERR("%s:%d shouldn't come here", caller, line); +} + + +static int suite_all(struct ctest* t) { + (void) t; // avoid unused parameter warning + return 1; +} + +static int suite_filter(struct ctest* t) { + return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0; +} + +static void color_print(const char* color, const char* text) { + if (color_output) + printf("%s%s" ANSI_NORMAL "\n", color, text); + else + printf("%s\n", text); +} + +#ifndef CTEST_NO_SEGFAULT +#include <signal.h> +static void sighandler(int signum) +{ + const char msg_color[] = ANSI_BRED "[SIGSEGV: Segmentation fault]" ANSI_NORMAL "\n"; + const char msg_nocolor[] = "[SIGSEGV: Segmentation fault]\n"; + + const char* msg = color_output ? msg_color : msg_nocolor; + intptr_t n = write(1, msg, (unsigned int)strlen(msg)); + (void)n; + /* "Unregister" the signal handler and send the signal back to the process + * so it can terminate as expected */ + signal(signum, SIG_DFL); +#if !defined(_WIN32) || defined(__CYGWIN__) + kill(getpid(), signum); +#endif +} +#endif + +int ctest_main(int argc, const char *argv[]); +#ifdef __GNUC__ +__attribute__((no_sanitize_address)) +#endif +int ctest_main(int argc, const char *argv[]) +{ + static int total = 0; + static int num_ok = 0; + static int num_fail = 0; + static int num_skip = 0; + static int idx = 1; + static ctest_filter_func filter = suite_all; + +#ifndef CTEST_NO_SEGFAULT + signal(SIGSEGV, sighandler); +#endif + + if (argc == 2) { + suite_name = argv[1]; + filter = suite_filter; + } +#ifdef CTEST_NO_COLORS + color_output = 0; +#else + color_output = isatty(1); +#endif + clock_t t1 = clock(); + + uint32_t* magic_begin = &CTEST_IMPL_TNAME(suite, test).magic1; + uint32_t* magic_end = &CTEST_IMPL_TNAME(suite, test).magic0, *m; + size_t num_ints = sizeof(struct ctest)/sizeof *m; + +#if (defined __TINYC__ && defined __unix__) + #define CTEST_IMPL_MAGIC_SEEK 10 /* search 4*(1+10) bytes outside ctest entry bounds */ +#else + #define CTEST_IMPL_MAGIC_SEEK 0 /* access only 4 bytes outside outer ctest entry bounds */ +#endif + for (m = magic_begin; magic_begin - m <= num_ints + CTEST_IMPL_MAGIC_SEEK; --m) { + if (*m == 0xBADCAFE1) { + magic_begin = m; + m -= num_ints - 1; + } + } + for (m = magic_end; m - magic_end <= num_ints; ++m) { + if (*m == 0xBADCAFE0) { + magic_end = m; + m += num_ints - 1; + } + } + magic_begin = &CTEST_CONTAINER_OF(magic_begin, struct ctest, magic1)->magic0; + + static struct ctest* test; + for (m = magic_begin; m <= magic_end; m += num_ints) { + while (*m != 0xBADCAFE0) ++m; + test = CTEST_CONTAINER_OF(m, struct ctest, magic0); + if (test == &CTEST_IMPL_TNAME(suite, test)) continue; + if (filter(test)) total++; + } + + for (m = magic_begin; m <= magic_end; m += num_ints) { + while (*m != 0xBADCAFE0) ++m; + test = CTEST_CONTAINER_OF(m, struct ctest, magic0); + if (test == &CTEST_IMPL_TNAME(suite, test)) continue; + if (filter(test)) { + ctest_errorbuffer[0] = 0; + ctest_errorsize = MSG_SIZE-1; + ctest_errormsg = ctest_errorbuffer; + printf("TEST %d/%d %s:%s ", idx, total, test->ssname, test->ttname); + fflush(stdout); + if (test->skip) { + color_print(ANSI_BYELLOW, "[SKIPPED]"); + num_skip++; + } else { + int result = setjmp(ctest_err); + if (result == 0) { + if (test->setup && *test->setup) (*test->setup)(test->data); + if (test->data) + test->run.unary(test->data); + else + test->run.nullary(); + if (test->teardown && *test->teardown) (*test->teardown)(test->data); + // if we got here it's ok +#ifdef CTEST_NO_COLOR_OK + printf("[OK]\n"); +#else + color_print(ANSI_BGREEN, "[OK]"); +#endif + num_ok++; + } else { + color_print(ANSI_BRED, "[FAIL]"); + num_fail++; + } + if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer); + } + idx++; + } + } + clock_t t2 = clock(); + + const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN; + char results[80]; + snprintf(results, sizeof(results), "RESULTS: %d tests (%d ok, %d failed, %d skipped) ran in %.1f ms", + total, num_ok, num_fail, num_skip, (double)(t2 - t1)*1000.0/CLOCKS_PER_SEC); + color_print(color, results); + return num_fail; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/misc/tests/main.c b/misc/tests/main.c new file mode 100644 index 00000000..2b8931c4 --- /dev/null +++ b/misc/tests/main.c @@ -0,0 +1,31 @@ +/* Copyright 2011-2023 Bas van den Berg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> + +#define CTEST_MAIN + +// uncomment lines below to enable/disable features. See README.md for details +//#define CTEST_NO_SEGFAULT +//#define CTEST_NO_COLORS +//#define CTEST_NO_COLOR_OK + +#include "ctest.h" + +int main(int argc, const char *argv[]) +{ + return ctest_main(argc, argv); +} + diff --git a/misc/tests/mytests.c.txt b/misc/tests/mytests.c.txt new file mode 100644 index 00000000..54413e42 --- /dev/null +++ b/misc/tests/mytests.c.txt @@ -0,0 +1,233 @@ +/* Copyright 2011-2023 Bas van den Berg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include "ctest.h" + +// basic test without setup/teardown +CTEST(suite1, test1) { +} + +// there are many different ASSERT macro's (see ctest.h) +CTEST(suite1, test2) { + ASSERT_EQ(1,2); +} + +CTEST(suite2, test1) { + ASSERT_STREQ("foo", "bar"); +} + +CTEST(suite3, test3) { +} + + +// A test suite with a setup/teardown function +// This is converted into a struct that's automatically passed to all tests in the suite +CTEST_FIXTURE(memtest) { + unsigned char* buffer; +}; + +// Optional setup function for suite, called before every test in suite +CTEST_SETUP(memtest) { + CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer); + self->buffer = (unsigned char*)malloc(1024); +} + +// Optional teardown function for suite, called after every test in suite +CTEST_TEARDOWN(memtest) { + CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer); + if (self->buffer) free(self->buffer); +} + +// These tests are called with the struct* (named self) as argument +CTEST_F(memtest, test1) { + CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer); +} + +CTEST_F_SKIP(memtest, test3) { + (void)self; + ASSERT_FAIL(); +} + +CTEST_F(memtest, test2) { + CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer); + ASSERT_FAIL(); +} + + +CTEST_FIXTURE(fail) { + int unused; +}; + +// Asserts can also be used in setup/teardown functions +CTEST_SETUP(fail) { + (void)self; + ASSERT_FAIL(); +} + +CTEST_F(fail, test1) { + (void)self; +} + + + +CTEST_FIXTURE(weaklinkage) { + int number; +}; + +// This suite has data, but no setup/teardown +CTEST_F(weaklinkage, test1) { + (void)self; + CTEST_LOG("%s()", __func__); +} + +CTEST_F(weaklinkage, test2) { + (void)self; + CTEST_LOG("%s()", __func__); +} + + +CTEST_FIXTURE(nosetup) { + int value; +}; + +CTEST_TEARDOWN(nosetup) { + (void)self; + CTEST_LOG("%s()", __func__); +} + +CTEST_F(nosetup, test1) { + (void)self; + CTEST_LOG("%s()", __func__); +} + + +// more ASSERT examples +CTEST(ctest, test_assert_str) { + ASSERT_STREQ("foo", "foo"); + ASSERT_STREQ("foo", "bar"); +} + +CTEST(ctest, test_assert_equal) { + ASSERT_EQ(123, 123); + ASSERT_EQ(123, 456); +} + +CTEST(ctest, test_assert_not_equal) { + ASSERT_NE(123, 456); + ASSERT_NE(123, 123); +} + +CTEST(ctest, test_assert_interval) { + ASSERT_INTERVAL(10, 20, 15); + ASSERT_INTERVAL(1000, 2000, 3000); +} + +CTEST(ctest, test_assert_null) { + ASSERT_NULL(NULL); + ASSERT_NULL((void*)0xdeadbeef); +} + +CTEST(ctest, test_assert_not_null_const) { + char *p = NULL; + ASSERT_PTR_NE(p, (const char*)"hallo"); +} + +CTEST(ctest, test_assert_true) { + ASSERT_TRUE(1); + ASSERT_TRUE(0); +} + +CTEST(ctest, test_assert_false) { + ASSERT_FALSE(0); + ASSERT_FALSE(1); +} + +CTEST_SKIP(ctest, test_skip) { + ASSERT_FAIL(); +} + +CTEST(ctest, test_assert_fail) { + ASSERT_FAIL(); +} + +/* Test that NULL-strings won't result in segv */ +CTEST(ctest, test_null_null) { + ASSERT_STREQ(NULL, NULL); +} + +CTEST(ctest, test_null_string) { + ASSERT_STREQ(NULL, "shouldfail"); +} + +CTEST(ctest, test_string_null) { + ASSERT_STREQ("shouldfail", NULL); +} + +CTEST(ctest, test_string_diff_ptrs) { + const char *str = "abc\0abc"; + ASSERT_STREQ(str, str+4); +} + +CTEST(ctest, test_large_numbers) { + unsigned long exp = 4200000000u; + ASSERT_EQ(exp, 4200000000u); + ASSERT_NE(exp, 1200000000u); +} + +CTEST(ctest, test_ctest_err) { + CTEST_ERR("error log"); +} + +CTEST(ctest, test_dbl_near) { + double a = 0.000111; + ASSERT_DOUBLE_EQ(0.0001, a); +} + +CTEST(ctest, test_dbl_near_tol) { + double a = 0.000111; + ASSERT_NEAR(0.0001, a, 1e-5); /* will fail */ +} + +CTEST(ctest, test_dbl_far) { + double a = 1.1; + ASSERT_DOUBLE_NE(1., a); + ASSERT_NOT_NEAR(1., a, 0.01); +} + +CTEST(ctest, test_assert_compare) { + ASSERT_LT(123, 456); + ASSERT_GE(123, 123); + ASSERT_GT(99, 100); +} + +CTEST(ctest, test_dbl_near2) { + float a = 0.000001000003f; + ASSERT_FLOAT_EQ(0.000001f, a); /* ok, uses float epsilon -1e-5 */ + ASSERT_NEAR(0.000001, a, -1e-5); /* ok, tol < 0 = relative err (epsilon) */ + ASSERT_DOUBLE_EQ(0.000001, a); /* fail, tol = -1e-12 (epsilon) */ +} + +CTEST(ctest, test_dbl_compare) { + float a = 0.000001000003f; + ASSERT_DOUBLE_LT(0.000001, a); + ASSERT_DOUBLE_GT(0.000001, a); /* fail */ +} + +CTEST(ctest, test_str_contains) { + ASSERT_STRNE("Hello", "World"); + ASSERT_SUBSTR("ello", "Hello"); + ASSERT_NOT_SUBSTR("Hell", "Hello"); +} diff --git a/src/cregex.c b/src/cregex.c index d2b54ef1..c17e1967 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -78,7 +78,7 @@ typedef struct _Reprog { _Reinst *startinst; /* start pc */ _Reflags flags; - unsigned nsubids; + int nsubids; _Reclass cclass[_NCLASS]; /* .data */ _Reinst firstinst[]; /* .text : originally 5 elements? */ } _Reprog; @@ -214,7 +214,7 @@ utfrune(const char *s, _Rune c) if (c < 128) /* ascii */ return strchr((char *)s, (int)c); int n; - for (_Rune r = *s; r; s += n, r = *(unsigned char*)s) { + for (_Rune r = (uint32_t)*s; r; s += n, r = *(unsigned char*)s) { if (r < 128) { n = 1; continue; } n = chartorune(&r, s); if (r == c) return s; @@ -225,10 +225,10 @@ utfrune(const char *s, _Rune c) static const char* utfruneicase(const char *s, _Rune c) { - _Rune r = *s; + _Rune r = (uint32_t)*s; int n; - if (c < 128) for (c = tolower(c); r; ++s, r = *(unsigned char*)s) { - if (r < 128 && (unsigned)tolower(r) == c) return s; + if (c < 128) for (c = (_Rune)tolower((int)c); r; ++s, r = *(unsigned char*)s) { + if (r < 128 && (_Rune)tolower((int)r) == c) return s; } else for (c = utf8_casefold(c); r; s += n, r = *(unsigned char*)s) { if (r < 128) { n = 1; continue; } @@ -246,13 +246,13 @@ utfruneicase(const char *s, _Rune c) * save a new match in mp */ static void -_renewmatch(_Resub *mp, unsigned ms, _Resublist *sp, unsigned nsubids) +_renewmatch(_Resub *mp, int ms, _Resublist *sp, int nsubids) { if (mp==NULL || ms==0) return; if (mp[0].str == NULL || sp->m[0].str < mp[0].str || (sp->m[0].str == mp[0].str && sp->m[0].size > mp[0].size)) { - for (unsigned i=0; i<ms && i<=nsubids; i++) + for (int i=0; i<ms && i<=nsubids; i++) mp[i] = sp->m[i]; } } @@ -265,7 +265,7 @@ _renewmatch(_Resub *mp, unsigned ms, _Resublist *sp, unsigned nsubids) static _Relist* _renewthread(_Relist *lp, /* _relist to add to */ _Reinst *ip, /* instruction to add */ - unsigned ms, + int ms, _Resublist *sep) /* pointers to subexpressions */ { _Relist *p; @@ -297,7 +297,7 @@ _renewthread(_Relist *lp, /* _relist to add to */ static _Relist* _renewemptythread(_Relist *lp, /* _relist to add to */ _Reinst *ip, /* instruction to add */ - unsigned ms, + int ms, const char *sp) /* pointers to subexpressions */ { _Relist *p; @@ -549,7 +549,7 @@ _optimize(_Parser *par, _Reprog *pp) */ intptr_t ipp = (intptr_t)pp; size_t size = sizeof(_Reprog) + (size_t)(par->freep - pp->firstinst)*sizeof(_Reinst); - _Reprog *npp = (_Reprog *)c_REALLOC(pp, size); + _Reprog *npp = (_Reprog *)c_realloc(pp, size); ptrdiff_t diff = (intptr_t)npp - ipp; if ((npp == NULL) | (diff == 0)) @@ -661,7 +661,7 @@ _lexutfclass(_Parser *par, _Rune *rp) {"{Devanagari}", 10, UTF_devanagari}, {"{Greek}", 7, UTF_greek}, {"{Han}", 5, UTF_han}, {"{Latin}", 7, UTF_latin}, }; - int inv = (*rp == 'P'); + unsigned inv = (*rp == 'P'); for (unsigned i = 0; i < (sizeof cls/sizeof *cls); ++i) { if (!strncmp(par->exprp, cls[i].c, (size_t)cls[i].n)) { if (par->rune_type == TOK_IRUNE && (cls[i].r == UTF_ll || cls[i].r == UTF_lu)) @@ -844,10 +844,10 @@ _regcomp1(_Reprog *progp, _Parser *par, const char *s, int cflags) /* get memory for the program. estimated max usage */ const size_t instcap = 5 + 6*strlen(s); - _Reprog* pp = (_Reprog *)c_REALLOC(progp, sizeof(_Reprog) + instcap*sizeof(_Reinst)); + _Reprog* pp = (_Reprog *)c_realloc(progp, sizeof(_Reprog) + instcap*sizeof(_Reinst)); if (pp == NULL) { par->error = CREG_OUTOFMEMORY; - c_FREE(progp); + c_free(progp); return NULL; } pp->flags.icase = (cflags & CREG_C_ICASE) != 0; @@ -895,10 +895,10 @@ _regcomp1(_Reprog *progp, _Parser *par, const char *s, int cflags) pp->startinst = par->andp->first; pp = _optimize(par, pp); - pp->nsubids = (unsigned)par->cursubid; + pp->nsubids = par->cursubid; out: if (par->error) { - c_FREE(pp); + c_free(pp); pp = NULL; } return pp; @@ -908,23 +908,22 @@ out: static int _runematch(_Rune s, _Rune r) { - int inv = 0; - uint32_t n; + int inv = 0, n; switch (s) { - case ASC_D: inv = 1; case ASC_d: return inv ^ (isdigit(r) != 0); - case ASC_S: inv = 1; case ASC_s: return inv ^ (isspace(r) != 0); - case ASC_W: inv = 1; case ASC_w: return inv ^ ((isalnum(r) != 0) | (r == '_')); - case ASC_AL: inv = 1; case ASC_al: return inv ^ (isalpha(r) != 0); - case ASC_AN: inv = 1; case ASC_an: return inv ^ (isalnum(r) != 0); + case ASC_D: inv = 1; case ASC_d: return inv ^ (isdigit((int)r) != 0); + case ASC_S: inv = 1; case ASC_s: return inv ^ (isspace((int)r) != 0); + case ASC_W: inv = 1; case ASC_w: return inv ^ ((isalnum((int)r) != 0) | (r == '_')); + case ASC_AL: inv = 1; case ASC_al: return inv ^ (isalpha((int)r) != 0); + case ASC_AN: inv = 1; case ASC_an: return inv ^ (isalnum((int)r) != 0); case ASC_AS: return (r >= 128); case ASC_as: return (r < 128); case ASC_BL: inv = 1; case ASC_bl: return inv ^ ((r == ' ') | (r == '\t')); - case ASC_CT: inv = 1; case ASC_ct: return inv ^ (iscntrl(r) != 0); - case ASC_GR: inv = 1; case ASC_gr: return inv ^ (isgraph(r) != 0); - case ASC_PR: inv = 1; case ASC_pr: return inv ^ (isprint(r) != 0); - case ASC_PU: inv = 1; case ASC_pu: return inv ^ (ispunct(r) != 0); - case ASC_LO: inv = 1; case ASC_lo: return inv ^ (islower(r) != 0); - case ASC_UP: inv = 1; case ASC_up: return inv ^ (isupper(r) != 0); - case ASC_XD: inv = 1; case ASC_xd: return inv ^ (isxdigit(r) != 0); + case ASC_CT: inv = 1; case ASC_ct: return inv ^ (iscntrl((int)r) != 0); + case ASC_GR: inv = 1; case ASC_gr: return inv ^ (isgraph((int)r) != 0); + case ASC_PR: inv = 1; case ASC_pr: return inv ^ (isprint((int)r) != 0); + case ASC_PU: inv = 1; case ASC_pu: return inv ^ (ispunct((int)r) != 0); + case ASC_LO: inv = 1; case ASC_lo: return inv ^ (islower((int)r) != 0); + case ASC_UP: inv = 1; case ASC_up: return inv ^ (isupper((int)r) != 0); + case ASC_XD: inv = 1; case ASC_xd: return inv ^ (isxdigit((int)r) != 0); case UTF_AN: inv = 1; case UTF_an: return inv ^ utf8_isalnum(r); case UTF_BL: inv = 1; case UTF_bl: return inv ^ utf8_isblank(r); case UTF_SP: inv = 1; case UTF_sp: return inv ^ utf8_isspace(r); @@ -951,7 +950,7 @@ _runematch(_Rune s, _Rune r) case UTF_greek: case UTF_GREEK: case UTF_han: case UTF_HAN: case UTF_latin: case UTF_LATIN: - n = s - UTF_GRP; + n = (int)s - UTF_GRP; inv = n & 1; return inv ^ utf8_isgroup(n / 2, r); } @@ -967,7 +966,7 @@ static int _regexec1(const _Reprog *progp, /* program to run */ const char *bol, /* string to run machine on */ _Resub *mp, /* subexpression elements */ - unsigned ms, /* number of elements at mp */ + int ms, /* number of elements at mp */ _Reljunk *j, int mflags ) @@ -980,7 +979,7 @@ _regexec1(const _Reprog *progp, /* program to run */ const char *s, *p; _Rune r, *rp, *ep; int n, checkstart, match = 0; - unsigned i; + int i; bool icase = progp->flags.icase; checkstart = j->starttype; @@ -1050,7 +1049,7 @@ _regexec1(const _Reprog *progp, /* program to run */ tlp->se.m[inst->r.subid].str = s; continue; case TOK_RBRA: - tlp->se.m[inst->r.subid].size = (size_t)(s - tlp->se.m[inst->r.subid].str); + tlp->se.m[inst->r.subid].size = (s - tlp->se.m[inst->r.subid].str); continue; case TOK_ANY: ok = (r != '\n'); @@ -1100,7 +1099,7 @@ _regexec1(const _Reprog *progp, /* program to run */ match = !(mflags & CREG_M_FULLMATCH) || ((s == j->eol || r == 0 || r == '\n') && (tlp->se.m[0].str == bol || tlp->se.m[0].str[-1] == '\n')); - tlp->se.m[0].size = (size_t)(s - tlp->se.m[0].str); + tlp->se.m[0].size = (s - tlp->se.m[0].str); if (mp != NULL) _renewmatch(mp, ms, &tlp->se, progp->nsubids); break; @@ -1124,7 +1123,7 @@ static int _regexec2(const _Reprog *progp, /* program to run */ const char *bol, /* string to run machine on */ _Resub *mp, /* subexpression elements */ - unsigned ms, /* number of elements at mp */ + int ms, /* number of elements at mp */ _Reljunk *j, int mflags ) @@ -1133,7 +1132,7 @@ _regexec2(const _Reprog *progp, /* program to run */ _Relist *relists; /* mark space */ - relists = (_Relist *)c_MALLOC(2 * _BIGLISTSIZE*sizeof(_Relist)); + relists = (_Relist *)c_malloc(2 * _BIGLISTSIZE*sizeof(_Relist)); if (relists == NULL) return -1; @@ -1143,14 +1142,14 @@ _regexec2(const _Reprog *progp, /* program to run */ j->reliste[1] = relists + 2*_BIGLISTSIZE - 2; rv = _regexec1(progp, bol, mp, ms, j, mflags); - c_FREE(relists); + c_free(relists); return rv; } static int _regexec(const _Reprog *progp, /* program to run */ const char *bol, /* string to run machine on */ - unsigned ms, /* number of elements at mp */ + int ms, /* number of elements at mp */ _Resub mp[], /* subexpression elements */ int mflags) { @@ -1196,10 +1195,10 @@ _regexec(const _Reprog *progp, /* program to run */ static void -_build_subst(const char* replace, unsigned nmatch, const csview match[], +_build_subst(const char* replace, int nmatch, const csview match[], bool (*mfun)(int, csview, cstr*), cstr* subst) { cstr_buf buf = cstr_buffer(subst); - size_t len = 0, cap = buf.cap; + intptr_t len = 0, cap = buf.cap; char* dst = buf.data; cstr mstr = cstr_NULL; @@ -1217,7 +1216,7 @@ _build_subst(const char* replace, unsigned nmatch, const csview match[], csview m = mfun && mfun(g, match[g], &mstr) ? cstr_sv(&mstr) : match[g]; if (len + m.size > cap) dst = cstr_reserve(subst, cap = cap*3/2 + m.size); - for (unsigned i = 0; i < m.size; ++i) + for (int i = 0; i < (int)m.size; ++i) dst[len++] = m.str[i]; } ++replace; @@ -1239,20 +1238,19 @@ _build_subst(const char* replace, unsigned nmatch, const csview match[], */ int -cregex_compile(cregex *self, const char* pattern, int cflags) { +cregex_compile_3(cregex *self, const char* pattern, int cflags) { _Parser par; self->prog = _regcomp1(self->prog, &par, pattern, cflags); return self->error = par.error; } -unsigned +int cregex_captures(const cregex* self) { - return self->prog ? 1U + self->prog->nsubids : 0U; + return self->prog ? 1 + self->prog->nsubids : 0; } int -cregex_find(const cregex* re, const char* input, - csview match[], int mflags) { +cregex_find_4(const cregex* re, const char* input, csview match[], int mflags) { int res = _regexec(re->prog, input, cregex_captures(re), match, mflags); switch (res) { case 1: return CREG_OK; @@ -1262,8 +1260,8 @@ cregex_find(const cregex* re, const char* input, } int -cregex_find_pattern(const char* pattern, const char* input, - csview match[], int cmflags) { +cregex_find_pattern_4(const char* pattern, const char* input, + csview match[], int cmflags) { cregex re = cregex_init(); int res = cregex_compile(&re, pattern, cmflags); if (res != CREG_OK) return res; @@ -1273,18 +1271,18 @@ cregex_find_pattern(const char* pattern, const char* input, } cstr -cregex_replace_sv(const cregex* re, csview input, const char* replace, unsigned count, - bool (*mfun)(int, csview, cstr*), int rflags) { +cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, + bool (*mfun)(int, csview, cstr*), int rflags) { cstr out = cstr_NULL; cstr subst = cstr_NULL; csview match[CREG_MAX_CAPTURES]; - unsigned nmatch = cregex_captures(re); - if (!count) count = ~0U; + int nmatch = cregex_captures(re); + if (!count) count = INT32_MAX; bool copy = !(rflags & CREG_R_STRIP); while (count-- && cregex_find_sv(re, input, match) == CREG_OK) { _build_subst(replace, nmatch, match, mfun, &subst); - const size_t mpos = (size_t)(match[0].str - input.str); + const intptr_t mpos = (match[0].str - input.str); if (copy & (mpos > 0)) cstr_append_n(&out, input.str, mpos); cstr_append_s(&out, subst); input.str = match[0].str + match[0].size; @@ -1296,12 +1294,12 @@ cregex_replace_sv(const cregex* re, csview input, const char* replace, unsigned } cstr -cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count, - bool (*mfun)(int, csview, cstr*), int crflags) { +cregex_replace_pattern_6(const char* pattern, const char* input, const char* replace, int count, + bool (*mfun)(int, csview, cstr*), int crflags) { cregex re = cregex_init(); if (cregex_compile(&re, pattern, crflags) != CREG_OK) assert(0); - csview sv = {input, strlen(input)}; + csview sv = {input, c_strlen(input)}; cstr out = cregex_replace_sv(&re, sv, replace, count, mfun, crflags); cregex_drop(&re); return out; @@ -1309,6 +1307,6 @@ cregex_replace_pattern_ex(const char* pattern, const char* input, const char* re void cregex_drop(cregex* self) { - c_FREE(self->prog); + c_free(self->prog); } #endif diff --git a/src/libstc.c b/src/libstc.c deleted file mode 100644 index e8980a7a..00000000 --- a/src/libstc.c +++ /dev/null @@ -1,11 +0,0 @@ -#define STC_EXTERN // implement common extern, non-templated functions and dependencies. - -#define i_val int -#define i_header // don't implement clist_int itself, just dummy declare it. -#include "../include/stc/clist.h" - -#define STC_IMPLEMENT // implement the following. - -#include "../include/stc/cregex.h" -#include "../include/stc/csview.h" -//#include "../include/stc/crandom.h" diff --git a/src/singleheader.py b/src/singleheader.py new file mode 100644 index 00000000..f5272cfb --- /dev/null +++ b/src/singleheader.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +import re +import sys +import os +from os.path import dirname, join as path_join, abspath, basename, exists + +extra_paths = [path_join(dirname(abspath(__file__)), "include")] + + +def find_file(included_name, current_file): + current_dir = dirname(abspath(current_file)) + for idir in [current_dir] + extra_paths: + try_path = path_join(idir, included_name) + if exists(try_path): + return try_path + return None + + +def process_file( + file_path, + out_lines=[], + processed_files=[], +): + out_lines += "// ### BEGIN_FILE_INCLUDE: " + basename(file_path) + '\n' + comment_block = False + with open(file_path, "r") as f: + for line in f: + is_comment = comment_block + if re.search('/\*.*?\*/', line): + pass + elif re.search('^\\s*/\*', line): + comment_block, is_comment = True, True + elif re.search('\*/', line): + comment_block = False + + if is_comment: + continue + + m_inc = re.search('^\\s*# *include\\s*[<"](.+)[>"]', line) if not is_comment else False + if m_inc: + inc_name = m_inc.group(1) + inc_path = find_file(inc_name, file_path) + if inc_path not in processed_files: + if inc_path is not None: + processed_files += [inc_path] + process_file( + inc_path, + out_lines, + processed_files, + ) + else: + # assume it's a system header + out_lines += [line] + continue + m_once = re.match('^\\s*# *pragma once\\s*', line) if not is_comment else False + # ignore pragma once; we're handling it here + if m_once: + continue + # otherwise, just add the line to the output + if line[-1] != '\n': + line += '\n' + out_lines += [line] + out_lines += "// ### END_FILE_INCLUDE: " + basename(file_path) + '\n' + return ( + "".join(out_lines) + ) + + +if __name__ == "__main__": + print( + process_file( + abspath(sys.argv[1]), + [], + # We use an include guard instead of `#pragma once` because Godbolt will + # cause complaints about `#pragma once` when they are used in URL includes. + [abspath(sys.argv[1])], + ) + ) diff --git a/src/utf8code.c b/src/utf8code.c index ecf79880..a892f5fd 100644 --- a/src/utf8code.c +++ b/src/utf8code.c @@ -20,7 +20,7 @@ const uint8_t utf8_dtab[] = { 12,36,12,12,12,12,12,12,12,12,12,12, }; -unsigned utf8_encode(char *out, uint32_t c) +int utf8_encode(char *out, uint32_t c) { if (c < 0x80U) { out[0] = (char) c; @@ -53,7 +53,7 @@ uint32_t utf8_peek_off(const char* s, int pos) { return utf8_peek(s); } -bool utf8_valid_n(const char* s, size_t nbytes) { +bool utf8_valid_n(const char* s, intptr_t nbytes) { utf8_decode_t d = {.state=0}; while ((nbytes-- != 0) & (*s != 0)) utf8_decode(&d, (uint8_t)*s++); @@ -61,7 +61,7 @@ bool utf8_valid_n(const char* s, size_t nbytes) { } uint32_t utf8_casefold(uint32_t c) { - for (size_t i=0; i < casefold_len; ++i) { + for (int i=0; i < casefold_len; ++i) { const struct CaseMapping entry = casemappings[i]; if (c <= entry.c2) { if (c < entry.c1) return c; @@ -74,7 +74,7 @@ uint32_t utf8_casefold(uint32_t c) { } uint32_t utf8_tolower(uint32_t c) { - for (size_t i=0; i < sizeof upcase_ind/sizeof *upcase_ind; ++i) { + for (int i=0; i < (int)(sizeof upcase_ind/sizeof *upcase_ind); ++i) { const struct CaseMapping entry = casemappings[upcase_ind[i]]; if (c <= entry.c2) { if (c < entry.c1) return c; @@ -87,7 +87,7 @@ uint32_t utf8_tolower(uint32_t c) { } uint32_t utf8_toupper(uint32_t c) { - for (size_t i=0; i < sizeof lowcase_ind/sizeof *lowcase_ind; ++i) { + for (int i=0; i < (int)(sizeof lowcase_ind/sizeof *lowcase_ind); ++i) { const struct CaseMapping entry = casemappings[lowcase_ind[i]]; if (c <= entry.m2) { int d = entry.m2 - entry.c2; @@ -101,7 +101,7 @@ uint32_t utf8_toupper(uint32_t c) { int utf8_icmp_sv(const csview s1, const csview s2) { utf8_decode_t d1 = {.state=0}, d2 = {.state=0}; - size_t j1 = 0, j2 = 0; + intptr_t j1 = 0, j2 = 0; while ((j1 < s1.size) & (j2 < s2.size)) { do { utf8_decode(&d1, (uint8_t)s1.str[j1++]); } while (d1.state); do { utf8_decode(&d2, (uint8_t)s2.str[j2++]); } while (d2.state); @@ -122,13 +122,18 @@ typedef struct { int nr16; } UGroup; -static const UGroup unicode_groups[U8G_SIZE]; +#ifndef __cplusplus +static +#else +extern +#endif +const UGroup _utf8_unicode_groups[U8G_SIZE]; bool utf8_isgroup(int group, uint32_t c) { - for (int j=0; j<unicode_groups[group].nr16; ++j) { - if (c < unicode_groups[group].r16[j].lo) + for (int j=0; j<_utf8_unicode_groups[group].nr16; ++j) { + if (c < _utf8_unicode_groups[group].r16[j].lo) return false; - if (c <= unicode_groups[group].r16[j].hi) + if (c <= _utf8_unicode_groups[group].r16[j].hi) return true; } return false; @@ -137,21 +142,21 @@ bool utf8_isgroup(int group, uint32_t c) { bool utf8_isalpha(uint32_t c) { static int16_t groups[] = {U8G_Latin, U8G_Nl, U8G_Greek, U8G_Cyrillic, U8G_Han, U8G_Devanagari, U8G_Arabic}; - if (c < 128) return isalpha(c) != 0; - for (unsigned j=0; j < c_ARRAYLEN(groups); ++j) + if (c < 128) return isalpha((int)c) != 0; + for (int j=0; j < c_ARRAYLEN(groups); ++j) if (utf8_isgroup(groups[j], c)) return true; return false; } bool utf8_iscased(uint32_t c) { - if (c < 128) return isalpha(c) != 0; + if (c < 128) return isalpha((int)c) != 0; return utf8_islower(c) || utf8_isupper(c) || utf8_isgroup(U8G_Lt, c); } bool utf8_isword(uint32_t c) { - if (c < 128) return (isalnum(c) != 0) | (c == '_'); + if (c < 128) return (isalnum((int)c) != 0) | (c == '_'); return utf8_isalpha(c) || utf8_isgroup(U8G_Nd, c) || utf8_isgroup(U8G_Pc, c); } @@ -323,139 +328,141 @@ static const URange16 Zs_range16[] = { // Space separator }; static const URange16 Arabic_range16[] = { - { 1536, 1540 }, - { 1542, 1547 }, - { 1549, 1562 }, - { 1564, 1566 }, - { 1568, 1599 }, - { 1601, 1610 }, - { 1622, 1647 }, - { 1649, 1756 }, - { 1758, 1791 }, - { 1872, 1919 }, - { 2160, 2190 }, - { 2192, 2193 }, - { 2200, 2273 }, - { 2275, 2303 }, - { 64336, 64450 }, - { 64467, 64829 }, - { 64832, 64911 }, - { 64914, 64967 }, - { 64975, 64975 }, - { 65008, 65023 }, - { 65136, 65140 }, - { 65142, 65276 }, + { 1536, 1540 }, + { 1542, 1547 }, + { 1549, 1562 }, + { 1564, 1566 }, + { 1568, 1599 }, + { 1601, 1610 }, + { 1622, 1647 }, + { 1649, 1756 }, + { 1758, 1791 }, + { 1872, 1919 }, + { 2160, 2190 }, + { 2192, 2193 }, + { 2200, 2273 }, + { 2275, 2303 }, + { 64336, 64450 }, + { 64467, 64829 }, + { 64832, 64911 }, + { 64914, 64967 }, + { 64975, 64975 }, + { 65008, 65023 }, + { 65136, 65140 }, + { 65142, 65276 }, }; static const URange16 Cyrillic_range16[] = { - { 1024, 1156 }, - { 1159, 1327 }, - { 7296, 7304 }, - { 7467, 7467 }, - { 7544, 7544 }, - { 11744, 11775 }, - { 42560, 42655 }, - { 65070, 65071 }, + { 1024, 1156 }, + { 1159, 1327 }, + { 7296, 7304 }, + { 7467, 7467 }, + { 7544, 7544 }, + { 11744, 11775 }, + { 42560, 42655 }, + { 65070, 65071 }, }; static const URange16 Devanagari_range16[] = { - { 2304, 2384 }, - { 2389, 2403 }, - { 2406, 2431 }, - { 43232, 43263 }, + { 2304, 2384 }, + { 2389, 2403 }, + { 2406, 2431 }, + { 43232, 43263 }, }; static const URange16 Greek_range16[] = { - { 880, 883 }, - { 885, 887 }, - { 890, 893 }, - { 895, 895 }, - { 900, 900 }, - { 902, 902 }, - { 904, 906 }, - { 908, 908 }, - { 910, 929 }, - { 931, 993 }, - { 1008, 1023 }, - { 7462, 7466 }, - { 7517, 7521 }, - { 7526, 7530 }, - { 7615, 7615 }, - { 7936, 7957 }, - { 7960, 7965 }, - { 7968, 8005 }, - { 8008, 8013 }, - { 8016, 8023 }, - { 8025, 8025 }, - { 8027, 8027 }, - { 8029, 8029 }, - { 8031, 8061 }, - { 8064, 8116 }, - { 8118, 8132 }, - { 8134, 8147 }, - { 8150, 8155 }, - { 8157, 8175 }, - { 8178, 8180 }, - { 8182, 8190 }, - { 8486, 8486 }, - { 43877, 43877 }, + { 880, 883 }, + { 885, 887 }, + { 890, 893 }, + { 895, 895 }, + { 900, 900 }, + { 902, 902 }, + { 904, 906 }, + { 908, 908 }, + { 910, 929 }, + { 931, 993 }, + { 1008, 1023 }, + { 7462, 7466 }, + { 7517, 7521 }, + { 7526, 7530 }, + { 7615, 7615 }, + { 7936, 7957 }, + { 7960, 7965 }, + { 7968, 8005 }, + { 8008, 8013 }, + { 8016, 8023 }, + { 8025, 8025 }, + { 8027, 8027 }, + { 8029, 8029 }, + { 8031, 8061 }, + { 8064, 8116 }, + { 8118, 8132 }, + { 8134, 8147 }, + { 8150, 8155 }, + { 8157, 8175 }, + { 8178, 8180 }, + { 8182, 8190 }, + { 8486, 8486 }, + { 43877, 43877 }, }; static const URange16 Han_range16[] = { - { 11904, 11929 }, - { 11931, 12019 }, - { 12032, 12245 }, - { 12293, 12293 }, - { 12295, 12295 }, - { 12321, 12329 }, - { 12344, 12347 }, - { 13312, 19903 }, - { 19968, 40959 }, - { 63744, 64109 }, - { 64112, 64217 }, + { 11904, 11929 }, + { 11931, 12019 }, + { 12032, 12245 }, + { 12293, 12293 }, + { 12295, 12295 }, + { 12321, 12329 }, + { 12344, 12347 }, + { 13312, 19903 }, + { 19968, 40959 }, + { 63744, 64109 }, + { 64112, 64217 }, }; static const URange16 Latin_range16[] = { - { 65, 90 }, - { 97, 122 }, - { 170, 170 }, - { 186, 186 }, - { 192, 214 }, - { 216, 246 }, - { 248, 696 }, - { 736, 740 }, - { 7424, 7461 }, - { 7468, 7516 }, - { 7522, 7525 }, - { 7531, 7543 }, - { 7545, 7614 }, - { 7680, 7935 }, - { 8305, 8305 }, - { 8319, 8319 }, - { 8336, 8348 }, - { 8490, 8491 }, - { 8498, 8498 }, - { 8526, 8526 }, - { 8544, 8584 }, - { 11360, 11391 }, - { 42786, 42887 }, - { 42891, 42954 }, - { 42960, 42961 }, - { 42963, 42963 }, - { 42965, 42969 }, - { 42994, 43007 }, - { 43824, 43866 }, - { 43868, 43876 }, - { 43878, 43881 }, - { 64256, 64262 }, - { 65313, 65338 }, - { 65345, 65370 }, + { 65, 90 }, + { 97, 122 }, + { 170, 170 }, + { 186, 186 }, + { 192, 214 }, + { 216, 246 }, + { 248, 696 }, + { 736, 740 }, + { 7424, 7461 }, + { 7468, 7516 }, + { 7522, 7525 }, + { 7531, 7543 }, + { 7545, 7614 }, + { 7680, 7935 }, + { 8305, 8305 }, + { 8319, 8319 }, + { 8336, 8348 }, + { 8490, 8491 }, + { 8498, 8498 }, + { 8526, 8526 }, + { 8544, 8584 }, + { 11360, 11391 }, + { 42786, 42887 }, + { 42891, 42954 }, + { 42960, 42961 }, + { 42963, 42963 }, + { 42965, 42969 }, + { 42994, 43007 }, + { 43824, 43866 }, + { 43868, 43876 }, + { 43878, 43881 }, + { 64256, 64262 }, + { 65313, 65338 }, + { 65345, 65370 }, }; #define UNI_ENTRY(Code) \ { Code##_range16, sizeof(Code##_range16)/sizeof(URange16) } - -static const UGroup unicode_groups[U8G_SIZE] = { +#ifndef __cplusplus +static +#endif +const UGroup _utf8_unicode_groups[U8G_SIZE] = { [U8G_Cc] = UNI_ENTRY(Cc), [U8G_Lt] = UNI_ENTRY(Lt), [U8G_Nd] = UNI_ENTRY(Nd), |
