summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2023-04-12 15:55:33 -0400
committerrealtradam <[email protected]>2023-04-12 15:55:33 -0400
commit0841165881871ee01b782129be681209aeed2423 (patch)
tree8a76b61dcaab381b6b42305201ae8b6259f6b6c0
parent554f3e8acf7855b5d6a90cc68cefb7445460b03c (diff)
parent0516aa3ae823ed9a22b2c5f776948c8447c32c31 (diff)
downloadSTC-modified-0841165881871ee01b782129be681209aeed2423.tar.gz
STC-modified-0841165881871ee01b782129be681209aeed2423.zip
Merge branch 'master' into modified
-rw-r--r--README.md529
-rw-r--r--docs/carc_api.md96
-rw-r--r--docs/cbox_api.md11
-rw-r--r--docs/ccommon_api.md525
-rw-r--r--docs/clist_api.md27
-rw-r--r--docs/cmap_api.md201
-rw-r--r--docs/coption_api.md2
-rw-r--r--docs/cpque_api.md43
-rw-r--r--docs/crandom_api.md45
-rw-r--r--docs/cregex_api.md43
-rw-r--r--docs/cset_api.md58
-rw-r--r--docs/csmap_api.md169
-rw-r--r--docs/cspan_api.md19
-rw-r--r--docs/csset_api.md56
-rw-r--r--docs/cstr_api.md7
-rw-r--r--docs/csview_api.md28
-rw-r--r--docs/cvec_api.md46
-rw-r--r--docs/pics/containers.jpgbin96093 -> 138703 bytes
-rw-r--r--include/c11/print.h (renamed from include/c11/fmt.h)35
-rw-r--r--include/stc/algo/coroutine.h25
-rw-r--r--include/stc/algo/crange.h6
-rw-r--r--include/stc/algo/csort.h6
-rw-r--r--include/stc/algo/filter.h95
-rw-r--r--include/stc/calgo.h8
-rw-r--r--include/stc/carc.h20
-rw-r--r--include/stc/cbits.h40
-rw-r--r--include/stc/cbox.h20
-rw-r--r--include/stc/ccommon.h102
-rw-r--r--include/stc/cdeq.h13
-rw-r--r--include/stc/clist.h112
-rw-r--r--include/stc/cmap.h98
-rw-r--r--include/stc/cpque.h14
-rw-r--r--include/stc/cqueue.h10
-rw-r--r--include/stc/crand.h174
-rw-r--r--include/stc/csmap.h112
-rw-r--r--include/stc/cspan.h23
-rw-r--r--include/stc/cstack.h4
-rw-r--r--include/stc/cvec.h15
-rw-r--r--include/stc/extend.h66
-rw-r--r--include/stc/forward.h2
-rw-r--r--include/stc/priv/altnames.h4
-rw-r--r--include/stc/priv/raii.h27
-rw-r--r--include/stc/priv/template.h76
-rw-r--r--include/stc/priv/template2.h78
-rw-r--r--misc/benchmarks/picobench/picobench_cmap.cpp68
-rw-r--r--misc/benchmarks/picobench/picobench_csmap.cpp72
-rw-r--r--misc/benchmarks/plotbench/cdeq_benchmark.cpp34
-rw-r--r--misc/benchmarks/plotbench/clist_benchmark.cpp30
-rw-r--r--misc/benchmarks/plotbench/cmap_benchmark.cpp40
-rw-r--r--misc/benchmarks/plotbench/cpque_benchmark.cpp34
-rw-r--r--misc/benchmarks/plotbench/csmap_benchmark.cpp38
-rw-r--r--misc/benchmarks/plotbench/cvec_benchmark.cpp24
-rw-r--r--misc/benchmarks/plotbench/plot.py2
-rw-r--r--misc/benchmarks/plotbench/run_all.bat4
-rw-r--r--misc/benchmarks/plotbench/run_clang.sh2
-rw-r--r--misc/benchmarks/plotbench/run_gcc.sh4
-rw-r--r--misc/benchmarks/plotbench/run_vc.bat3
-rw-r--r--misc/benchmarks/shootout_hashmaps.cpp9
-rw-r--r--misc/benchmarks/various/cbits_benchmark.cpp14
-rw-r--r--misc/benchmarks/various/csort_bench.c14
-rw-r--r--misc/benchmarks/various/prng_bench.cpp8
-rw-r--r--misc/benchmarks/various/rust_cmap.c68
-rw-r--r--misc/benchmarks/various/sso_bench.cpp14
-rw-r--r--misc/examples/arc_containers.c11
-rw-r--r--misc/examples/arc_demo.c65
-rw-r--r--misc/examples/arcvec_erase.c66
-rw-r--r--misc/examples/astar.c47
-rw-r--r--misc/examples/birthday.c50
-rw-r--r--misc/examples/bits.c51
-rw-r--r--misc/examples/books.c97
-rw-r--r--misc/examples/box.c46
-rw-r--r--misc/examples/box2.c34
-rw-r--r--misc/examples/city.c92
-rw-r--r--misc/examples/complex.c37
-rw-r--r--misc/examples/convert.c15
-rw-r--r--misc/examples/coread.c13
-rw-r--r--misc/examples/coroutines.c1
-rw-r--r--misc/examples/csmap_erase.c113
-rw-r--r--misc/examples/csmap_find.c48
-rw-r--r--misc/examples/csmap_insert.c134
-rw-r--r--misc/examples/csset_erase.c69
-rw-r--r--misc/examples/cstr_match.c32
-rw-r--r--misc/examples/demos.c196
-rw-r--r--misc/examples/forfilter.c146
-rw-r--r--misc/examples/forloops.c74
-rw-r--r--misc/examples/functor.c74
-rw-r--r--misc/examples/gauss1.c56
-rw-r--r--misc/examples/gauss2.c44
-rw-r--r--misc/examples/generator.c2
-rw-r--r--misc/examples/hashmap.c55
-rw-r--r--misc/examples/inits.c112
-rw-r--r--misc/examples/intrusive.c61
-rw-r--r--misc/examples/list.c94
-rw-r--r--misc/examples/list_erase.c39
-rw-r--r--misc/examples/list_splice.c31
-rw-r--r--misc/examples/lower_bound.c11
-rw-r--r--misc/examples/mapmap.c66
-rw-r--r--misc/examples/mmap.c58
-rw-r--r--misc/examples/multimap.c53
-rw-r--r--misc/examples/music_arc.c58
-rw-r--r--misc/examples/new_deq.c61
-rw-r--r--misc/examples/new_list.c59
-rw-r--r--misc/examples/new_map.c60
-rw-r--r--misc/examples/new_pque.c17
-rw-r--r--misc/examples/new_queue.c45
-rw-r--r--misc/examples/new_smap.c61
-rw-r--r--misc/examples/new_sptr.c44
-rw-r--r--misc/examples/new_vec.c52
-rw-r--r--misc/examples/person_arc.c25
-rw-r--r--misc/examples/phonebook.c48
-rw-r--r--misc/examples/prime.c35
-rw-r--r--misc/examples/printspan.c66
-rw-r--r--misc/examples/priority.c46
-rw-r--r--misc/examples/queue.c39
-rw-r--r--misc/examples/random.c16
-rw-r--r--misc/examples/rawptr_elements.c74
-rw-r--r--misc/examples/regex1.c34
-rw-r--r--misc/examples/regex2.c5
-rw-r--r--misc/examples/regex_match.c33
-rw-r--r--misc/examples/regex_replace.c30
-rw-r--r--misc/examples/replace.c35
-rw-r--r--misc/examples/shape.c58
-rw-r--r--misc/examples/sidebyside.cpp12
-rw-r--r--misc/examples/sorted_map.c7
-rw-r--r--misc/examples/splitstr.c9
-rw-r--r--misc/examples/sso_map.c17
-rw-r--r--misc/examples/stack.c34
-rw-r--r--misc/examples/sview_split.c7
-rw-r--r--misc/examples/triples.c37
-rw-r--r--misc/examples/unordered_set.c6
-rw-r--r--misc/examples/utf8replace_c.c35
-rw-r--r--misc/examples/vikings.c28
-rw-r--r--misc/examples/words.c68
-rw-r--r--misc/tests/cregex_test.c25
-rw-r--r--src/checkauto.l7
-rw-r--r--src/singleupdate.sh27
-rw-r--r--src/utf8code.c2
137 files changed, 3601 insertions, 3486 deletions
diff --git a/README.md b/README.md
index f74ee916..65d00324 100644
--- a/README.md
+++ b/README.md
@@ -1,41 +1,16 @@
![STC](docs/pics/containers.jpg)
-STC - Smart Template Containers for C
-=====================================
+STC - Smart Template Containers
+===============================
-News: Version 4.1.1 Released (Feb 2023)
-------------------------------------------------
-I am happy to finally announce a new release! Major changes:
-- A new exciting [**cspan**](docs/cspan_api.md) single/multi-dimensional array view (with numpy-like slicing).
-- Signed sizes and indices for all containers. See C++ Core Guidelines by Stroustrup/Sutter: [ES.100](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es100-dont-mix-signed-and-unsigned-arithmetic), [ES.102](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es102-use-signed-types-for-arithmetic), [ES.106](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es106-dont-try-to-avoid-negative-values-by-using-unsigned), and [ES.107](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es107-dont-use-unsigned-for-subscripts-prefer-gslindex).
-- Customizable allocator [per templated container type](https://github.com/tylov/STC/discussions/44#discussioncomment-4891925).
-- Updates on **cregex** with several [new unicode character classes](docs/cregex_api.md#regex-cheatsheet).
-- Algorithms:
- - [crange](docs/ccommon_api.md#crange) - similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html) integer range generator.
- - [c_forfilter](docs/ccommon_api.md#c_forfilter) - ranges-like view filtering.
- - [csort](include/stc/algo/csort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison.
-- Renamed `c_ARGSV()` => `c_SV()`: **csview** print arg. Note `c_sv()` is shorthand for *csview_from()*.
-- Support for [uppercase flow-control](include/stc/priv/altnames.h) macro names in ccommon.h.
-- Some API changes in **cregex** and **cstr**.
-- Create single header container versions with python script.
-- [Previous changes for version 4](#version-4).
-
-Introduction
-------------
-STC is a *modern*, *ergonomic*, *type-safe*, *very fast* and *compact* container library for C99.
-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
-more on complex container hierarchies without resorting to cumbersome function pointers with type casting.
-Usage with trivial data types is simple to use compared to most generic container libraries for C because
-of its type safety with an intuitive and consistent API.
+### [Version 4.2](#version-history)
-The library is mature and well tested, so you may use it in projects. However, minor breaking API changes may
-still happen. The main development of this project is finished, but I will handle PRs with bugs and improvements
-in the future, and do minor modifications.
+---
+Description
+-----------
+STC is a *modern*, *typesafe*, *fast* and *compact* container and algorithms library for C99.
+The API naming is similar to C++ STL, but it takes inspiration from Rust and Python as well.
+The library handles everything from trivial to highly complex data using *templates*.
Containers
----------
@@ -56,31 +31,77 @@ Containers
- [***cdeq*** - **std::deque** alike type](docs/cdeq_api.md)
- [***cvec*** - **std::vector** alike type](docs/cvec_api.md)
-Others
-------
-- [***ccommon*** - Generic safe macros and algorithms](docs/ccommon_api.md)
-- [***cregex*** - Regular expressions (extended from Rob Pike's regexp9)](docs/cregex_api.md)
-- [***crandom*** - A novel very fast *PRNG* named **stc64**](docs/crandom_api.md)
-- [***coption*** - getopt() alike command line args parser](docs/coption_api.md)
-
-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.
+Algorithms
+----------
+- [***Ranged for-loops*** - c_foreach, c_forpair, c_forlist](docs/ccommon_api.md#ranged-for-loops)
+- [***Range algorithms*** - c_forrange, crange, c_forfilter](docs/ccommon_api.md#range-algorithms)
+- [***Generic algorithms*** - c_make, c_find_if, c_erase_if, csort, etc.](docs/ccommon_api.md#generic-algorithms)
+- [***Coroutines*** - Simon Tatham's coroutines done right.](docs/ccommon_api.md#coroutines)
+- [***Regular expressions*** - Rob Pike's Plan 9 regexp modernized!](docs/cregex_api.md)
+- [***Random numbers*** - a very fast *PRNG* based on *SFC64*](docs/crandom_api.md)
+- [***Command line argument parser*** - similar to *getopt()*](docs/coption_api.md)
+
+---
+List of contents
+-----------------
+- [Highlights](#highlights)
+- [STC is unique!](#stc-is-unique)
+- [Performance](#performance)
+- [Naming conventions](#naming-conventions)
+- [Usage](#usage)
+- [Installation](#installation)
+- [Specifying template parameters](#specifying-template-parameters)
+- [The *emplace* methods](#the-emplace-methods)
+- [The *erase* methods](#the-erase-methods)
+- [User-defined container type name](#user-defined-container-type-name)
+- [Forward declarations](#forward-declarations)
+- [Per container-instance customization](#per-container-instance-customization)
+- [Memory efficiency](#memory-efficiency)
+
+---
+## Highlights
+
+- **No boilerplate code** - Specify only the required template parameters, e.g. ***cmp***- and/or ***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, 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.
-- **No signed/unsigned mixing** - Unsigned sizes and indices mixed with signed in comparisons and calculations is asking for trouble. STC uses only signed numbers in the API.
-- **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.
+- **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.
+- **Unparalleled performance** - Maps and sets are much faster than the C++ STL containers, the remaining are similar in speed.
+- **Fully memory managed** - Containers destructs keys/values via default or user supplied drop function. They may be cloned if element types are clonable. Also, smart pointers are supported and can be stored in containers. See [***carc***](docs/carc_api.md) and [***cbox***](docs/cbox_api.md).
+- **Uniform, easy-to-learn API** - Intuitive method/type names and uniform usage across the various containers.
+- **No signed/unsigned mixing** - Unsigned sizes and indices mixed with signed for comparison and calculation is asking for trouble. STC only uses signed numbers in the API for this reason.
+- **Small footprint** - Small source code and generated executables. The executable from the example below using *four 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).
-- **Forward declaration** - Templated containers may be forward declared without including the full API/implementation. See documentation below.
+- **Forward declaration** - Templated containers may be [forward declared](#forward-declarations) without including the full API/implementation.
+- **Extendable containers** - STC provides a mechanism to wrap containers inside a struct with [custom data per instance](#per-container-instance-customization).
+
+---
+## STC is unique!
+
+1. ***Centralized analysis of template parameters***. The analyser assigns values to all
+non-specified template parameters (based on the specified ones) using meta-programming, so
+that you don't have to! You may specify a set of "standard" template parameters for each
+container, but as a minimum *only one is required*: `i_val` (+ `i_key` for maps). In this
+case, STC assumes that the elements are of basic types. For non-trivial types, additional
+template parameters must be given.
+2. ***Alternative insert/lookup type***. You may specify an alternative type to use for
+lookup in containers. E.g., containers with STC string elements (**cstr**) uses `const char*`
+as lookup type, so constructing a `cstr` (which may allocate memory) for the lookup
+*is not needed*. Hence, the alternative lookup key does not need to be destroyed after use,
+as it is normally a POD type. Finally, the key may be passed to an ***emplace***-function.
+So instead of calling e.g. `cvec_str_push(&vec, cstr_from("Hello"))`, you may call
+`cvec_str_emplace(&vec, "Hello")`, which is functionally identical, but more convenient.
+3. ***Standardized container iterators***. All containers can be iterated in the same manner, and all use the
+same element access syntax. E.g.:
+ - `c_foreach (it, MyInts, myints) *it.ref += 42;` works for any container defined as
+ `MyInts` with `int` elements.
+ - `c_foreach (it, MyInts, it1, it2) *it.ref += 42;` iterates from `it1` up to `it2`.
+
+---
+## Performance
+
+STC is a fast and memory efficient library, and code compiles fast:
-Performance
------------
![Benchmark](misc/benchmarks/pics/benchmark.gif)
Benchmark notes:
@@ -92,8 +113,9 @@ Benchmark notes:
- **deque**: *insert*: n/3 push_front(), n/3 push_back()+pop_front(), n/3 push_back().
- **map and unordered map**: *insert*: n/2 random numbers, n/2 sequential numbers. *erase*: n/2 keys in the map, n/2 random keys.
-STC conventions
----------------
+---
+## Naming conventions
+
- Container names are prefixed by `c`, e.g. `cvec`, `cstr`.
- Public STC macros are prefixed by `c_`, e.g. `c_foreach`, `c_make`.
- Template parameter macros are prefixed by `i_`, e.g. `i_val`, `i_type`.
@@ -103,8 +125,7 @@ STC conventions
- Con_value
- Con_raw
- Con_iter
- - Con_ssize
-- Common function names for a container type Con:
+- Some common function names:
- Con_init()
- Con_reserve(&con, capacity)
- Con_drop(&con)
@@ -113,7 +134,6 @@ STC conventions
- Con_clone(con)
- Con_push(&con, value)
- Con_emplace(&con, rawval)
- - Con_put_n(&con, rawval[], n)
- Con_erase_at(&con, iter)
- Con_front(&con)
- Con_back(&con)
@@ -122,160 +142,164 @@ STC conventions
- Con_next(&iter)
- Con_advance(iter, n)
-Some 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 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. A great ergonomic feature is that the alternative lookup type can also be used when adding
-entries into containers through using the *emplace*-functions. E.g. `cvec_str_emplace_back(&vec, "Hello")`.
-3. ***Standardized container iterators***. All container can be iterated in similar manner, 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)`
-may be used to iterate from `it1` up to `it2`.
-
-Usage
------
-The usage of the containers is similar to the c++ standard containers in STL, so it should be easy if you
-are familiar with them. All containers are generic/templated, except for **cstr** and **cbits**.
-No casting is used, so containers are type-safe like templates in c++. A basic usage example:
+---
+## Usage
+STC containers have similar functionality to C++ STL standard containers. All containers except for a few,
+like **cstr** and **cbits** are generic/templated. No type casting is used, so containers are type-safe like
+templated types in C++. However, to specify template parameters with STC, you define them as macros prior to
+including the container:
```c
-#define i_type FVec // Container type name; if not defined, it would be cvec_float
+#define i_type Floats // Container type name; unless defined name would be cvec_float
#define i_val float // Container element type
-#include <stc/cvec.h>
+#include <stc/cvec.h> // "instantiate" the desired container type
+#include <stdio.h>
int main(void)
{
- FVec vec = FVec_init();
- FVec_push(&vec, 10.f);
- FVec_push(&vec, 20.f);
- FVec_push(&vec, 30.f);
+ Floats nums = {0};
+ Floats_push(&nums, 30.f);
+ Floats_push(&nums, 10.f);
+ Floats_push(&nums, 20.f);
+
+ for (int i = 0; i < Floats_size(&nums); ++i)
+ printf(" %g", nums.data[i]);
+
+ Floats_sort(&nums);
- for (intptr_t i = 0; i < FVec_size(vec); ++i)
- printf(" %g", vec.data[i]);
+ c_foreach (i, Floats, nums) // Alternative and recommended way to iterate.
+ printf(" %g", *i.ref); // i.ref is a pointer to the current element.
- FVec_drop(&vec); // cleanup memory
+ Floats_drop(&nums); // cleanup memory
}
```
-Below is an alternative way to write this with STC. It uses the generic flow control macros `c_auto` and `c_foreach`, and the function macro *c_make()*. This simplifies the code and makes it less prone to errors:
+You may switch to a different container type, e.g. a sorted set (csset):
+
+[ [Run this code](https://godbolt.org/z/qznfa65e1) ]
```c
+#define i_type Floats
+#define i_val float
+#include <stc/csset.h> // Use a sorted set instead
+#include <stdio.h>
+
int main()
{
- c_auto (FVec, vec) // RAII: define, init() and drop() combined.
- {
- vec = c_make(FVec, {10.f, 20.f, 30.f}); // Initialize with a list of floats.
+ Floats nums = {0};
+ Floats_push(&nums, 30.f);
+ Floats_push(&nums, 10.f);
+ Floats_push(&nums, 20.f);
- c_foreach (i, FVec, vec) // Iterate elements of the container.
- printf(" %g", *i.ref); // i.ref is a pointer to the current element.
- }
- // vec is "dropped" at end of c_auto scope
+ // already sorted, print the numbers
+ c_foreach (i, Floats, nums)
+ printf(" %g", *i.ref);
+
+ Floats_drop(&nums);
}
```
-For user defined struct elements, `i_cmp` compare function should be defined, as the default `<` and `==`
-only works for integral types. *Alternatively, `#define i_opt c_no_cmp` to disable sorting and searching*.
-
-Similarily, if an element destructor `i_valdrop` is defined, `i_valclone` function is required.
+For user-defined struct elements, `i_cmp` compare function should be defined as the default `<` and `==`
+only works for integral types. *Alternatively, `#define i_opt c_no_cmp` to disable sorting and searching*. Similarily, if an element destructor `i_valdrop` is defined, `i_valclone` function is required.
*Alternatively `#define i_opt c_no_clone` to disable container cloning.*
-In order to include two **cvec**'s with different element types, include <stc/cvec.h> twice:
+Let's make a vector of vectors, which can be cloned. All of its element vectors will be destroyed when destroying the Vec2D.
+
+[ [Run this code](https://godbolt.org/z/5EY56qnfM) ]
```c
-#define i_val struct One
-#define i_opt c_no_cmp
-#define i_tag one
+#include <stdio.h>
+
+#define i_type Vec
+#define i_val float
#include <stc/cvec.h>
-#define i_val struct Two
-#define i_opt c_no_cmp
-#define i_tag two
+#define i_type Vec2D
+#define i_valclass Vec // Use i_valclass when element type has "members" _clone(), _drop() and _cmp().
+#define i_opt c_no_cmp // Disable cmp (search/sort) for Vec2D because Vec_cmp() is not defined.
#include <stc/cvec.h>
-...
-cvec_one v1 = cvec_one_init();
-cvec_two v2 = cvec_two_init();
+
+int main(void)
+{
+ Vec* v;
+ Vec2D vec = {0}; // All containers in STC can be initialized with {0}.
+ v = Vec2D_push(&vec, Vec_init()); // push() returns a pointer to the new element in vec.
+ Vec_push(v, 10.f);
+ Vec_push(v, 20.f);
+
+ v = Vec2D_push(&vec, Vec_init());
+ Vec_push(v, 30.f);
+ Vec_push(v, 40.f);
+
+ Vec2D clone = Vec2D_clone(vec); // Make a deep-copy of vec
+
+ c_foreach (i, Vec2D, clone) // Loop through the cloned vector
+ c_foreach (j, Vec, *i.ref)
+ printf(" %g", *j.ref);
+
+ c_drop(Vec2D, &vec, &clone); // Cleanup all (6) vectors.
+}
```
+This example uses four different container types:
-An example using six different container types:
+[ [Run this code](https://godbolt.org/z/x5YKeMrEh) ]
```c
#include <stdio.h>
-#include <stc/ccommon.h>
-
-struct Point { float x, y; };
-int Point_cmp(const struct Point* a, const struct Point* b);
#define i_key int
#include <stc/cset.h> // cset_int: unordered set
+struct Point { float x, y; };
+// Define cvec_pnt with a less-comparison function for Point.
#define i_val struct Point
-#define i_cmp Point_cmp
+#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y)
#define i_tag pnt
-#include <stc/cvec.h> // cvec_pnt: vector of struct Point
-
-#define i_val int
-#include <stc/cdeq.h> // cdeq_int: deque of int
+#include <stc/cvec.h> // cvec_pnt: vector of struct Point
#define i_val int
-#include <stc/clist.h> // clist_int: singly linked list
-
-#define i_val int
-#include <stc/cstack.h>
+#include <stc/clist.h> // clist_int: singly linked list
#define i_key int
#define i_val int
-#include <stc/csmap.h> // csmap_int: sorted map int => int
-
-int Point_cmp(const struct Point* a, const struct Point* b) {
- int cmp = c_default_cmp(&a->x, &b->x);
- return cmp ? cmp : c_default_cmp(&a->y, &b->y);
-}
+#include <stc/csmap.h> // csmap_int: sorted map int => int
int main(void)
{
- /* Define six containers with automatic call of init and drop (destruction after scope exit) */
- c_auto (cset_int, set)
- c_auto (cvec_pnt, vec)
- c_auto (cdeq_int, deq)
- c_auto (clist_int, lst)
- c_auto (cstack_int, stk)
- c_auto (csmap_int, map)
- {
- int nums[4] = {10, 20, 30, 40};
- struct Point pts[4] = { {10, 1}, {20, 2}, {30, 3}, {40, 4} };
- int pairs[4][2] = { {20, 2}, {10, 1}, {30, 3}, {40, 4} };
+ // Define four empty containers
+ cset_int set = {0};
+ cvec_pnt vec = {0};
+ clist_int lst = {0};
+ csmap_int map = {0};
+
+ c_defer( // Drop the containers at scope exit
+ cset_int_drop(&set),
+ cvec_pnt_drop(&vec),
+ clist_int_drop(&lst),
+ csmap_int_drop(&map)
+ ){
+ enum{N = 5};
+ int nums[N] = {10, 20, 30, 40, 50};
+ struct Point pts[N] = { {10, 1}, {20, 2}, {30, 3}, {40, 4}, {50, 5} };
+ int pairs[N][2] = { {20, 2}, {10, 1}, {30, 3}, {40, 4}, {50, 5} };
- /* Add some elements to each container */
- for (int i = 0; i < 4; ++i) {
+ // Add some elements to each container
+ for (int i = 0; i < N; ++i) {
cset_int_insert(&set, nums[i]);
cvec_pnt_push(&vec, pts[i]);
- cdeq_int_push_back(&deq, nums[i]);
clist_int_push_back(&lst, nums[i]);
- cstack_int_push(&stk, nums[i]);
csmap_int_insert(&map, pairs[i][0], pairs[i][1]);
}
- /* Find an element in each container (except cstack) */
+ // Find an element in each container
cset_int_iter i1 = cset_int_find(&set, 20);
cvec_pnt_iter i2 = cvec_pnt_find(&vec, (struct Point){20, 2});
- cdeq_int_iter i3 = cdeq_int_find(&deq, 20);
- clist_int_iter i4 = clist_int_find(&lst, 20);
- csmap_int_iter i5 = csmap_int_find(&map, 20);
+ clist_int_iter i3 = clist_int_find(&lst, 20);
+ csmap_int_iter i4 = csmap_int_find(&map, 20);
- printf("\nFound: %d, (%g, %g), %d, %d, [%d: %d]\n",
- *i1.ref, i2.ref->x, i2.ref->y, *i3.ref,
- *i4.ref, i5.ref->first, i5.ref->second);
+ printf("\nFound: %d, (%g, %g), %d, [%d: %d]\n",
+ *i1.ref, i2.ref->x, i2.ref->y, *i3.ref,
+ i4.ref->first, i4.ref->second);
- /* Erase the elements found */
+ // Erase all the elements found
cset_int_erase_at(&set, i1);
cvec_pnt_erase_at(&vec, i2);
- cdeq_int_erase_at(&deq, i3);
- clist_int_erase_at(&lst, i4);
- csmap_int_erase_at(&map, i5);
+ clist_int_erase_at(&lst, i3);
+ csmap_int_erase_at(&map, i4);
printf("After erasing the elements found:");
printf("\n set:");
@@ -286,18 +310,10 @@ int main(void)
c_foreach (i, cvec_pnt, vec)
printf(" (%g, %g)", i.ref->x, i.ref->y);
- printf("\n deq:");
- c_foreach (i, cdeq_int, deq)
- printf(" %d", *i.ref);
-
printf("\n lst:");
c_foreach (i, clist_int, lst)
printf(" %d", *i.ref);
- printf("\n stk:");
- c_foreach (i, cstack_int, stk)
- printf(" %d", *i.ref);
-
printf("\n map:");
c_foreach (i, csmap_int, map)
printf(" [%d: %d]", i.ref->first, i.ref->second);
@@ -307,18 +323,16 @@ int main(void)
Output
```
-Found: 20, (20, 2), 20, 20, [20: 2]
-After erasing elements found:
- set: 10 30 40
- vec: (10, 1) (30, 3) (40, 4)
- deq: 5 10 30
- lst: 5 10 30
- stk: 10 20 30 40
- map: [10: 1] [30: 3] [40: 4]
+Found: 20, (20, 2), 20, [20: 2]
+After erasing the elements found:
+ set: 40 10 30 50
+ vec: (10, 1) (30, 3) (40, 4) (50, 5)
+ lst: 10 30 40 50
+ map: [10: 1] [30: 3] [40: 4] [50: 5]
```
+---
+## Installation
-Installation
-------------
Because it is headers-only, headers can simply be included in your program. By default, functions are static
(some inlined). You may add the *include* folder to the **CPATH** environment variable to
let GCC, Clang, and TinyC locate the headers.
@@ -337,7 +351,7 @@ once and if needed. Currently, define `i_extern` before including **clist** for
It is possible to generate single headers by executing the python script `src/singleheader.py header-file > single`.
Conveniently, `src\libstc.c` implements non-templated functions as shared symbols for **cstr**, **csview**,
-**cbits** and **crandom**. When building in shared mode (-DSTC_HEADER), you may include this file in your project,
+**cbits** and **crand**. When building in shared mode (-DSTC_HEADER), you may include this file in your project,
or define your own as descibed above.
```c
// stc_libs.c
@@ -362,9 +376,9 @@ or define your own as descibed above.
#define i_tag pnt
#include <stc/clist.h> // clist_pnt
```
+---
+## Specifying template parameters
-Specifying template parameters
-------------------------------
Each templated type requires one `#include`, even if it's the same container base type, as described earlier.
The template parameters are given by a `#define i_xxxx` statement, where *xxxx* is the parameter name.
The list of template parameters:
@@ -414,8 +428,9 @@ NB: Do not use when defining carc/cbox types themselves.
- Instead of defining `i_*clone`, you may define *i_opt c_no_clone* to disable *clone* functionality.
- For `i_keyclass`, if *i_keyraw* is defined along with it, *i_keyfrom* may also be defined to enable the *emplace*-functions. NB: the signature for ***cmp***, ***eq***, and ***hash*** uses *i_keyraw* as input.
-The *emplace* versus non-emplace container methods
---------------------------------------------------
+---
+## The *emplace* methods
+
STC, like c++ STL, has two sets of methods for adding elements to containers. One set begins
with **emplace**, e.g. *cvec_X_emplace_back()*. This is an ergonimic alternative to
*cvec_X_push_back()* when dealing non-trivial container elements, e.g. strings, shared pointers or
@@ -446,17 +461,19 @@ and non-emplace methods:
#define i_val_str // special macro to enable container of cstr
#include <stc/cvec.h> // vector of string (cstr)
...
-c_auto (cvec_str, vec) // declare and call cvec_str_init() and defer cvec_str_drop(&vec)
-c_with (cstr s = cstr_lit("a string literal"), cstr_drop(&s))
-{
- const char* hello = "Hello";
- cvec_str_push_back(&vec, cstr_from(hello); // construct and add string from const char*
- cvec_str_push_back(&vec, cstr_clone(s)); // clone and append a cstr
+cvec_str vec = {0};
+cstr s = cstr_lit("a string literal");
+const char* hello = "Hello";
- cvec_str_emplace_back(&vec, "Yay, literal"); // internally constructs cstr from const char*
- cvec_str_emplace_back(&vec, cstr_clone(s)); // <-- COMPILE ERROR: expects const char*
- cvec_str_emplace_back(&vec, cstr_str(&s)); // Ok: const char* input type.
-}
+cvec_str_push(&vec, cstr_from(hello); // make a cstr from const char* and move it onto vec
+cvec_str_push(&vec, cstr_clone(s)); // make a cstr clone and move it onto vec
+
+cvec_str_emplace(&vec, "Yay, literal"); // internally make a cstr from const char*
+cvec_str_emplace(&vec, cstr_clone(s)); // <-- COMPILE ERROR: expects const char*
+cvec_str_emplace(&vec, cstr_str(&s)); // Ok: const char* input type.
+
+cstr_drop(&s)
+cvec_str_drop(&vec);
```
This is made possible because the type configuration may be given an optional
conversion/"rawvalue"-type as template parameter, along with a back and forth conversion
@@ -484,8 +501,9 @@ it = cmap_str_find(&map, "Hello");
Apart from strings, maps and sets are normally used with trivial value types. However, the
last example on the **cmap** page demonstrates how to specify a map with non-trivial keys.
-Erase methods
--------------
+---
+## The *erase* methods
+
| Name | Description | Container |
|:--------------------------|:-----------------------------|:--------------------------------------------|
| erase() | key based | csmap, csset, cmap, cset, cstr |
@@ -494,8 +512,23 @@ Erase methods
| erase_n() | index based | cvec, cdeq, cstr |
| remove() | remove all matching values | clist |
-Forward declaring containers
-----------------------------
+---
+## User-defined container type name
+
+Define `i_type` instead of `i_tag`:
+```c
+#define i_type MyVec
+#define i_val int
+#include <stc/cvec.h>
+
+myvec vec = MyVec_init();
+MyVec_push_back(&vec, 1);
+...
+```
+
+---
+## Forward declarations
+
It is possible to forward declare containers. This is useful when a container is part of a struct,
but still not expose or include the full implementation / API of the container.
```c
@@ -508,30 +541,64 @@ typedef struct Dataset {
cstack_pnt colors;
} Dataset;
-...
// Implementation
-#define c_opt c_is_forward // flag that the container was forward declared.
+#define i_is_forward // flag that the container was forward declared.
#define i_val struct Point
#define i_tag pnt
#include <stc/cstack.h>
```
-User-defined container type name
---------------------------------
-Define `i_type` instead of `i_tag`:
+---
+## Per container-instance customization
+Sometimes it is useful to extend a container type to store extra data, e.g. a comparison
+or allocator function pointer or a context which the function pointers can use. Most
+libraries solve this by adding an opaque pointer (void*) or function pointer(s) into
+the data structure for the user to manage. This solution has a few disadvantages: the
+pointers are not typesafe, and they take up space when not needed. STC solves this by letting
+the user create a container wrapper struct where both the container and extra data fields can
+be stored. The template parameters may then access the extra data using the "container_of"
+technique.
+
+The example below shows how to customize containers to work with PostgreSQL memory management.
+It adds a MemoryContext to each container by defining the `i_extend` template parameter followed
+the by inclusion of `<stc/extend.h>`.
```c
-#define i_type MyVec
+// stcpgs.h
+#define pgs_malloc(sz) MemoryContextAlloc(c_getcon(self)->memctx, sz)
+#define pgs_calloc(n, sz) MemoryContextAllocZero(c_getcon(self)->memctx, (n)*(sz))
+#define pgs_realloc(p, sz) (p ? repalloc(p, sz) : pgs_malloc(sz))
+#define pgs_free(p) (p ? pfree(p) : (void)0) // pfree/repalloc does not accept NULL.
+
+#define i_allocator pgs
+#define i_no_clone
+#define i_extend MemoryContext memctx;
+#include <stc/extend.h>
+```
+To use it, define both `i_type` and `i_con` (the container type) before including the custom header:
+```c
+#define i_type IMap
+#define i_key int
#define i_val int
-#include <stc/cvec.h>
+#define i_con csmap
+#include "stcpgs.h"
-myvec vec = MyVec_init();
-MyVec_push_back(&vec, 1);
-...
+// Note the wrapper struct type is IMap_ext. IMap is accessed by .get
+void maptest()
+{
+ IMap_ext map = {.memctx=CurrentMemoryContext};
+ c_forrange (i, 1, 16)
+ IMap_insert(&map.get, i*i, i);
+
+ c_foreach (i, IMap, map.get)
+ printf("%d:%d ", i.ref->first, i.ref->second);
+
+ IMap_drop(&map.get);
+}
```
+---
+## Memory efficiency
-Memory efficiency
------------------
-STC is generally very memory efficient. Type sizes:
+STC is generally very memory efficient. Memory usage for the different containers:
- **cstr**, **cvec**, **cstack**, **cpque**: 1 pointer, 2 intptr_t + memory for elements.
- **csview**, 1 pointer, 1 intptr_t. Does not own data!
- **cspan**, 1 pointer and 2 \* dimension \* int32_t. Does not own data!
@@ -542,20 +609,48 @@ STC is generally very memory efficient. Type sizes:
- **carc**: Type size: 1 pointer, 1 long for the reference counter + memory for the shared element.
- **cbox**: Type size: 1 pointer + memory for the pointed-to element.
-# Version 4
+---
+# Version History
+## Version 4.2
+- New home! And online single headers for https://godbolt.org
+ - Library: https://github.com/stclib/STC
+ - Headers, e.g. https://raw.githubusercontent.com/stclib/stcsingle/main/stc/cvec.h
+- Much improved documentation
+- Added Coroutines + documentation
+- Added new crand.h API & header. Old crandom.h is deprecated.
+- Added `c_const_cast()` typesafe macro.
+- Removed RAII macros usage from examples
+- Renamed c_foreach_r => `c_foreach_rv`
+- Renamed c_flt_count(i) => `c_flt_counter(i)`
+- Renamed c_flt_last(i) => `c_flt_getcount(i)`
+- Renamed c_ARRAYLEN() => c_arraylen()
+- Removed deprecated c_ARGSV(). Use c_SV()
+- Removed c_PAIR
+
+## Version 4.1.1
+Major changes:
+- A new exciting [**cspan**](docs/cspan_api.md) single/multi-dimensional array view (with numpy-like slicing).
+- Signed sizes and indices for all containers. See C++ Core Guidelines by Stroustrup/Sutter: [ES.100](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es100-dont-mix-signed-and-unsigned-arithmetic), [ES.102](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es102-use-signed-types-for-arithmetic), [ES.106](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es106-dont-try-to-avoid-negative-values-by-using-unsigned), and [ES.107](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es107-dont-use-unsigned-for-subscripts-prefer-gslindex).
+- Customizable allocator [per templated container type](https://github.com/tylov/STC/discussions/44#discussioncomment-4891925).
+- Updates on **cregex** with several [new unicode character classes](docs/cregex_api.md#regex-cheatsheet).
+- Algorithms:
+ - [crange](docs/ccommon_api.md#crange) - similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html) integer range generator.
+ - [c_forfilter](docs/ccommon_api.md#c_forfilter) - ranges-like view filtering.
+ - [csort](include/stc/algo/csort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison.
+- Renamed `c_ARGSV()` => `c_SV()`: **csview** print arg. Note `c_sv()` is shorthand for *csview_from()*.
+- Support for [uppercase flow-control](include/stc/priv/altnames.h) macro names in ccommon.h.
+- Some API changes in **cregex** and **cstr**.
+- Create single header container versions with python script.
+
## API changes summary V4.0
- Added **cregex** with documentation - powerful regular expressions.
- Added: `c_forfilter`: container iteration with "piped" filtering using && operator. 4 built-in filters.
-- Added: `c_forwhile`: *c_foreach* container iteration with extra predicate.
- Added: **crange**: number generator type, which can be iterated (e.g. with *c_forfilter*).
- Added back **coption** - command line argument parsing.
- New + renamed loop iteration/scope macros:
- `c_forlist`: macro replacing `c_forarray` and `c_apply`. Iterate a compound literal list.
- `c_forrange`: macro replacing `c_forrange`. Iterate a `long long` type number sequence.
- - `c_with`: macro renamed from `c_autovar`. Like Python's **with** statement.
- - `c_scope`: macro renamed from `c_autoscope`.
- - `c_defer`: macro renamed from `c_autodefer`. Resembles Go's and Zig's **defer**.
- Updated **cstr**, now always takes self as pointer, like all containers except csview.
- Updated **cvec**, **cdeq**, changed `*_range*` function names.
@@ -588,7 +683,7 @@ STC is generally very memory efficient. Type sizes:
- Allows for `i_key*` template parameters instead of `i_val*` for all containers, not only for **cset** and **csset**.
- Optimized *c_default_hash()*. Therefore *c_hash32()* and *c_hash64()* are removed (same speed).
- Added *.._push()* and *.._emplace()* function to all containers to allow for more generic coding.
-- Renamed global PRNGs *stc64_random()* and *stc64_srandom()* to *crandom()* and *csrandom()*.
+- Renamed global PRNGs *stc64_random()* and *stc64_srandom()* to *crand()* and *csrand()*.
- Added some examples and benchmarks for SSO and heterogenous lookup comparison with c++20 (string_bench_*.cpp).
## Brief summary of changes from version 2.x to 3.0
diff --git a/docs/carc_api.md b/docs/carc_api.md
index cc6c9c32..48b64ff0 100644
--- a/docs/carc_api.md
+++ b/docs/carc_api.md
@@ -98,56 +98,56 @@ bool carc_X_value_eq(const i_val* x, const i_val* y);
int main()
{
- c_auto (Stack, s1, s2) // RAII
- {
- // POPULATE s1 with shared pointers to Map:
- Map *map;
-
- map = Stack_push(&s1, Arc_make(Map_init()))->get; // push empty map to s1.
- c_forlist (i, Map_raw, { {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} }) {
- Map_emplace(map, c_PAIR(i.ref)); // populate it.
- }
-
- map = Stack_push(&s1, Arc_make(Map_init()))->get;
- c_forlist (i, Map_raw, { {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} }) {
- Map_emplace(map, c_PAIR(i.ref));
- }
-
- // POPULATE s2:
- map = Stack_push(&s2, Arc_make(Map_init()))->get;
- c_forlist (i, Map_raw, { {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} }) {
- Map_emplace(map, c_PAIR(i.ref));
- }
-
- // Share two Maps from s1 with s2 by cloning(=sharing) the carcs:
- Stack_push(&s2, Arc_clone(s1.data[0]));
- Stack_push(&s2, Arc_clone(s1.data[1]));
-
- // Deep-copy (does not share) a Map from s1 to s2.
- // s2 will contain two shared and two unshared maps.
- map = Stack_push(&s2, Arc_from(Map_clone(*s1.data[1].get)))->get;
-
- // Add one more element to the cloned map:
- Map_emplace_or_assign(map, "Cloned", 2022);
-
- // Add one more element to the shared map:
- Map_emplace_or_assign(s1.data[1].get, "Shared", 2022);
-
- puts("S1");
- c_foreach (i, Stack, s1) {
- c_forpair (name, year, Map, *i.ref->get)
- printf(" %s:%d", cstr_str(_.name), *_.year);
- puts("");
- }
-
- puts("S2");
- c_foreach (i, Stack, s2) {
- c_forpair (name, year, Map, *i.ref->get)
- printf(" %s:%d", cstr_str(_.name), *_.year);
- puts("");
- }
+ Stack s1 = {0}, s2 = {0};
+ Map *map;
+
+ // POPULATE s1 with shared pointers to Map:
+ map = Stack_push(&s1, Arc_make(Map_init()))->get; // push empty map to s1.
+ Map_emplace(map, "Joey", 1990);
+ Map_emplace(map, "Mary", 1995);
+ Map_emplace(map, "Joanna", 1992);
+
+ map = Stack_push(&s1, Arc_make(Map_init()))->get;
+ Map_emplace(map, "Rosanna", 2001);
+ Map_emplace(map, "Brad", 1999);
+ Map_emplace(map, "Jack", 1980);
+
+ // POPULATE s2:
+ map = Stack_push(&s2, Arc_make(Map_init()))->get;
+ Map_emplace(map, "Steve", 1979);
+ Map_emplace(map, "Rick", 1974);
+ Map_emplace(map, "Tracy", 2003);
+
+ // Share two Maps from s1 with s2 by cloning(=sharing) the carcs:
+ Stack_push(&s2, Arc_clone(s1.data[0]));
+ Stack_push(&s2, Arc_clone(s1.data[1]));
+
+ // Deep-copy (does not share) a Map from s1 to s2.
+ // s2 will contain two shared and two unshared maps.
+ map = Stack_push(&s2, Arc_from(Map_clone(*s1.data[1].get)))->get;
+
+ // Add one more element to the cloned map:
+ Map_emplace_or_assign(map, "Cloned", 2022);
+
+ // Add one more element to the shared map:
+ Map_emplace_or_assign(s1.data[1].get, "Shared", 2022);
+
+ puts("S1");
+ c_foreach (i, Stack, s1) {
+ c_forpair (name, year, Map, *i.ref->get)
+ printf(" %s:%d", cstr_str(_.name), *_.year);
puts("");
}
+
+ puts("S2");
+ c_foreach (i, Stack, s2) {
+ c_forpair (name, year, Map, *i.ref->get)
+ printf(" %s:%d", cstr_str(_.name), *_.year);
+ puts("");
+ }
+ puts("");
+
+ c_drop(Stack, &s1, &s2);
}
```
Output:
diff --git a/docs/cbox_api.md b/docs/cbox_api.md
index 8b03d004..ca4d90da 100644
--- a/docs/cbox_api.md
+++ b/docs/cbox_api.md
@@ -92,11 +92,12 @@ void int_drop(int* x) {
int main()
{
- c_auto (IVec, vec) // declare and init vec, call drop at scope exit
- c_auto (ISet, set) // similar
- {
- vec = c_make(Vec, {2021, 2012, 2022, 2015});
-
+ IVec vec = c_make(Vec, {2021, 2012, 2022, 2015});
+ ISet set = {0};
+ c_defer(
+ IVec_drop(&vec),
+ ISet_drop(&set)
+ ){
printf("vec:");
c_foreach (i, IVec, vec)
printf(" %d", *i.ref->get);
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 8dcb2ff3..7a3c3196 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -1,106 +1,16 @@
-# STC [ccommon](../include/stc/ccommon.h): Generic algorithms and macros
+# STC Algorithms
-The following macros are recommended to use, and they safe/have no side-effects.
+---
+## Ranged for-loops
-## Scope macros (RAII)
-### c_auto, c_with, c_scope, c_defer
-General ***defer*** mechanics for resource acquisition. These macros allows you to specify the
-freeing of the resources at the point where the acquisition takes place.
-The **checkauto** utility described below, ensures that the `c_auto*` macros are used correctly.
+### c_foreach, c_foreach_rv, c_forpair
-| Usage | Description |
-|:---------------------------------------|:----------------------------------------------------------|
-| `c_with (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope |
-| `c_with (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed |
-| `c_auto (Type, var1,...,var4)` | `c_with (Type var1=Type_init(), Type_drop(&var1))` ... |
-| `c_scope (init, drop)` | Execute `init` and defer `drop` to end of scope |
-| `c_defer (drop...)` | Defer `drop...` to end of scope |
-| `continue` | Exit a block above without memory leaks |
-
-For multiple variables, use either multiple **c_with** in sequence, or declare variable outside
-scope and use **c_scope**. For convenience, **c_auto** support up to 4 variables.
-```c
-// `c_with` is similar to python `with`: it declares and can drop a variable after going out of scope.
-bool ok = false;
-c_with (uint8_t* buf = malloc(BUF_SIZE), buf != NULL, free(buf))
-c_with (FILE* fp = fopen(fname, "rb"), fp != NULL, fclose(fp))
-{
- int n = fread(buf, 1, BUF_SIZE, fp);
- if (n <= 0) continue; // auto cleanup! NB do not break or return here.
- ...
- ok = true;
-}
-return ok;
-
-// `c_auto` automatically initialize and destruct up to 4 variables:
-c_auto (cstr, s1, s2)
-{
- cstr_append(&s1, "Hello");
- cstr_append(&s1, " world");
-
- cstr_append(&s2, "Cool");
- cstr_append(&s2, " stuff");
-
- printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
-}
-
-// `c_with` is a general variant of `c_auto`:
-c_with (cstr str = cstr_lit("Hello"), cstr_drop(&str))
-{
- cstr_append(&str, " world");
- printf("%s\n", cstr_str(&str));
-}
-
-// `c_scope` is like `c_with` but works with an already declared variable.
-static pthread_mutex_t mut;
-c_scope (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut))
-{
- /* Do syncronized work. */
-}
-
-// `c_defer` executes the expressions when leaving scope. Prefer c_with or c_scope.
-cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world");
-c_defer (cstr_drop(&s1), cstr_drop(&s2))
-{
- printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
-}
-```
-**Example**: Load each line of a text file into a vector of strings:
-```c
-#include <errno.h>
-#include <stc/cstr.h>
-
-#define i_val_str
-#include <stc/cvec.h>
-
-// receiver should check errno variable
-cvec_str readFile(const char* name)
-{
- cvec_str vec = cvec_str_init(); // returned
-
- c_with (FILE* fp = fopen(name, "r"), fp != NULL, fclose(fp))
- c_with (cstr line = cstr_NULL, cstr_drop(&line))
- while (cstr_getline(&line, fp))
- cvec_str_emplace_back(&vec, cstr_str(&line));
- return vec;
-}
-
-int main()
-{
- c_with (cvec_str x = readFile(__FILE__), cvec_str_drop(&x))
- c_foreach (i, cvec_str, x)
- printf("%s\n", cstr_str(i.ref));
-}
-```
-## Loop abstraction macros
-
-### c_foreach, c_forpair
-
-| Usage | Description |
-|:-----------------------------------------|:--------------------------------|
-| `c_foreach (it, ctype, container)` | Iteratate all elements |
-| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
-| `c_forpair (key, val, ctype, container)` | Iterate with structured binding |
+| Usage | Description |
+|:-----------------------------------------|:------------------------------------------|
+| `c_foreach (it, ctype, container)` | Iteratate all elements |
+| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
+| `c_foreach_rv (it, ctype, container)` | Iteratate in reverse (cstack, cvec, cdeq) |
+| `c_forpair (key, val, ctype, container)` | Iterate with structured binding |
```c
#define i_key int
@@ -129,6 +39,25 @@ c_forpair (id, count, csmap_ii, map)
// (3 2) (5 4) (7 3) (12 5) (23 1)
```
+### c_forlist
+Iterate compound literal array elements. Additional to `i.ref`, you can access `i.data`, `i.size`, and `i.index` of the input list/element.
+```c
+// apply multiple push_backs
+c_forlist (i, int, {1, 2, 3})
+ cvec_i_push_back(&vec, *i.ref);
+
+// insert in existing map
+c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} })
+ cmap_ii_insert(&map, i.ref->first, i.ref->second);
+
+// string literals pushed to a stack of cstr:
+c_forlist (i, const char*, {"Hello", "crazy", "world"})
+ cstack_str_emplace(&stk, *i.ref);
+```
+
+---
+## Range algorithms
+
### c_forrange
Abstraction for iterating sequence of integers. Like python's **for** *i* **in** *range()* loop.
@@ -150,46 +79,56 @@ c_forrange (i, 30, 0, -5) printf(" %lld", i);
// 30 25 20 15 10 5
```
-### c_forlist
-Iterate compound literal array elements. Additional to `i.ref`, you can access `i.data`, `i.size`, and `i.index` of the input list/element.
+### crange
+A number sequence generator type, similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html). The **crange_value** type is `long long`. Below *start*, *stop*, and *step* are of type *crange_value*:
```c
-// apply multiple push_backs
-c_forlist (i, int, {1, 2, 3})
- cvec_i_push_back(&vec, *i.ref);
-
-// insert in existing map
-c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} })
- cmap_ii_insert(&map, i.ref->first, i.ref->second);
+crange& crange_obj(...) // create a compound literal crange object
+crange crange_make(stop); // will generate 0, 1, ..., stop-1
+crange crange_make(start, stop); // will generate start, start+1, ... stop-1
+crange crange_make(start, stop, step); // will generate start, start+step, ... upto-not-including stop
+ // note that step may be negative.
+crange_iter crange_begin(crange* self);
+crange_iter crange_end(crange* self);
+void crange_next(crange_iter* it);
-// string literals pushed to a stack of cstr:
-c_forlist (i, const char*, {"Hello", "crazy", "world"})
- cstack_str_emplace(&stk, *i.ref);
+// 1. All primes less than 32:
+crange r1 = crange_make(3, 32, 2);
+printf("2"); // first prime
+c_forfilter (i, crange, r1, isPrime(*i.ref))
+ printf(" %lld", *i.ref);
+// 2 3 5 7 11 13 17 19 23 29 31
-// reverse the list:
-c_forlist (i, int, {1, 2, 3})
- cvec_i_push_back(&vec, i.data[i.size - 1 - i.index]);
+// 2. The first 11 primes:
+printf("2");
+c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2),
+ isPrime(*i.ref) &&
+ c_flt_take(10)
+){
+ printf(" %lld", *i.ref);
+}
+// 2 3 5 7 11 13 17 19 23 29 31
```
### c_forfilter
-Iterate containers with stop-criteria and chained range filtering.
+Iterate a container/range with chained range filtering.
| Usage | Description |
|:----------------------------------------------------|:---------------------------------------|
| `c_forfilter (it, ctype, container, filter)` | Filter out items in chain with && |
-| `c_forwhile (it, ctype, start, pred)` | Iterate until pred is false |
-
-| Built-in filter | Description |
-|:----------------------------------|:-------------------------------------|
-| `c_flt_skip(it, numItems)` | Skip numItems (inc count) |
-| `c_flt_take(it, numItems)` | Take numItems (inc count) |
-| `c_flt_skipwhile(it, predicate)` | Skip items until predicate is false |
-| `c_flt_takewhile(it, predicate)` | Take items until predicate is false |
-| `c_flt_count(it)` | Increment current and return value |
-| `c_flt_last(it)` | Get value of last count/skip/take |
+| `c_forfilter_it (it, ctype, startit, filter)` | Filter from startit position |
+
+| Built-in filter | Description |
+|:----------------------------------|:-------------------------------------------|
+| `c_flt_skip(it, numItems)` | Skip numItems (inc count) |
+| `c_flt_take(it, numItems)` | Take numItems (inc count) |
+| `c_flt_skipwhile(it, predicate)` | Skip items until predicate is false |
+| `c_flt_takewhile(it, predicate)` | Take items until predicate is false |
+| `c_flt_counter(it)` | Increment current and return count |
+| `c_flt_getcount(it)` | Number of items passed skip*/take*/counter |
+
+[ [Run this example](https://godbolt.org/z/n9aYrYPv8) ]
```c
-// Example:
-#include <stc/algo/crange.h>
-#include <stc/algo/filter.h>
+#include <stc/calgo.h>
#include <stdio.h>
bool isPrime(long long i) {
@@ -197,59 +136,33 @@ bool isPrime(long long i) {
if (i % j == 0) return false;
return true;
}
+
int main() {
- // Get 10 prime numbers starting from 1000.
- // Skip the first 24 primes, then select every 15th prime.
- crange R = crange_make(1001, INT32_MAX, 2);
+ // Get 10 prime numbers starting from 1000. Skip the first 15 primes,
+ // then select every 25th prime (including the initial).
+ crange R = crange_make(1001, INT64_MAX, 2); // 1001, 1003, ...
c_forfilter (i, crange, R,
- isPrime(*i.ref)
- && c_flt_skip(i, 24)
- && c_flt_count(i) % 15 == 1
- && c_flt_take(i, 10))
+ isPrime(*i.ref) &&
+ c_flt_skip(i, 15) &&
+ c_flt_counter(i) % 25 == 1 &&
+ c_flt_take(i, 10)
+ ){
printf(" %lld", *i.ref);
- puts("");
+ }
}
-// out: 1171 1283 1409 1493 1607 1721 1847 1973 2081 2203
+// out: 1097 1289 1481 1637 1861 2039 2243 2417 2657 2803
```
-Note that `c_flt_take()` and `c_flt_takewhile()`breaks the loop on false.
+Note that `c_flt_take()` and `c_flt_takewhile()` breaks the loop on false.
-## Generators
+---
+## Generic algorithms
-### crange
-A number sequence generator type, similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html). The **crange_value** type is `long long`. Below *start*, *stop*, and *step* are of type *crange_value*:
-```c
-crange& crange_obj(...) // create a compound literal crange object
-crange crange_make(stop); // will generate 0, 1, ..., stop-1
-crange crange_make(start, stop); // will generate start, start+1, ... stop-1
-crange crange_make(start, stop, step); // will generate start, start+step, ... upto-not-including stop
- // note that step may be negative.
-crange_iter crange_begin(crange* self);
-crange_iter crange_end(crange* self);
-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, isPrime(*i.ref))
- printf(" %lld", *i.ref);
-// 2 3 5 7 11 13 17 19 23 29 31
+### c_make, c_drop
-// 2. The 11 first primes:
-printf("2");
-c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2)
- , isPrime(*i.ref)
- && c_flt_take(10))
- printf(" %lld", *i.ref);
-// 2 3 5 7 11 13 17 19 23 29 31
-```
-## Algorithms
-
-### c_make, c_new, c_delete
-
-- *c_make(C, {...})*: Make any container from an initializer list. Example:
+Make any container from an initializer list:
```c
-#define i_val_str // cstr value type
+#define i_val_str // owned cstr string value type
#include <stc/cset.h>
#define i_key int
@@ -258,26 +171,21 @@ c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2)
...
// Initializes with const char*, internally converted to cstr!
cset_str myset = c_make(cset_str, {"This", "is", "the", "story"});
+cset_str myset2 = c_clone(myset);
int x = 7, y = 8;
cmap_int mymap = c_make(cmap_int, { {1, 2}, {3, 4}, {5, 6}, {x, y} });
```
-
-- ***c_new(Type)***: Allocate *and init* a new object on the heap
-- ***c_delete(Type, ptr)***: Drop *and free* an object allocated on the heap
+Drop multiple containers of the same type:
```c
-#include <stc/cstr.h>
-
-cstr *stringptr = c_new(cstr, cstr_from("Hello"));
-printf("%s\n", cstr_str(stringptr));
-c_delete(cstr, stringptr);
+c_drop(cset_str, &myset, &myset2);
```
### c_find_if, c_erase_if, c_eraseremove_if
Find or erase linearily in containers using a predicate
-- For *c_find_if (iter, C, c, pred)*, ***iter*** must be declared outside/prior to call.
-- Use *c_erase_if (iter, C, c, pred)* with **clist**, **cmap**, **cset**, **csmap**, and **csset**.
-- Use *c_eraseremove_if (iter, C, c, pred)* with **cstack**, **cvec**, **cdeq**, and **cqueue**.
+- For `c_find_if(iter, C, c, pred)`, ***iter*** is in/out and must be declared prior to call.
+- Use `c_erase_if(iter, C, c, pred)` with **clist**, **cmap**, **cset**, **csmap**, and **csset**.
+- Use `c_eraseremove_if(iter, C, c, pred)` with **cstack**, **cvec**, **cdeq**, and **cqueue**.
```c
// Search vec for first value > 2:
cvec_i_iter i;
@@ -296,29 +204,36 @@ if (it.ref) cmap_str_erase_at(&map, it);
c_erase_if(i, csmap_str, map, cstr_contains(i.ref, "hello"));
```
-### c_swap, c_drop
+### csort - two times faster qsort
+
+When very fast array sorting is required, **csort** is about twice as fast as *qsort()*, and often simpler to use.
+You may customize `i_tag` and the comparison function `i_cmp` or `i_less`.
+
+There is a [benchmark/test file here](../misc/benchmarks/various/csort_bench.c).
```c
-// Safe macro for swapping internals of two objects of same type:
-c_swap(cmap_int, &map1, &map2);
+#define i_val int
+#include <stc/algo/csort.h>
-// Drop multiple containers of same type:
-c_drop(cvec_i, &vec1, &vec2, &vec3);
+int main() {
+ int array[] = {5, 3, 5, 9, 7, 4, 7, 2, 4, 9, 3, 1, 2, 6, 4};
+ csort_int(array, c_arraylen(array));
+}
```
-### General predefined template parameter functions
+
+### c_new, c_delete
+
+- `c_new(Type, val)` - Allocate *and init* a new object on the heap
+- `c_delete(Type, ptr)` - Drop *and free* an object allocated on the heap. NULL is OK.
```c
-int c_default_cmp(const Type*, const Type*);
-Type c_default_clone(Type val); // simple copy
-Type c_default_toraw(const Type* val); // dereference val
-void c_default_drop(Type* val); // does nothing
+#include <stc/cstr.h>
-typedef const char* crawstr;
-int crawstr_cmp(const crawstr* x, const crawstr* y);
-bool crawstr_eq(const crawstr* x, const crawstr* y);
-uint64_t crawstr_hash(const crawstr* x);
+cstr *str_p = c_new(cstr, cstr_from("Hello"));
+printf("%s\n", cstr_str(str_p));
+c_delete(cstr, str_p);
```
-### c_malloc, c_calloc, c_realloc, c_free: customizable allocators
+### c_malloc, c_calloc, c_realloc, c_free
Memory allocator wrappers that uses signed sizes.
### c_arraylen
@@ -328,7 +243,219 @@ int array[] = {1, 2, 3, 4};
intptr_t n = c_arraylen(array);
```
-## The **checkauto** utility program (for RAII)
+### c_swap, c_const_cast
+```c
+// Safe macro for swapping internals of two objects of same type:
+c_swap(cmap_int, &map1, &map2);
+
+// Type-safe casting a from const (pointer):
+const char cs[] = "Hello";
+char* s = c_const_cast(char*, cs); // OK
+int* ip = c_const_cast(int*, cs); // issues a warning!
+```
+
+### Predefined template parameter functions
+
+**crawstr** - Non-owned `const char*` "class" element type: `#define i_valclass crawstr`
+```c
+typedef const char* crawstr;
+int crawstr_cmp(const crawstr* x, const crawstr* y);
+bool crawstr_eq(const crawstr* x, const crawstr* y);
+uint64_t crawstr_hash(const crawstr* x);
+```
+Default implementations
+```c
+int c_default_cmp(const Type*, const Type*); // <=>
+bool c_default_less(const Type*, const Type*); // <
+bool c_default_eq(const Type*, const Type*); // ==
+uint64_t c_default_hash(const Type*);
+Type c_default_clone(Type val); // return val
+Type c_default_toraw(const Type* p); // return *p
+void c_default_drop(Type* p); // does nothing
+```
+
+---
+## Coroutines
+This is a much improved implementation of
+[Simon Tatham's coroutines](https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html),
+which utilizes the *Duff's device* trick. Tatham's implementation is not typesafe,
+and it always allocates the coroutine's internal state dynamically. But crucially,
+it does not let the coroutine do self-cleanup on early finish - i.e. it
+only frees the initial dynamically allocated memory.
+
+In this implementation, a coroutine may have any signature, but it should
+take a struct pointer as parameter, which must contain the member `int cco_state;`
+The struct should normally store all the *local* variables to be used in the
+coroutine. It can also store input and output data if desired.
+
+The coroutine example below generates Pythagorian triples, but the calling loop
+skips the triples which are upscaled version of smaller ones, by checking
+the gcd() function. It also ensures that it stops when the diagonal size >= 100:
+
+[ [Run this code](https://godbolt.org/z/coqqrfbd5) ]
+```c
+#include <stc/calgo.h>
+
+struct triples {
+ int n; // input: max number of triples to be generated.
+ int a, b, c;
+ int cco_state; // required member
+};
+
+bool triples_next(struct triples* i) { // coroutine
+ cco_begin(i);
+ for (i->c = 5; i->n; ++i->c) {
+ for (i->a = 1; i->a < i->c; ++i->a) {
+ for (i->b = i->a + 1; i->b < i->c; ++i->b) {
+ if ((int64_t)i->a*i->a + (int64_t)i->b*i->b == (int64_t)i->c*i->c) {
+ cco_yield(true);
+ if (--i->n == 0) cco_return;
+ }
+ }
+ }
+ }
+ cco_final: // required label
+ puts("done");
+ cco_end(false);
+}
+
+int gcd(int a, int b) { // greatest common denominator
+ while (b) {
+ int t = a % b;
+ a = b;
+ b = t;
+ }
+ return a;
+}
+
+int main()
+{
+ struct triples t = {.n=INT32_MAX};
+ int n = 0;
+
+ while (triples_next(&t)) {
+ // Skip triples with GCD(a,b) > 1
+ if (gcd(t.a, t.b) > 1)
+ continue;
+
+ // Stop when c >= 100
+ if (t.c < 100)
+ printf("%d: [%d, %d, %d]\n", ++n, t.a, t.b, t.c);
+ else
+ cco_stop(&t); // cleanup in next coroutine call/resume
+ }
+}
+```
+### Coroutine API
+**Note**: *cco_yield()* may not be called inside a `switch` statement. Use `if-else-if` constructs instead.
+To resume the coroutine from where it was suspended with *cco_yield()*, simply call the coroutine again.
+
+| | Function / operator | Description |
+|:----------|:-------------------------------------|:----------------------------------------|
+| | `cco_final:` | Obligatory label in coroutine |
+| | `cco_return;` | Early return from the coroutine |
+| `bool` | `cco_alive(ctx)` | Is coroutine in initial or suspended state? |
+| `bool` | `cco_suspended(ctx)` | Is coroutine in suspended state? |
+| `void` | `cco_begin(ctx)` | Begin coroutine block |
+| `rettype` | `cco_end(retval)` | End coroutine block with return value |
+| `void` | `cco_end()` | End coroutine block |
+| `rettype` | `cco_yield(retval)` | Suspend execution and return a value |
+| `void` | `cco_yield()` | Suspend execution |
+| `rettype` | `cco_yield(corocall2, ctx2, retval)` | Yield from another coroutine and return val |
+| `void` | `cco_yield(corocall2, ctx2)` | Yield from another coroutine |
+| | From the caller side: | |
+| `void` | `cco_stop(ctx)` | Next call of coroutine returns `cco_end()` |
+| `void` | `cco_reset(ctx)` | Reset state to initial (for reuse) |
+
+---
+## RAII scope macros
+General ***defer*** mechanics for resource acquisition. These macros allows you to specify the
+freeing of the resources at the point where the acquisition takes place.
+The **checkauto** utility described below, ensures that the `c_auto*` macros are used correctly.
+
+| Usage | Description |
+|:---------------------------------------|:----------------------------------------------------------|
+| `c_defer (drop...)` | Defer `drop...` to end of scope |
+| `c_scope (init, drop)` | Execute `init` and defer `drop` to end of scope |
+| `c_scope (init, pred, drop)` | Adds a predicate in order to exit early if init failed |
+| `c_with (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope |
+| `c_with (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed |
+| `c_auto (Type, var1,...,var4)` | `c_with (Type var1=Type_init(), Type_drop(&var1))` ... |
+| `continue` | Exit a defer-block without resource leak |
+
+```c
+// `c_defer` executes the expression(s) when leaving scope.
+cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world");
+c_defer (cstr_drop(&s1), cstr_drop(&s2))
+{
+ printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
+}
+
+// `c_scope` syntactically "binds" initialization and defer.
+static pthread_mutex_t mut;
+c_scope (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut))
+{
+ /* Do syncronized work. */
+}
+
+// `c_with` is similar to python `with`: declare a variable and defer the drop call.
+c_with (cstr str = cstr_lit("Hello"), cstr_drop(&str))
+{
+ cstr_append(&str, " world");
+ printf("%s\n", cstr_str(&str));
+}
+
+// `c_auto` automatically initialize and drops up to 4 variables:
+c_auto (cstr, s1, s2)
+{
+ cstr_append(&s1, "Hello");
+ cstr_append(&s1, " world");
+ cstr_append(&s2, "Cool");
+ cstr_append(&s2, " stuff");
+ printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
+}
+```
+**Example 1**: Use multiple **c_with** in sequence:
+```c
+bool ok = false;
+c_with (uint8_t* buf = malloc(BUF_SIZE), buf != NULL, free(buf))
+c_with (FILE* fp = fopen(fname, "rb"), fp != NULL, fclose(fp))
+{
+ int n = fread(buf, 1, BUF_SIZE, fp);
+ if (n <= 0) continue; // auto cleanup! NB do not break or return here.
+ ...
+ ok = true;
+}
+return ok;
+```
+**Example 2**: Load each line of a text file into a vector of strings:
+```c
+#include <errno.h>
+#include <stc/cstr.h>
+
+#define i_val_str
+#include <stc/cvec.h>
+
+// receiver should check errno variable
+cvec_str readFile(const char* name)
+{
+ cvec_str vec = {0}; // returned
+ c_with (FILE* fp = fopen(name, "r"), fp != NULL, fclose(fp))
+ c_with (cstr line = {0}, cstr_drop(&line))
+ while (cstr_getline(&line, fp))
+ cvec_str_emplace(&vec, cstr_str(&line));
+ return vec;
+}
+
+int main()
+{
+ c_with (cvec_str vec = readFile(__FILE__), cvec_str_drop(&vec))
+ c_foreach (i, cvec_str, vec)
+ printf("| %s\n", cstr_str(i.ref));
+}
+```
+
+### The **checkauto** utility program (for RAII)
The **checkauto** program will check the source code for any misuses of the `c_auto*` macros which
may lead to resource leakages. The `c_auto*`- macros are implemented as one-time executed **for-loops**,
so any `return` or `break` appearing within such a block will lead to resource leaks, as it will disable
diff --git a/docs/clist_api.md b/docs/clist_api.md
index 929931af..a1dbe105 100644
--- a/docs/clist_api.md
+++ b/docs/clist_api.md
@@ -80,8 +80,8 @@ const i_val* clist_X_get(const clist_X* self, i_valraw raw);
i_val* clist_X_get_mut(clist_X* self, i_valraw raw);
void clist_X_reverse(clist_X* self);
-void clist_X_sort(clist_X* self); // needs i_extern defined
-void clist_X_sort_with(clist_X* self, int(*cmp)(const clist_X_node*, const clist_X_node*));
+void clist_X_sort(clist_X* self);
+void clist_X_sort_with(clist_X* self, int(*cmp)(const clist_X_value*, const clist_X_value*));
// Node API
clist_X_node* clist_X_get_node(clist_X_value* val); // get the enclosing node
@@ -193,21 +193,20 @@ Splice `[30, 40]` from *L2* into *L1* before `3`:
#include <stdio.h>
int main() {
- c_auto (clist_i, L1, L2)
- {
- L1 = c_make(clist_i, {1, 2, 3, 4, 5});
- L2 = c_make(clist_i, {10, 20, 30, 40, 50});
+ clist_i L1 = c_make(clist_i, {1, 2, 3, 4, 5});
+ clist_i L2 = c_make(clist_i, {10, 20, 30, 40, 50});
- clist_i_iter i = clist_i_advance(clist_i_begin(&L1), 2);
- clist_i_iter j1 = clist_i_advance(clist_i_begin(&L2), 2), j2 = clist_i_advance(j1, 2);
+ clist_i_iter i = clist_i_advance(clist_i_begin(&L1), 2);
+ clist_i_iter j1 = clist_i_advance(clist_i_begin(&L2), 2), j2 = clist_i_advance(j1, 2);
- clist_i_splice_range(&L1, i, &L2, j1, j2);
+ clist_i_splice_range(&L1, i, &L2, j1, j2);
- c_foreach (i, clist_i, L1)
- printf(" %d", *i.ref); puts("");
- c_foreach (i, clist_i, L2)
- printf(" %d", *i.ref); puts("");
- }
+ c_foreach (i, clist_i, L1)
+ printf(" %d", *i.ref); puts("");
+ c_foreach (i, clist_i, L2)
+ printf(" %d", *i.ref); puts("");
+
+ c_drop(clist_i, &L1, &L2);
}
```
Output:
diff --git a/docs/cmap_api.md b/docs/cmap_api.md
index bf3dddcc..d2a94ee8 100644
--- a/docs/cmap_api.md
+++ b/docs/cmap_api.md
@@ -36,9 +36,7 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain
#define i_valto // convertion func i_val* => i_valraw
#define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_val
-#define i_hash_functor // advanced, see examples/functor.c for similar usage.
-#define i_eq_functor // advanced, see examples/functor.c for similar usage.
-#define i_ssize // internal; default int32_t. If defined, table expand 2x (else 1.5x)
+#define i_ssize // internal; default int32_t. If defined, table expand 2x (else 1.5x)
#include <stc/cmap.h>
```
`X` should be replaced by the value of `i_tag` in all of the following documentation.
@@ -104,12 +102,12 @@ bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !
| Type name | Type definition | Used to represent... |
|:-------------------|:------------------------------------------------|:------------------------------|
| `cmap_X` | `struct { ... }` | The cmap type |
-| `cmap_X_rawkey` | `i_keyraw` | The raw key type |
-| `cmap_X_rawmapped` | `i_valraw` | The raw mapped type |
-| `cmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw + i_valraw type |
| `cmap_X_key` | `i_key` | The key type |
| `cmap_X_mapped` | `i_val` | The mapped type |
| `cmap_X_value` | `struct { const i_key first; i_val second; }` | The value: key is immutable |
+| `cmap_X_keyraw` | `i_keyraw` | The raw key type |
+| `cmap_X_rmapped` | `i_valraw` | The raw mapped type |
+| `cmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw + i_valraw type |
| `cmap_X_result` | `struct { cmap_X_value *ref; bool inserted; }` | Result of insert/emplace |
| `cmap_X_iter` | `struct { cmap_X_value *ref; ... }` | Iterator type |
@@ -125,27 +123,26 @@ bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !
int main()
{
// Create an unordered_map of three strings (that map to strings)
- c_auto (cmap_str, u)
- {
- u = c_make(cmap_str, {
- {"RED", "#FF0000"},
- {"GREEN", "#00FF00"},
- {"BLUE", "#0000FF"}
- });
-
- // Iterate and print keys and values of unordered map
- c_foreach (n, cmap_str, u) {
- printf("Key:[%s] Value:[%s]\n", cstr_str(&n.ref->first), cstr_str(&n.ref->second));
- }
-
- // Add two new entries to the unordered map
- cmap_str_emplace(&u, "BLACK", "#000000");
- cmap_str_emplace(&u, "WHITE", "#FFFFFF");
-
- // Output values by key
- printf("The HEX of color RED is:[%s]\n", cstr_str(cmap_str_at(&u, "RED")));
- printf("The HEX of color BLACK is:[%s]\n", cstr_str(cmap_str_at(&u, "BLACK")));
+ cmap_str umap = c_make(cmap_str, {
+ {"RED", "#FF0000"},
+ {"GREEN", "#00FF00"},
+ {"BLUE", "#0000FF"}
+ });
+
+ // Iterate and print keys and values of unordered map
+ c_foreach (n, cmap_str, umap) {
+ printf("Key:[%s] Value:[%s]\n", cstr_str(&n.ref->first), cstr_str(&n.ref->second));
}
+
+ // Add two new entries to the unordered map
+ cmap_str_emplace(&umap, "BLACK", "#000000");
+ cmap_str_emplace(&umap, "WHITE", "#FFFFFF");
+
+ // Output values by key
+ printf("The HEX of color RED is:[%s]\n", cstr_str(cmap_str_at(&umap, "RED")));
+ printf("The HEX of color BLACK is:[%s]\n", cstr_str(cmap_str_at(&umap, "BLACK")));
+
+ cmap_str_drop(&umap);
}
```
Output:
@@ -161,33 +158,33 @@ The HEX of color BLACK is:[#000000]
This example uses a cmap with cstr as mapped value.
```c
#include <stc/cstr.h>
-
+#define i_type IDMap
#define i_key int
#define i_val_str
-#define i_tag id
#include <stc/cmap.h>
int main()
{
uint32_t col = 0xcc7744ff;
- c_auto (cmap_id, idnames)
- {
- c_forlist (i, cmap_id_raw, { {100, "Red"}, {110, "Blue"} })
- cmap_id_emplace(&idnames, c_PAIR(i.ref));
-
- // replace existing mapped value:
- cmap_id_emplace_or_assign(&idnames, 110, "White");
-
- // insert a new constructed mapped string into map:
- cmap_id_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
-
- // emplace/insert does nothing if key already exist:
- cmap_id_emplace(&idnames, 100, "Green");
-
- c_foreach (i, cmap_id, idnames)
- printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
- }
+ IDMap idnames = {0};
+
+ c_forlist (i, IDMap_raw, { {100, "Red"}, {110, "Blue"} })
+ IDMap_emplace(&idnames, i.ref->first, i.ref->second);
+
+ // replace existing mapped value:
+ IDMap_emplace_or_assign(&idnames, 110, "White");
+
+ // insert a new constructed mapped string into map:
+ IDMap_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
+
+ // emplace/insert does nothing if key already exist:
+ IDMap_emplace(&idnames, 100, "Green");
+
+ c_foreach (i, IDMap, idnames)
+ printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
+
+ IDMap_drop(&idnames);
}
```
Output:
@@ -212,16 +209,17 @@ typedef struct { int x, y, z; } Vec3i;
int main()
{
// Define map with defered destruct
- c_with (cmap_vi vecs = cmap_vi_init(), cmap_vi_drop(&vecs))
- {
- cmap_vi_insert(&vecs, (Vec3i){100, 0, 0}, 1);
- cmap_vi_insert(&vecs, (Vec3i){ 0, 100, 0}, 2);
- cmap_vi_insert(&vecs, (Vec3i){ 0, 0, 100}, 3);
- cmap_vi_insert(&vecs, (Vec3i){100, 100, 100}, 4);
-
- c_forpair (v3, num, cmap_vi, vecs)
- printf("{ %3d, %3d, %3d }: %d\n", _.v3->x, _.v3->y, _.v3->z, *_.num);
- }
+ cmap_vi vecs = {0};
+
+ cmap_vi_insert(&vecs, (Vec3i){100, 0, 0}, 1);
+ cmap_vi_insert(&vecs, (Vec3i){ 0, 100, 0}, 2);
+ cmap_vi_insert(&vecs, (Vec3i){ 0, 0, 100}, 3);
+ cmap_vi_insert(&vecs, (Vec3i){100, 100, 100}, 4);
+
+ c_forpair (v3, num, cmap_vi, vecs)
+ printf("{ %3d, %3d, %3d }: %d\n", _.v3->x, _.v3->y, _.v3->z, *_.num);
+
+ cmap_vi_drop(&vecs);
}
```
Output:
@@ -245,16 +243,17 @@ typedef struct { int x, y, z; } Vec3i;
int main()
{
- c_auto (cmap_iv, vecs) // shorthand for c_with with _init(), _drop().
- {
- cmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0});
- cmap_iv_insert(&vecs, 2, (Vec3i){ 0, 100, 0});
- cmap_iv_insert(&vecs, 3, (Vec3i){ 0, 0, 100});
- cmap_iv_insert(&vecs, 4, (Vec3i){100, 100, 100});
-
- c_forpair (num, v3, cmap_iv, vecs)
- printf("%d: { %3d, %3d, %3d }\n", *_.num, _.v3->x, _.v3->y, _.v3->z);
- }
+ cmap_iv vecs = {0}
+
+ cmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0});
+ cmap_iv_insert(&vecs, 2, (Vec3i){ 0, 100, 0});
+ cmap_iv_insert(&vecs, 3, (Vec3i){ 0, 0, 100});
+ cmap_iv_insert(&vecs, 4, (Vec3i){100, 100, 100});
+
+ c_forpair (num, v3, cmap_iv, vecs)
+ printf("%d: { %3d, %3d, %3d }\n", *_.num, _.v3->x, _.v3->y, _.v3->z);
+
+ cmap_iv_drop(&vecs);
}
```
Output:
@@ -300,35 +299,27 @@ static inline void Viking_drop(Viking* vk) {
#define i_type Vikings
#define i_keyclass Viking
#define i_val int
-/*
- i_keyclass implies these defines, unless they are already defined:
- #define i_cmp Viking_cmp
- #define i_hash Viking_hash
- #define i_keyclone Viking_clone
- #define i_keydrop Viking_drop
-*/
#include <stc/cmap.h>
int main()
{
// Use a HashMap to store the vikings' health points.
- c_auto (Vikings, vikings) // uses Vikings_init(), Vikings_drop()
- {
- Vikings_insert(&vikings, (Viking){cstr_lit("Einar"), cstr_lit("Norway")}, 25);
- Vikings_insert(&vikings, (Viking){cstr_lit("Olaf"), cstr_lit("Denmark")}, 24);
- Vikings_insert(&vikings, (Viking){cstr_lit("Harald"), cstr_lit("Iceland")}, 12);
- Vikings_insert(&vikings, (Viking){cstr_lit("Einar"), cstr_lit("Denmark")}, 21);
-
- c_auto (Viking, lookup) {
- lookup = (Viking){cstr_lit("Einar"), cstr_lit("Norway")};
- printf("Lookup: Einar of Norway has %d hp\n\n", *Vikings_at(&vikings, lookup));
- }
-
- // Print the status of the vikings.
- c_forpair (vik, hp, Vikings, vikings) {
- printf("%s of %s has %d hp\n", cstr_str(&_.vik->name), cstr_str(&_.vik->country), *_.hp);
- }
+ Vikings vikings = {0};
+
+ Vikings_insert(&vikings, (Viking){cstr_lit("Einar"), cstr_lit("Norway")}, 25);
+ Vikings_insert(&vikings, (Viking){cstr_lit("Olaf"), cstr_lit("Denmark")}, 24);
+ Vikings_insert(&vikings, (Viking){cstr_lit("Harald"), cstr_lit("Iceland")}, 12);
+ Vikings_insert(&vikings, (Viking){cstr_lit("Einar"), cstr_lit("Denmark")}, 21);
+
+ Viking lookup = (Viking){cstr_lit("Einar"), cstr_lit("Norway")};
+ printf("Lookup: Einar of Norway has %d hp\n\n", *Vikings_at(&vikings, lookup));
+ Viking_drop(&lookup);
+
+ // Print the status of the vikings.
+ c_forpair (vik, hp, Vikings, vikings) {
+ printf("%s of %s has %d hp\n", cstr_str(&_.vik->name), cstr_str(&_.vik->country), *_.hp);
}
+ Vikings_drop(&vikings);
}
```
Output:
@@ -384,30 +375,22 @@ static inline RViking Viking_toraw(const Viking* vp) {
#define i_hash(rp) (cstrhash(rp->name) ^ cstrhash(rp->country))
#define i_val int
#include <stc/cmap.h>
-/*
- i_keyclass implies these defines, unless they are already defined:
- #define i_cmp RViking_cmp
- //#define i_hash RViking_hash // already defined above.
- //#define i_keyclone Viking_clone // not used because c_no_clone
- #define i_keyto Viking_toraw // because i_keyraw type is defined
- #define i_keydrop Viking_drop
-*/
int main()
{
- c_auto (Vikings, vikings)
- {
- Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20);
- Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24);
- Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12);
- Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10);
-
- Vikings_value *v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"});
- if (v) v->second += 3; // add 3 hp points to Einar
-
- c_forpair (vk, hp, Vikings, vikings) {
- printf("%s of %s has %d hp\n", cstr_str(&_.vk->name), cstr_str(&_.vk->country), *_.hp);
- }
+ Vikings vikings = {0};
+
+ Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20);
+ Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24);
+ Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12);
+ Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10);
+
+ Vikings_value *v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"});
+ if (v) v->second += 3; // add 3 hp points to Einar
+
+ c_forpair (vk, hp, Vikings, vikings) {
+ printf("%s of %s has %d hp\n", cstr_str(&_.vk->name), cstr_str(&_.vk->country), *_.hp);
}
+ Vikings_drop(&vikings);
}
```
diff --git a/docs/coption_api.md b/docs/coption_api.md
index be0d0978..1e85ac2a 100644
--- a/docs/coption_api.md
+++ b/docs/coption_api.md
@@ -66,6 +66,4 @@ int main(int argc, char *argv[]) {
printf(" %s", argv[i]);
putchar('\n');
}
- return 0;
-}
```
diff --git a/docs/cpque_api.md b/docs/cpque_api.md
index 991623d7..962ee162 100644
--- a/docs/cpque_api.md
+++ b/docs/cpque_api.md
@@ -18,7 +18,6 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai
#define i_valfrom // convertion func i_valraw => i_val
#define i_valto // convertion func i_val* => i_valraw.
-#define i_less_functor // takes self as first argument. See examples/functor.c for usage.
#define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_val
#include <stc/cpque.h>
```
@@ -61,7 +60,7 @@ i_val cpque_X_value_clone(i_val value);
## Example
```c
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stdio.h>
#define i_val int64_t
@@ -72,27 +71,27 @@ i_val cpque_X_value_clone(i_val value);
int main()
{
intptr_t N = 10000000;
- stc64_t rng = stc64_new(1234);
- stc64_uniform_t dist = stc64_uniform_new(0, N * 10);
-
- // Declare heap, with defered drop()
- c_auto (cpque_i, heap)
- {
- // Push ten million random numbers to priority queue.
- c_forrange (N)
- cpque_i_push(&heap, stc64_uniform(&rng, &dist));
-
- // Add some negative ones.
- int nums[] = {-231, -32, -873, -4, -343};
- c_forrange (i, c_ARRAYLEN(nums))
- cpque_i_push(&heap, nums[i]);
-
- // Extract and display the fifty smallest.
- c_forrange (50) {
- printf("%" PRId64 " ", *cpque_i_top(&heap));
- cpque_i_pop(&heap);
- }
+ crand_t rng = crand_init(1234);
+ crand_unif_t dist = crand_unif_init(0, N * 10);
+
+ // Define heap
+ cpque_i heap = {0};
+
+ // Push ten million random numbers to priority queue.
+ c_forrange (N)
+ cpque_i_push(&heap, crand_unif(&rng, &dist));
+
+ // Add some negative ones.
+ int nums[] = {-231, -32, -873, -4, -343};
+ c_forrange (i, c_arraylen(nums))
+ cpque_i_push(&heap, nums[i]);
+
+ // Extract and display the fifty smallest.
+ c_forrange (50) {
+ printf("%" PRId64 " ", *cpque_i_top(&heap));
+ cpque_i_pop(&heap);
}
+ cpque_i_drop(&heap);
}
```
Output:
diff --git a/docs/crandom_api.md b/docs/crandom_api.md
index e69cc539..7281b2d7 100644
--- a/docs/crandom_api.md
+++ b/docs/crandom_api.md
@@ -1,4 +1,4 @@
-# STC [crandom](../include/stc/crandom.h): Pseudo Random Number Generator
+# STC [crand](../include/stc/crand.h): Pseudo Random Number Generator
![Random](pics/random.jpg)
This features a *64-bit PRNG* named **stc64**, and can generate bounded uniform and normal
@@ -33,45 +33,40 @@ xoshiro and pcg (Vigna/O'Neill) PRNGs: https://www.pcg-random.org/posts/on-vigna
## Header file
-All crandom definitions and prototypes are available by including a single header file.
+All crand definitions and prototypes are available by including a single header file.
```c
-#include <stc/crandom.h>
+#include <stc/crand.h>
```
## 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 csrand(uint64_t seed); // seed global stc64 prng
+uint64_t crand(void); // global crand_u64(rng)
+double crandf(void); // global crand_f64(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
+crand_t crand_init(uint64_t seed); // stc64_init(s) is deprecated
+uint64_t crand_u64(crand_t* rng); // range [0, 2^64 - 1]
+double crand_f64(crand_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)
+crand_unif_t crand_unif_init(int64_t low, int64_t high); // uniform-distribution
+int64_t crand_unif(crand_t* rng, crand_unif_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)
-
-stc64_normalf_t stc64_normalf_new(double mean, double stddev); // normal-distribution
-double stc64_normalf(stc64_t* rng, stc64_normalf_t* dist);
+crand_norm_t crand_norm_init(double mean, double stddev); // normal-distribution
+double crand_norm(crand_t* rng, crand_norm_t* dist);
```
## Types
| Name | Type definition | Used to represent... |
|:-------------------|:------------------------------------------|:-----------------------------|
-| `stc64_t` | `struct {uint64_t state[4];}` | The PRNG engine type |
-| `stc64_uniform_t` | `struct {int64_t lower; uint64_t range;}` | Integer uniform distribution |
-| `stc64_uniformf_t` | `struct {double lower, range;}` | Real number uniform distr. |
-| `stc64_normalf_t` | `struct {double mean, stddev;}` | Normal distribution type |
+| `crand_t` | `struct {uint64_t state[4];}` | The PRNG engine type |
+| `crand_unif_t` | `struct {int64_t lower; uint64_t range;}` | Integer uniform distribution |
+| `crand_norm_t` | `struct {double mean, stddev;}` | Normal distribution type |
## Example
```c
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stc/cstr.h>
// Declare int -> int sorted map. Uses typetag 'i' for ints.
@@ -89,13 +84,13 @@ int main()
// Setup random engine with normal distribution.
uint64_t seed = time(NULL);
- stc64_t rng = stc64_new(seed);
- stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev);
+ crand_t rng = crand_init(seed);
+ crand_norm_t dist = crand_norm_init(Mean, StdDev);
// Create histogram map
csmap_i mhist = csmap_i_init();
c_forrange (N) {
- int index = (int) round( stc64_normalf(&rng, &dist) );
+ int index = (int)round(crand_norm(&rng, &dist));
csmap_i_emplace(&mhist, index, 0).ref->second += 1;
}
diff --git a/docs/cregex_api.md b/docs/cregex_api.md
index 64fb6a2b..9a15a869 100644
--- a/docs/cregex_api.md
+++ b/docs/cregex_api.md
@@ -11,15 +11,17 @@ The API is simple and includes powerful string pattern matches and replace funct
```c
enum {
- /* compile-flags */
- CREG_C_DOTALL = 1<<0, /* dot matches newline too: can be set/overridden by (?s) and (?-s) in RE */
- CREG_C_ICASE = 1<<1, /* ignore case mode: can be set/overridden by (?i) and (?-i) in RE */
- /* match-flags */
- CREG_M_FULLMATCH = 1<<2, /* like start-, end-of-line anchors were in pattern: "^ ... $" */
- CREG_M_NEXT = 1<<3, /* use end of previous match[0] as start of input */
- CREG_M_STARTEND = 1<<4, /* use match[0] as start+end of input */
- /* replace-flags */
- CREG_R_STRIP = 1<<5, /* only keep the replaced matches, strip the rest */
+ // compile-flags
+ CREG_C_DOTALL = 1<<0, // dot matches newline too: can be set/overridden by (?s) and (?-s) in RE
+ CREG_C_ICASE = 1<<1, // ignore case mode: can be set/overridden by (?i) and (?-i) in RE
+
+ // match-flags
+ CREG_M_FULLMATCH = 1<<2, // like start-, end-of-line anchors were in pattern: "^ ... $"
+ CREG_M_NEXT = 1<<3, // use end of previous match[0] as start of input
+ CREG_M_STARTEND = 1<<4, // use match[0] as start+end of input
+
+ // replace-flags
+ CREG_R_STRIP = 1<<5, // only keep the replaced matches, strip the rest
};
cregex cregex_init(void);
@@ -80,11 +82,11 @@ void cregex_drop(cregex* self);
### Compiling a regular expression
```c
cregex re1 = cregex_init();
-int result = cregex_compile(&re1, "[0-9]+", CREG_DEFAULT);
+int result = cregex_compile(&re1, "[0-9]+");
if (result < 0) return result;
const char* url = "(https?://|ftp://|www\\.)([0-9A-Za-z@:%_+~#=-]+\\.)+([a-z][a-z][a-z]?)(/[/0-9A-Za-z\\.@:%_+~#=\\?&-]*)?";
-cregex re2 = cregex_from(url, CREG_DEFAULT);
+cregex re2 = cregex_from(url);
if (re2.error != CREG_OK)
return re2.error;
...
@@ -94,27 +96,28 @@ cregex_drop(&re1);
If an error occurs ```cregex_compile``` returns a negative error code stored in re2.error.
### Getting the first match and making text replacements
+
+[ [Run this code](https://godbolt.org/z/z434TMKfo) ]
```c
-#define i_extern // include external utf8 and cregex functions implementation.
+#define i_extern // include external cstr, utf8, cregex functions implementation.
#include <stc/cregex.h>
-#include <stc/cstr.h>
int main() {
- const char* input = "start date is 2023-03-01, and end date is 2025-12-31.";
+ const char* input = "start date is 2023-03-01, end date 2025-12-31.";
const char* pattern = "\\b(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)\\b";
- cregex re = cregex_from(pattern, CREG_DEFAULT);
+ cregex re = cregex_from(pattern);
// Lets find the first date in the string:
csview match[4]; // full-match, year, month, date.
- if (cregex_find(&re, input, match, CREG_DEFAULT) == CREG_OK)
+ if (cregex_find(&re, input, match) == CREG_OK)
printf("Found date: %.*s\n", c_SV(match[0]));
else
printf("Could not find any date\n");
// Lets change all dates into US date format MM/DD/YYYY:
cstr us_input = cregex_replace(&re, input, "$2/$3/$1");
- printf("US input: %s\n", cstr_str(&us_input));
+ printf("%s\n", cstr_str(&us_input));
// Free allocated data
cstr_drop(&us_input);
@@ -123,11 +126,11 @@ int main() {
```
For a single match you may use the all-in-one function:
```c
-if (cregex_find_pattern(pattern, input, match, CREG_DEFAULT))
+if (cregex_find_pattern(pattern, input, match))
printf("Found date: %.*s\n", c_SV(match[0]));
```
-To compile, use: `gcc first_match.c src/cregex.c src/utf8code.c`.
+To use: `gcc first_match.c src/cregex.c src/utf8code.c`.
In order to use a callback function in the replace call, see `examples/regex_replace.c`.
### Iterate through regex matches, *c_formatch*
@@ -139,7 +142,7 @@ while (cregex_find(&re, input, match, CREG_M_NEXT) == CREG_OK)
c_forrange (k, cregex_captures(&re))
printf("submatch %lld: %.*s\n", k, c_SV(match[k]));
```
-There is also a safe macro which simplifies this:
+There is also a for-loop macro to simplify it:
```c
c_formatch (it, &re, input)
c_forrange (k, cregex_captures(&re))
diff --git a/docs/cset_api.md b/docs/cset_api.md
index 287f7636..026d7462 100644
--- a/docs/cset_api.md
+++ b/docs/cset_api.md
@@ -19,8 +19,6 @@ A **cset** is an associative container that contains a set of unique objects of
#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy
#define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_val
-#define i_hash_functor // advanced, see examples/functor.c for similar usage.
-#define i_eq_functor // advanced, see examples/functor.c for similar usage.
#define i_ssize // default int32_t. If defined, table expand 2x (else 1.5x)
#include <stc/cset.h>
```
@@ -70,47 +68,45 @@ cset_X_value cset_X_value_clone(cset_X_value val);
| Type name | Type definition | Used to represent... |
|:-------------------|:-------------------------------------------------|:----------------------------|
| `cset_X` | `struct { ... }` | The cset type |
-| `cset_X_rawkey` | `i_keyraw` | The raw key type |
-| `cset_X_raw` | `i_keyraw` | The raw value type |
| `cset_X_key` | `i_key` | The key type |
-| `cset_X_value` | `i_key` | The value |
+| `cset_X_value` | `i_key` | The key type (alias) |
+| `cset_X_keyraw` | `i_keyraw` | The raw key type |
+| `cset_X_raw` | `i_keyraw` | The raw key type (alias) |
| `cset_X_result` | `struct { cset_X_value* ref; bool inserted; }` | Result of insert/emplace |
| `cset_X_iter` | `struct { cset_X_value *ref; ... }` | Iterator type |
## Example
```c
#include <stc/cstr.h>
-
+#define i_type Strset
#define i_key_str
#include <stc/cset.h>
int main ()
{
- c_auto (cset_str, fifth)
- {
- c_auto (cset_str, first, second)
- c_auto (cset_str, third, fourth)
- {
- second = c_make(cset_str, {"red", "green", "blue"});
-
- c_forlist (i, const char*, {"orange", "pink", "yellow"})
- cset_str_emplace(&third, *i.ref);
-
- cset_str_emplace(&fourth, "potatoes");
- cset_str_emplace(&fourth, "milk");
- cset_str_emplace(&fourth, "flour");
-
- fifth = cset_str_clone(second);
- c_foreach (i, cset_str, third)
- cset_str_emplace(&fifth, cstr_str(i.ref));
-
- c_foreach (i, cset_str, fourth)
- cset_str_emplace(&fifth, cstr_str(i.ref));
- }
- printf("fifth contains:\n\n");
- c_foreach (i, cset_str, fifth)
- printf("%s\n", cstr_str(i.ref));
- }
+ Strset first, second={0}, third={0}, fourth={0}, fifth;
+
+ first = c_make(Strset, {"red", "green", "blue"});
+ fifth = Strset_clone(second);
+
+ c_forlist (i, const char*, {"orange", "pink", "yellow"})
+ Strset_emplace(&third, *i.ref);
+
+ c_foreach (i, Strset, third)
+ Strset_insert(&fifth, cstr_clone(*i.ref));
+
+ Strset_emplace(&fourth, "potatoes");
+ Strset_emplace(&fourth, "milk");
+ Strset_emplace(&fourth, "flour");
+
+ c_foreach (i, Strset, fourth)
+ Strset_emplace(&fifth, cstr_str(i.ref));
+
+ printf("fifth contains:\n\n");
+ c_foreach (i, Strset, fifth)
+ printf("%s\n", cstr_str(i.ref));
+
+ c_drop(Strset, &first, &second, &third, &fourth, &fifth);
}
```
Output:
diff --git a/docs/csmap_api.md b/docs/csmap_api.md
index 8e5780e3..93faa4f9 100644
--- a/docs/csmap_api.md
+++ b/docs/csmap_api.md
@@ -33,7 +33,6 @@ See the c++ class [std::map](https://en.cppreference.com/w/cpp/container/map) fo
#define i_valto // convertion func i_val* => i_valraw
#define i_tag // alternative typename: csmap_{i_tag}. i_tag defaults to i_val
-#define i_cmp_functor // advanced, see examples/functor.c for similar usage.
#define i_ssize // internal size rep. defaults to int32_t
#include <stc/csmap.h>
```
@@ -92,12 +91,12 @@ csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval);
| Type name | Type definition | Used to represent... |
|:--------------------|:--------------------------------------------------|:-----------------------------|
| `csmap_X` | `struct { ... }` | The csmap type |
-| `csmap_X_rawkey` | `i_keyraw` | The raw key type |
-| `csmap_X_rawmapped` | `i_valraw` | The raw mapped type |
-| `csmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw+i_valraw type |
| `csmap_X_key` | `i_key` | The key type |
| `csmap_X_mapped` | `i_val` | The mapped type |
-| `csmap_X_value` | `struct { const i_key first; i_val second; }` | The value: key is immutable |
+| `csmap_X_value` | `struct { i_key first; i_val second; }` | The value: key is immutable |
+| `csmap_X_keyraw` | `i_keyraw` | The raw key type |
+| `csmap_X_rmapped` | `i_valraw` | The raw mapped type |
+| `csmap_X_raw` | `struct { i_keyraw first; i_valraw second; }` | i_keyraw+i_valraw type |
| `csmap_X_result` | `struct { csmap_X_value *ref; bool inserted; }` | Result of insert/put/emplace |
| `csmap_X_iter` | `struct { csmap_X_value *ref; ... }` | Iterator type |
@@ -112,27 +111,26 @@ csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval);
int main()
{
// Create a sorted map of three strings (maps to string)
- c_auto (csmap_str, colors) // RAII
- {
- colors = c_make(csmap_str, {
- {"RED", "#FF0000"},
- {"GREEN", "#00FF00"},
- {"BLUE", "#0000FF"}
- });
-
- // Iterate and print keys and values of sorted map
- c_foreach (i, csmap_str, colors) {
- printf("Key:[%s] Value:[%s]\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second));
- }
-
- // Add two new entries to the sorted map
- csmap_str_emplace(&colors, "BLACK", "#000000");
- csmap_str_emplace(&colors, "WHITE", "#FFFFFF");
-
- // Output values by key
- printf("The HEX of color RED is:[%s]\n", cstr_str(csmap_str_at(&colors, "RED")));
- printf("The HEX of color BLACK is:[%s]\n", cstr_str(csmap_str_at(&colors, "BLACK")));
+ csmap_str colors = c_make(csmap_str, {
+ {"RED", "#FF0000"},
+ {"GREEN", "#00FF00"},
+ {"BLUE", "#0000FF"}
+ });
+
+ // Iterate and print keys and values of sorted map
+ c_foreach (i, csmap_str, colors) {
+ printf("Key:[%s] Value:[%s]\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second));
}
+
+ // Add two new entries to the sorted map
+ csmap_str_emplace(&colors, "BLACK", "#000000");
+ csmap_str_emplace(&colors, "WHITE", "#FFFFFF");
+
+ // Output values by key
+ printf("The HEX of color RED is:[%s]\n", cstr_str(csmap_str_at(&colors, "RED")));
+ printf("The HEX of color BLACK is:[%s]\n", cstr_str(csmap_str_at(&colors, "BLACK")));
+
+ csmap_str_drop(&colors);
}
```
Output:
@@ -144,37 +142,71 @@ The HEX of color RED is:[#FF0000]
The HEX of color BLACK is:[#000000]
```
+
### Example 2
+Translate a
+[C++ example using *insert* and *emplace*](https://en.cppreference.com/w/cpp/container/map/try_emplace)
+ to STC:
+
+[ [Run this code](https://godbolt.org/z/9d1PP77Pa) ]
+```c
+#include <stc/cstr.h>
+#define i_type strmap
+#define i_key_str
+#define i_val_str
+#include <stc/csmap.h>
+
+static void print_node(const strmap_value* node) {
+ printf("[%s] = %s\n", cstr_str(&node->first), cstr_str(&node->second));
+}
+
+static void print_result(strmap_result result) {
+ printf("%s", result.inserted ? "inserted: " : "ignored: ");
+ print_node(result.ref);
+}
+
+int main()
+{
+ strmap m = {0};
+
+ print_result( strmap_emplace(&m, "a", "a") );
+ print_result( strmap_emplace(&m, "b", "abcd") );
+ print_result( strmap_insert(&m, cstr_from("c"), cstr_with_size(10, 'c') ) );
+ print_result( strmap_emplace(&m, "c", "Won't be inserted") );
+
+ c_foreach (p, strmap, m) { print_node(p.ref); }
+ strmap_drop(&m);
+}
+```
+
+### Example 3
This example uses a csmap with cstr as mapped value.
```c
#include <stc/cstr.h>
+#define i_type IDSMap
#define i_key int
#define i_val_str
-#define i_tag id
#include <stc/csmap.h>
int main()
{
uint32_t col = 0xcc7744ff;
- csmap_id idnames = csmap_id_init();
- c_defer (csmap_id_drop(&idnames))
- {
- c_forlist (i, csmap_id_raw, { {100, "Red"}, {110, "Blue"} })
- csmap_id_emplace(&idnames, c_PAIR(i.ref));
+ IDSMap idnames = c_make(IDSMap, { {100, "Red"}, {110, "Blue"} });
- // put replaces existing mapped value:
- csmap_id_emplace_or_assign(&idnames, 110, "White");
+ // Assign/overwrite an existing mapped value with a const char*
+ IDSMap_emplace_or_assign(&idnames, 110, "White");
- // put a constructed mapped value into map:
- csmap_id_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
+ // Insert (or assign) a new cstr
+ IDSMap_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
- // emplace adds only when key does not exist:
- csmap_id_emplace(&idnames, 100, "Green");
+ // emplace() adds only when key does not already exist:
+ IDSMap_emplace(&idnames, 100, "Green"); // ignored
- c_foreach (i, csmap_id, idnames)
- printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
- }
+ c_foreach (i, IDSMap, idnames)
+ printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
+
+ IDSMap_drop(&idnames);
}
```
Output:
@@ -184,7 +216,7 @@ Output:
120: #cc7744ff
```
-### Example 3
+### Example 4
Demonstrate csmap with plain-old-data key type Vec3i and int as mapped type: csmap<Vec3i, int>.
```c
typedef struct { int x, y, z; } Vec3i;
@@ -205,16 +237,17 @@ static int Vec3i_cmp(const Vec3i* a, const Vec3i* b) {
int main()
{
- c_auto (csmap_vi, vecs)
- {
- csmap_vi_insert(&vecs, (Vec3i){100, 0, 0}, 1);
- csmap_vi_insert(&vecs, (Vec3i){0, 100, 0}, 2);
- csmap_vi_insert(&vecs, (Vec3i){0, 0, 100}, 3);
- csmap_vi_insert(&vecs, (Vec3i){100, 100, 100}, 4);
-
- c_foreach (i, csmap_vi, vecs)
- printf("{ %3d, %3d, %3d }: %d\n", i.ref->first.x, i.ref->first.y, i.ref->first.z, i.ref->second);
- }
+ csmap_vi vmap = {0};
+
+ csmap_vi_insert(&vmap, (Vec3i){100, 0, 0}, 1);
+ csmap_vi_insert(&vmap, (Vec3i){0, 100, 0}, 2);
+ csmap_vi_insert(&vmap, (Vec3i){0, 0, 100}, 3);
+ csmap_vi_insert(&vmap, (Vec3i){100, 100, 100}, 4);
+
+ c_forpair (v, n, csmap_vi, vmap)
+ printf("{ %3d, %3d, %3d }: %d\n", _.v->x, _.v->y, _.v->z, *_.n);
+
+ csmap_vi_drop(&vmap)
}
```
Output:
@@ -224,37 +257,3 @@ Output:
{ 100, 0, 0 }: 1
{ 100, 100, 100 }: 4
```
-
-### Example 4
-Inverse: demonstrate csmap with mapped POD type Vec3i: csmap<int, Vec3i>:
-```c
-typedef struct { int x, y, z; } Vec3i;
-
-#define i_key int
-#define i_val Vec3i
-#define i_tag iv
-#include <stc/csmap.h>
-#include <stdio.h>
-
-int main()
-{
- // equivalent to: c_auto (csmap_iv, vecs)
- c_with (csmap_iv vecs = csmap_iv_init(), csmap_iv_drop(&vecs))
- {
- csmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0});
- csmap_iv_insert(&vecs, 2, (Vec3i){0, 100, 0});
- csmap_iv_insert(&vecs, 3, (Vec3i){0, 0, 100});
- csmap_iv_insert(&vecs, 4, (Vec3i){100, 100, 100});
-
- c_foreach (i, csmap_iv, vecs)
- printf("%d: { %3d, %3d, %3d }\n", i.ref->first, i.ref->second.x, i.ref->second.y, i.ref->second.z);
- }
-}
-```
-Output:
-```c
-1: { 100, 0, 0 }
-2: { 0, 100, 0 }
-3: { 0, 0, 100 }
-4: { 100, 100, 100 }
-```
diff --git a/docs/cspan_api.md b/docs/cspan_api.md
index 1e60a526..10565b0f 100644
--- a/docs/cspan_api.md
+++ b/docs/cspan_api.md
@@ -136,7 +136,7 @@ int main() {
## Example 2
Slicing cspan without and with reducing the rank:
```c
-#include <c11/fmt.h>
+#include <c11/print.h>
#include <stc/cspan.h>
using_cspan3(Span, int); // Shorthand to define Span, Span2, and Span3
@@ -154,7 +154,7 @@ int main()
puts("\niterate span2 flat:");
c_foreach (i, Span2, span2)
- fmt_print(" {}", *i.ref);
+ print(" {}", *i.ref);
puts("");
// slice without reducing rank:
@@ -164,26 +164,23 @@ int main()
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(" |");
+ print(" {:2}", *cspan_at(&ss3, i, j, k));
+ print(" |");
}
- 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("");
+ c_forrange (j, ss2.shape[1])
+ print(" {:2}", *cspan_at(&ss2, i, j));
+ print(" |");
}
puts("\niterate ss2 flat:");
c_foreach (i, Span2, ss2)
- fmt_print(" {:2}", *i.ref);
+ print(" {:2}", *i.ref);
puts("");
}
```
diff --git a/docs/csset_api.md b/docs/csset_api.md
index 80ee1844..e83ab857 100644
--- a/docs/csset_api.md
+++ b/docs/csset_api.md
@@ -18,7 +18,6 @@ See the c++ class [std::set](https://en.cppreference.com/w/cpp/container/set) fo
#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy
#define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy
-#define i_cmp_functor // advanced, see examples/functor.c for similar usage.
#define i_tag // alternative typename: csset_{i_tag}. i_tag defaults to i_val
#define i_ssize // defaults to int32_t
#include <stc/csset.h>
@@ -69,10 +68,10 @@ csset_X_value csset_X_value_clone(csset_X_value val);
| Type name | Type definition | Used to represent... |
|:-------------------|:--------------------------------------------------|:----------------------------|
| `csset_X` | `struct { ... }` | The csset type |
-| `csset_X_rawkey` | `i_keyraw` | The raw key type |
-| `csset_X_raw` | `i_keyraw` | The raw key type |
| `csset_X_key` | `i_key` | The key type |
-| `csset_X_value` | `i_key ` | The value: key is immutable |
+| `csset_X_value` | `i_key` | The key type (alias) |
+| `csset_X_keyraw` | `i_keyraw` | The raw key type |
+| `csset_X_raw` | `i_keyraw` | The raw key type (alias) |
| `csset_X_result` | `struct { csset_X_value* ref; bool inserted; }` | Result of insert/emplace |
| `csset_X_iter` | `struct { csset_X_value *ref; ... }` | Iterator type |
@@ -80,33 +79,38 @@ csset_X_value csset_X_value_clone(csset_X_value val);
```c
#include <stc/cstr.h>
+#define i_type SSet
#define i_key_str
#include <stc/csset.h>
int main ()
{
- c_auto (csset_str, first, second, third)
- c_auto (csset_str, fourth, fifth)
- {
- second = c_make(csset_str, {"red", "green", "blue"});
-
- c_forlist (i, const char*, {"orange", "pink", "yellow"})
- csset_str_emplace(&third, *i.ref);
-
- csset_str_emplace(&fourth, "potatoes");
- csset_str_emplace(&fourth, "milk");
- csset_str_emplace(&fourth, "flour");
-
- fifth = csset_str_clone(second);
- c_foreach (i, csset_str, third)
- csset_str_emplace(&fifth, cstr_str(i.ref));
- c_foreach (i, csset_str, fourth)
- csset_str_emplace(&fifth, cstr_str(i.ref));
-
- printf("fifth contains:\n\n");
- c_foreach (i, csset_str, fifth)
- printf("%s\n", cstr_str(i.ref));
- }
+ SSet second={0}, third={0}, fourth={0}, fifth={0};
+
+ second = c_make(SSet, {"red", "green", "blue"});
+
+ c_forlist (i, const char*, {"orange", "pink", "yellow"})
+ SSet_emplace(&third, *i.ref);
+
+ SSet_emplace(&fourth, "potatoes");
+ SSet_emplace(&fourth, "milk");
+ SSet_emplace(&fourth, "flour");
+
+ // Copy all to fifth:
+
+ fifth = SSet_clone(second);
+
+ c_foreach (i, SSet, third)
+ SSet_emplace(&fifth, cstr_str(i.ref));
+
+ c_foreach (i, SSet, fourth)
+ SSet_emplace(&fifth, cstr_str(i.ref));
+
+ printf("fifth contains:\n\n");
+ c_foreach (i, SSet, fifth)
+ printf("%s\n", cstr_str(i.ref));
+
+ c_drop(SSet, &second, &third, &fourth, &fifth);
}
```
Output:
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 64099675..64ad002c 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -160,7 +160,12 @@ char* cstrnstrn(const char* str, const char* search, intptr_t slen, intpt
#include <stc/cstr.h>
int main() {
- c_auto (cstr, s0, s1, full_path) {
+ cstr s0, s1, full_path;
+ c_defer(
+ cstr_drop(&s0),
+ cstr_drop(&s1),
+ cstr_drop(&full_path)
+ ){
s0 = cstr_lit("Initialization without using strlen().");
printf("%s\nLength: %" c_ZI "\n\n", cstr_str(&s0), cstr_size(&s0));
diff --git a/docs/csview_api.md b/docs/csview_api.md
index 33e61f0e..ec3bf121 100644
--- a/docs/csview_api.md
+++ b/docs/csview_api.md
@@ -151,14 +151,15 @@ red Apples
int main()
{
- c_auto (cstr, s1) {
- s1 = cstr_lit("hell😀 w😀rld");
- cstr_u8_replace_at(&s1, cstr_find(&s1, "😀rld"), 1, c_sv("ø"));
- printf("%s\n", cstr_str(&s1));
-
- c_foreach (i, cstr, s1)
- printf("%.*s,", c_SV(i.u8.chr));
- }
+ cstr s1 = cstr_lit("hell😀 w😀rld");
+
+ cstr_u8_replace_at(&s1, cstr_find(&s1, "😀rld"), 1, c_sv("ø"));
+ printf("%s\n", cstr_str(&s1));
+
+ c_foreach (i, cstr, s1)
+ printf("%.*s,", c_SV(i.u8.chr));
+
+ cstr_drop(&s1);
}
```
Output:
@@ -178,6 +179,7 @@ void print_split(csview input, const char* sep)
{
c_fortoken_sv (i, input, sep)
printf("[%.*s]\n", c_SV(i.token));
+ puts("");
}
#include <stc/cstr.h>
@@ -197,13 +199,15 @@ cstack_str string_split(csview input, const char* sep)
int main()
{
print_split(c_sv("//This is a//double-slash//separated//string"), "//");
- puts("");
print_split(c_sv("This has no matching separator"), "xx");
+
+ cstack_str s = string_split(c_sv("Split,this,,string,now,"), ",");
+
+ c_foreach (i, cstack_str, s)
+ printf("[%s]\n", cstr_str(i.ref));
puts("");
- c_with (cstack_str s = string_split(c_sv("Split,this,,string,now,"), ","), cstack_str_drop(&s))
- c_foreach (i, cstack_str, s)
- printf("[%s]\n", cstr_str(i.ref));
+ cstack_str_drop(&s);
}
```
Output:
diff --git a/docs/cvec_api.md b/docs/cvec_api.md
index 68e08cb2..5879bc1f 100644
--- a/docs/cvec_api.md
+++ b/docs/cvec_api.md
@@ -119,29 +119,29 @@ cvec_X_value cvec_X_value_clone(cvec_X_value val);
int main()
{
// Create a vector containing integers
- c_auto (cvec_int, vec)
- {
- // Add two integers to vector
- cvec_int_push(&vec, 25);
- cvec_int_push(&vec, 13);
-
- // Append a set of numbers
- c_forlist (i, int, {7, 5, 16, 8})
- cvec_int_push(&vec, *i.ref);
-
- printf("initial:");
- c_foreach (k, cvec_int, vec) {
- printf(" %d", *k.ref);
- }
-
- // Sort the vector
- cvec_int_sort(&vec);
-
- printf("\nsorted:");
- c_foreach (k, cvec_int, vec) {
- printf(" %d", *k.ref);
- }
+ cvec_int vec = {0};
+
+ // Add two integers to vector
+ cvec_int_push(&vec, 25);
+ cvec_int_push(&vec, 13);
+
+ // Append a set of numbers
+ c_forlist (i, int, {7, 5, 16, 8})
+ cvec_int_push(&vec, *i.ref);
+
+ printf("initial:");
+ c_foreach (k, cvec_int, vec) {
+ printf(" %d", *k.ref);
+ }
+
+ // Sort the vector
+ cvec_int_sort(&vec);
+
+ printf("\nsorted:");
+ c_foreach (k, cvec_int, vec) {
+ printf(" %d", *k.ref);
}
+ cvec_int_drop(&vec);
}
```
Output:
@@ -212,7 +212,7 @@ User User_clone(User user) {
#include <stc/cvec.h>
int main(void) {
- UVec vec = UVec_init();
+ UVec vec = {0};
UVec_push(&vec, (User){cstr_lit("mary"), 0});
UVec_push(&vec, (User){cstr_lit("joe"), 1});
UVec_push(&vec, (User){cstr_lit("admin"), 2});
diff --git a/docs/pics/containers.jpg b/docs/pics/containers.jpg
index cc56a141..2eddd82b 100644
--- a/docs/pics/containers.jpg
+++ b/docs/pics/containers.jpg
Binary files differ
diff --git a/include/c11/fmt.h b/include/c11/print.h
index a6f7985c..7c155875 100644
--- a/include/c11/fmt.h
+++ b/include/c11/print.h
@@ -1,7 +1,10 @@
#ifndef FMT_H_INCLUDED
#define FMT_H_INCLUDED
/*
-VER 2.0: NEW API:
+VER 2.1: NEW API:
+void print(fmt, ...);
+void println(fmt, ...);
+void printd(dest, fmt, ...);
void fmt_print(fmt, ...);
void fmt_println(fmt, ...);
@@ -28,7 +31,7 @@ void fmt_destroy(fmt_buffer* buf);
* Static linking by default, shared symbols by defining FMT_HEADER / FMT_IMPLEMENT.
* (c) operamint, 2022, MIT License.
-----------------------------------------------------------------------------------
-#include "c11/fmt.h"
+#include "c11/print.h"
int main() {
const double pi = 3.141592653589793;
@@ -40,21 +43,21 @@ int main() {
unsigned char r = 123, g = 214, b = 90, w = 110;
char buffer[64];
- fmt_print("Color: ({} {} {}), {}\n", r, g, b, flag);
- fmt_println("Wide: {}, {}", wstr, L"wide world");
- fmt_println("{:10} {:10} {:10.2f}", 42ull, 43, pi);
- fmt_println("{:>10} {:>10} {:>10}", z, z, w);
- fmt_printd(stdout, "{:10} {:10} {:10}\n", "Hello", "Mad", "World");
- fmt_printd(stderr, "100%: {:<20} {:.*} {}\n", string, 4, pi, x);
- fmt_printd(buffer, "Precision: {} {:.10} {}", string, pi, x);
- fmt_println("{}", buffer);
- fmt_println("Vector: ({}, {}, {})", 3.2, 3.3, pi);
+ print("Color: ({} {} {}), {}\n", r, g, b, flag);
+ println("Wide: {}, {}", wstr, L"wide world");
+ println("{:10} {:10} {:10.2f}", 42ull, 43, pi);
+ println("{:>10} {:>10} {:>10}", z, z, w);
+ printd(stdout, "{:10} {:10} {:10}\n", "Hello", "Mad", "World");
+ printd(stderr, "100%: {:<20} {:.*} {}\n", string, 4, pi, x);
+ printd(buffer, "Precision: {} {:.10} {}", string, pi, x);
+ println("{}", buffer);
+ println("Vector: ({}, {}, {})", 3.2, 3.3, pi);
fmt_buffer out[1] = {{.stream=1}};
- fmt_printd(out, "{} {}", "Pi is:", pi);
- fmt_print("{}, len={}, cap={}\n", out->data, out->len, out->cap);
- fmt_printd(out, "{} {}", ", Pi squared is:", pi*pi);
- fmt_print("{}, len={}, cap={}\n", out->data, out->len, out->cap);
+ printd(out, "{} {}", "Pi is:", pi);
+ print("{}, len={}, cap={}\n", out->data, out->len, out->cap);
+ printd(out, "{} {}", ", Pi squared is:", pi*pi);
+ print("{}, len={}, cap={}\n", out->data, out->len, out->cap);
fmt_destroy(out);
}
*/
@@ -99,7 +102,7 @@ FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...);
#define FMT_MAX 256
#endif
-#ifdef FMT_SHORTS
+#ifndef FMT_NOSHORTS
#define print(...) fmt_printd(stdout, __VA_ARGS__)
#define println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__)
#define printd fmt_printd
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index 59e4cfca..b0ecd6b7 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -59,20 +59,20 @@ int main(void) {
enum {
cco_state_final = -1,
- cco_state_expired = -2,
+ cco_state_done = -2,
};
-#define cco_alive(ctx) ((ctx)->cco_state > 0)
+#define cco_suspended(ctx) ((ctx)->cco_state > 0)
+#define cco_alive(ctx) ((ctx)->cco_state != cco_state_done)
#define cco_begin(ctx) \
int *_state = &(ctx)->cco_state; \
switch (*_state) { \
- case cco_state_expired: \
case 0:
#define cco_end(retval) \
- *_state = cco_state_expired; break; \
- default: goto _cco_final_; /* avoid unused-warning */ \
+ *_state = cco_state_done; break; \
+ case -99: goto _cco_final_; \
} \
return retval
@@ -83,13 +83,16 @@ enum {
case __LINE__:; \
} while (0)
-#define cco_yield_3(corocall, ctx, retval) \
+#define cco_yield_2(corocall2, ctx2) \
+ cco_yield_3(corocall2, ctx2, )
+
+#define cco_yield_3(corocall2, ctx2, retval) \
do { \
*_state = __LINE__; \
do { \
- corocall; if (cco_alive(ctx)) return retval; \
+ corocall2; if (cco_suspended(ctx2)) return retval; \
case __LINE__:; \
- } while ((ctx)->cco_state >= cco_state_final); \
+ } while (cco_alive(ctx2)); \
} while (0)
#define cco_final \
@@ -105,4 +108,10 @@ enum {
if (*_state > 0) *_state = cco_state_final; \
} while (0)
+#define cco_reset(ctx) \
+ do { \
+ int* _state = &(ctx)->cco_state; \
+ if (*_state == cco_state_done) *_state = 0; \
+ } while (0)
+
#endif
diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h
index 4fc957b6..ca06c258 100644
--- a/include/stc/algo/crange.h
+++ b/include/stc/algo/crange.h
@@ -34,9 +34,9 @@ int main()
// use a temporary crange object.
int a = 100, b = INT32_MAX;
- c_forfilter (i, crange, crange_obj(a, b, 8)
- , i.index > 10
- && c_flt_take(i, 3))
+ c_forfilter (i, crange, crange_obj(a, b, 8),
+ c_flt_skip(i, 10) &&
+ c_flt_take(i, 3))
printf(" %lld", *i.ref);
puts("");
}
diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h
index c452064f..53fe9fcc 100644
--- a/include/stc/algo/csort.h
+++ b/include/stc/algo/csort.h
@@ -20,8 +20,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include <stc/ccommon.h>
-#include <stc/priv/template.h>
+#include "../ccommon.h"
+#include "../priv/template.h"
/* Generic Quicksort in C, performs as fast as c++ std::sort().
template params:
@@ -86,4 +86,4 @@ 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[], intptr_t n)
{ c_PASTE(cqsort_, i_tag)(arr, 0, n - 1); }
-#include <stc/priv/template.h>
+#include "../priv/template2.h"
diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h
index 48a36d9b..e133577c 100644
--- a/include/stc/algo/filter.h
+++ b/include/stc/algo/filter.h
@@ -24,24 +24,24 @@
#include <stdio.h>
#define i_val int
#include <stc/cstack.h>
-#include <stc/algo/filter.h>
+#include <stc/calgo.h>
int main()
{
- c_with (cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7, 8, 9}),
- cstack_int_drop(&stk))
- {
- c_foreach (i, cstack_int, stk)
- printf(" %d", *i.ref);
- puts("");
-
- c_forfilter (i, cstack_int, stk
- , c_flt_skipwhile(i, *i.ref < 3)
- && (*i.ref & 1) == 0 // even only
- && c_flt_take(i, 2)) // break after 2
- printf(" %d", *i.ref);
- puts("");
- }
+ cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ c_foreach (i, cstack_int, stk)
+ printf(" %d", *i.ref);
+ puts("");
+
+ c_forfilter (i, cstack_int, stk,
+ c_flt_skipwhile(i, *i.ref < 3) &&
+ (*i.ref & 1) == 0 && // even only
+ c_flt_take(i, 2)) // break after 2
+ printf(" %d", *i.ref);
+ puts("");
+
+ cstack_int_drop(&stk);
}
*/
#ifndef STC_FILTER_H_INCLUDED
@@ -49,24 +49,71 @@ int main()
#include <stc/ccommon.h>
-#ifndef c_NFILTERS
-#define c_NFILTERS 32
-#endif
+// c_forfilter:
-#define c_flt_take(i, n) _flt_take(&(i).b, n)
-#define c_flt_skip(i, n) (c_flt_count(i) > (n))
+#define c_flt_skip(i, n) (c_flt_counter(i) > (n))
#define c_flt_skipwhile(i, pred) ((i).b.s2[(i).b.s2top++] |= !(pred))
+#define c_flt_take(i, n) _flt_take(&(i).b, n)
#define c_flt_takewhile(i, pred) _flt_takewhile(&(i).b, pred)
-#define c_flt_last(i) (i).b.s1[(i).b.s1top-1]
-#define c_flt_count(i) ++(i).b.s1[(i).b.s1top++]
+#define c_flt_counter(i) ++(i).b.s1[(i).b.s1top++]
+#define c_flt_getcount(i) (i).b.s1[(i).b.s1top - 1]
#define c_forfilter(i, C, cnt, filter) \
+ c_forfilter_it(i, C, C##_begin(&cnt), filter)
+
+#define c_forfilter_it(i, C, start, filter) \
for (struct {struct _flt_base b; C##_iter it; C##_value *ref;} \
- i = {.it=C##_begin(&cnt), .ref=i.it.ref} ; !i.b.done & (i.ref != NULL) ; \
+ i = {.it=start, .ref=i.it.ref} ; !i.b.done & (i.it.ref != NULL) ; \
C##_next(&i.it), i.ref = i.it.ref, i.b.s1top=0, i.b.s2top=0) \
if (!(filter)) ; else
-// -----
+
+// c_find_if, c_erase_if, c_eraseremove_if:
+
+#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_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)
+
+
+// Use with: clist, cmap, cset, csmap, csset:
+#define c_erase_if(it, C, cnt, pred) do { \
+ C* _cnt = &cnt; \
+ intptr_t _index = 0; \
+ for (C##_iter it = C##_begin(_cnt); it.ref; ++_index) { \
+ if (pred) it = C##_erase_at(_cnt, it); \
+ else C##_next(&it); \
+ } \
+} while (0)
+
+
+// Use with: cstack, cvec, cdeq, cqueue:
+#define c_eraseremove_if(it, C, cnt, pred) do { \
+ C* _cnt = &cnt; \
+ intptr_t _n = 0, _index = 0; \
+ C##_iter it = C##_begin(_cnt), _i; \
+ while (it.ref && !(pred)) \
+ C##_next(&it), ++_index; \
+ for (_i = it; it.ref; C##_next(&it), ++_index) \
+ if (pred) C##_value_drop(it.ref), ++_n; \
+ else *_i.ref = *it.ref, C##_next(&_i); \
+ _cnt->_len -= _n; \
+} while (0)
+
+// ------------------------ private -------------------------
+#ifndef c_NFILTERS
+#define c_NFILTERS 32
+#endif
struct _flt_base {
uint32_t s1[c_NFILTERS];
diff --git a/include/stc/calgo.h b/include/stc/calgo.h
new file mode 100644
index 00000000..21e73faf
--- /dev/null
+++ b/include/stc/calgo.h
@@ -0,0 +1,8 @@
+#ifndef STC_CALGO_INCLUDED
+#define STC_CALGO_INCLUDED
+
+#include "algo/crange.h"
+#include "algo/filter.h"
+#include "algo/coroutine.h"
+
+#endif
diff --git a/include/stc/carc.h b/include/stc/carc.h
index 02bbaf52..8ef80b12 100644
--- a/include/stc/carc.h
+++ b/include/stc/carc.h
@@ -90,7 +90,7 @@ typedef i_keyraw _cx_raw;
#define _i_atomic_inc(v) (void)(++*(v))
#define _i_atomic_dec_and_test(v) !(--*(v))
#endif
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_carc_types, _cx_self, i_key);
#endif
struct _cx_memb(_rep_) { catomic_long counter; i_key value; };
@@ -177,8 +177,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) {
STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry); }
-STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_cmp((&rx), (&ry));
}
#endif
@@ -187,27 +187,27 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_eq(rx, ry); }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_eq((&rx), (&ry));
}
#elif !defined i_no_cmp
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry) == 0; }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y)
- { return _cx_memb(_cmp)(x, y) == 0; }
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other)
+ { return _cx_memb(_cmp)(self, other) == 0; }
#endif
#ifndef i_no_hash
STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx)
{ return i_hash(rx); }
-STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x)
- { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); }
+STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self)
+ { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); }
#endif
#undef _i_eq
#undef _i_atomic_inc
#undef _i_atomic_dec_and_test
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/cbits.h b/include/stc/cbits.h
index fa0da665..826df847 100644
--- a/include/stc/cbits.h
+++ b/include/stc/cbits.h
@@ -27,26 +27,26 @@ Similar to boost::dynamic_bitset / std::bitset
#include "cbits.h"
int main() {
- c_with (cbits bset = cbits_with_size(23, true), cbits_drop(&bset))
- {
- cbits_reset(&bset, 9);
- cbits_resize(&bset, 43, false);
-
- printf("%4zu: ", cbits_size(&bset));
- c_forrange (i, cbits_size(&bset))
- printf("%d", cbits_at(&bset, i));
- puts("");
- cbits_set(&bset, 28);
- cbits_resize(&bset, 77, true);
- cbits_resize(&bset, 93, false);
- cbits_resize(&bset, 102, true);
- cbits_set_value(&bset, 99, false);
-
- printf("%4zu: ", cbits_size(&bset));
- c_forrange (i, cbits_size(&bset))
- printf("%d", cbits_at(&bset, i));
- puts("");
- }
+ cbits bset = cbits_with_size(23, true);
+ cbits_reset(&bset, 9);
+ cbits_resize(&bset, 43, false);
+
+ printf("%4zu: ", cbits_size(&bset));
+ c_forrange (i, cbits_size(&bset))
+ printf("%d", cbits_at(&bset, i));
+ puts("");
+ cbits_set(&bset, 28);
+ cbits_resize(&bset, 77, true);
+ cbits_resize(&bset, 93, false);
+ cbits_resize(&bset, 102, true);
+ cbits_set_value(&bset, 99, false);
+
+ printf("%4zu: ", cbits_size(&bset));
+ c_forrange (i, cbits_size(&bset))
+ printf("%d", cbits_at(&bset, i));
+ puts("");
+
+ cbits_drop(&bset);
}
*/
#ifndef CBITS_H_INCLUDED
diff --git a/include/stc/cbox.h b/include/stc/cbox.h
index 641fcbfc..ca88fc66 100644
--- a/include/stc/cbox.h
+++ b/include/stc/cbox.h
@@ -76,7 +76,7 @@ int main() {
#include "priv/template.h"
typedef i_keyraw _cx_raw;
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cbox_types, _cx_self, i_key);
#endif
@@ -163,8 +163,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* moved) {
STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry); }
-STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_cmp((&rx), (&ry));
}
#endif
@@ -173,25 +173,25 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) {
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_eq(rx, ry); }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get);
return i_eq((&rx), (&ry));
}
#elif !defined i_no_cmp
STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry) == 0; }
-STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y)
- { return _cx_memb(_cmp)(x, y) == 0; }
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other)
+ { return _cx_memb(_cmp)(self, other) == 0; }
#endif
#ifndef i_no_hash
STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx)
{ return i_hash(rx); }
-STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x)
- { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); }
+STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self)
+ { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); }
#endif
#undef _i_eq
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index d163b4ab..d5508807 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -30,6 +30,7 @@
#include <string.h>
#include <assert.h>
#include "priv/altnames.h"
+#include "priv/raii.h"
#define c_NPOS INTPTR_MAX
#define c_ZI PRIiPTR
@@ -81,7 +82,8 @@
#define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); free(_tp); } while (0)
#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_container_of(p, C, m) ((C*)((char*)(1 ? (p) : &((C*)0)->m) - offsetof(C, m)))
+#define c_const_cast(T, p) ((T)(p) + 0*sizeof((T)0 == (p)))
#define c_swap(T, xp, yp) do { T *_xp = xp, *_yp = yp, \
_tv = *_xp; *_xp = *_yp; *_yp = _tv; } while (0)
#define c_sizeof (intptr_t)sizeof
@@ -120,10 +122,13 @@
#define c_make(C, ...) \
C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw))
-#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a])
#define c_litstrlen(literal) (c_sizeof("" literal) - 1)
+#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a])
+// Non-owning c-string
typedef const char* crawstr;
+#define crawstr_clone(s) (s)
+#define crawstr_drop(p) ((void)p)
#define crawstr_cmp(xp, yp) strcmp(*(xp), *(yp))
#define crawstr_hash(p) cstrhash(*(p))
@@ -132,24 +137,23 @@ typedef const char* crawstr;
#define c_sv_2(str, n) (c_LITERAL(csview){str, n})
#define c_SV(sv) (int)(sv).size, (sv).str // print csview: use format "%.*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, intptr_t len) {
- const uint8_t *x = (const uint8_t*) key;
- uint64_t u8, h = 1; intptr_t n = len >> 3;
- uint32_t u4;
+ uint32_t u4; uint64_t u8;
+ switch (len) {
+ case 8: memcpy(&u8, key, 8); return u8*0xc6a4a7935bd1e99d;
+ case 4: memcpy(&u4, key, 4); return u4*0xc6a4a7935bd1e99d;
+ case 0: return 1;
+ }
+ const uint8_t *x = (const uint8_t*)key;
+ uint64_t h = *x, n = (uint64_t)len >> 3;
+ len &= 7;
while (n--) {
memcpy(&u8, x, 8), x += 8;
- h += (c_ROTL(u8, 26) ^ u8)*0xc6a4a7935bd1e99d;
+ h += u8*0xc6a4a7935bd1e99d;
}
- switch (len &= 7) {
- case 0: return h;
- case 4: memcpy(&u4, x, 4);
- return h + u4*0xc6a4a7935bd1e99d;
- }
- h += *x++;
- while (--len) h = (h << 10) - h + *x++;
+ while (len--) h = (h << 10) - h - *x++;
return c_ROTL(h, 26) ^ h;
}
@@ -178,10 +182,9 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
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; 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)
+#define c_foreach_rv(it, C, cnt) \
+ for (C##_iter it = {.ref=C##_end(&cnt).end - 1, .end=(cnt).data - 1} \
+ ; it.ref != it.end; --it.ref)
#define c_forpair(key, val, C, cnt) /* structured binding */ \
for (struct {C##_iter it; const C##_key* key; C##_mapped* val;} _ = {.it=C##_begin(&cnt)} \
@@ -196,10 +199,11 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
#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=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \
+ for (struct {T* ref; int size, index;} \
+ it = {.ref=(T[])__VA_ARGS__, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \
; it.index < it.size; ++it.ref, ++it.index)
#else
#include <initializer_list>
@@ -208,63 +212,9 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
it = {._il=__VA_ARGS__, .data=it._il.begin(), .ref=it.data, .size=it._il.size()} \
; it.index < it.size; ++it.ref, ++it.index)
#endif
-#define c_with(...) c_MACRO_OVERLOAD(c_with, __VA_ARGS__)
-#define c_with_2(declvar, drop) for (declvar, *_i, **_ip = &_i; _ip; _ip = 0, drop)
-#define c_with_3(declvar, pred, drop) for (declvar, *_i, **_ip = &_i; _ip && (pred); _ip = 0, drop)
-#define c_scope(...) c_MACRO_OVERLOAD(c_scope, __VA_ARGS__)
-#define c_scope_2(init, drop) for (int _i = (init, 1); _i; _i = 0, drop)
-#define c_scope_3(init, pred, drop) for (int _i = (init, 1); _i && (pred); _i = 0, drop)
-#define c_defer(...) for (int _i = 1; _i; _i = 0, __VA_ARGS__)
-
-#define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__)
-#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_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_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)))
-
-/* 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_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)
-
-// use with: clist, cmap, cset, csmap, csset, cstr:
-#define c_erase_if(it, C, cnt, pred) do { \
- C* _cnt = &cnt; \
- for (C##_iter it = C##_begin(_cnt); it.ref;) { \
- if (pred) it = C##_erase_at(_cnt, it); \
- else C##_next(&it); \
- } \
-} while (0)
-// use with: cstack, cvec, cdeq, cqueue:
-#define c_eraseremove_if(it, C, cnt, pred) do { \
- C* _cnt = &cnt; \
- intptr_t _n = 0; \
- C##_iter _first = C##_begin(_cnt), it = _first; \
- for (; it.ref; C##_next(&it)) \
- if (pred) ++_n; \
- else C##_value_drop(_first.ref), *_first.ref = *it.ref, C##_next(&_first); \
- _cnt->_len -= _n; \
-} while (0)
+#define c_drop(C, ...) \
+ do { c_forlist (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0)
#endif // CCOMMON_H_INCLUDED
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index c4f84a1b..ff6e744f 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -36,7 +36,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
@@ -196,11 +196,10 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw)
{ return (_cx_value *) _cx_memb(_get)(self, raw); }
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- if (x->_len != y->_len) return false;
- _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y);
- for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) {
- const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (self->_len != other->_len) return false;
+ for (intptr_t i = 0; i < self->_len; ++i) {
+ const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i);
if (!(i_eq((&_rx), (&_ry)))) return false;
}
return true;
@@ -443,5 +442,5 @@ _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
#endif // !c_no_cmp
#endif // !_i_queue
#endif // IMPLEMENTATION
-#include "priv/template.h"
#define CDEQ_H_INCLUDED
+#include "priv/template2.h"
diff --git a/include/stc/clist.h b/include/stc/clist.h
index f8a21f40..f7fb4152 100644
--- a/include/stc/clist.h
+++ b/include/stc/clist.h
@@ -26,7 +26,7 @@
it also support both push_back() and push_front(), unlike std::forward_list:
#include <stdio.h>
- #include <stc/crandom.h>
+ #include <stc/crand.h>
#define i_key int64_t
#define i_tag ix
@@ -38,12 +38,12 @@
{
int n;
for (int i = 0; i < 1000000; ++i) // one million
- clist_ix_push_back(&list, crandom() >> 32);
+ clist_ix_push_back(&list, crand() >> 32);
n = 0;
c_foreach (i, clist_ix, list)
if (++n % 10000 == 0) printf("%8d: %10zu\n", n, *i.ref);
// Sort them...
- clist_ix_sort(&list); // mergesort O(n*log n)
+ clist_ix_sort(&list); // qsort O(n*log n)
n = 0;
puts("sorted");
c_foreach (i, clist_ix, list)
@@ -66,11 +66,6 @@
#define _clist_tonode(vp) c_container_of(vp, _cx_node, value)
-_c_clist_types(clist_VOID, int);
-_c_clist_complete_types(clist_VOID, dummy);
-typedef int clist_VOID_comp(const clist_VOID_node*, const clist_VOID_node*);
-extern clist_VOID_node* _clist_mergesort(clist_VOID_node*, clist_VOID_comp*);
-
#define _c_clist_insert_entry_after(ref, val) \
_cx_node *entry = (_cx_node *)i_malloc(c_sizeof *entry); entry->value = val; \
_c_clist_insert_after_node(ref, entry)
@@ -87,7 +82,7 @@ extern clist_VOID_node* _clist_mergesort(clist_VOID_node*, clist_VOID_comp*);
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_clist_types, _cx_self, i_key);
#endif
_cx_deftypes(_c_clist_complete_types, _cx_self, dummy);
@@ -104,7 +99,10 @@ STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw v
STC_API intptr_t _cx_memb(_remove)(_cx_self* self, _cx_raw val);
#endif
#ifndef i_no_cmp
-STC_API int _cx_memb(_sort_cmp_)(const _cx_node* x, const _cx_node* y);
+STC_API bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, const _cx_value*));
+STC_API int _cx_memb(_sort_cmp_)(const _cx_value*, const _cx_value*);
+STC_INLINE bool _cx_memb(_sort)(_cx_self* self)
+ { return _cx_memb(_sort_with)(self, _cx_memb(_sort_cmp_)); }
#endif
STC_API void _cx_memb(_reverse)(_cx_self* self);
STC_API _cx_iter _cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other);
@@ -206,9 +204,8 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw val) {
return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val).ref;
}
-STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y);
+STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ _cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other);
for (; i.ref && j.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) {
const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
if (!(i_eq((&_rx), (&_ry)))) return false;
@@ -216,68 +213,6 @@ _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
return !(i.ref || j.ref);
}
#endif
-#ifndef i_no_cmp
-
-STC_INLINE void
-_cx_memb(_sort)(_cx_self* self) {
- if (self->last)
- self->last = (_cx_node *)_clist_mergesort((clist_VOID_node *)self->last->next,
- (clist_VOID_comp *)_cx_memb(_sort_cmp_));
-}
-STC_INLINE void
-_cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_node*, const _cx_node*)) {
- if (self->last)
- self->last = (_cx_node *)_clist_mergesort((clist_VOID_node *)self->last->next,
- (clist_VOID_comp *)cmp);
-}
-#endif
-
-#if defined(i_extern)
-/* Implement non-templated extern functions */
-// Singly linked list Mergesort implementation by Simon Tatham. O(n*log n).
-// https://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
-clist_VOID_node *
-_clist_mergesort(clist_VOID_node *list, clist_VOID_comp* cmp) {
- clist_VOID_node *p, *q, *e, *tail, *oldhead;
- int insize = 1, nmerges, psize, qsize, i;
-
- while (1) {
- p = oldhead = list;
- list = tail = NULL;
- nmerges = 0;
-
- while (p) {
- ++nmerges;
- q = p, psize = 0;
- for (i = 0; i < insize; ++i) {
- ++psize;
- q = (q->next == oldhead ? NULL : q->next);
- if (!q) break;
- }
- qsize = insize;
-
- while (psize || (qsize && q)) {
- if (psize && (!(qsize && q) || cmp(p, q) <= 0)) {
- e = p, p = p->next, --psize;
- if (p == oldhead) p = NULL;
- } else {
- e = q, q = q->next, --qsize;
- if (q == oldhead) q = NULL;
- }
- if (tail) tail->next = e; else list = e;
- tail = e;
- }
- p = q;
- }
- tail->next = list;
-
- if (nmerges <= 1)
- return tail;
-
- insize *= 2;
- }
-}
-#endif // i_extern
// -------------------------- IMPLEMENTATION -------------------------
#if defined(i_implement)
@@ -443,15 +378,30 @@ _cx_memb(_remove)(_cx_self* self, _cx_raw val) {
return n;
}
#endif
-#ifndef i_no_cmp
-STC_DEF int
-_cx_memb(_sort_cmp_)(const _cx_node* x, const _cx_node* y) {
- const _cx_raw a = i_keyto((&x->value));
- const _cx_raw b = i_keyto((&y->value));
+#ifndef i_no_cmp
+STC_DEF int _cx_memb(_sort_cmp_)(const _cx_value* x, const _cx_value* y) {
+ const _cx_raw a = i_keyto(x), b = i_keyto(y);
return i_cmp((&a), (&b));
}
+
+STC_DEF bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, const _cx_value*)) {
+ size_t len = 0, cap = 0;
+ _cx_value *a = NULL, *p = NULL;
+ _cx_iter i;
+ for (i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i)) {
+ if (len == cap) {
+ if ((p = (_cx_value *)i_realloc(a, (cap += cap/2 + 4)*sizeof *a))) a = p;
+ else { i_free(a); return false; }
+ }
+ a[len++] = *i.ref;
+ }
+ qsort(a, len, sizeof *a, (int(*)(const void*, const void*))cmp);
+ for (i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i), ++p)
+ *i.ref = *p;
+ i_free(a); return true;
+}
#endif // !c_no_cmp
#endif // i_implement
#define CLIST_H_INCLUDED
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/cmap.h b/include/stc/cmap.h
index bc3b5546..14782b71 100644
--- a/include/stc/cmap.h
+++ b/include/stc/cmap.h
@@ -31,20 +31,20 @@
#include <stc/cmap.h>
int main(void) {
- c_with (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m))
- {
- cmap_ichar_emplace(&m, 5, 'a');
- cmap_ichar_emplace(&m, 8, 'b');
- cmap_ichar_emplace(&m, 12, 'c');
-
- cmap_ichar_value* v = cmap_ichar_get(&m, 10); // NULL
- char val = *cmap_ichar_at(&m, 5); // 'a'
- cmap_ichar_emplace_or_assign(&m, 5, 'd'); // update
- cmap_ichar_erase(&m, 8);
-
- c_foreach (i, cmap_ichar, m)
- printf("map %d: %c\n", i.ref->first, i.ref->second);
- }
+ cmap_ichar m = {0};
+ cmap_ichar_emplace(&m, 5, 'a');
+ cmap_ichar_emplace(&m, 8, 'b');
+ cmap_ichar_emplace(&m, 12, 'c');
+
+ cmap_ichar_value* v = cmap_ichar_get(&m, 10); // NULL
+ char val = *cmap_ichar_at(&m, 5); // 'a'
+ cmap_ichar_emplace_or_assign(&m, 5, 'd'); // update
+ cmap_ichar_erase(&m, 8);
+
+ c_foreach (i, cmap_ichar, m)
+ printf("map %d: %c\n", i.ref->first, i.ref->second);
+
+ cmap_ichar_drop(&m);
}
*/
#include "ccommon.h"
@@ -82,13 +82,7 @@ typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t;
#define _i_size i_ssize
#endif
#include "priv/template.h"
-#ifndef i_hash_functor
- #define i_hash_functor(self, x) i_hash(x)
-#endif
-#ifndef i_eq_functor
- #define i_eq_functor(self, x, y) i_eq(x, y)
-#endif
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY);
#endif
@@ -97,8 +91,8 @@ _i_MAP_ONLY( struct _cx_value {
_cx_mapped second;
}; )
-typedef i_keyraw _cx_rawkey;
-typedef i_valraw _cx_memb(_rawmapped);
+typedef i_keyraw _cx_keyraw;
+typedef i_valraw _cx_memb(_rmapped);
typedef _i_SET_ONLY( i_keyraw )
_i_MAP_ONLY( struct { i_keyraw first;
i_valraw second; } )
@@ -111,8 +105,8 @@ STC_API _cx_self _cx_memb(_clone)(_cx_self map);
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, _i_size 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 chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr);
+STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey);
STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val);
STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self map = {0}; return map; }
@@ -123,23 +117,23 @@ STC_INLINE _i_size _cx_memb(_size)(const _cx_self* map) { return map->size;
STC_INLINE _i_size _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; }
STC_INLINE _i_size _cx_memb(_capacity)(const _cx_self* map)
{ return (_i_size)((float)map->bucket_count * (i_max_load_factor)); }
-STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_rawkey rkey)
+STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey)
{ return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; }
#ifndef _i_isset
STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped);
#if !defined i_no_emplace
- STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_rawkey rkey, i_valraw rmapped);
+ STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped);
#endif
STC_INLINE const _cx_mapped*
- _cx_memb(_at)(const _cx_self* self, _cx_rawkey rkey) {
+ _cx_memb(_at)(const _cx_self* self, _cx_keyraw rkey) {
chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey);
assert(self->_hashx[b.idx]);
return &self->table[b.idx].second;
}
STC_INLINE _cx_mapped*
- _cx_memb(_at_mut)(_cx_self* self, _cx_rawkey rkey)
+ _cx_memb(_at_mut)(_cx_self* self, _cx_keyraw rkey)
{ return (_cx_mapped*)_cx_memb(_at)(self, rkey); }
#endif // !_i_isset
@@ -161,7 +155,7 @@ _cx_memb(_value_clone)(_cx_value _val) {
#if !defined i_no_emplace
STC_INLINE _cx_result
-_cx_memb(_emplace)(_cx_self* self, _cx_rawkey rkey _i_MAP_ONLY(, i_valraw rmapped)) {
+_cx_memb(_emplace)(_cx_self* self, _cx_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);
@@ -224,7 +218,7 @@ STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) {
if (it._hx)
while (*it._hx == 0)
++it.ref, ++it._hx;
- if (it.ref == it.end) it.ref = NULL;
+ if (it.ref == it._end) it.ref = NULL;
return it;
}
@@ -235,7 +229,7 @@ _cx_memb(_end)(const _cx_self* self)
STC_INLINE void
_cx_memb(_next)(_cx_iter* it) {
while ((++it->ref, *++it->_hx == 0)) ;
- if (it->ref == it->end) it->ref = NULL;
+ if (it->ref == it->_end) it->ref = NULL;
}
STC_INLINE _cx_iter
@@ -245,7 +239,7 @@ _cx_memb(_advance)(_cx_iter it, size_t n) {
}
STC_INLINE _cx_iter
-_cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) {
int64_t idx;
if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx])
return c_LITERAL(_cx_iter){self->table + idx,
@@ -255,7 +249,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) {
+_cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) {
int64_t idx;
if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx])
return self->table + idx;
@@ -263,11 +257,11 @@ _cx_memb(_get)(const _cx_self* self, _cx_rawkey rkey) {
}
STC_INLINE _cx_value*
-_cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey)
+_cx_memb(_get_mut)(_cx_self* self, _cx_keyraw rkey)
{ return (_cx_value*)_cx_memb(_get)(self, rkey); }
STC_INLINE int
-_cx_memb(_erase)(_cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) {
if (self->size == 0)
return 0;
chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey);
@@ -283,11 +277,11 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
}
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* m1, const _cx_self* m2) {
- if (_cx_memb(_size)(m1) != _cx_memb(_size)(m2)) return false;
- for (_cx_iter i = _cx_memb(_begin)(m1); i.ref; _cx_memb(_next)(&i)) {
- const _cx_rawkey _raw = i_keyto(_i_keyref(i.ref));
- if (!_cx_memb(_contains)(m2, _raw)) return false;
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false;
+ for (_cx_iter i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i)) {
+ const _cx_keyraw _raw = i_keyto(_i_keyref(i.ref));
+ if (!_cx_memb(_contains)(other, _raw)) return false;
}
return true;
}
@@ -355,7 +349,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) {
#if !defined i_no_emplace
STC_DEF _cx_result
- _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_rawkey rkey, i_valraw rmapped) {
+ _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped) {
_cx_result _res = _cx_memb(_insert_entry_)(self, rkey);
if (_res.inserted)
_res.ref->first = i_keyfrom(rkey);
@@ -370,15 +364,15 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) {
#endif // !_i_isset
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);
+_cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) {
+ const uint64_t _hash = i_hash(rkeyptr);
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) {
- const _cx_rawkey _raw = i_keyto(_i_keyref(self->table + b.idx));
- if (i_eq_functor(self, (&_raw), rkeyptr))
+ const _cx_keyraw _raw = i_keyto(_i_keyref(self->table + b.idx));
+ if (i_eq((&_raw), rkeyptr))
break;
}
if (++b.idx == _cap)
@@ -388,7 +382,7 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) {
}
STC_DEF _cx_result
-_cx_memb(_insert_entry_)(_cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) {
_cx_result res = {NULL};
if (self->size + 2 > (i_ssize)((float)self->bucket_count * (i_max_load_factor)))
if (!_cx_memb(_reserve)(self, self->size*3/2))
@@ -444,7 +438,7 @@ _cx_memb(_reserve)(_cx_self* self, const _i_size newcap) {
const _cx_value* e = self->table;
const uint8_t* h = self->_hashx;
for (i_ssize i = 0; i < _oldbuckets; ++i, ++e) if (*h++) {
- _cx_rawkey r = i_keyto(_i_keyref(e));
+ _cx_keyraw r = i_keyto(_i_keyref(e));
chash_bucket_t b = _cx_memb(_bucket_)(&m, &r);
m.table[b.idx] = *e;
m._hashx[b.idx] = b.hx;
@@ -468,8 +462,8 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) {
j = 0;
if (! _hashx[j])
break;
- const _cx_rawkey _raw = i_keyto(_i_keyref(_slot + j));
- k = (i_ssize)c_PASTE(fastrange_,_i_expandby)(i_hash_functor(self, (&_raw)), (uint64_t)_cap);
+ const _cx_keyraw _raw = i_keyto(_i_keyref(_slot + j));
+ k = (i_ssize)c_PASTE(fastrange_,_i_expandby)(i_hash((&_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;
}
@@ -479,8 +473,6 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) {
#endif // i_implement
#undef i_max_load_factor
-#undef i_hash_functor
-#undef i_eq_functor
#undef _i_size
#undef _i_isset
#undef _i_ismap
@@ -489,4 +481,4 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) {
#undef _i_MAP_ONLY
#undef _i_SET_ONLY
#define CMAP_H_INCLUDED
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/cpque.h b/include/stc/cpque.h
index 4955f2e0..b95b5020 100644
--- a/include/stc/cpque.h
+++ b/include/stc/cpque.h
@@ -32,10 +32,7 @@
#endif
#include "priv/template.h"
-#ifndef i_less_functor
- #define i_less_functor(self, x, y) i_less(x, y)
-#endif
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cpque_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
@@ -120,8 +117,8 @@ STC_DEF void
_cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) {
_cx_value t, *arr = self->data - 1;
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;
+ c += i_less((&arr[c]), (&arr[c + (c < n)]));
+ if (!(i_less((&arr[r]), (&arr[c])))) return;
t = arr[r], arr[r] = arr[c], arr[r = c] = t;
}
}
@@ -156,12 +153,11 @@ _cx_memb(_push)(_cx_self* self, _cx_value value) {
_cx_memb(_reserve)(self, self->_len*3/2 + 4);
_cx_value *arr = self->data - 1; /* base 1 */
intptr_t c = ++self->_len;
- for (; c > 1 && (i_less_functor(self, (&arr[c/2]), (&value))); c /= 2)
+ for (; c > 1 && (i_less((&arr[c/2]), (&value))); c /= 2)
arr[c] = arr[c/2];
arr[c] = value;
}
#endif
#define CPQUE_H_INCLUDED
-#undef i_less_functor
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h
index 67909f8e..1934305a 100644
--- a/include/stc/cqueue.h
+++ b/include/stc/cqueue.h
@@ -22,7 +22,7 @@
*/
// STC queue
/*
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stdio.h>
#define i_key int
@@ -30,19 +30,19 @@
int main() {
int n = 10000000;
- stc64_t rng = stc64_new(1234);
- stc64_uniform_t dist = stc64_uniform_new(0, n);
+ crand_t rng = crand_init(1234);
+ crand_unif_t dist = crand_unif_init(0, n);
c_auto (cqueue_int, Q)
{
// Push ten million random numbers onto the queue.
for (int i=0; i<n; ++i)
- cqueue_int_push(&Q, stc64_uniform(&rng, &dist));
+ cqueue_int_push(&Q, crand_unif(&rng, &dist));
// Push or pop on the queue ten million times
printf("before: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q));
for (int i=n; i>0; --i) {
- int r = stc64_uniform(&rng, &dist);
+ int r = crand_unif(&rng, &dist);
if (r & 1)
++n, cqueue_int_push(&Q, r);
else
diff --git a/include/stc/crand.h b/include/stc/crand.h
new file mode 100644
index 00000000..a1b7250d
--- /dev/null
+++ b/include/stc/crand.h
@@ -0,0 +1,174 @@
+/* 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.
+ */
+#include "ccommon.h"
+
+#ifndef CRAND_H_INCLUDED
+#define CRAND_H_INCLUDED
+/*
+// crand: Pseudo-random number generator
+#include "stc/crand.h"
+
+int main() {
+ uint64_t seed = 123456789;
+ crand_t rng = crand_init(seed);
+ crand_unif_t dist1 = crand_unif_init(1, 6);
+ crand_norm_t dist3 = crand_norm_init(1.0, 10.0);
+
+ uint64_t i = crand_u64(&rng);
+ int64_t iu = crand_unif(&rng, &dist1);
+ double xn = crand_norm(&rng, &dist3);
+}
+*/
+#include <string.h>
+#include <math.h>
+
+typedef struct crand { uint64_t state[5]; } crand_t;
+typedef struct crand_unif { int64_t lower; uint64_t range, threshold; } crand_unif_t;
+typedef struct crand_norm { double mean, stddev, next; int has_next; } crand_norm_t;
+
+/* PRNG crand_t.
+ * Very fast PRNG suited for parallel usage with Weyl-sequence parameter.
+ * 320-bit state, 256 bit is mutable.
+ * Noticable faster than xoshiro and pcg, slighly slower than wyrand64 and
+ * Romu, but these have restricted capacity for larger parallel jobs or unknown minimum periods.
+ * crand_t supports 2^63 unique threads with a minimum 2^64 period lengths each.
+ * Passes all statistical tests, e.g PractRand and correlation tests, i.e. interleaved
+ * streams with one-bit diff state. Even the 16-bit version (LR=6, RS=5, LS=3) passes
+ * PractRand to multiple TB input.
+ */
+
+/* Global crand_t PRNGs */
+STC_API void csrand(uint64_t seed);
+STC_API uint64_t crand(void);
+STC_API double crandf(void);
+
+/* Init crand_t prng with a seed */
+STC_API crand_t crand_init(uint64_t seed);
+
+/* Unbiased bounded uniform distribution. range [low, high] */
+STC_API crand_unif_t crand_unif_init(int64_t low, int64_t high);
+STC_API int64_t crand_unif(crand_t* rng, crand_unif_t* dist);
+
+/* Normal/gaussian distribution. */
+STC_INLINE crand_norm_t crand_norm_init(double mean, double stddev)
+ { crand_norm_t r = {mean, stddev, 0.0, 0}; return r; }
+
+STC_API double crand_norm(crand_t* rng, crand_norm_t* dist);
+
+/* Main crand_t prng */
+STC_INLINE uint64_t crand_u64(crand_t* rng) {
+ uint64_t *s = rng->state;
+ const uint64_t result = (s[0] ^ (s[3] += s[4])) + s[1];
+ s[0] = s[1] ^ (s[1] >> 11);
+ s[1] = s[2] + (s[2] << 3);
+ s[2] = ((s[2] << 24) | (s[2] >> (64 - 24))) + result;
+ return result;
+}
+
+/* Float64 random number in range [0.0, 1.0). */
+STC_INLINE double crand_f64(crand_t* rng) {
+ union {uint64_t i; double f;} u = {0x3FF0000000000000U | (crand_u64(rng) >> 12)};
+ return u.f - 1.0;
+}
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+/* Global random() */
+static crand_t crand_global = {{
+ 0x26aa069ea2fb1a4d, 0x70c72c95cd592d04,
+ 0x504f333d3aa0b359, 0x9e3779b97f4a7c15,
+ 0x6a09e667a754166b
+}};
+
+STC_DEF void csrand(uint64_t seed)
+ { crand_global = crand_init(seed); }
+
+STC_DEF uint64_t crand(void)
+ { return crand_u64(&crand_global); }
+
+STC_DEF double crandf(void)
+ { return crand_f64(&crand_global); }
+
+STC_DEF crand_t crand_init(uint64_t seed) {
+ crand_t rng; uint64_t* s = rng.state;
+ s[0] = seed + 0x9e3779b97f4a7c15;
+ s[1] = (s[0] ^ (s[0] >> 30))*0xbf58476d1ce4e5b9;
+ s[2] = (s[1] ^ (s[1] >> 27))*0x94d049bb133111eb;
+ s[3] = (s[2] ^ (s[2] >> 31));
+ s[4] = ((seed + 0x6aa069ea2fb1a4d) << 1) | 1;
+ return rng;
+}
+
+/* Init unbiased uniform uint RNG with bounds [low, high] */
+STC_DEF crand_unif_t crand_unif_init(int64_t low, int64_t high) {
+ crand_unif_t dist = {low, (uint64_t) (high - low + 1)};
+ dist.threshold = (uint64_t)(0 - dist.range) % dist.range;
+ return dist;
+}
+
+#if defined(__SIZEOF_INT128__)
+ #define c_umul128(a, b, lo, hi) \
+ do { __uint128_t _z = (__uint128_t)(a)*(b); \
+ *(lo) = (uint64_t)_z, *(hi) = (uint64_t)(_z >> 64U); } while(0)
+#elif defined(_MSC_VER) && defined(_WIN64)
+ #include <intrin.h>
+ #define c_umul128(a, b, lo, hi) ((void)(*(lo) = _umul128(a, b, hi)))
+#elif defined(__x86_64__)
+ #define c_umul128(a, b, lo, hi) \
+ asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b))
+#endif
+
+/* Int64 uniform distributed RNG, range [low, high]. */
+STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) {
+ uint64_t lo, hi;
+#ifdef c_umul128
+ do { c_umul128(crand_u64(rng), d->range, &lo, &hi); } while (lo < d->threshold);
+#else
+ do { lo = crand_u64(rng); hi = lo % d->range; } while (lo - hi > -d->range);
+#endif
+ return d->lower + (int64_t)hi;
+}
+
+/* Normal distribution PRNG. Marsaglia polar method */
+STC_DEF double crand_norm(crand_t* rng, crand_norm_t* dist) {
+ double u1, u2, s, m;
+ if (dist->has_next++ & 1)
+ return dist->next*dist->stddev + dist->mean;
+ do {
+ u1 = 2.0 * crand_f64(rng) - 1.0;
+ u2 = 2.0 * crand_f64(rng) - 1.0;
+ s = u1*u1 + u2*u2;
+ } while (s >= 1.0 || s == 0.0);
+ m = sqrt(-2.0 * log(s) / s);
+ dist->next = u2*m;
+ return (u1*m)*dist->stddev + dist->mean;
+}
+
+#endif
+#endif
+#undef i_opt
+#undef i_static
+#undef i_header
+#undef i_implement
+#undef i_extern
diff --git a/include/stc/csmap.h b/include/stc/csmap.h
index 0f72ca2d..ebfe8d44 100644
--- a/include/stc/csmap.h
+++ b/include/stc/csmap.h
@@ -32,25 +32,22 @@
#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);
- }
+ csmap_sx m = {0};
+ 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);
+
+ csmap_sx_drop(&m);
}
*/
-#ifdef STC_CSMAP_V1
-#include "alt/csmap.h"
-#else
#include "ccommon.h"
#ifndef CSMAP_H_INCLUDED
@@ -80,10 +77,7 @@ int main(void) {
#define _i_size i_ssize
#endif
#include "priv/template.h"
-#ifndef i_cmp_functor
- #define i_cmp_functor(self, x, y) i_cmp(x, y)
-#endif
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY);
#endif
@@ -97,14 +91,14 @@ struct _cx_node {
_cx_value value;
};
-typedef i_keyraw _cx_rawkey;
-typedef i_valraw _cx_memb(_rawmapped);
+typedef i_keyraw _cx_keyraw;
+typedef i_valraw _cx_memb(_rmapped);
typedef _i_SET_ONLY( i_keyraw )
_i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } )
_cx_raw;
#if !defined i_no_emplace
-STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, _cx_rawkey rkey _i_MAP_ONLY(, i_valraw rmapped));
+STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped));
#endif // !i_no_emplace
#if !defined i_no_clone
STC_API _cx_self _cx_memb(_clone)(_cx_self tree);
@@ -113,11 +107,11 @@ STC_API _cx_result _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(
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, _i_size 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(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out);
+STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, _cx_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, _cx_rawkey rkey);
+STC_API int _cx_memb(_erase)(_cx_self* self, _cx_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);
@@ -126,13 +120,13 @@ STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self tree = {0}; return tree
STC_INLINE bool _cx_memb(_empty)(const _cx_self* cx) { return cx->size == 0; }
STC_INLINE _i_size _cx_memb(_size)(const _cx_self* cx) { return cx->size; }
STC_INLINE _i_size _cx_memb(_capacity)(const _cx_self* cx) { return cx->cap; }
-STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey)
+STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_keyraw 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)
+STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_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, _cx_rawkey rkey)
+STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey)
{ _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); }
-STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey)
+STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, _cx_keyraw rkey)
{ _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); }
STC_INLINE _cx_self
@@ -185,14 +179,14 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) {
#ifndef _i_isset
STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped);
#if !defined i_no_emplace
- STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_rawkey rkey, i_valraw rmapped);
+ STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped);
#endif
STC_INLINE const _cx_mapped*
- _cx_memb(_at)(const _cx_self* self, _cx_rawkey rkey)
+ _cx_memb(_at)(const _cx_self* self, _cx_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, _cx_rawkey rkey)
+ _cx_memb(_at_mut)(_cx_self* self, _cx_keyraw rkey)
{ _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; }
#endif // !_i_isset
@@ -222,12 +216,12 @@ _cx_memb(_advance)(_cx_iter it, size_t n) {
}
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* m1, const _cx_self* m2) {
- if (_cx_memb(_size)(m1) != _cx_memb(_size)(m2)) return false;
- _cx_iter i = _cx_memb(_begin)(m1), j = _cx_memb(_begin)(m2);
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false;
+ _cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other);
for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) {
- const _cx_rawkey _rx = i_keyto(_i_keyref(i.ref)), _ry = i_keyto(_i_keyref(j.ref));
- if ((i_cmp_functor(m1, (&_rx), (&_ry))) != 0) return false;
+ const _cx_keyraw _rx = i_keyto(_i_keyref(i.ref)), _ry = i_keyto(_i_keyref(j.ref));
+ if (!(i_eq((&_rx), (&_ry)))) return false;
}
return true;
}
@@ -299,7 +293,7 @@ _cx_memb(_new_node_)(_cx_self* self, int level) {
return tn;
}
-static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_rawkey rkey);
+static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey);
STC_DEF _cx_result
_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) {
@@ -336,7 +330,7 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) {
#if !defined i_no_emplace
STC_DEF _cx_result
- _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_rawkey rkey, i_valraw rmapped) {
+ _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped) {
_cx_result _res = _cx_memb(_insert_entry_)(self, rkey);
if (_res.inserted)
_res.ref->first = i_keyfrom(rkey);
@@ -351,13 +345,13 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) {
#endif // !_i_isset
STC_DEF _cx_value*
-_cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out) {
+_cx_memb(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out) {
i_ssize tn = self->root;
_cx_node *d = out->_d = self->nodes;
out->_top = 0;
while (tn) {
- int c; const _cx_rawkey _raw = i_keyto(_i_keyref(&d[tn].value));
- if ((c = i_cmp_functor(self, (&_raw), (&rkey))) < 0)
+ int c; const _cx_keyraw _raw = i_keyto(_i_keyref(&d[tn].value));
+ if ((c = i_cmp((&_raw), (&rkey))) < 0)
tn = d[tn].link[1];
else if (c > 0)
{ out->_st[out->_top++] = tn; tn = d[tn].link[0]; }
@@ -368,7 +362,7 @@ _cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out) {
}
STC_DEF _cx_iter
-_cx_memb(_lower_bound)(const _cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_lower_bound)(const _cx_self* self, _cx_keyraw rkey) {
_cx_iter it;
_cx_memb(_find_it)(self, rkey, &it);
if (!it.ref && it._top) {
@@ -418,14 +412,14 @@ _cx_memb(_split_)(_cx_node *d, i_ssize tn) {
}
static i_ssize
-_cx_memb(_insert_entry_i_)(_cx_self* self, i_ssize tn, const _cx_rawkey* rkey, _cx_result* _res) {
+_cx_memb(_insert_entry_i_)(_cx_self* self, i_ssize tn, const _cx_keyraw* rkey, _cx_result* _res) {
i_ssize up[64], tx = tn;
_cx_node* d = self->nodes;
int c, top = 0, dir = 0;
while (tx) {
up[top++] = tx;
- const _cx_rawkey _raw = i_keyto(_i_keyref(&d[tx].value));
- if (!(c = i_cmp_functor(self, (&_raw), rkey)))
+ const _cx_keyraw _raw = i_keyto(_i_keyref(&d[tx].value));
+ if (!(c = i_cmp((&_raw), rkey)))
{ _res->ref = &d[tx].value; return tn; }
dir = (c < 0);
tx = d[tx].link[dir];
@@ -450,7 +444,7 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, i_ssize tn, const _cx_rawkey* rkey, _
}
static _cx_result
-_cx_memb(_insert_entry_)(_cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) {
_cx_result res = {NULL};
i_ssize tn = _cx_memb(_insert_entry_i_)(self, self->root, &rkey, &res);
self->root = tn;
@@ -459,12 +453,12 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_rawkey rkey) {
}
static i_ssize
-_cx_memb(_erase_r_)(_cx_self *self, i_ssize tn, const _cx_rawkey* rkey, int *erased) {
+_cx_memb(_erase_r_)(_cx_self *self, i_ssize tn, const _cx_keyraw* rkey, int *erased) {
_cx_node *d = self->nodes;
if (tn == 0)
return 0;
- _cx_rawkey raw = i_keyto(_i_keyref(&d[tn].value));
- i_ssize tx; int c = i_cmp_functor(self, (&raw), rkey);
+ _cx_keyraw raw = i_keyto(_i_keyref(&d[tn].value));
+ i_ssize tx; int c = i_cmp((&raw), rkey);
if (c != 0)
d[tn].link[c < 0] = _cx_memb(_erase_r_)(self, d[tn].link[c < 0], rkey, erased);
else {
@@ -499,7 +493,7 @@ _cx_memb(_erase_r_)(_cx_self *self, i_ssize tn, const _cx_rawkey* rkey, int *era
}
STC_DEF int
-_cx_memb(_erase)(_cx_self* self, _cx_rawkey rkey) {
+_cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) {
int erased = 0;
i_ssize root = _cx_memb(_erase_r_)(self, self->root, &rkey, &erased);
if (!erased)
@@ -511,10 +505,10 @@ _cx_memb(_erase)(_cx_self* self, _cx_rawkey rkey) {
STC_DEF _cx_iter
_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
- _cx_rawkey raw = i_keyto(_i_keyref(it.ref));
+ _cx_keyraw raw = i_keyto(_i_keyref(it.ref));
_cx_memb(_next)(&it);
if (it.ref) {
- _cx_rawkey nxt = i_keyto(_i_keyref(it.ref));
+ _cx_keyraw nxt = i_keyto(_i_keyref(it.ref));
_cx_memb(_erase)(self, raw);
_cx_memb(_find_it)(self, nxt, &it);
} else
@@ -530,7 +524,7 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) {
return it1;
}
_cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref);
- _cx_rawkey r1 = i_keyto((&k1));
+ _cx_keyraw r1 = i_keyto((&k1));
for (;;) {
if (memcmp(&k1, &k2, sizeof k1) == 0)
return it1;
@@ -566,7 +560,7 @@ _cx_memb(_clone)(_cx_self tree) {
#if !defined i_no_emplace
STC_DEF _cx_result
-_cx_memb(_emplace)(_cx_self* self, _cx_rawkey rkey _i_MAP_ONLY(, i_valraw rmapped)) {
+_cx_memb(_emplace)(_cx_self* self, _cx_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);
@@ -594,7 +588,6 @@ _cx_memb(_drop)(_cx_self* self) {
}
#endif // i_implement
-#undef i_cmp_functor
#undef _i_size
#undef _i_isset
#undef _i_ismap
@@ -602,5 +595,4 @@ _cx_memb(_drop)(_cx_self* self) {
#undef _i_MAP_ONLY
#undef _i_SET_ONLY
#define CSMAP_H_INCLUDED
-#include "priv/template.h"
-#endif // !STC_CSMAP_V1
+#include "priv/template2.h"
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index 00313540..ac3e9206 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -48,10 +48,12 @@ int demo2() {
puts("");
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_skipwhile(i, *i.ref < 25) &&
+ (*i.ref & 1) == 0 && // even only
+ c_flt_take(i, 2) // break after 2
+ ){
printf(" %d", *i.ref);
+ }
puts("");
}
*/
@@ -65,9 +67,6 @@ int demo2() {
using_cspan_3(Self, T, 1)
#define using_cspan_3(Self, T, RANK) \
- using_cspan_4(Self, T, RANK, c_default_eq)
-
-#define using_cspan_4(Self, T, RANK, i_eq) \
typedef T Self##_value; typedef T Self##_raw; \
typedef struct { \
Self##_value *data; \
@@ -99,18 +98,6 @@ int demo2() {
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; \
} \
- STC_INLINE bool Self##_eq(const Self* x, const Self* y) { \
- if (memcmp(x->shape, y->shape, sizeof x->shape)) return false; \
- Self##_iter i = Self##_begin(x), j = Self##_begin(y); \
- for (; i.ref; Self##_next(&i), Self##_next(&j)) \
- if (!(i_eq(i.ref, j.ref))) return false; \
- return true; \
- } \
- STC_INLINE Self##_iter Self##_find(const Self* self, Self##_raw raw) { \
- Self##_iter i = Self##_begin(self); \
- for (; i.ref; Self##_next(&i)) if (i_eq(i.ref, &raw)) return i; \
- return i; \
- } \
struct stc_nostruct
#define using_cspan2(Self, T) using_cspan_3(Self, T, 1); using_cspan_3(Self##2, T, 2)
diff --git a/include/stc/cstack.h b/include/stc/cstack.h
index f0c930e5..c2792358 100644
--- a/include/stc/cstack.h
+++ b/include/stc/cstack.h
@@ -33,7 +33,7 @@
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
#ifdef i_capacity
#define i_no_clone
_cx_deftypes(_c_cstack_fixed, _cx_self, i_key, i_capacity);
@@ -189,4 +189,4 @@ STC_INLINE void _cx_memb(_next)(_cx_iter* it)
STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n)
{ if ((it.ref += n) >= it.end) it.ref = NULL ; return it; }
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 91cdb25c..a1aa74b2 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -39,7 +39,7 @@ struct MyStruct {
#include <stc/cvec.h>
#define i_key int
-#define i_opt c_is_forward // forward declared
+#define i_is_forward // forward declared
#define i_tag i32
#include <stc/cvec.h>
@@ -73,7 +73,7 @@ int main() {
#endif
#include "priv/template.h"
-#if !c_option(c_is_forward)
+#ifndef i_is_forward
_cx_deftypes(_c_cvec_types, _cx_self, i_key);
#endif
typedef i_keyraw _cx_raw;
@@ -234,11 +234,10 @@ _cx_memb(_get_mut)(const _cx_self* self, _cx_raw raw)
{ return (_cx_value*) _cx_memb(_get)(self, raw); }
STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) {
- if (x->_len != y->_len) return false;
- _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y);
- for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) {
- const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (self->_len != other->_len) return false;
+ for (intptr_t i = 0; i < self->_len; ++i) {
+ const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i);
if (!(i_eq((&_rx), (&_ry)))) return false;
}
return true;
@@ -439,4 +438,4 @@ STC_DEF int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
#endif // !c_no_cmp
#endif // i_implement
#define CVEC_H_INCLUDED
-#include "priv/template.h"
+#include "priv/template2.h"
diff --git a/include/stc/extend.h b/include/stc/extend.h
new file mode 100644
index 00000000..66b3ebd1
--- /dev/null
+++ b/include/stc/extend.h
@@ -0,0 +1,66 @@
+/* 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.
+ */
+#include <stc/ccommon.h>
+#include <stc/forward.h>
+
+#ifdef i_key_str
+ #define _i_key cstr
+#elif defined i_keyclass
+ #define _i_key i_keyclass
+#elif defined i_keyboxed
+ #define _i_key i_keyboxed
+#elif defined i_key
+ #define _i_key i_key
+#endif
+
+#ifdef i_val_str
+ #define _i_val cstr
+#elif defined i_valclass
+ #define _i_val i_valclass
+#elif defined i_valboxed
+ #define _i_val i_valboxed
+#elif defined i_val
+ #define _i_val i_val
+#endif
+
+#ifdef _i_key
+ c_PASTE(forward_, i_con)(i_type, _i_key, _i_val);
+#else
+ c_PASTE(forward_, i_con)(i_type, _i_val);
+#endif
+
+typedef struct {
+ i_extend
+ i_type get;
+} c_PASTE(i_type, _ext);
+
+#define c_getcon(cptr) c_container_of(cptr, _cx_memb(_ext), get)
+
+#define i_is_forward
+#define _i_inc <stc/i_con.h>
+#include _i_inc
+#undef _i_inc
+#undef _i_key
+#undef _i_val
+#undef i_con
+#undef i_extend
diff --git a/include/stc/forward.h b/include/stc/forward.h
index 00c531fe..31e67e7d 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -118,7 +118,7 @@ typedef union {
} SELF##_result; \
\
typedef struct { \
- SELF##_value *ref, *end; \
+ SELF##_value *ref, *_end; \
uint8_t* _hx; \
} SELF##_iter; \
\
diff --git a/include/stc/priv/altnames.h b/include/stc/priv/altnames.h
index b10c7a11..723b6a66 100644
--- a/include/stc/priv/altnames.h
+++ b/include/stc/priv/altnames.h
@@ -23,7 +23,6 @@
#define c_FORLIST c_forlist
#define c_FORRANGE c_forrange
#define c_FOREACH c_foreach
-#define c_FORWHILE c_forwhile
#define c_FORPAIR c_forpair
#define c_FORFILTER c_forfilter
#define c_FORMATCH c_formatch
@@ -33,6 +32,3 @@
#define c_WITH c_with
#define c_SCOPE c_scope
#define c_DEFER c_defer
-#define c_NEW c_new
-#define c_ARRAYLEN c_arraylen
-#define c_ARGSV c_SV // [deprecated]
diff --git a/include/stc/priv/raii.h b/include/stc/priv/raii.h
new file mode 100644
index 00000000..bb41e0d1
--- /dev/null
+++ b/include/stc/priv/raii.h
@@ -0,0 +1,27 @@
+#define c_defer(...) \
+ for (int _i = 1; _i; _i = 0, __VA_ARGS__)
+
+#define c_with(...) c_MACRO_OVERLOAD(c_with, __VA_ARGS__)
+#define c_with_2(declvar, drop) \
+ for (declvar, *_i, **_ip = &_i; _ip; _ip = 0, drop)
+#define c_with_3(declvar, pred, drop) \
+ for (declvar, *_i, **_ip = &_i; _ip && (pred); _ip = 0, drop)
+
+#define c_scope(...) c_MACRO_OVERLOAD(c_scope, __VA_ARGS__)
+#define c_scope_2(init, drop) \
+ for (int _i = (init, 1); _i; _i = 0, drop)
+#define c_scope_3(init, pred, drop) \
+ for (int _i = (init, 1); _i && (pred); _i = 0, drop)
+
+#define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__)
+#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_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_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)))
diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h
index e352f488..16ef51af 100644
--- a/include/stc/priv/template.h
+++ b/include/stc/priv/template.h
@@ -20,28 +20,28 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifndef _i_template
+#ifdef _i_template
+ #error template.h already included
+#endif
#define _i_template
#ifndef STC_TEMPLATE_H_INCLUDED
#define STC_TEMPLATE_H_INCLUDED
- #define _cx_self c_PASTE(_i_prefix, i_tag)
+ #define _cx_self i_type
#define _cx_memb(name) c_PASTE(_cx_self, name)
#define _cx_deftypes(macro, SELF, ...) c_EXPAND(macro(SELF, __VA_ARGS__))
#define _cx_value _cx_memb(_value)
#define _cx_key _cx_memb(_key)
#define _cx_mapped _cx_memb(_mapped)
#define _cx_raw _cx_memb(_raw)
- #define _cx_rawkey _cx_memb(_rawkey)
+ #define _cx_keyraw _cx_memb(_keyraw)
#define _cx_iter _cx_memb(_iter)
#define _cx_result _cx_memb(_result)
#define _cx_node _cx_memb(_node)
#endif
-#ifdef i_type
- #define i_tag i_type
- #undef _i_prefix
- #define _i_prefix
+#ifndef i_type
+ #define i_type c_PASTE(_i_prefix, i_tag)
#endif
#ifndef i_ssize
@@ -96,6 +96,9 @@
#endif
#endif
+#if c_option(c_is_forward)
+ #define i_is_forward
+#endif
#if c_option(c_no_cmp)
#define i_no_cmp
#endif
@@ -289,62 +292,3 @@
#ifndef _i_has_from
#define i_no_emplace
#endif
-
-#else // ============================================================
-
-#undef i_type
-#undef i_tag
-#undef i_imp
-#undef i_opt
-#undef i_less
-#undef i_cmp
-#undef i_eq
-#undef i_hash
-#undef i_rawclass
-#undef i_capacity
-#undef i_ssize
-
-#undef i_val
-#undef i_val_str
-#undef i_val_ssv
-#undef i_valboxed
-#undef i_valclass
-#undef i_valraw
-#undef i_valclone
-#undef i_valfrom
-#undef i_valto
-#undef i_valdrop
-
-#undef i_key
-#undef i_key_str
-#undef i_key_ssv
-#undef i_keyboxed
-#undef i_keyclass
-#undef i_keyraw
-#undef i_keyclone
-#undef i_keyfrom
-#undef i_keyto
-#undef i_keydrop
-
-#undef i_header
-#undef i_implement
-#undef i_static
-#undef i_extern
-
-#undef i_allocator
-#undef i_malloc
-#undef i_calloc
-#undef i_realloc
-#undef i_free
-
-#undef i_no_cmp
-#undef i_no_hash
-#undef i_no_clone
-#undef i_no_emplace
-
-#undef _i_prefix
-#undef _i_expandby
-#undef _i_has_from
-#undef _i_has_eq
-#undef _i_template
-#endif
diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h
new file mode 100644
index 00000000..27c6a890
--- /dev/null
+++ b/include/stc/priv/template2.h
@@ -0,0 +1,78 @@
+/* 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.
+ */
+#undef i_type
+#undef i_tag
+#undef i_imp
+#undef i_opt
+#undef i_less
+#undef i_cmp
+#undef i_eq
+#undef i_hash
+#undef i_rawclass
+#undef i_capacity
+#undef i_ssize
+
+#undef i_val
+#undef i_val_str
+#undef i_val_ssv
+#undef i_valboxed
+#undef i_valclass
+#undef i_valraw
+#undef i_valclone
+#undef i_valfrom
+#undef i_valto
+#undef i_valdrop
+
+#undef i_key
+#undef i_key_str
+#undef i_key_ssv
+#undef i_keyboxed
+#undef i_keyclass
+#undef i_keyraw
+#undef i_keyclone
+#undef i_keyfrom
+#undef i_keyto
+#undef i_keydrop
+
+#undef i_header
+#undef i_implement
+#undef i_static
+#undef i_extern
+
+#undef i_allocator
+#undef i_malloc
+#undef i_calloc
+#undef i_realloc
+#undef i_free
+
+#undef i_no_cmp
+#undef i_no_hash
+#undef i_no_clone
+#undef i_no_emplace
+#undef i_is_forward
+
+#undef _i_prefix
+#undef _i_expandby
+#undef _i_has_from
+#undef _i_has_eq
+#undef _i_template
diff --git a/misc/benchmarks/picobench/picobench_cmap.cpp b/misc/benchmarks/picobench/picobench_cmap.cpp
index 3ffba5b9..bccbe70c 100644
--- a/misc/benchmarks/picobench/picobench_cmap.cpp
+++ b/misc/benchmarks/picobench/picobench_cmap.cpp
@@ -1,5 +1,5 @@
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_static
#include <stc/cstr.h>
#include <cmath>
@@ -54,36 +54,36 @@ static void ins_and_erase_i(picobench::state& s)
{
MapInt map;
map.max_load_factor((int)MaxLoadFactor100 / 100.0);
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations())
- map[crandom()];
+ map[crand()];
map.clear();
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations())
- map[crandom()];
- csrandom(seed);
+ map[crand()];
+ csrand(seed);
c_forrange (s.iterations())
- map.erase(crandom());
+ map.erase(crand());
s.set_result(map.size());
}
/*
static void ins_and_erase_cmap_i(picobench::state& s)
{
cmap_i map = cmap_i_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations())
- cmap_i_insert(&map, crandom(), 0);
+ cmap_i_insert(&map, crand(), 0);
cmap_i_clear(&map);
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations())
- cmap_i_insert(&map, crandom(), 0);
- csrandom(seed);
+ cmap_i_insert(&map, crand(), 0);
+ csrand(seed);
c_forrange (s.iterations())
- cmap_i_erase(&map, crandom());
+ cmap_i_erase(&map, crand());
s.set_result(cmap_i_size(&map));
cmap_i_drop(&map);
}
@@ -91,18 +91,18 @@ static void ins_and_erase_cmap_i(picobench::state& s)
static void ins_and_erase_cmap_x(picobench::state& s)
{
cmap_x map = cmap_x_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations())
- cmap_x_insert(&map, crandom(), 0);
+ cmap_x_insert(&map, crand(), 0);
cmap_x_clear(&map);
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations())
- cmap_x_insert(&map, crandom(), 0);
- csrandom(seed);
+ cmap_x_insert(&map, crand(), 0);
+ csrand(seed);
c_forrange (s.iterations())
- cmap_x_erase(&map, crandom());
+ cmap_x_erase(&map, crand());
s.set_result(cmap_x_size(&map));
cmap_x_drop(&map);
}
@@ -124,11 +124,11 @@ static void ins_and_access_i(picobench::state& s)
size_t result = 0;
MapInt map;
map.max_load_factor((int)MaxLoadFactor100 / 100.0);
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (N1)
- result += ++map[crandom() & mask];
+ result += ++map[crand() & mask];
s.set_result(result);
}
@@ -137,11 +137,11 @@ static void ins_and_access_cmap_i(picobench::state& s)
uint64_t mask = (1ull << s.arg()) - 1;
size_t result = 0;
cmap_i map = cmap_i_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (N1)
- result += ++cmap_i_insert(&map, crandom() & mask, 0).ref->second;
+ result += ++cmap_i_insert(&map, crand() & mask, 0).ref->second;
s.set_result(result);
cmap_i_drop(&map);
}
@@ -158,7 +158,7 @@ PICOBENCH_SUITE("Map3");
static void randomize(char* str, size_t len) {
for (size_t k=0; k < len; ++k) {
- union {uint64_t i; char c[8];} r = {.i = crandom()};
+ union {uint64_t i; char c[8];} r = {.i = crand()};
for (unsigned i=0; i<8 && k<len; ++k, ++i)
str[k] = (r.c[i] & 63) + 48;
}
@@ -171,7 +171,7 @@ static void ins_and_access_s(picobench::state& s)
size_t result = 0;
MapStr map;
map.max_load_factor((int)MaxLoadFactor100 / 100.0);
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations()) {
@@ -189,7 +189,7 @@ static void ins_and_access_cmap_s(picobench::state& s)
char* buf = cstr_data(&str);
size_t result = 0;
cmap_str map = cmap_str_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations()) {
@@ -223,22 +223,22 @@ static void iterate_x(picobench::state& s)
uint64_t K = (1ull << s.arg()) - 1;
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
size_t result = 0;
// measure insert then iterate whole map
c_forrange (n, s.iterations()) {
- map[crandom()] = n;
+ map[crand()] = n;
if (!(n & K)) for (auto const& keyVal : map)
result += keyVal.second;
}
// reset rng back to inital state
- csrandom(seed);
+ csrand(seed);
// measure erase then iterate whole map
c_forrange (n, s.iterations()) {
- map.erase(crandom());
+ map.erase(crand());
if (!(n & K)) for (auto const& keyVal : map)
result += keyVal.second;
}
@@ -251,22 +251,22 @@ static void iterate_cmap_x(picobench::state& s)
uint64_t K = (1ull << s.arg()) - 1;
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
size_t result = 0;
// measure insert then iterate whole map
c_forrange (n, s.iterations()) {
- cmap_x_insert_or_assign(&map, crandom(), n);
+ cmap_x_insert_or_assign(&map, crand(), n);
if (!(n & K)) c_foreach (i, cmap_x, map)
result += i.ref->second;
}
// reset rng back to inital state
- csrandom(seed);
+ csrand(seed);
// measure erase then iterate whole map
c_forrange (n, s.iterations()) {
- cmap_x_erase(&map, crandom());
+ cmap_x_erase(&map, crand());
if (!(n & K)) c_foreach (i, cmap_x, map)
result += i.ref->second;
}
diff --git a/misc/benchmarks/picobench/picobench_csmap.cpp b/misc/benchmarks/picobench/picobench_csmap.cpp
index 5caab6cc..a6a97b14 100644
--- a/misc/benchmarks/picobench/picobench_csmap.cpp
+++ b/misc/benchmarks/picobench/picobench_csmap.cpp
@@ -1,6 +1,6 @@
#include <iostream>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_static
#include <stc/cstr.h>
#include <cmath>
@@ -71,20 +71,20 @@ template <class MapInt>
static void insert_i(picobench::state& s)
{
MapInt map;
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (n, s.iterations())
- map.emplace(crandom() & 0xfffffff, n);
+ map.emplace(crand() & 0xfffffff, n);
s.set_result(map.size());
}
static void insert_csmap_i(picobench::state& s)
{
csmap_i map = csmap_i_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (n, s.iterations())
- csmap_i_insert(&map, crandom() & 0xfffffff, n);
+ csmap_i_insert(&map, crand() & 0xfffffff, n);
s.set_result(csmap_i_size(&map));
csmap_i_drop(&map);
}
@@ -103,21 +103,21 @@ static void ins_and_erase_i(picobench::state& s)
size_t result = 0;
uint64_t mask = (1ull << s.arg()) - 1;
MapInt map;
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (i, s.iterations())
- map.emplace(crandom() & mask, i);
+ map.emplace(crand() & mask, i);
result = map.size();
map.clear();
- csrandom(seed);
+ csrand(seed);
c_forrange (i, s.iterations())
- map[crandom() & mask] = i;
+ map[crand() & mask] = i;
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations())
- map.erase(crandom() & mask);
+ map.erase(crand() & mask);
s.set_result(result);
}
@@ -126,21 +126,21 @@ static void ins_and_erase_csmap_i(picobench::state& s)
size_t result = 0;
uint64_t mask = (1ull << s.arg()) - 1;
csmap_i map = csmap_i_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (i, s.iterations())
- csmap_i_insert(&map, crandom() & mask, i);
+ csmap_i_insert(&map, crand() & mask, i);
result = csmap_i_size(&map);
csmap_i_clear(&map);
- csrandom(seed);
+ csrand(seed);
c_forrange (i, s.iterations())
- csmap_i_insert_or_assign(&map, crandom() & mask, i);
+ csmap_i_insert_or_assign(&map, crand() & mask, i);
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations())
- csmap_i_erase(&map, crandom() & mask);
+ csmap_i_erase(&map, crand() & mask);
s.set_result(result);
csmap_i_drop(&map);
}
@@ -158,12 +158,12 @@ static void ins_and_access_i(picobench::state& s)
uint64_t mask = (1ull << s.arg()) - 1;
size_t result = 0;
MapInt map;
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations()) {
- result += ++map[crandom() & mask];
- auto it = map.find(crandom() & mask);
+ result += ++map[crand() & mask];
+ auto it = map.find(crand() & mask);
if (it != map.end()) map.erase(it->first);
}
s.set_result(result + map.size());
@@ -174,12 +174,12 @@ static void ins_and_access_csmap_i(picobench::state& s)
uint64_t mask = (1ull << s.arg()) - 1;
size_t result = 0;
csmap_i map = csmap_i_init();
- csrandom(seed);
+ csrand(seed);
picobench::scope scope(s);
c_forrange (s.iterations()) {
- result += ++csmap_i_insert(&map, crandom() & mask, 0).ref->second;
- const csmap_i_value* val = csmap_i_get(&map, crandom() & mask);
+ result += ++csmap_i_insert(&map, crand() & mask, 0).ref->second;
+ const csmap_i_value* val = csmap_i_get(&map, crand() & mask);
if (val) csmap_i_erase(&map, val->first);
}
s.set_result(result + csmap_i_size(&map));
@@ -194,7 +194,7 @@ PICOBENCH(ins_and_access_csmap_i).P;
PICOBENCH_SUITE("Map4");
static void randomize(char* str, int len) {
- union {uint64_t i; char c[8];} r = {.i = crandom()};
+ union {uint64_t i; char c[8];} r = {.i = crand()};
for (int i = len - 7, j = 0; i < len; ++j, ++i)
str[i] = (r.c[j] & 63) + 48;
}
@@ -207,12 +207,12 @@ static void ins_and_access_s(picobench::state& s)
MapStr map;
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations()) {
randomize(&str[0], str.size());
map.emplace(str, str);
}
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations()) {
randomize(&str[0], str.size());
result += map.erase(str);
@@ -228,12 +228,12 @@ static void ins_and_access_csmap_s(picobench::state& s)
csmap_str map = csmap_str_init();
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations()) {
randomize(buf, s.arg());
csmap_str_emplace(&map, buf, buf);
}
- csrandom(seed);
+ csrand(seed);
c_forrange (s.iterations()) {
randomize(buf, s.arg());
result += csmap_str_erase(&map, buf);
@@ -262,22 +262,22 @@ static void iterate_x(picobench::state& s)
uint64_t K = (1ull << s.arg()) - 1;
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
size_t result = 0;
// measure insert then iterate whole map
c_forrange (n, s.iterations()) {
- map[crandom()] = n;
+ map[crand()] = n;
if (!(n & K)) for (auto const& keyVal : map)
result += keyVal.second;
}
// reset rng back to inital state
- csrandom(seed);
+ csrand(seed);
// measure erase then iterate whole map
c_forrange (n, s.iterations()) {
- map.erase(crandom());
+ map.erase(crand());
if (!(n & K)) for (auto const& keyVal : map)
result += keyVal.second;
}
@@ -290,22 +290,22 @@ static void iterate_csmap_x(picobench::state& s)
uint64_t K = (1ull << s.arg()) - 1;
picobench::scope scope(s);
- csrandom(seed);
+ csrand(seed);
size_t result = 0;
// measure insert then iterate whole map
c_forrange (n, s.iterations()) {
- csmap_x_insert_or_assign(&map, crandom(), n);
+ csmap_x_insert_or_assign(&map, crand(), n);
if (!(n & K)) c_foreach (i, csmap_x, map)
result += i.ref->second;
}
// reset rng back to inital state
- csrandom(seed);
+ csrand(seed);
// measure erase then iterate whole map
c_forrange (n, s.iterations()) {
- csmap_x_erase(&map, crandom());
+ csmap_x_erase(&map, crand());
if (!(n & K)) c_foreach (i, csmap_x, map)
result += i.ref->second;
}
diff --git a/misc/benchmarks/plotbench/cdeq_benchmark.cpp b/misc/benchmarks/plotbench/cdeq_benchmark.cpp
index 1259cc07..bb0e28c8 100644
--- a/misc/benchmarks/plotbench/cdeq_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cdeq_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#ifdef __cplusplus
#include <deque>
@@ -12,7 +12,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 100000000, S = 0x3ffc, R = 4};
+enum {SAMPLES = 2, N = 50000000, S = 0x3ffc, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff, mask2 = 0xffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
@@ -28,10 +28,10 @@ Sample test_std_deque() {
{
s.test[INSERT].t1 = clock();
container con;
- csrandom(seed);
- c_forrange (N/3) con.push_front(crandom() & mask1);
- c_forrange (N/3) {con.push_back(crandom() & mask1); con.pop_front();}
- c_forrange (N/3) con.push_back(crandom() & mask1);
+ csrand(seed);
+ c_forrange (N/3) con.push_front(crand() & mask1);
+ c_forrange (N/3) {con.push_back(crand() & mask1); con.pop_front();}
+ c_forrange (N/3) con.push_back(crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = con.size();
s.test[ERASE].t1 = clock();
@@ -40,13 +40,13 @@ Sample test_std_deque() {
s.test[ERASE].sum = con.size();
}{
container con;
- csrandom(seed);
- c_forrange (N) con.push_back(crandom() & mask2);
+ csrand(seed);
+ c_forrange (N) con.push_back(crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
// Iteration - not inherent find - skipping
//container::iterator it;
- //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crandom() & mask2)) != con.end()) sum += *it;
+ //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crand() & mask2)) != con.end()) sum += *it;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -72,10 +72,10 @@ Sample test_stc_deque() {
s.test[INSERT].t1 = clock();
container con = cdeq_x_init();
//cdeq_x_reserve(&con, N);
- csrandom(seed);
- c_forrange (N/3) cdeq_x_push_front(&con, crandom() & mask1);
- c_forrange (N/3) {cdeq_x_push_back(&con, crandom() & mask1); cdeq_x_pop_front(&con);}
- c_forrange (N/3) cdeq_x_push_back(&con, crandom() & mask1);
+ csrand(seed);
+ c_forrange (N/3) cdeq_x_push_front(&con, crand() & mask1);
+ c_forrange (N/3) {cdeq_x_push_back(&con, crand() & mask1); cdeq_x_pop_front(&con);}
+ c_forrange (N/3) cdeq_x_push_back(&con, crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = cdeq_x_size(&con);
s.test[ERASE].t1 = clock();
@@ -84,13 +84,13 @@ Sample test_stc_deque() {
s.test[ERASE].sum = cdeq_x_size(&con);
cdeq_x_drop(&con);
}{
- csrandom(seed);
+ csrand(seed);
container con = cdeq_x_init();
- c_forrange (N) cdeq_x_push_back(&con, crandom() & mask2);
+ c_forrange (N) cdeq_x_push_back(&con, crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
//cdeq_x_iter it, end = cdeq_x_end(&con);
- //c_forrange (S) if ((it = cdeq_x_find(&con, crandom() & mask2)).ref != end.ref) sum += *it.ref;
+ //c_forrange (S) if ((it = cdeq_x_find(&con, crand() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -122,7 +122,7 @@ int main(int argc, char* argv[])
bool header = (argc > 2 && argv[2][0] == '1');
float std_sum = 0, stc_sum = 0;
- c_forrange (j, N_TESTS) {
+ c_forrange (j, N_TESTS) {
std_sum += secs(std_s[0].test[j]);
stc_sum += secs(stc_s[0].test[j]);
}
diff --git a/misc/benchmarks/plotbench/clist_benchmark.cpp b/misc/benchmarks/plotbench/clist_benchmark.cpp
index 04c8e8cd..01bfbf83 100644
--- a/misc/benchmarks/plotbench/clist_benchmark.cpp
+++ b/misc/benchmarks/plotbench/clist_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#ifdef __cplusplus
#include <forward_list>
@@ -12,7 +12,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 50000000, S = 0x3ffc, R = 4};
+enum {SAMPLES = 2, N = 10000000, S = 0x3ffc, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff, mask2 = 0xffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
@@ -28,9 +28,9 @@ Sample test_std_forward_list() {
{
s.test[INSERT].t1 = clock();
container con;
- csrandom(seed);
- c_forrange (N/2) con.push_front(crandom() & mask1);
- c_forrange (N/2) con.push_front(crandom() & mask1);
+ csrand(seed);
+ c_forrange (N/2) con.push_front(crand() & mask1);
+ c_forrange (N/2) con.push_front(crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = 0;
s.test[ERASE].t1 = clock();
@@ -39,13 +39,13 @@ Sample test_std_forward_list() {
s.test[ERASE].sum = 0;
}{
container con;
- csrandom(seed);
- c_forrange (N) con.push_front(crandom() & mask2);
+ csrand(seed);
+ c_forrange (N) con.push_front(crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
container::iterator it;
// Iteration - not inherent find - skipping
- //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crandom() & mask2)) != con.end()) sum += *it;
+ //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crand() & mask2)) != con.end()) sum += *it;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -70,9 +70,9 @@ Sample test_stc_forward_list() {
{
s.test[INSERT].t1 = clock();
container con = clist_x_init();
- csrandom(seed);
- c_forrange (N/2) clist_x_push_front(&con, crandom() & mask1);
- c_forrange (N/2) clist_x_push_back(&con, crandom() & mask1);
+ csrand(seed);
+ c_forrange (N/2) clist_x_push_front(&con, crand() & mask1);
+ c_forrange (N/2) clist_x_push_back(&con, crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = 0;
s.test[ERASE].t1 = clock();
@@ -81,13 +81,13 @@ Sample test_stc_forward_list() {
s.test[ERASE].sum = 0;
clist_x_drop(&con);
}{
- csrandom(seed);
+ csrand(seed);
container con = clist_x_init();
- c_forrange (N) clist_x_push_front(&con, crandom() & mask2);
+ c_forrange (N) clist_x_push_front(&con, crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
//clist_x_iter it, end = clist_x_end(&con);
- //c_forrange (S) if ((it = clist_x_find(&con, crandom() & mask2)).ref != end.ref) sum += *it.ref;
+ //c_forrange (S) if ((it = clist_x_find(&con, crand() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -132,4 +132,4 @@ int main(int argc, char* argv[])
c_forrange (j, N_TESTS)
printf("%s,%s n:%d,%s,%.3f,%.3f\n", comp, stc_s[0].name, N, operations[j], secs(stc_s[0].test[j]), secs(std_s[0].test[j]) ? secs(stc_s[0].test[j])/secs(std_s[0].test[j]) : 1.0f);
printf("%s,%s n:%d,%s,%.3f,%.3f\n", comp, stc_s[0].name, N, "total", stc_sum, stc_sum/std_sum);
-} \ No newline at end of file
+}
diff --git a/misc/benchmarks/plotbench/cmap_benchmark.cpp b/misc/benchmarks/plotbench/cmap_benchmark.cpp
index 7a8f29d2..6b2edbd7 100644
--- a/misc/benchmarks/plotbench/cmap_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cmap_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#ifdef __cplusplus
#include <unordered_map>
@@ -11,7 +11,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 8000000, R = 4};
+enum {SAMPLES = 2, N = 2000000, R = 4};
uint64_t seed = 1, mask1 = 0xffffffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
@@ -26,28 +26,28 @@ Sample test_std_unordered_map() {
typedef std::unordered_map<uint64_t, uint64_t> container;
Sample s = {"std,unordered_map"};
{
- csrandom(seed);
+ csrand(seed);
s.test[INSERT].t1 = clock();
container con;
- c_forrange (i, N/2) con.emplace(crandom() & mask1, i);
+ c_forrange (i, N/2) con.emplace(crand() & mask1, i);
c_forrange (i, N/2) con.emplace(i, i);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = con.size();
- csrandom(seed);
+ csrand(seed);
s.test[ERASE].t1 = clock();
- c_forrange (N) con.erase(crandom() & mask1);
+ c_forrange (N) con.erase(crand() & mask1);
s.test[ERASE].t2 = clock();
s.test[ERASE].sum = con.size();
}{
container con;
- csrandom(seed);
- c_forrange (i, N/2) con.emplace(crandom() & mask1, i);
+ csrand(seed);
+ c_forrange (i, N/2) con.emplace(crand() & mask1, i);
c_forrange (i, N/2) con.emplace(i, i);
- csrandom(seed);
+ csrand(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
container::iterator it;
- c_forrange (N) if ((it = con.find(crandom() & mask1)) != con.end()) sum += it->second;
+ c_forrange (N) if ((it = con.find(crand() & mask1)) != con.end()) sum += it->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -70,30 +70,30 @@ Sample test_stc_unordered_map() {
typedef cmap_x container;
Sample s = {"STC,unordered_map"};
{
- csrandom(seed);
+ csrand(seed);
s.test[INSERT].t1 = clock();
container con = cmap_x_init();
- c_forrange (i, N/2) cmap_x_insert(&con, crandom() & mask1, i);
+ c_forrange (i, N/2) cmap_x_insert(&con, crand() & mask1, i);
c_forrange (i, N/2) cmap_x_insert(&con, i, i);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = cmap_x_size(&con);
- csrandom(seed);
+ csrand(seed);
s.test[ERASE].t1 = clock();
- c_forrange (N) cmap_x_erase(&con, crandom() & mask1);
+ c_forrange (N) cmap_x_erase(&con, crand() & mask1);
s.test[ERASE].t2 = clock();
s.test[ERASE].sum = cmap_x_size(&con);
cmap_x_drop(&con);
}{
container con = cmap_x_init();
- csrandom(seed);
- c_forrange (i, N/2) cmap_x_insert(&con, crandom() & mask1, i);
+ csrand(seed);
+ c_forrange (i, N/2) cmap_x_insert(&con, crand() & mask1, i);
c_forrange (i, N/2) cmap_x_insert(&con, i, i);
- csrandom(seed);
+ csrand(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
const cmap_x_value* val;
- c_forrange (N)
- if ((val = cmap_x_get(&con, crandom() & mask1)))
+ c_forrange (N)
+ if ((val = cmap_x_get(&con, crand() & mask1)))
sum += val->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
@@ -139,4 +139,4 @@ int main(int argc, char* argv[])
c_forrange (j, N_TESTS)
printf("%s,%s n:%d,%s,%.3f,%.3f\n", comp, stc_s[0].name, N, operations[j], secs(stc_s[0].test[j]), secs(std_s[0].test[j]) ? secs(stc_s[0].test[j])/secs(std_s[0].test[j]) : 1.0f);
printf("%s,%s n:%d,%s,%.3f,%.3f\n", comp, stc_s[0].name, N, "total", stc_sum, stc_sum/std_sum);
-} \ No newline at end of file
+}
diff --git a/misc/benchmarks/plotbench/cpque_benchmark.cpp b/misc/benchmarks/plotbench/cpque_benchmark.cpp
index a729c09f..2d4c7a28 100644
--- a/misc/benchmarks/plotbench/cpque_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cpque_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_val float
#define i_cmp -c_default_cmp
@@ -11,19 +11,17 @@
#include <queue>
static const uint32_t seed = 1234;
+static const int N = 2500000;
void std_test()
{
- stc64_t rng;
- int N = 10000000;
-
std::priority_queue<float, std::vector<float>, std::greater<float>> pq;
- rng = stc64_new(seed);
+ csrand(seed);
clock_t start = clock();
c_forrange (i, N)
- pq.push((float) stc64_randf(&rng)*100000);
+ pq.push((float) crandf()*100000.0);
- printf("Built priority queue: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+ printf("Built priority queue: %f secs\n", (float)(clock() - start)/(float)CLOCKS_PER_SEC);
printf("%g ", pq.top());
start = clock();
@@ -31,32 +29,30 @@ void std_test()
pq.pop();
}
- printf("\npopped PQ: %f secs\n\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+ printf("\npopped PQ: %f secs\n\n", (float)(clock() - start)/(float)CLOCKS_PER_SEC);
}
void stc_test()
{
- stc64_t rng;
- int N = 10000000, M = 10;
+ int N = 10000000;
c_auto (cpque_f, pq)
{
- rng = stc64_new(seed);
+ csrand(seed);
clock_t start = clock();
- c_forrange (i, N)
- cpque_f_push(&pq, (float) stc64_randf(&rng)*100000);
+ c_forrange (i, N) {
+ cpque_f_push(&pq, (float) crandf()*100000);
+ }
- printf("Built priority queue: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+ printf("Built priority queue: %f secs\n", (float)(clock() - start)/(float)CLOCKS_PER_SEC);
printf("%g ", *cpque_f_top(&pq));
-
- c_forrange (i, M) {
- cpque_f_pop(&pq);
- }
start = clock();
- c_forrange (i, M, N)
+ c_forrange (i, N) {
cpque_f_pop(&pq);
+ }
+
printf("\npopped PQ: %f secs\n", (clock() - start) / (float) CLOCKS_PER_SEC);
}
}
diff --git a/misc/benchmarks/plotbench/csmap_benchmark.cpp b/misc/benchmarks/plotbench/csmap_benchmark.cpp
index 46bd695c..60f2db49 100644
--- a/misc/benchmarks/plotbench/csmap_benchmark.cpp
+++ b/misc/benchmarks/plotbench/csmap_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#ifdef __cplusplus
#include <map>
@@ -11,7 +11,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 4000000, R = 4};
+enum {SAMPLES = 2, N = 1000000, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
@@ -26,28 +26,28 @@ Sample test_std_map() {
typedef std::map<size_t, size_t> container;
Sample s = {"std,map"};
{
- csrandom(seed);
+ csrand(seed);
s.test[INSERT].t1 = clock();
container con;
- c_forrange (i, N/2) con.emplace(crandom() & mask1, i);
+ c_forrange (i, N/2) con.emplace(crand() & mask1, i);
c_forrange (i, N/2) con.emplace(i, i);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = con.size();
- csrandom(seed);
+ csrand(seed);
s.test[ERASE].t1 = clock();
- c_forrange (N) con.erase(crandom() & mask1);
+ c_forrange (N) con.erase(crand() & mask1);
s.test[ERASE].t2 = clock();
s.test[ERASE].sum = con.size();
}{
container con;
- csrandom(seed);
- c_forrange (i, N/2) con.emplace(crandom() & mask1, i);
+ csrand(seed);
+ c_forrange (i, N/2) con.emplace(crand() & mask1, i);
c_forrange (i, N/2) con.emplace(i, i);
- csrandom(seed);
+ csrand(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
container::iterator it;
- c_forrange (N) if ((it = con.find(crandom() & mask1)) != con.end()) sum += it->second;
+ c_forrange (N) if ((it = con.find(crand() & mask1)) != con.end()) sum += it->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -71,30 +71,30 @@ Sample test_stc_map() {
typedef csmap_x container;
Sample s = {"STC,map"};
{
- csrandom(seed);
+ csrand(seed);
s.test[INSERT].t1 = clock();
container con = csmap_x_init();
- c_forrange (i, N/2) csmap_x_insert(&con, crandom() & mask1, i);
+ c_forrange (i, N/2) csmap_x_insert(&con, crand() & mask1, i);
c_forrange (i, N/2) csmap_x_insert(&con, i, i);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = csmap_x_size(&con);
- csrandom(seed);
+ csrand(seed);
s.test[ERASE].t1 = clock();
- c_forrange (N) csmap_x_erase(&con, crandom() & mask1);
+ c_forrange (N) csmap_x_erase(&con, crand() & mask1);
s.test[ERASE].t2 = clock();
s.test[ERASE].sum = csmap_x_size(&con);
csmap_x_drop(&con);
}{
container con = csmap_x_init();
- csrandom(seed);
- c_forrange (i, N/2) csmap_x_insert(&con, crandom() & mask1, i);
+ csrand(seed);
+ c_forrange (i, N/2) csmap_x_insert(&con, crand() & mask1, i);
c_forrange (i, N/2) csmap_x_insert(&con, i, i);
- csrandom(seed);
+ csrand(seed);
s.test[FIND].t1 = clock();
size_t sum = 0;
const csmap_x_value* val;
- c_forrange (N)
- if ((val = csmap_x_get(&con, crandom() & mask1)))
+ c_forrange (N)
+ if ((val = csmap_x_get(&con, crand() & mask1)))
sum += val->second;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
diff --git a/misc/benchmarks/plotbench/cvec_benchmark.cpp b/misc/benchmarks/plotbench/cvec_benchmark.cpp
index fe7e09fb..c488a01c 100644
--- a/misc/benchmarks/plotbench/cvec_benchmark.cpp
+++ b/misc/benchmarks/plotbench/cvec_benchmark.cpp
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#ifdef __cplusplus
#include <vector>
@@ -12,7 +12,7 @@ enum {INSERT, ERASE, FIND, ITER, DESTRUCT, N_TESTS};
const char* operations[] = {"insert", "erase", "find", "iter", "destruct"};
typedef struct { time_t t1, t2; uint64_t sum; float fac; } Range;
typedef struct { const char* name; Range test[N_TESTS]; } Sample;
-enum {SAMPLES = 2, N = 150000000, S = 0x3ffc, R = 4};
+enum {SAMPLES = 2, N = 80000000, S = 0x3ffc, R = 4};
uint64_t seed = 1, mask1 = 0xfffffff, mask2 = 0xffff;
static float secs(Range s) { return (float)(s.t2 - s.t1) / CLOCKS_PER_SEC; }
@@ -28,8 +28,8 @@ Sample test_std_vector() {
{
s.test[INSERT].t1 = clock();
container con;
- csrandom(seed);
- c_forrange (N) con.push_back(crandom() & mask1);
+ csrand(seed);
+ c_forrange (N) con.push_back(crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = con.size();
s.test[ERASE].t1 = clock();
@@ -38,13 +38,13 @@ Sample test_std_vector() {
s.test[ERASE].sum = con.size();
}{
container con;
- csrandom(seed);
- c_forrange (N) con.push_back(crandom() & mask2);
+ csrand(seed);
+ c_forrange (N) con.push_back(crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
//container::iterator it;
// Iteration - not inherent find - skipping
- //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crandom() & mask2)) != con.end()) sum += *it;
+ //c_forrange (S) if ((it = std::find(con.begin(), con.end(), crand() & mask2)) != con.end()) sum += *it;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
@@ -70,8 +70,8 @@ Sample test_stc_vector() {
{
s.test[INSERT].t1 = clock();
container con = cvec_x_init();
- csrandom(seed);
- c_forrange (N) cvec_x_push_back(&con, crandom() & mask1);
+ csrand(seed);
+ c_forrange (N) cvec_x_push_back(&con, crand() & mask1);
s.test[INSERT].t2 = clock();
s.test[INSERT].sum = cvec_x_size(&con);
s.test[ERASE].t1 = clock();
@@ -80,13 +80,13 @@ Sample test_stc_vector() {
s.test[ERASE].sum = cvec_x_size(&con);
cvec_x_drop(&con);
}{
- csrandom(seed);
+ csrand(seed);
container con = cvec_x_init();
- c_forrange (N) cvec_x_push_back(&con, crandom() & mask2);
+ c_forrange (N) cvec_x_push_back(&con, crand() & mask2);
s.test[FIND].t1 = clock();
size_t sum = 0;
//cvec_x_iter it, end = cvec_x_end(&con);
- //c_forrange (S) if ((it = cvec_x_find(&con, crandom() & mask2)).ref != end.ref) sum += *it.ref;
+ //c_forrange (S) if ((it = cvec_x_find(&con, crand() & mask2)).ref != end.ref) sum += *it.ref;
s.test[FIND].t2 = clock();
s.test[FIND].sum = sum;
s.test[ITER].t1 = clock();
diff --git a/misc/benchmarks/plotbench/plot.py b/misc/benchmarks/plotbench/plot.py
index fa538285..0ba92264 100644
--- a/misc/benchmarks/plotbench/plot.py
+++ b/misc/benchmarks/plotbench/plot.py
@@ -4,7 +4,7 @@ import pandas as pd
import matplotlib.pyplot as plt
#sns.set_theme(style="whitegrid")
-comp = ['All compilers', 'Mingw-g++-10.30', 'Win-Clang-12', 'VC-19.28']
+comp = ['All compilers', 'Mingw-g++-11.3.0', 'Win-Clang-14.0.1', 'VC-19.28']
n = int(sys.argv[1]) if len(sys.argv) > 1 else 0
file = sys.argv[2] if len(sys.argv) > 2 else 'plot_win.csv'
df = pd.read_csv(file)
diff --git a/misc/benchmarks/plotbench/run_all.bat b/misc/benchmarks/plotbench/run_all.bat
index 2edd0a1e..98913a50 100644
--- a/misc/benchmarks/plotbench/run_all.bat
+++ b/misc/benchmarks/plotbench/run_all.bat
@@ -1,5 +1,7 @@
set out=plot_win.csv
echo Compiler,Library,C,Method,Seconds,Ratio> %out%
+echo gcc
sh run_gcc.sh >> %out%
+echo clang
sh run_clang.sh >> %out%
-call run_vc.bat >> %out%
+REM call run_vc.bat >> %out%
diff --git a/misc/benchmarks/plotbench/run_clang.sh b/misc/benchmarks/plotbench/run_clang.sh
index ae19486e..096e71be 100644
--- a/misc/benchmarks/plotbench/run_clang.sh
+++ b/misc/benchmarks/plotbench/run_clang.sh
@@ -6,7 +6,7 @@ clang++ -I../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp
clang++ -I../include -O3 -o csmap_benchmark$exe csmap_benchmark.cpp
clang++ -I../include -O3 -o cvec_benchmark$exe cvec_benchmark.cpp
-c='Win-Clang-12'
+c='Win-Clang-14.0.1'
./cdeq_benchmark$exe $c
./clist_benchmark$exe $c
./cmap_benchmark$exe $c
diff --git a/misc/benchmarks/plotbench/run_gcc.sh b/misc/benchmarks/plotbench/run_gcc.sh
index 6a6472c0..5249ed1e 100644
--- a/misc/benchmarks/plotbench/run_gcc.sh
+++ b/misc/benchmarks/plotbench/run_gcc.sh
@@ -4,9 +4,9 @@ g++ -I../include -O3 -o cmap_benchmark cmap_benchmark.cpp
g++ -I../include -O3 -o csmap_benchmark csmap_benchmark.cpp
g++ -I../include -O3 -o cvec_benchmark cvec_benchmark.cpp
-c='Mingw-g++-10.30'
+c='Mingw-g++-11.3.0'
./cdeq_benchmark $c
./clist_benchmark $c
./cmap_benchmark $c
./csmap_benchmark $c
-./cvec_benchmark $c \ No newline at end of file
+./cvec_benchmark $c
diff --git a/misc/benchmarks/plotbench/run_vc.bat b/misc/benchmarks/plotbench/run_vc.bat
index 3dca925b..dc4938f8 100644
--- a/misc/benchmarks/plotbench/run_vc.bat
+++ b/misc/benchmarks/plotbench/run_vc.bat
@@ -1,3 +1,4 @@
+
@echo off
if "%VSINSTALLDIR%"=="" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" >nul
cl.exe -nologo -EHsc -std:c++latest -I../include -O2 cdeq_benchmark.cpp >nul
@@ -12,4 +13,4 @@ cdeq_benchmark.exe %c%
clist_benchmark.exe %c%
cmap_benchmark.exe %c%
csmap_benchmark.exe %c%
-cvec_benchmark.exe %c% \ No newline at end of file
+cvec_benchmark.exe %c%
diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp
index 39ad1786..bae9a42b 100644
--- a/misc/benchmarks/shootout_hashmaps.cpp
+++ b/misc/benchmarks/shootout_hashmaps.cpp
@@ -1,6 +1,6 @@
#include <stdio.h>
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define MAX_LOAD_FACTOR 85
@@ -35,12 +35,13 @@ KHASH_MAP_INIT_INT64(ii, IValue)
// cmap template expansion
#define i_key IKey
#define i_val IValue
+#define i_ssize int32_t // enable 2^K buckets like the rest.
#define i_tag ii
#define i_max_load_factor MAX_LOAD_FACTOR / 100.0f
#include <stc/cmap.h>
-#define SEED(s) rng = stc64_new(s)
-#define RAND(N) (stc64_rand(&rng) & (((uint64_t)1 << N) - 1))
+#define SEED(s) rng = crand_init(s)
+#define RAND(N) (crand_u64(&rng) & (((uint64_t)1 << N) - 1))
#define CMAP_SETUP(X, Key, Value) cmap_##X map = cmap_##X##_init()
#define CMAP_PUT(X, key, val) cmap_##X##_insert_or_assign(&map, key, val).ref->second
@@ -313,7 +314,7 @@ int main(int argc, char* argv[])
unsigned keybits = argc >= 3 ? atoi(argv[2]) : DEFAULT_KEYBITS;
unsigned n = n_mill * 1000000;
unsigned N1 = n, N2 = n, N3 = n, N4 = n, N5 = n;
- stc64_t rng;
+ crand_t rng;
size_t seed = 123456; // time(NULL);
printf("\nUnordered hash map shootout\n");
diff --git a/misc/benchmarks/various/cbits_benchmark.cpp b/misc/benchmarks/various/cbits_benchmark.cpp
index dd709db1..1764f556 100644
--- a/misc/benchmarks/various/cbits_benchmark.cpp
+++ b/misc/benchmarks/various/cbits_benchmark.cpp
@@ -5,7 +5,7 @@
enum{ N=1<<22 }; // 4.2 mill.
#define i_static
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_type cbits
#define i_len N
#include <stc/cbits.h>
@@ -39,12 +39,12 @@ int main(int argc, char **argv)
one_sec_delay();
total = 0;
- csrandom(seed);
+ csrand(seed);
current_time = get_time_in_ms();
c_forrange (40 * N)
{
- uint64_t r = crandom();
+ uint64_t r = crand();
bools[r & (N-1)] = r & 1<<29;
}
@@ -66,13 +66,13 @@ int main(int argc, char **argv)
one_sec_delay();
total = 0;
- csrandom(seed);
+ csrand(seed);
current_time = get_time_in_ms();
bitset<N> bits;
c_forrange (40 * N)
{
- uint64_t r = crandom();
+ uint64_t r = crand();
bits[r & (N-1)] = r & 1<<29;
}
@@ -92,13 +92,13 @@ int main(int argc, char **argv)
one_sec_delay();
total = 0;
- csrandom(seed);
+ csrand(seed);
current_time = get_time_in_ms();
cbits bits2 = cbits_with_size(N, false);
c_forrange (40 * N)
{
- uint64_t r = crandom();
+ uint64_t r = crand();
cbits_set_value(&bits2, r & (N-1), r & 1<<29);
}
diff --git a/misc/benchmarks/various/csort_bench.c b/misc/benchmarks/various/csort_bench.c
index 97885eb8..d5d7fa7c 100644
--- a/misc/benchmarks/various/csort_bench.c
+++ b/misc/benchmarks/various/csort_bench.c
@@ -9,7 +9,7 @@
#include <stc/algo/csort.h>
#define ROTL(d,bits) ((d<<(bits)) | (d>>(8*sizeof(d)-(bits))))
-uint64_t random(uint64_t s[3]) {
+uint64_t romutrio(uint64_t s[3]) {
uint64_t xp = s[0], yp = s[1], zp = s[2];
s[0] = 15241094284759029579u * zp;
s[1] = yp - xp; s[1] = ROTL(s[1], 12);
@@ -17,12 +17,18 @@ uint64_t random(uint64_t s[3]) {
return xp;
}
+static int cmp_int(const void* a, const void* b) {
+ return c_default_cmp((const int*)a, (const int*)b);
+}
+
void testsort(int *a, int size, const char *desc) {
clock_t t = clock();
#ifdef __cplusplus
- { printf("std::sort: "); std::sort(a, a + size); }
+ printf("std::sort: "); std::sort(a, a + size);
+#elif defined QSORT
+ printf("qsort: "); qsort(a, size, sizeof *a, cmp_int);
#else
- { printf("stc_sort: "); csort_int(a, size); }
+ printf("stc_sort: "); csort_int(a, size);
#endif
t = clock() - t;
@@ -39,7 +45,7 @@ int main(int argc, char *argv[]) {
if (!a) return -1;
for (i = 0; i < size; i++)
- a[i] = random(s) & (1U << 30) - 1;
+ a[i] = romutrio(s) & (1U << 30) - 1;
testsort(a, size, "random");
for (i = 0; i < 20; i++)
printf(" %d", (int)a[i]);
diff --git a/misc/benchmarks/various/prng_bench.cpp b/misc/benchmarks/various/prng_bench.cpp
index 6f4e0e47..234e3805 100644
--- a/misc/benchmarks/various/prng_bench.cpp
+++ b/misc/benchmarks/various/prng_bench.cpp
@@ -2,7 +2,7 @@
#include <iostream>
#include <ctime>
#include <random>
-#include <stc/crandom.h>
+#include <stc/crand.h>
static inline uint64_t rotl64(const uint64_t x, const int k)
{ return (x << k) | (x >> (64 - k)); }
@@ -122,9 +122,9 @@ using namespace std;
int main(void)
{
- enum {N = 2000000000};
+ enum {N = 500000000};
uint16_t* recipient = new uint16_t[N];
- static stc64_t rng;
+ static crand_t rng;
init_state(rng.state, 12345123);
std::mt19937 mt(12345123);
@@ -187,7 +187,7 @@ int main(void)
beg = clock();
for (size_t i = 0; i < N; i++)
- recipient[i] = stc64_rand(&rng);
+ recipient[i] = crand_u64(&rng);
end = clock();
cout << "stc64:\t\t"
<< (float(end - beg) / CLOCKS_PER_SEC)
diff --git a/misc/benchmarks/various/rust_cmap.c b/misc/benchmarks/various/rust_cmap.c
index 83b7dd19..abdb42b0 100644
--- a/misc/benchmarks/various/rust_cmap.c
+++ b/misc/benchmarks/various/rust_cmap.c
@@ -24,38 +24,40 @@ uint64_t romu_trio(uint64_t s[3]) {
int main()
{
- c_auto (cmap_u64, m) {
- const size_t n = 50000000,
- mask = (1 << 25) - 1,
- ms = CLOCKS_PER_SEC/1000;
- cmap_u64_reserve(&m, n);
- printf("STC cmap n = %" c_ZU ", mask = 0x%" PRIxMAX "\n", n, mask);
-
- uint64_t rng[3] = {1872361123, 123879177, 87739234}, sum;
- clock_t now = clock();
- c_forrange (n) {
- uint64_t key = romu_trio(rng) & mask;
- cmap_u64_insert(&m, key, 0).ref->second += 1;
- }
- printf("insert : %" c_ZU "ms \tsize : %" c_ZU "\n", (clock() - now)/ms, cmap_u64_size(&m));
-
- now = clock();
- sum = 0;
- c_forrange (key, mask + 1) { sum += cmap_u64_contains(&m, key); }
- printf("lookup : %" c_ZU "ms \tsum : %" c_ZU "\n", (clock() - now)/ms, sum);
-
- now = clock();
- sum = 0;
- c_foreach (i, cmap_u64, m) { sum += i.ref->second; }
- printf("iterate : %" c_ZU "ms \tsum : %" c_ZU "\n", (clock() - now)/ms, sum);
-
- uint64_t rng2[3] = {1872361123, 123879177, 87739234};
- now = clock();
- c_forrange (n) {
- uint64_t key = romu_trio(rng2) & mask;
- cmap_u64_erase(&m, key);
- }
- printf("remove : %" c_ZU "ms \tsize : %" c_ZU "\n", (clock() - now)/ms, cmap_u64_size(&m));
- printf("press a key:\n"); getchar();
+ cmap_u64 m = {0};
+
+ const size_t n = 50000000,
+ mask = (1 << 25) - 1,
+ ms = CLOCKS_PER_SEC/1000;
+ cmap_u64_reserve(&m, n);
+ printf("STC cmap n = %" c_ZU ", mask = 0x%" PRIxMAX "\n", n, mask);
+
+ uint64_t rng[3] = {1872361123, 123879177, 87739234}, sum;
+ clock_t now = clock();
+ c_forrange (n) {
+ uint64_t key = romu_trio(rng) & mask;
+ cmap_u64_insert(&m, key, 0).ref->second += 1;
}
+ printf("insert : %" c_ZU "ms \tsize : %" c_ZU "\n", (clock() - now)/ms, cmap_u64_size(&m));
+
+ now = clock();
+ sum = 0;
+ c_forrange (key, mask + 1) { sum += cmap_u64_contains(&m, key); }
+ printf("lookup : %" c_ZU "ms \tsum : %" c_ZU "\n", (clock() - now)/ms, sum);
+
+ now = clock();
+ sum = 0;
+ c_foreach (i, cmap_u64, m) { sum += i.ref->second; }
+ printf("iterate : %" c_ZU "ms \tsum : %" c_ZU "\n", (clock() - now)/ms, sum);
+
+ uint64_t rng2[3] = {1872361123, 123879177, 87739234};
+ now = clock();
+ c_forrange (n) {
+ uint64_t key = romu_trio(rng2) & mask;
+ cmap_u64_erase(&m, key);
+ }
+ printf("remove : %" c_ZU "ms \tsize : %" c_ZU "\n", (clock() - now)/ms, cmap_u64_size(&m));
+ printf("press a key:\n"); getchar();
+
+ cmap_u64_drop(&m);
}
diff --git a/misc/benchmarks/various/sso_bench.cpp b/misc/benchmarks/various/sso_bench.cpp
index 0fffef7a..993ff1bb 100644
--- a/misc/benchmarks/various/sso_bench.cpp
+++ b/misc/benchmarks/various/sso_bench.cpp
@@ -2,7 +2,7 @@
#include <iostream>
#include <chrono>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stc/cstr.h>
#define i_type StcVec
@@ -30,7 +30,7 @@ static inline std::string randomString_STD(int strsize) {
char* p = &s[0];
union { uint64_t u8; uint8_t b[8]; } r;
for (int i = 0; i < strsize; ++i) {
- if ((i & 7) == 0) r.u8 = crandom() & 0x3f3f3f3f3f3f3f3f;
+ if ((i & 7) == 0) r.u8 = crand() & 0x3f3f3f3f3f3f3f3f;
p[i] = CHARS[r.b[i & 7]];
}
return s;
@@ -41,7 +41,7 @@ static inline cstr randomString_STC(int strsize) {
char* p = cstr_data(&s);
union { uint64_t u8; uint8_t b[8]; } r;
for (int i = 0; i < strsize; ++i) {
- if ((i & 7) == 0) r.u8 = crandom() & 0x3f3f3f3f3f3f3f3f;
+ if ((i & 7) == 0) r.u8 = crand() & 0x3f3f3f3f3f3f3f3f;
p[i] = CHARS[r.b[i & 7]];
}
return s;
@@ -85,7 +85,7 @@ int main() {
// VECTOR WITH STRINGS
- csrandom(seed);
+ csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tstd::vector<std::string>, size=" << BENCHMARK_SIZE << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
@@ -95,7 +95,7 @@ int main() {
}
std::cout << "Avg:\t" << sum/n << '\n';
- csrandom(seed);
+ csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tcvec<cstr>, size=" << BENCHMARK_SIZE << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
@@ -108,7 +108,7 @@ int main() {
// SORTED SET WITH STRINGS
- csrandom(seed);
+ csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tstd::set<std::string>, size=" << BENCHMARK_SIZE/16 << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
@@ -118,7 +118,7 @@ int main() {
}
std::cout << "Avg:\t" << sum/n << '\n';
- csrandom(seed);
+ csrand(seed);
sum = 0, n = 0;
std::cerr << "\nstrsize\tmsecs\tcsset<cstr>, size=" << BENCHMARK_SIZE/16 << "\n";
for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) {
diff --git a/misc/examples/arc_containers.c b/misc/examples/arc_containers.c
index b621c386..84ba8dda 100644
--- a/misc/examples/arc_containers.c
+++ b/misc/examples/arc_containers.c
@@ -27,9 +27,12 @@
int main()
{
- c_auto (Stack, stack)
- c_auto (List, list)
- {
+ Stack stack = {0};
+ List list = {0};
+ c_defer(
+ Stack_drop(&stack),
+ List_drop(&list)
+ ){
// POPULATE stack with shared pointers to Maps:
Map *map;
map = Stack_push(&stack, Arc_from(Map_init()))->get;
@@ -62,13 +65,13 @@ int main()
// Add one more element to the shared map:
Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021);
-
puts("STACKS");
c_foreach (i, Stack, stack) {
c_forpair (name, year, Map, *i.ref->get)
printf(" %s:%d", cstr_str(_.name), *_.year);
puts("");
}
+
puts("LIST");
c_foreach (i, List, list) {
c_forpair (name, year, Map, *i.ref->get)
diff --git a/misc/examples/arc_demo.c b/misc/examples/arc_demo.c
index 867cfc83..2339adbb 100644
--- a/misc/examples/arc_demo.c
+++ b/misc/examples/arc_demo.c
@@ -22,36 +22,37 @@ void int_drop(int* x) {
int main()
{
- c_auto (cvec_Arc, vec) // declare and init vec, call cvec_Arc_drop() at scope exit
- c_auto (csset_Arc, set) // declare and init set, call csset_Arc_drop() at scope exit
- {
- const int years[] = {2021, 2012, 2022, 2015};
- c_forrange (i, c_ARRAYLEN(years))
- cvec_Arc_push(&vec, Arc_from(years[i]));
-
- printf("vec:");
- c_foreach (i, cvec_Arc, vec) printf(" %d", *i.ref->get);
- puts("");
-
- // add odd numbers from vec to set
- c_foreach (i, cvec_Arc, vec)
- if (*i.ref->get & 1)
- csset_Arc_insert(&set, Arc_clone(*i.ref)); // copy shared pointer => increments counter.
-
- // erase the two last elements in vec
- cvec_Arc_pop_back(&vec);
- cvec_Arc_pop_back(&vec);
-
- printf("vec:");
- c_foreach (i, cvec_Arc, vec) printf(" %d", *i.ref->get);
-
- printf("\nset:");
- c_foreach (i, csset_Arc, set) printf(" %d", *i.ref->get);
-
- c_with (Arc p = Arc_clone(vec.data[0]), Arc_drop(&p)) {
- printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count);
- }
-
- puts("\nDone");
- }
+ const int years[] = {2021, 2012, 2022, 2015};
+
+ cvec_Arc vec = {0};
+ c_forrange (i, c_arraylen(years))
+ cvec_Arc_push(&vec, Arc_from(years[i]));
+
+ printf("vec:");
+ c_foreach (i, cvec_Arc, vec)
+ printf(" %d", *i.ref->get);
+ puts("");
+
+ // add odd numbers from vec to set
+ csset_Arc set = {0};
+ c_foreach (i, cvec_Arc, vec)
+ if (*i.ref->get & 1)
+ csset_Arc_insert(&set, Arc_clone(*i.ref)); // copy shared pointer => increments counter.
+
+ // erase the two last elements in vec
+ cvec_Arc_pop_back(&vec);
+ cvec_Arc_pop_back(&vec);
+
+ printf("vec:");
+ c_foreach (i, cvec_Arc, vec) printf(" %d", *i.ref->get);
+
+ printf("\nset:");
+ c_foreach (i, csset_Arc, set) printf(" %d", *i.ref->get);
+
+ Arc p = Arc_clone(vec.data[0]);
+ printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count);
+
+ Arc_drop(&p);
+ cvec_Arc_drop(&vec);
+ csset_Arc_drop(&set);
}
diff --git a/misc/examples/arcvec_erase.c b/misc/examples/arcvec_erase.c
index 38f11097..3bf41559 100644
--- a/misc/examples/arcvec_erase.c
+++ b/misc/examples/arcvec_erase.c
@@ -15,38 +15,36 @@ void show_drop(int* x) { printf("drop: %d\n", *x); }
int main()
{
- c_auto (Vec, vec)
- {
- vec = c_make(Vec, {2012, 1990, 2012, 2019, 2015});
-
- // clone the second 2012 and push it back.
- // note: cloning make sure that vec.data[2] has ref count 2.
- Vec_push(&vec, Arc_clone(vec.data[2]));
-
- printf("vec before erase :");
- c_foreach (i, Vec, vec)
- printf(" %d", *i.ref->get);
-
- printf("\nerase vec.data[2]; or first matching value depending on compare.\n");
- Vec_iter it;
- it = Vec_find(&vec, *vec.data[2].get);
- if (it.ref != Vec_end(&vec).ref)
- Vec_erase_at(&vec, it);
-
- int year = 2015;
- it = Vec_find(&vec, year); // Ok as tmp only.
- if (it.ref != Vec_end(&vec).ref)
- Vec_erase_at(&vec, it);
-
- printf("vec after erase :");
- c_foreach (i, Vec, vec)
- printf(" %d", *i.ref->get);
-
- Vec_sort(&vec);
- printf("\nvec after sort :");
- c_foreach (i, Vec, vec)
- printf(" %d", *i.ref->get);
-
- puts("\nDone");
- }
+ Vec vec = c_make(Vec, {2012, 1990, 2012, 2019, 2015});
+
+ // clone the second 2012 and push it back.
+ // note: cloning make sure that vec.data[2] has ref count 2.
+ Vec_push(&vec, Arc_clone(vec.data[2]));
+
+ printf("vec before erase :");
+ c_foreach (i, Vec, vec)
+ printf(" %d", *i.ref->get);
+
+ printf("\nerase vec.data[2]; or first matching value depending on compare.\n");
+ Vec_iter it;
+ it = Vec_find(&vec, *vec.data[2].get);
+ if (it.ref)
+ Vec_erase_at(&vec, it);
+
+ int year = 2015;
+ it = Vec_find(&vec, year); // Ok as tmp only.
+ if (it.ref)
+ Vec_erase_at(&vec, it);
+
+ printf("vec after erase :");
+ c_foreach (i, Vec, vec)
+ printf(" %d", *i.ref->get);
+
+ Vec_sort(&vec);
+ printf("\nvec after sort :");
+ c_foreach (i, Vec, vec)
+ printf(" %d", *i.ref->get);
+
+ puts("\nDone");
+ Vec_drop(&vec);
}
diff --git a/misc/examples/astar.c b/misc/examples/astar.c
index 10e45d3c..7dd12d50 100644
--- a/misc/examples/astar.c
+++ b/misc/examples/astar.c
@@ -78,12 +78,16 @@ point_key_cmp(const point* a, const point* b)
cdeq_point
astar(cstr* maze, int width)
{
- cdeq_point path = cdeq_point_init();
+ cdeq_point ret_path = {0};
- c_auto (cpque_point, front)
- c_auto (csmap_pstep, from)
- c_auto (csmap_pcost, costs)
- {
+ cpque_point front = {0};
+ csmap_pstep from = {0};
+ csmap_pcost costs = {0};
+ c_defer(
+ cpque_point_drop(&front),
+ csmap_pstep_drop(&from),
+ csmap_pcost_drop(&costs)
+ ){
point start = point_from(maze, "@", width);
point goal = point_from(maze, "!", width);
csmap_pcost_insert(&costs, start, 0);
@@ -99,7 +103,7 @@ astar(cstr* maze, int width)
{ -1, 0, 0, width }, /* ~ ~ ~ ~ ~ ~ ~ */ { 1, 0, 0, width },
{ -1, -1, 0, width }, { 0, -1, 0, width }, { 1, -1, 0, width },
};
- for (size_t i = 0; i < c_ARRAYLEN(deltas); i++)
+ for (size_t i = 0; i < c_arraylen(deltas); i++)
{
point delta = deltas[i];
point next = point_init(current.x + delta.x, current.y + delta.y, width);
@@ -120,18 +124,18 @@ astar(cstr* maze, int width)
point current = goal;
while (!point_equal(&current, &start))
{
- cdeq_point_push_front(&path, current);
+ cdeq_point_push_front(&ret_path, current);
current = *csmap_pstep_at(&from, current);
}
- cdeq_point_push_front(&path, start);
+ cdeq_point_push_front(&ret_path, start);
}
- return path;
+ return ret_path;
}
int
main(void)
{
- c_with (cstr maze = cstr_lit(
+ cstr maze = cstr_lit(
"#########################################################################\n"
"# # # # # # #\n"
"# # ######### # ##### ######### ##### ##### ##### # ! #\n"
@@ -154,15 +158,16 @@ main(void)
"# # # # # # # # # #\n"
"# @ # ##### ##### ##### ######### ##### # ######### # #\n"
"# # # # # # #\n"
- "#########################################################################\n"), cstr_drop(&maze))
- {
- 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)
- cstr_data(&maze)[point_index(it.ref)] = 'x';
-
- printf("%s", cstr_str(&maze));
- }
- }
+ "#########################################################################\n"
+ );
+ int width = (int)cstr_find(&maze, "\n") + 1;
+ cdeq_point ret_path = astar(&maze, width);
+
+ c_foreach (it, cdeq_point, ret_path)
+ cstr_data(&maze)[point_index(it.ref)] = 'x';
+
+ printf("%s", cstr_str(&maze));
+
+ cdeq_point_drop(&ret_path);
+ cstr_drop(&maze);
}
diff --git a/misc/examples/birthday.c b/misc/examples/birthday.c
index cb627ef8..c301128a 100644
--- a/misc/examples/birthday.c
+++ b/misc/examples/birthday.c
@@ -1,7 +1,7 @@
#include <math.h>
#include <stdio.h>
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_tag ic
#define i_key uint64_t
@@ -17,17 +17,16 @@ static void test_repeats(void)
const static uint64_t mask = (1ull << BITS) - 1;
printf("birthday paradox: value range: 2^%d, testing repeats of 2^%d values\n", BITS, BITS_TEST);
- stc64_t rng = stc64_new(seed);
- c_auto (cmap_ic, m)
- {
- cmap_ic_reserve(&m, N);
- c_forrange (i, N) {
- uint64_t k = stc64_rand(&rng) & mask;
- int v = cmap_ic_insert(&m, k, 0).ref->second += 1;
- if (v > 1) printf("repeated value %" PRIu64 " (%d) at 2^%d\n",
- k, v, (int) log2((double) i));
- }
+ crand_t rng = crand_init(seed);
+
+ cmap_ic m = cmap_ic_with_capacity(N);
+ c_forrange (i, N) {
+ uint64_t k = crand_u64(&rng) & mask;
+ int v = cmap_ic_insert(&m, k, 0).ref->second += 1;
+ if (v > 1) printf("repeated value %" PRIu64 " (%d) at 2^%d\n",
+ k, v, (int)log2((double)i));
}
+ cmap_ic_drop(&m);
}
#define i_key uint32_t
@@ -39,25 +38,26 @@ void test_distribution(void)
{
enum {BITS = 26};
printf("distribution test: 2^%d values\n", BITS);
- stc64_t rng = stc64_new(seed);
+ crand_t rng = crand_init(seed);
const size_t N = 1ull << BITS ;
- c_auto (cmap_x, map) {
- c_forrange (N) {
- uint64_t k = stc64_rand(&rng);
- cmap_x_insert(&map, k & 0xf, 0).ref->second += 1;
- }
+ cmap_x map = {0};
+ c_forrange (N) {
+ uint64_t k = crand_u64(&rng);
+ cmap_x_insert(&map, k & 0xf, 0).ref->second += 1;
+ }
- uint64_t sum = 0;
- c_foreach (i, cmap_x, map) sum += i.ref->second;
- sum /= (uint64_t)map.size;
+ uint64_t sum = 0;
+ c_foreach (i, cmap_x, map) sum += i.ref->second;
+ 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.0 - (double)i.ref->second / (double)sum));
- }
+ c_foreach (i, cmap_x, map) {
+ printf("%4" PRIu32 ": %" PRIu64 " - %" PRIu64 ": %11.8f\n",
+ i.ref->first, i.ref->second, sum,
+ (1.0 - (double)i.ref->second / (double)sum));
}
+
+ cmap_x_drop(&map);
}
int main()
diff --git a/misc/examples/bits.c b/misc/examples/bits.c
index 6f28c52d..1323d4e7 100644
--- a/misc/examples/bits.c
+++ b/misc/examples/bits.c
@@ -3,7 +3,12 @@
int main(void)
{
- c_with (cbits set = cbits_with_size(23, true), cbits_drop(&set)) {
+ cbits set = cbits_with_size(23, true);
+ cbits s2;
+ c_defer(
+ cbits_drop(&set),
+ cbits_drop(&s2)
+ ){
printf("count %" c_ZI ", %" c_ZI "\n", cbits_count(&set), cbits_size(&set));
cbits s1 = cbits_from("1110100110111");
char buf[256];
@@ -35,27 +40,27 @@ int main(void)
printf("%d", cbits_test(&set, i));
puts("");
- c_with (cbits s2 = cbits_clone(set), cbits_drop(&s2)) {
- cbits_flip_all(&s2);
- cbits_set(&s2, 16);
- cbits_set(&s2, 17);
- cbits_set(&s2, 18);
- printf(" new: ");
- c_forrange (i, cbits_size(&s2))
- printf("%d", cbits_test(&s2, i));
- puts("");
-
- printf(" xor: ");
- cbits_xor(&set, &s2);
- c_forrange (i, cbits_size(&set))
- printf("%d", cbits_test(&set, i));
- puts("");
-
- cbits_set_all(&set, false);
- printf("%4" c_ZI ": ", cbits_size(&set));
- c_forrange (i, cbits_size(&set))
- printf("%d", cbits_test(&set, i));
- puts("");
- }
+ // Make a clone
+ s2 = cbits_clone(set);
+ cbits_flip_all(&s2);
+ cbits_set(&s2, 16);
+ cbits_set(&s2, 17);
+ cbits_set(&s2, 18);
+ printf(" new: ");
+ c_forrange (i, cbits_size(&s2))
+ printf("%d", cbits_test(&s2, i));
+ puts("");
+
+ printf(" xor: ");
+ cbits_xor(&set, &s2);
+ c_forrange (i, cbits_size(&set))
+ printf("%d", cbits_test(&set, i));
+ puts("");
+
+ cbits_set_all(&set, false);
+ 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/books.c b/misc/examples/books.c
index 098771ae..a62769b0 100644
--- a/misc/examples/books.c
+++ b/misc/examples/books.c
@@ -8,53 +8,54 @@
// would be `HashMap<String, String>` in this example).
int main()
{
- c_auto (cmap_str, book_reviews)
- {
- // Review some books.
- cmap_str_emplace(&book_reviews,
- "Adventures of Huckleberry Finn",
- "My favorite book."
- );
- cmap_str_emplace(&book_reviews,
- "Grimms' Fairy Tales",
- "Masterpiece."
- );
- cmap_str_emplace(&book_reviews,
- "Pride and Prejudice",
- "Very enjoyable"
- );
- cmap_str_insert(&book_reviews,
- cstr_lit("The Adventures of Sherlock Holmes"),
- cstr_lit("Eye lyked it alot.")
- );
-
- // Check for a specific one.
- // 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_ZI " reviews, but Les Misérables ain't one.",
- cmap_str_size(&book_reviews));
- }
-
- // oops, this review has a lot of spelling mistakes, let's delete it.
- cmap_str_erase(&book_reviews, "The Adventures of Sherlock Holmes");
-
- // Look up the values associated with some keys.
- const char* to_find[] = {"Pride and Prejudice", "Alice's Adventure in Wonderland"};
- c_forrange (i, c_ARRAYLEN(to_find)) {
- const cmap_str_value* b = cmap_str_get(&book_reviews, to_find[i]);
- if (b)
- printf("%s: %s\n", cstr_str(&b->first), cstr_str(&b->second));
- else
- printf("%s is unreviewed.\n", to_find[i]);
- }
-
- // Look up the value for a key (will panic if the key is not found).
- printf("Review for Jane: %s\n", cstr_str(cmap_str_at(&book_reviews, "Pride and Prejudice")));
-
- // Iterate over everything.
- c_forpair (book, review, cmap_str, book_reviews) {
- printf("%s: \"%s\"\n", cstr_str(_.book), cstr_str(_.review));
- }
+ cmap_str book_reviews = {0};
+
+ // Review some books.
+ cmap_str_emplace(&book_reviews,
+ "Adventures of Huckleberry Finn",
+ "My favorite book."
+ );
+ cmap_str_emplace(&book_reviews,
+ "Grimms' Fairy Tales",
+ "Masterpiece."
+ );
+ cmap_str_emplace(&book_reviews,
+ "Pride and Prejudice",
+ "Very enjoyable"
+ );
+ cmap_str_insert(&book_reviews,
+ cstr_lit("The Adventures of Sherlock Holmes"),
+ cstr_lit("Eye lyked it alot.")
+ );
+
+ // Check for a specific one.
+ // 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_ZI " reviews, but Les Misérables ain't one.",
+ cmap_str_size(&book_reviews));
+ }
+
+ // oops, this review has a lot of spelling mistakes, let's delete it.
+ cmap_str_erase(&book_reviews, "The Adventures of Sherlock Holmes");
+
+ // Look up the values associated with some keys.
+ const char* to_find[] = {"Pride and Prejudice", "Alice's Adventure in Wonderland"};
+ c_forrange (i, c_arraylen(to_find)) {
+ const cmap_str_value* b = cmap_str_get(&book_reviews, to_find[i]);
+ if (b)
+ printf("%s: %s\n", cstr_str(&b->first), cstr_str(&b->second));
+ else
+ printf("%s is unreviewed.\n", to_find[i]);
}
+
+ // Look up the value for a key (will panic if the key is not found).
+ printf("Review for Jane: %s\n", cstr_str(cmap_str_at(&book_reviews, "Pride and Prejudice")));
+
+ // Iterate over everything.
+ c_forpair (book, review, cmap_str, book_reviews) {
+ printf("%s: \"%s\"\n", cstr_str(_.book), cstr_str(_.review));
+ }
+
+ cmap_str_drop(&book_reviews);
}
diff --git a/misc/examples/box.c b/misc/examples/box.c
index da13501f..9954883c 100644
--- a/misc/examples/box.c
+++ b/misc/examples/box.c
@@ -37,32 +37,32 @@ void Person_drop(Person* p) {
int main()
{
- c_auto (Persons, vec)
- c_auto (PBox, p, q)
- {
- p = PBox_from(Person_make("Laura", "Palmer"));
- q = PBox_clone(p);
- cstr_assign(&q.get->name, "Leland");
+ Persons vec = {0};
+ PBox p = PBox_from(Person_make("Laura", "Palmer"));
+ PBox q = PBox_clone(p);
+ cstr_assign(&q.get->name, "Leland");
- printf("orig: %s %s\n", cstr_str(&p.get->name), cstr_str(&p.get->last));
- printf("copy: %s %s\n", cstr_str(&q.get->name), cstr_str(&q.get->last));
+ printf("orig: %s %s\n", cstr_str(&p.get->name), cstr_str(&p.get->last));
+ printf("copy: %s %s\n", cstr_str(&q.get->name), cstr_str(&q.get->last));
- Persons_emplace(&vec, Person_make("Dale", "Cooper"));
- Persons_emplace(&vec, Person_make("Audrey", "Home"));
+ Persons_emplace(&vec, Person_make("Dale", "Cooper"));
+ Persons_emplace(&vec, Person_make("Audrey", "Home"));
- // NB! Clone/share p and q in the Persons container.
- Persons_push(&vec, PBox_clone(p));
- Persons_push(&vec, PBox_clone(q));
+ // NB! Clone/share p and q in the Persons container.
+ Persons_push(&vec, PBox_clone(p));
+ Persons_push(&vec, PBox_clone(q));
- c_foreach (i, Persons, vec)
- printf("%s %s\n", cstr_str(&i.ref->get->name), cstr_str(&i.ref->get->last));
- puts("");
+ c_foreach (i, Persons, vec)
+ printf("%s %s\n", cstr_str(&i.ref->get->name), cstr_str(&i.ref->get->last));
+ puts("");
- // Look-up Audrey! Create a temporary Person for lookup.
- c_with (Person a = Person_make("Audrey", "Home"), Person_drop(&a)) {
- const PBox *v = Persons_get(&vec, a); // lookup
- if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last));
- }
- puts("");
- }
+ // Look-up Audrey! Create a temporary Person for lookup.
+ Person a = Person_make("Audrey", "Home");
+ const PBox *v = Persons_get(&vec, a); // lookup
+ if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last));
+
+ Person_drop(&a);
+ PBox_drop(&p);
+ PBox_drop(&q);
+ Persons_drop(&vec);
}
diff --git a/misc/examples/box2.c b/misc/examples/box2.c
index f7d21976..cba255d2 100644
--- a/misc/examples/box2.c
+++ b/misc/examples/box2.c
@@ -40,31 +40,27 @@ cbox_Point boxed_origin(void) {
int main(void) {
// Stack allocated variables
Point point = origin();
- Rectangle rectangle = (Rectangle){
+ Rectangle rectangle = {
.top_left = origin(),
.bottom_right = { .x=3.0, .y=-4.0 }
};
- // Declare RAII'ed box objects
- c_auto (cbox_Rectangle, boxed_rectangle)
- c_auto (cbox_Point, boxed_point)
- c_auto (BoxBoxPoint, box_in_a_box)
- {
- // Heap allocated rectangle
- boxed_rectangle = cbox_Rectangle_make((Rectangle){
- .top_left = origin(),
- .bottom_right = { .x=3.0, .y=-4.0 }
- });
+ // Heap allocated rectangle
+ cbox_Rectangle boxed_rectangle = cbox_Rectangle_make((Rectangle){
+ .top_left = origin(),
+ .bottom_right = { .x=3.0, .y=-4.0 }
+ });
+ // The output of functions can be boxed
+ cbox_Point boxed_point = cbox_Point_make(origin());
- // The output of functions can be boxed
- boxed_point = cbox_Point_make(origin());
+ // Can use from(raw) and toraw instead:
+ BoxBoxPoint box_in_a_box = BoxBoxPoint_from(origin());
- // Double indirection
- //box_in_a_box = BoxBoxPoint_make(boxed_origin());
- //printf("box_in_a_box: x = %g\n", box_in_a_box.get->get->x);
-
- // Can use from(raw) and toraw instead:
- box_in_a_box = BoxBoxPoint_from(origin());
+ c_defer(
+ BoxBoxPoint_drop(&box_in_a_box),
+ cbox_Point_drop(&boxed_point),
+ cbox_Rectangle_drop(&boxed_rectangle)
+ ){
printf("box_in_a_box: x = %g\n", BoxBoxPoint_toraw(&box_in_a_box).x);
printf("Point occupies %d bytes on the stack\n",
diff --git a/misc/examples/city.c b/misc/examples/city.c
deleted file mode 100644
index 67471cfb..00000000
--- a/misc/examples/city.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include <stc/cstr.h>
-
-typedef struct {
- cstr name;
- cstr country;
- float lat, lon;
- int population;
-} City;
-
-int City_cmp(const City* a, const City* b);
-uint64_t City_hash(const City* a);
-City City_clone(City c);
-void City_drop(City* c);
-
-#define i_type CityArc
-#define i_valclass City
-#include <stc/cbox.h>
-//#include <stc/carc.h> // try instead of cbox.h
-
-#define i_type Cities
-#define i_keyboxed CityArc
-#include <stc/cvec.h>
-
-#define i_type CityMap
-#define i_key int
-#define i_valboxed CityArc
-#include <stc/csmap.h>
-
-
-int City_cmp(const City* a, const City* b) {
- int c = cstr_cmp(&a->name, &b->name);
- return c ? c : cstr_cmp(&a->country, &b->country);
-}
-
-uint64_t City_hash(const City* a) {
- return cstr_hash(&a->name) ^ cstr_hash(&a->country);
-}
-
-City City_clone(City c) {
- c.name = cstr_clone(c.name);
- c.country = cstr_clone(c.country);
- return c;
-}
-
-void City_drop(City* c) {
- printf("drop %s\n", cstr_str(&c->name));
- c_drop(cstr, &c->name, &c->country);
-}
-
-
-int main(void)
-{
- c_auto (Cities, cities, copy)
- c_auto (CityMap, map)
- {
- // Create a cvec with smart pointers to City objects!
- cities = c_make(Cities, {
- {cstr_lit("New York"), cstr_lit("US"), 40.71427f, -74.00597f, 8804190},
- {cstr_lit("Paris"), cstr_lit("France"), 48.85341f, 2.3488f, 2138551},
- {cstr_lit("Berlin"), cstr_lit("Germany"), 52.52437f, 13.41053f, 3426354},
- {cstr_lit("London"), cstr_lit("UK"), 51.50853f, -0.12574f, 8961989},
- });
-
- Cities_sort(&cities);
-
- printf("Vec:\n");
- c_foreach (c, Cities, cities)
- printf("city: %8s, %8d, use: %ld\n", cstr_str(&c.ref->get->name),
- c.ref->get->population,
- CityArc_use_count(c.ref));
- puts("");
- copy = Cities_clone(cities); // share each city!
-
- int k = 0, id[] = {8, 4, 3, 9, 2, 5};
- c_foreach (i, Cities, cities)
- CityMap_insert(&map, id[k++], CityArc_clone(*i.ref));
-
- Cities_pop(&cities);
- Cities_pop(&cities);
-
- printf("Vec:\n");
- c_foreach (c, Cities, cities)
- printf("city: %8s, %8d, use: %ld\n", cstr_str(&c.ref->get->name),
- c.ref->get->population,
- CityArc_use_count(c.ref));
- printf("\nMap:\n");
- c_forpair (id, city, CityMap, map)
- printf("city: %8s, %8d, use: %ld, id:%d\n", cstr_str(&_.city->get->name),
- _.city->get->population, CityArc_use_count(_.city), *_.id);
- puts("");
- }
-}
diff --git a/misc/examples/complex.c b/misc/examples/complex.c
index e73d7aa1..7dde981d 100644
--- a/misc/examples/complex.c
+++ b/misc/examples/complex.c
@@ -31,25 +31,20 @@
int main()
{
- c_auto (MapMap, mmap)
- {
- FloatStack stack = FloatStack_with_size(10, 0);
-
- // Put in some data in the structures
- stack.data[3] = 3.1415927f;
- printf("stack size: %" c_ZI "\n", FloatStack_size(&stack));
-
- StackList list = StackList_init();
- StackList_push_back(&list, stack);
-
- ListMap lmap = ListMap_init();
- ListMap_insert(&lmap, 42, list);
- MapMap_insert(&mmap, cstr_from("first"), lmap);
-
- // Access the data entry
- const ListMap* lmap_p = MapMap_at(&mmap, "first");
- const StackList* list_p = ListMap_at(lmap_p, 42);
- const FloatStack* stack_p = StackList_back(list_p);
- printf("value is: %f\n", *FloatStack_at(stack_p, 3)); // pi
- }
+ MapMap mmap = {0};
+
+ // Put in some data in the structures
+ ListMap* lmap = &MapMap_emplace(&mmap, "first", ListMap_init()).ref->second;
+ StackList* list = &ListMap_insert(lmap, 42, StackList_init()).ref->second;
+ FloatStack* stack = StackList_push_back(list, FloatStack_with_size(10, 0));
+ stack->data[3] = 3.1415927f;
+ printf("stack size: %" c_ZI "\n", FloatStack_size(stack));
+
+ // Access the data entry
+ const ListMap* lmap_p = MapMap_at(&mmap, "first");
+ const StackList* list_p = ListMap_at(lmap_p, 42);
+ const FloatStack* stack_p = StackList_back(list_p);
+ printf("value is: %f\n", *FloatStack_at(stack_p, 3)); // pi
+
+ MapMap_drop(&mmap);
}
diff --git a/misc/examples/convert.c b/misc/examples/convert.c
index 160812b7..0f09e830 100644
--- a/misc/examples/convert.c
+++ b/misc/examples/convert.c
@@ -13,10 +13,17 @@
int main()
{
- c_auto (cmap_str, map, mclone)
- c_auto (cvec_str, keys, values)
- c_auto (clist_str, list)
- {
+ cmap_str map, mclone;
+ cvec_str keys = {0}, values = {0};
+ clist_str list = {0};
+
+ c_defer(
+ cmap_str_drop(&map),
+ cmap_str_drop(&mclone),
+ cvec_str_drop(&keys),
+ cvec_str_drop(&values),
+ clist_str_drop(&list)
+ ){
map = c_make(cmap_str, {
{"green", "#00ff00"},
{"blue", "#0000ff"},
diff --git a/misc/examples/coread.c b/misc/examples/coread.c
index c5f85e08..0a7f4816 100644
--- a/misc/examples/coread.c
+++ b/misc/examples/coread.c
@@ -20,17 +20,20 @@ bool file_nextline(struct file_nextline* U)
while (cstr_getline(&U->line, U->fp))
cco_yield(true);
- cco_final: // required label.
+ cco_final: // this label is required.
printf("finish\n");
cstr_drop(&U->line);
fclose(U->fp);
cco_end(false);
}
-int main(void) {
- struct file_nextline z = {__FILE__};
+int main(void)
+{
+ struct file_nextline it = {__FILE__};
int n = 0;
- while (file_nextline(&z)) {
- printf("%3d %s\n", ++n, cstr_str(&z.line));
+ while (file_nextline(&it))
+ {
+ printf("%3d %s\n", ++n, cstr_str(&it.line));
+ //if (n == 10) cco_stop(&it);
}
}
diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c
index 2c9e6d5c..b11b8532 100644
--- a/misc/examples/coroutines.c
+++ b/misc/examples/coroutines.c
@@ -85,6 +85,7 @@ bool combined(struct combined* C) {
// Reuse the C->prm context and extend the count:
C->prm.count = 8; C->prm.result += 2;
+ cco_reset(&C->prm);
cco_yield(prime(&C->prm), &C->prm, true);
cco_final: puts("final comb");
diff --git a/misc/examples/csmap_erase.c b/misc/examples/csmap_erase.c
index a3bd250b..697e6c09 100644
--- a/misc/examples/csmap_erase.c
+++ b/misc/examples/csmap_erase.c
@@ -17,68 +17,65 @@ void printmap(mymap m)
int main()
{
- c_auto (mymap, m1)
- {
- // Fill in some data to test with, one at a time
- mymap_insert(&m1, 1, cstr_lit("A"));
- mymap_insert(&m1, 2, cstr_lit("B"));
- mymap_insert(&m1, 3, cstr_lit("C"));
- mymap_insert(&m1, 4, cstr_lit("D"));
- mymap_insert(&m1, 5, cstr_lit("E"));
+ mymap m1 = {0};
- puts("Starting data of map m1 is:");
- printmap(m1);
- // The 1st member function removes an element at a given position
- mymap_erase_at(&m1, mymap_advance(mymap_begin(&m1), 1));
- puts("After the 2nd element is deleted, the map m1 is:");
- printmap(m1);
- }
+ // Fill in some data to test with, one at a time
+ mymap_insert(&m1, 1, cstr_lit("A"));
+ mymap_insert(&m1, 2, cstr_lit("B"));
+ mymap_insert(&m1, 3, cstr_lit("C"));
+ mymap_insert(&m1, 4, cstr_lit("D"));
+ mymap_insert(&m1, 5, cstr_lit("E"));
- c_auto (mymap, m2)
- {
- // Fill in some data to test with, one at a time
- m2 = c_make(mymap, {
- {10, "Bob"},
- {11, "Rob"},
- {12, "Robert"},
- {13, "Bert"},
- {14, "Bobby"},
- });
+ puts("Starting data of map m1 is:");
+ printmap(m1);
+ // The 1st member function removes an element at a given position
+ mymap_erase_at(&m1, mymap_advance(mymap_begin(&m1), 1));
+ puts("After the 2nd element is deleted, the map m1 is:");
+ printmap(m1);
- puts("Starting data of map m2 is:");
- printmap(m2);
- mymap_iter it1 = mymap_advance(mymap_begin(&m2), 1);
- mymap_iter it2 = mymap_find(&m2, mymap_back(&m2)->first);
+ // Fill in some data to test with
+ mymap m2 = c_make(mymap, {
+ {10, "Bob"},
+ {11, "Rob"},
+ {12, "Robert"},
+ {13, "Bert"},
+ {14, "Bobby"},
+ });
- puts("to remove:");
- c_foreach (i, mymap, it1, it2)
- printf(" [%d, %s]", i.ref->first, cstr_str(&i.ref->second));
- puts("");
- // The 2nd member function removes elements
- // in the range [First, Last)
- mymap_erase_range(&m2, it1, it2);
- puts("After the middle elements are deleted, the map m2 is:");
- printmap(m2);
- }
+ puts("Starting data of map m2 is:");
+ printmap(m2);
+ mymap_iter it1 = mymap_advance(mymap_begin(&m2), 1);
+ mymap_iter it2 = mymap_find(&m2, mymap_back(&m2)->first);
- c_auto (mymap, m3)
- {
- // Fill in some data to test with, one at a time, using emplace
- mymap_emplace(&m3, 1, "red");
- mymap_emplace(&m3, 2, "yellow");
- mymap_emplace(&m3, 3, "blue");
- mymap_emplace(&m3, 4, "green");
- mymap_emplace(&m3, 5, "orange");
- mymap_emplace(&m3, 6, "purple");
- mymap_emplace(&m3, 7, "pink");
+ puts("to remove:");
+ c_foreach (i, mymap, it1, it2)
+ printf(" [%d, %s]", i.ref->first, cstr_str(&i.ref->second));
+ puts("");
+ // The 2nd member function removes elements
+ // in the range [First, Last)
+ mymap_erase_range(&m2, it1, it2);
+ puts("After the middle elements are deleted, the map m2 is:");
+ printmap(m2);
- puts("Starting data of map m3 is:");
- printmap(m3);
- // The 3rd member function removes elements with a given Key
- 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: %d\n", count);
- puts("After the element with a key of 2 is deleted, the map m3 is:");
- printmap(m3);
- }
+ mymap m3 = {0};
+
+ // Fill in some data to test with, one at a time, using emplace
+ mymap_emplace(&m3, 1, "red");
+ mymap_emplace(&m3, 2, "yellow");
+ mymap_emplace(&m3, 3, "blue");
+ mymap_emplace(&m3, 4, "green");
+ mymap_emplace(&m3, 5, "orange");
+ mymap_emplace(&m3, 6, "purple");
+ mymap_emplace(&m3, 7, "pink");
+
+ puts("Starting data of map m3 is:");
+ printmap(m3);
+ // The 3rd member function removes elements with a given Key
+ 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: %d\n", count);
+ puts("After the element with a key of 2 is deleted, the map m3 is:");
+ printmap(m3);
+
+ c_drop(mymap, &m1, &m2, &m3);
}
diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c
index fe5558e2..c417567a 100644
--- a/misc/examples/csmap_find.c
+++ b/misc/examples/csmap_find.c
@@ -33,7 +33,7 @@ void findit(csmap_istr c, csmap_istr_key val)
{
printf("Trying find() on value %d\n", val);
csmap_istr_iter result = csmap_istr_find(&c, val); // prefer contains() or get()
- if (result.ref != csmap_istr_end(&c).ref) {
+ if (result.ref) {
printf("Element found: "); print_elem(csmap_istr_value_toraw(result.ref)); puts("");
} else {
puts("Element not found.");
@@ -42,32 +42,32 @@ void findit(csmap_istr c, csmap_istr_key val)
int main()
{
- c_auto (csmap_istr, m1)
- c_auto (cvec_istr, v)
- {
- m1 = c_make(csmap_istr, {{40, "Zr"}, {45, "Rh"}});
+ csmap_istr m1 = c_make(csmap_istr, {{40, "Zr"}, {45, "Rh"}});
+ cvec_istr v = {0};
- puts("The starting map m1 is (key, value):");
- print_collection_csmap_istr(&m1);
+ puts("The starting map m1 is (key, value):");
+ print_collection_csmap_istr(&m1);
- typedef cvec_istr_value pair;
- cvec_istr_push(&v, (pair){43, "Tc"});
- cvec_istr_push(&v, (pair){41, "Nb"});
- cvec_istr_push(&v, (pair){46, "Pd"});
- cvec_istr_push(&v, (pair){42, "Mo"});
- cvec_istr_push(&v, (pair){44, "Ru"});
- cvec_istr_push(&v, (pair){44, "Ru"}); // attempt a duplicate
+ typedef cvec_istr_value pair;
+ cvec_istr_push(&v, (pair){43, "Tc"});
+ cvec_istr_push(&v, (pair){41, "Nb"});
+ cvec_istr_push(&v, (pair){46, "Pd"});
+ cvec_istr_push(&v, (pair){42, "Mo"});
+ cvec_istr_push(&v, (pair){44, "Ru"});
+ cvec_istr_push(&v, (pair){44, "Ru"}); // attempt a duplicate
- puts("Inserting the following vector data into m1:");
- print_collection_cvec_istr(&v);
+ puts("Inserting the following vector data into m1:");
+ print_collection_cvec_istr(&v);
- c_foreach (i, cvec_istr, cvec_istr_begin(&v), cvec_istr_end(&v))
- csmap_istr_emplace(&m1, c_PAIR(i.ref));
+ c_foreach (i, cvec_istr, cvec_istr_begin(&v), cvec_istr_end(&v))
+ csmap_istr_emplace(&m1, i.ref->first, i.ref->second);
- puts("The modified map m1 is (key, value):");
- print_collection_csmap_istr(&m1);
- puts("");
- findit(m1, 45);
- findit(m1, 6);
- }
+ puts("The modified map m1 is (key, value):");
+ print_collection_csmap_istr(&m1);
+ puts("");
+ findit(m1, 45);
+ findit(m1, 6);
+
+ csmap_istr_drop(&m1);
+ cvec_istr_drop(&v);
}
diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c
index 64d71b12..3da245c7 100644
--- a/misc/examples/csmap_insert.c
+++ b/misc/examples/csmap_insert.c
@@ -1,13 +1,11 @@
-#include <stc/cstr.h>
-
// This implements the std::map insert c++ example at:
// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-19
-
#define i_key int
#define i_val int
#define i_tag ii // Map of int => int
#include <stc/csmap.h>
+#include <stc/cstr.h>
#define i_key int
#define i_val_str
#define i_tag istr // Map of int => cstr
@@ -33,77 +31,77 @@ void print_istr(csmap_istr map) {
int main()
{
// insert single values
- c_auto (csmap_ii, m1) {
- csmap_ii_insert(&m1, 1, 10);
- csmap_ii_insert(&m1, 2, 20);
-
- puts("The original key and mapped values of m1 are:");
- print_ii(m1);
-
- // intentionally attempt a duplicate, single element
- csmap_ii_result ret = csmap_ii_insert(&m1, 1, 111);
- if (!ret.inserted) {
- csmap_ii_value pr = *ret.ref;
- puts("Insert failed, element with key value 1 already exists.");
- printf(" The existing element is (%d, %d)\n", pr.first, pr.second);
- }
- else {
- puts("The modified key and mapped values of m1 are:");
- print_ii(m1);
- }
- puts("");
-
- csmap_ii_insert(&m1, 3, 30);
+ csmap_ii m1 = {0};
+ csmap_ii_insert(&m1, 1, 10);
+ csmap_ii_push(&m1, (csmap_ii_value){2, 20});
+
+ puts("The original key and mapped values of m1 are:");
+ print_ii(m1);
+
+ // intentionally attempt a duplicate, single element
+ csmap_ii_result ret = csmap_ii_insert(&m1, 1, 111);
+ if (!ret.inserted) {
+ csmap_ii_value pr = *ret.ref;
+ puts("Insert failed, element with key value 1 already exists.");
+ printf(" The existing element is (%d, %d)\n", pr.first, pr.second);
+ }
+ else {
puts("The modified key and mapped values of m1 are:");
print_ii(m1);
- puts("");
}
+ puts("");
+
+ csmap_ii_insert(&m1, 3, 30);
+ puts("The modified key and mapped values of m1 are:");
+ print_ii(m1);
+ puts("");
// The templatized version inserting a jumbled range
- c_auto (csmap_ii, m2)
- c_auto (cvec_ii, v) {
- typedef cvec_ii_value ipair;
- cvec_ii_push(&v, (ipair){43, 294});
- cvec_ii_push(&v, (ipair){41, 262});
- cvec_ii_push(&v, (ipair){45, 330});
- cvec_ii_push(&v, (ipair){42, 277});
- cvec_ii_push(&v, (ipair){44, 311});
-
- puts("Inserting the following vector data into m2:");
- c_foreach (e, cvec_ii, v)
- printf("(%d, %d) ", e.ref->first, e.ref->second);
- puts("");
-
- c_foreach (e, cvec_ii, v)
- csmap_ii_insert_or_assign(&m2, e.ref->first, e.ref->second);
-
- puts("The modified key and mapped values of m2 are:");
- c_foreach (e, csmap_ii, m2)
- printf("(%d, %d) ", e.ref->first, e.ref->second);
- puts("\n");
- }
+ csmap_ii m2 = {0};
+ cvec_ii v = {0};
+ typedef cvec_ii_value ipair;
+ cvec_ii_push(&v, (ipair){43, 294});
+ cvec_ii_push(&v, (ipair){41, 262});
+ cvec_ii_push(&v, (ipair){45, 330});
+ cvec_ii_push(&v, (ipair){42, 277});
+ cvec_ii_push(&v, (ipair){44, 311});
+
+ puts("Inserting the following vector data into m2:");
+ c_foreach (e, cvec_ii, v)
+ printf("(%d, %d) ", e.ref->first, e.ref->second);
+ puts("");
+
+ c_foreach (e, cvec_ii, v)
+ csmap_ii_insert_or_assign(&m2, e.ref->first, e.ref->second);
+
+ puts("The modified key and mapped values of m2 are:");
+ c_foreach (e, csmap_ii, m2)
+ printf("(%d, %d) ", e.ref->first, e.ref->second);
+ puts("\n");
// The templatized versions move-constructing elements
- c_auto (csmap_istr, m3) {
- csmap_istr_value ip1 = {475, cstr_lit("blue")}, ip2 = {510, cstr_lit("green")};
-
- // single element
- csmap_istr_insert(&m3, ip1.first, cstr_move(&ip1.second));
- puts("After the first move insertion, m3 contains:");
- print_istr(m3);
-
- // single element
- csmap_istr_insert(&m3, ip2.first, cstr_move(&ip2.second));
- puts("After the second move insertion, m3 contains:");
- print_istr(m3);
- puts("");
- }
+ csmap_istr m3 = {0};
+ csmap_istr_value ip1 = {475, cstr_lit("blue")}, ip2 = {510, cstr_lit("green")};
+
+ // single element
+ csmap_istr_insert(&m3, ip1.first, cstr_move(&ip1.second));
+ puts("After the first move insertion, m3 contains:");
+ print_istr(m3);
+
+ // single element
+ csmap_istr_insert(&m3, ip2.first, cstr_move(&ip2.second));
+ puts("After the second move insertion, m3 contains:");
+ print_istr(m3);
+ puts("");
- c_auto (csmap_ii, m4) {
- // Insert the elements from an initializer_list
- m4 = c_make(csmap_ii, {{4, 44}, {2, 22}, {3, 33}, {1, 11}, {5, 55}});
- puts("After initializer_list insertion, m4 contains:");
- print_ii(m4);
- puts("");
- }
+ csmap_ii m4 = {0};
+ // Insert the elements from an initializer_list
+ m4 = c_make(csmap_ii, {{4, 44}, {2, 22}, {3, 33}, {1, 11}, {5, 55}});
+ puts("After initializer_list insertion, m4 contains:");
+ print_ii(m4);
+ puts("");
+
+ cvec_ii_drop(&v);
+ csmap_istr_drop(&m3);
+ c_drop(csmap_ii, &m1, &m2, &m4);
}
diff --git a/misc/examples/csset_erase.c b/misc/examples/csset_erase.c
index e8f2fec5..9fa40682 100644
--- a/misc/examples/csset_erase.c
+++ b/misc/examples/csset_erase.c
@@ -5,38 +5,37 @@
int main()
{
- c_auto (csset_int, set)
- {
- set = c_make(csset_int, {30, 20, 80, 40, 60, 90, 10, 70, 50});
-
- c_foreach (k, csset_int, set)
- printf(" %d", *k.ref);
- puts("");
-
- int val = 64;
- csset_int_iter it;
- printf("Show values >= %d:\n", val);
- it = csset_int_lower_bound(&set, val);
-
- c_foreach (k, csset_int, it, csset_int_end(&set))
- printf(" %d", *k.ref);
- puts("");
-
- printf("Erase values >= %d:\n", val);
- while (it.ref != csset_int_end(&set).ref)
- it = csset_int_erase_at(&set, it);
-
- c_foreach (k, csset_int, set)
- printf(" %d", *k.ref);
- puts("");
-
- val = 40;
- printf("Erase values < %d:\n", val);
- it = csset_int_lower_bound(&set, val);
- csset_int_erase_range(&set, csset_int_begin(&set), it);
-
- c_foreach (k, csset_int, set)
- printf(" %d", *k.ref);
- puts("");
- }
-}
+ csset_int set = c_make(csset_int, {30, 20, 80, 40, 60, 90, 10, 70, 50});
+
+ c_foreach (k, csset_int, set)
+ printf(" %d", *k.ref);
+ puts("");
+
+ int val = 64;
+ csset_int_iter it;
+ printf("Show values >= %d:\n", val);
+ it = csset_int_lower_bound(&set, val);
+
+ c_foreach (k, csset_int, it, csset_int_end(&set))
+ printf(" %d", *k.ref);
+ puts("");
+
+ printf("Erase values >= %d:\n", val);
+ while (it.ref)
+ it = csset_int_erase_at(&set, it);
+
+ c_foreach (k, csset_int, set)
+ printf(" %d", *k.ref);
+ puts("");
+
+ val = 40;
+ printf("Erase values < %d:\n", val);
+ it = csset_int_lower_bound(&set, val);
+ csset_int_erase_range(&set, csset_int_begin(&set), it);
+
+ c_foreach (k, csset_int, set)
+ printf(" %d", *k.ref);
+ puts("");
+
+ csset_int_drop(&set);
+} \ No newline at end of file
diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c
index 6682c4ba..58cf8884 100644
--- a/misc/examples/cstr_match.c
+++ b/misc/examples/cstr_match.c
@@ -4,20 +4,22 @@
int main()
{
- c_with (cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) {
- 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"));
- printf("ends_with: %d\n", cstr_ends_with(&ss, ".jpg"));
- printf("ends_with: %d\n", cstr_ends_with(&ss, ".JPG"));
+ cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG");
- 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_ZI ", %" c_ZI "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1));
- printf("ch1: %.*s\n", c_SV(ch1));
- printf("ch2: %.*s\n", c_SV(ch2));
- }
+ 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"));
+ printf("ends_with: %d\n", cstr_ends_with(&ss, ".jpg"));
+ printf("ends_with: %d\n", cstr_ends_with(&ss, ".JPG"));
+
+ 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_ZI ", %" c_ZI "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1));
+ printf("ch1: %.*s\n", c_SV(ch1));
+ printf("ch2: %.*s\n", c_SV(ch2));
+
+ c_drop(cstr, &ss, &s1);
}
diff --git a/misc/examples/demos.c b/misc/examples/demos.c
index d5336cbf..de92e378 100644
--- a/misc/examples/demos.c
+++ b/misc/examples/demos.c
@@ -2,30 +2,29 @@
void stringdemo1()
{
- printf("\nSTRINGDEMO1\n");
- c_with (cstr cs = cstr_lit("one-nine-three-seven-five"), cstr_drop(&cs))
- {
- printf("%s.\n", cstr_str(&cs));
+ cstr cs = cstr_lit("one-nine-three-seven-five");
+ printf("%s.\n", cstr_str(&cs));
- cstr_insert(&cs, 3, "-two");
- printf("%s.\n", cstr_str(&cs));
+ cstr_insert(&cs, 3, "-two");
+ printf("%s.\n", cstr_str(&cs));
- cstr_erase(&cs, 7, 5); // -nine
- printf("%s.\n", cstr_str(&cs));
+ cstr_erase(&cs, 7, 5); // -nine
+ printf("%s.\n", cstr_str(&cs));
- cstr_replace(&cs, "seven", "four", 1);
- printf("%s.\n", cstr_str(&cs));
+ 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)));
- printf("%s.\n", cstr_str(&cs));
+ cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
+ printf("%s.\n", cstr_str(&cs));
- printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(&cs, "four"));
+ printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(&cs, "four"));
- // reassign:
- cstr_assign(&cs, "one two three four five six seven");
- cstr_append(&cs, " eight");
- printf("append: %s\n", cstr_str(&cs));
- }
+ // reassign:
+ cstr_assign(&cs, "one two three four five six seven");
+ cstr_append(&cs, " eight");
+ printf("append: %s\n", cstr_str(&cs));
+
+ cstr_drop(&cs);
}
#define i_val int64_t
@@ -34,23 +33,22 @@ void stringdemo1()
void vectordemo1()
{
- printf("\nVECTORDEMO1\n");
- c_with (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_drop(&bignums))
- {
- cvec_ix_reserve(&bignums, 100);
- for (int i = 10; i <= 100; i += 10)
- cvec_ix_push(&bignums, i * i);
-
- printf("erase - %d: %" PRIu64 "\n", 3, bignums.data[3]);
- cvec_ix_erase_n(&bignums, 3, 1); // erase index 3
-
- cvec_ix_pop(&bignums); // erase the last
- cvec_ix_erase_n(&bignums, 0, 1); // erase the first
-
- for (int i = 0; i < cvec_ix_size(&bignums); ++i) {
- printf("%d: %" PRIu64 "\n", i, bignums.data[i]);
- }
+ cvec_ix bignums = cvec_ix_with_capacity(100);
+ cvec_ix_reserve(&bignums, 100);
+ for (int i = 10; i <= 100; i += 10)
+ cvec_ix_push(&bignums, i * i);
+
+ printf("erase - %d: %" PRIu64 "\n", 3, bignums.data[3]);
+ cvec_ix_erase_n(&bignums, 3, 1); // erase index 3
+
+ cvec_ix_pop(&bignums); // erase the last
+ cvec_ix_erase_n(&bignums, 0, 1); // erase the first
+
+ for (int i = 0; i < cvec_ix_size(&bignums); ++i) {
+ printf("%d: %" PRIu64 "\n", i, bignums.data[i]);
}
+
+ cvec_ix_drop(&bignums);
}
#define i_val_str
@@ -58,52 +56,51 @@ void vectordemo1()
void vectordemo2()
{
- printf("\nVECTORDEMO2\n");
- c_auto (cvec_str, names) {
- cvec_str_emplace_back(&names, "Mary");
- cvec_str_emplace_back(&names, "Joe");
- cvec_str_emplace_back(&names, "Chris");
- cstr_assign(&names.data[1], "Jane"); // replace Joe
- printf("names[1]: %s\n", cstr_str(&names.data[1]));
-
- cvec_str_sort(&names); // Sort the array
- c_foreach (i, cvec_str, names)
- printf("sorted: %s\n", cstr_str(i.ref));
- }
+ cvec_str names = {0};
+ cvec_str_emplace_back(&names, "Mary");
+ cvec_str_emplace_back(&names, "Joe");
+ cvec_str_emplace_back(&names, "Chris");
+ cstr_assign(&names.data[1], "Jane"); // replace Joe
+ printf("names[1]: %s\n", cstr_str(&names.data[1]));
+
+ cvec_str_sort(&names); // Sort the array
+
+ c_foreach (i, cvec_str, names)
+ printf("sorted: %s\n", cstr_str(i.ref));
+
+ cvec_str_drop(&names);
}
#define i_val int
#define i_tag ix
-#define i_extern // define _clist_mergesort() once
#include <stc/clist.h>
void listdemo1()
{
- printf("\nLISTDEMO1\n");
- c_auto (clist_ix, nums, nums2)
- {
- for (int i = 0; i < 10; ++i)
- clist_ix_push_back(&nums, i);
- for (int i = 100; i < 110; ++i)
- clist_ix_push_back(&nums2, i);
-
- /* splice nums2 to front of nums */
- clist_ix_splice(&nums, clist_ix_begin(&nums), &nums2);
- c_foreach (i, clist_ix, nums)
- printf("spliced: %d\n", *i.ref);
- puts("");
-
- *clist_ix_find(&nums, 104).ref += 50;
- clist_ix_remove(&nums, 103);
- clist_ix_iter it = clist_ix_begin(&nums);
- clist_ix_erase_range(&nums, clist_ix_advance(it, 5), clist_ix_advance(it, 15));
- clist_ix_pop_front(&nums);
- clist_ix_push_back(&nums, -99);
- clist_ix_sort(&nums);
-
- c_foreach (i, clist_ix, nums)
- printf("sorted: %d\n", *i.ref);
- }
+ clist_ix nums = {0}, nums2 = {0};
+ for (int i = 0; i < 10; ++i)
+ clist_ix_push_back(&nums, i);
+ for (int i = 100; i < 110; ++i)
+ clist_ix_push_back(&nums2, i);
+
+ /* splice nums2 to front of nums */
+ clist_ix_splice(&nums, clist_ix_begin(&nums), &nums2);
+ c_foreach (i, clist_ix, nums)
+ printf("spliced: %d\n", *i.ref);
+ puts("");
+
+ *clist_ix_find(&nums, 104).ref += 50;
+ clist_ix_remove(&nums, 103);
+ clist_ix_iter it = clist_ix_begin(&nums);
+ clist_ix_erase_range(&nums, clist_ix_advance(it, 5), clist_ix_advance(it, 15));
+ clist_ix_pop_front(&nums);
+ clist_ix_push_back(&nums, -99);
+ clist_ix_sort(&nums);
+
+ c_foreach (i, clist_ix, nums)
+ printf("sorted: %d\n", *i.ref);
+
+ c_drop(clist_ix, &nums, &nums2);
}
#define i_key int
@@ -112,8 +109,7 @@ void listdemo1()
void setdemo1()
{
- printf("\nSETDEMO1\n");
- cset_i nums = cset_i_init();
+ cset_i nums = {0};
cset_i_insert(&nums, 8);
cset_i_insert(&nums, 11);
@@ -129,8 +125,7 @@ void setdemo1()
void mapdemo1()
{
- printf("\nMAPDEMO1\n");
- cmap_ii nums = cmap_ii_init();
+ cmap_ii nums = {0};
cmap_ii_insert(&nums, 8, 64);
cmap_ii_insert(&nums, 11, 121);
printf("val 8: %d\n", *cmap_ii_at(&nums, 8));
@@ -144,21 +139,20 @@ void mapdemo1()
void mapdemo2()
{
- printf("\nMAPDEMO2\n");
- c_auto (cmap_si, nums)
- {
- cmap_si_emplace_or_assign(&nums, "Hello", 64);
- cmap_si_emplace_or_assign(&nums, "Groovy", 121);
- cmap_si_emplace_or_assign(&nums, "Groovy", 200); // overwrite previous
-
- // iterate the map:
- for (cmap_si_iter i = cmap_si_begin(&nums); i.ref != cmap_si_end(&nums).ref; cmap_si_next(&i))
- printf("long: %s: %d\n", cstr_str(&i.ref->first), i.ref->second);
-
- // or rather use the short form:
- c_foreach (i, cmap_si, nums)
- printf("short: %s: %d\n", cstr_str(&i.ref->first), i.ref->second);
- }
+ cmap_si nums = {0};
+ cmap_si_emplace_or_assign(&nums, "Hello", 64);
+ cmap_si_emplace_or_assign(&nums, "Groovy", 121);
+ cmap_si_emplace_or_assign(&nums, "Groovy", 200); // overwrite previous
+
+ // iterate the map:
+ for (cmap_si_iter i = cmap_si_begin(&nums); i.ref; cmap_si_next(&i))
+ printf("long: %s: %d\n", cstr_str(&i.ref->first), i.ref->second);
+
+ // or rather use the short form:
+ c_foreach (i, cmap_si, nums)
+ printf("short: %s: %d\n", cstr_str(&i.ref->first), i.ref->second);
+
+ cmap_si_drop(&nums);
}
#define i_key_str
@@ -167,8 +161,7 @@ void mapdemo2()
void mapdemo3()
{
- printf("\nMAPDEMO3\n");
- cmap_str table = cmap_str_init();
+ cmap_str table = {0};
cmap_str_emplace(&table, "Map", "test");
cmap_str_emplace(&table, "Make", "my");
cmap_str_emplace(&table, "Sunny", "day");
@@ -182,17 +175,18 @@ void mapdemo3()
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.
}
int main()
{
- stringdemo1();
- vectordemo1();
- vectordemo2();
- listdemo1();
- setdemo1();
- mapdemo1();
- mapdemo2();
- mapdemo3();
+ printf("\nSTRINGDEMO1\n"); stringdemo1();
+ printf("\nVECTORDEMO1\n"); vectordemo1();
+ printf("\nVECTORDEMO2\n"); vectordemo2();
+ printf("\nLISTDEMO1\n"); listdemo1();
+ printf("\nSETDEMO1\n"); setdemo1();
+ printf("\nMAPDEMO1\n"); mapdemo1();
+ printf("\nMAPDEMO2\n"); mapdemo2();
+ printf("\nMAPDEMO3\n"); mapdemo3();
}
diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c
index 2be975a6..fbb7280f 100644
--- a/misc/examples/forfilter.c
+++ b/misc/examples/forfilter.c
@@ -9,10 +9,6 @@
#define i_val int
#include <stc/cstack.h>
-#define i_type SVec
-#define i_valclass csview
-#include <stc/cstack.h>
-
// filters and transforms:
#define flt_skipValue(i, x) (*i.ref != (x))
#define flt_isEven(i) ((*i.ref & 1) == 0)
@@ -21,30 +17,26 @@
void demo1(void)
{
- c_auto (IVec, vec) {
- c_forlist (i, int, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80,
- 10, 11, 12, 13, 14, 15, 80, 16, 17})
- IVec_push(&vec, *i.ref);
-
- puts("demo1:");
- c_forfilter (i, IVec, vec, flt_skipValue(i, 80))
- printf(" %d", *i.ref);
- puts("");
-
- 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)
- && flt_isEven(i)
- && flt_skipValue(i, 80)
- && c_flt_take(i, 5) // short-circuit
- ){
- sum += res = flt_square(i);
- printf(" %d", res);
- }
- printf("\n sum: %d\n", sum);
+ IVec vec = c_make(IVec, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80,
+ 10, 11, 12, 13, 14, 15, 80, 16, 17});
+
+ c_forfilter (i, IVec, vec, flt_skipValue(i, 80))
+ printf(" %d", *i.ref);
+ puts("");
+
+ int sum = 0;
+ c_forfilter (i, IVec, vec,
+ c_flt_skipwhile(i, *i.ref != 80) &&
+ c_flt_skip(i, 1) &&
+ flt_isEven(i) &&
+ flt_skipValue(i, 80) &&
+ c_flt_take(i, 5) // short-circuit
+ ){
+ sum += flt_square(i);
}
+
+ printf("\n sum: %d\n", sum);
+ IVec_drop(&vec);
}
@@ -59,21 +51,20 @@ fn main() {
println!("{:?}", vector); // Print result
}
*/
-
void demo2(void)
{
- c_auto (IVec, vector) {
- puts("demo2:");
- 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, (int)(*x.ref * *x.ref));
- c_foreach (x, IVec, vector)
- printf(" %d", *x.ref);
- puts("");
+ IVec vector = {0};
+ c_forfilter (x, crange, crange_obj(INT64_MAX),
+ c_flt_skipwhile(x, *x.ref != 11) &&
+ (*x.ref % 2) != 0 &&
+ c_flt_take(x, 5)
+ ){
+ IVec_push(&vector, (int)(*x.ref * *x.ref));
}
+ c_foreach (x, IVec, vector) printf(" %d", *x.ref);
+
+ puts("");
+ IVec_drop(&vector);
}
/* Rust:
@@ -89,59 +80,68 @@ fn main() {
println!("{:?}", words_containing_i);
}
*/
+#define i_type SVec
+#define i_valclass csview
+#include <stc/cstack.h>
+
void demo3(void)
{
- c_auto (SVec, words, words_containing_i) {
- const char* sentence = "This is a sentence in C99.";
- c_fortoken (w, sentence, " ")
- SVec_push(&words, *w.ref);
-
- c_forfilter (w, SVec, words,
- csview_contains(*w.ref, "i"))
- SVec_push(&words_containing_i, *w.ref);
-
- puts("demo3:");
- c_foreach (w, SVec, words_containing_i)
- printf(" %.*s", c_SV(*w.ref));
- puts("");
- }
+ const char* sentence = "This is a sentence in C99.";
+ SVec words = {0};
+ c_fortoken (w, sentence, " ") // split words
+ SVec_push(&words, *w.ref);
+
+ SVec words_containing_i = {0};
+ c_forfilter (w, SVec, words,
+ csview_contains(*w.ref, "i"))
+ SVec_push(&words_containing_i, *w.ref);
+
+ c_foreach (w, SVec, words_containing_i)
+ printf(" %.*s", c_SV(*w.ref));
+
+ puts("");
+ c_drop(SVec, &words, &words_containing_i);
}
void demo4(void)
{
+ // Keep only uppercase letters and convert them to lowercase:
csview s = c_sv("ab123cReAghNGnΩoEp"); // Ω = multi-byte
- c_auto (cstr, out) {
- c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) {
- char chr[4];
- utf8_encode(chr, utf8_tolower(utf8_peek(i.ref)));
- cstr_push(&out, chr);
- }
- puts("demo4:");
- printf(" %s\n", cstr_str(&out));
+ cstr out = {0};
+
+ c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) {
+ char chr[4];
+ utf8_encode(chr, utf8_tolower(utf8_peek(i.ref)));
+ cstr_push(&out, chr);
}
+
+ printf(" %s\n", cstr_str(&out));
+ cstr_drop(&out);
}
void demo5(void)
{
#define flt_even(i) ((*i.ref & 1) == 0)
#define flt_mid_decade(i) ((*i.ref % 10) != 0)
- puts("demo5:");
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,5))
+
+ 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,5)
+ ){
printf(" %lld", *i.ref);
+ }
puts("");
}
int main(void)
{
- demo1();
- demo2();
- demo3();
- demo4();
- demo5();
+ puts("demo1"); demo1();
+ puts("demo2"); demo2();
+ puts("demo3"); demo3();
+ puts("demo4"); demo4();
+ puts("demo5"); demo5();
}
diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c
index 707e8285..1fc00614 100644
--- a/misc/examples/forloops.c
+++ b/misc/examples/forloops.c
@@ -25,7 +25,6 @@ int main()
c_forrange (i, 30, 90, 2) printf(" %lld", i);
-
puts("\n\nc_forlist:");
c_forlist (i, int, {12, 23, 453, 65, 676})
printf(" %d", *i.ref);
@@ -35,47 +34,36 @@ int main()
printf(" %s", *i.ref);
puts("");
- c_forlist (i, const char*, {"12", "23", "453", "65", "676"})
- printf(" %s", i.data[i.size - 1 - i.index]);
-
-
- c_auto (IVec, vec)
- c_auto (IMap, map)
- {
- c_forlist (i, int, {12, 23, 453, 65, 113, 215, 676, 34, 67, 20, 27, 66, 189, 45, 280, 199})
- IVec_push(&vec, *i.ref);
-
- c_forlist (i, IMap_value, {{12, 23}, {453, 65}, {676, 123}, {34, 67}})
- IMap_push(&map, *i.ref);
-
- puts("\n\nc_foreach:");
- c_foreach (i, IVec, vec)
- printf(" %d", *i.ref);
- puts("");
-
- c_foreach (i, IMap, map)
- printf(" (%d %d)", i.ref->first, i.ref->second);
-
- puts("\n\nc_forpair:");
- c_forpair (key, val, IMap, map)
- printf(" (%d %d)", *_.key, *_.val);
-
- puts("\n\nc_forwhile:");
- c_forwhile (i, IVec, IVec_begin(&vec), i.index < 3)
- printf(" %d", *i.ref);
-
- #define isOdd(i) (*i.ref & 1)
-
- 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))
- && isOdd(i)
- && c_flt_skip(i, 2)
- && c_flt_take(i, 2))
- printf(" %d", *i.ref);
- puts("");
- // 189
+ IVec vec = c_make(IVec, {12, 23, 453, 65, 113, 215, 676, 34, 67, 20, 27, 66, 189, 45, 280, 199});
+ IMap map = c_make(IMap, {{12, 23}, {453, 65}, {676, 123}, {34, 67}});
+
+ puts("\n\nc_foreach:");
+ c_foreach (i, IVec, vec)
+ printf(" %d", *i.ref);
+
+ puts("\n\nc_foreach_r: reverse");
+ c_foreach_rv (i, IVec, vec)
+ printf(" %d", *i.ref);
+
+ puts("\n\nc_foreach in map:");
+ c_foreach (i, IMap, map)
+ printf(" (%d %d)", i.ref->first, i.ref->second);
+
+ puts("\n\nc_forpair:");
+ c_forpair (key, val, IMap, map)
+ printf(" (%d %d)", *_.key, *_.val);
+
+ #define isOdd(i) (*i.ref & 1)
+
+ puts("\n\nc_forfilter:");
+ c_forfilter (i, IVec, vec,
+ isOdd(i) &&
+ c_flt_skip(i, 4) &&
+ c_flt_take(i, 4)
+ ){
+ printf(" %d", *i.ref);
}
+
+ IVec_drop(&vec);
+ IMap_drop(&map);
}
diff --git a/misc/examples/functor.c b/misc/examples/functor.c
index 6d42c4f8..c0a4f8e8 100644
--- a/misc/examples/functor.c
+++ b/misc/examples/functor.c
@@ -1,40 +1,29 @@
// Implements c++ example: https://en.cppreference.com/w/cpp/container/priority_queue
// Example of per-instance less-function on a single priority queue type
//
-// Note: i_less_functor: available for cpque types only
-// i_cmp_functor: available for csmap and csset types only
-// i_hash_functor/i_eq_functor: available for cmap and cset types only
+// Note: i_less: has self for cpque types only
+// i_cmp: has self for csmap and csset types only
+// i_hash/i_eq: has self for cmap and cset types only
#include <stdio.h>
-#include <stdbool.h>
-#include <stc/forward.h>
-#include <stc/algo/crange.h>
-#include <stc/cstr.h>
-// predeclare
-forward_cpque(ipque, int);
-
-struct {
- ipque Q;
- bool (*less)(const int*, const int*);
-} typedef IPQueue;
-
-
-#define i_type ipque
+#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)
-#include <stc/cpque.h>
+#define i_extend bool (*less)(const int*, const int*);
+#define i_less(x, y) c_getcon(self)->less(x, y)
+#define i_con cpque
+#include <stc/extend.h>
-void print_queue(const char* name, IPQueue q) {
+void print_queue(const char* name, IPQue_ext q) {
// NB: make a clone because there is no way to traverse
// priority_queue's content without erasing the queue.
- IPQueue copy = {ipque_clone(q.Q), q.less};
+ IPQue_ext copy = {q.less, IPQue_clone(q.get)};
- for (printf("%s: \t", name); !ipque_empty(&copy.Q); ipque_pop(&copy.Q))
- printf("%d ", *ipque_top(&copy.Q));
+ for (printf("%s: \t", name); !IPQue_empty(&copy.get); IPQue_pop(&copy.get))
+ printf("%d ", *IPQue_top(&copy.get));
puts("");
- ipque_drop(&copy.Q);
+
+ IPQue_drop(&copy.get);
}
static bool int_less(const int* x, const int* y) { return *x < *y; }
@@ -43,26 +32,27 @@ static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1);
int main()
{
- const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_ARRAYLEN(data);
+ const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data);
printf("data: \t");
- c_forrange (i, n) printf("%d ", data[i]);
+ c_forrange (i, n)
+ printf("%d ", data[i]);
puts("");
- IPQueue q1 = {ipque_init(), int_less}; // Max priority queue
- IPQueue minq1 = {ipque_init(), int_greater}; // Min priority queue
- IPQueue q5 = {ipque_init(), int_lambda}; // Using lambda to compare elements.
- c_defer (ipque_drop(&q1.Q), ipque_drop(&minq1.Q), ipque_drop(&q5.Q))
- {
- c_forrange (i, n)
- ipque_push(&q1.Q, data[i]);
- print_queue("q1", q1);
+ IPQue_ext q1 = {int_less}; // Max priority queue
+ IPQue_ext minq1 = {int_greater}; // Min priority queue
+ IPQue_ext q5 = {int_lambda}; // Using lambda to compare elements.
+
+ c_forrange (i, n)
+ IPQue_push(&q1.get, data[i]);
+ print_queue("q1", q1);
+
+ c_forrange (i, n)
+ IPQue_push(&minq1.get, data[i]);
+ print_queue("minq1", minq1);
- c_forrange (i, n)
- ipque_push(&minq1.Q, data[i]);
- print_queue("minq1", minq1);
+ c_forrange (i, n)
+ IPQue_push(&q5.get, data[i]);
+ print_queue("q5", q5);
- c_forrange (i, n)
- ipque_push(&q5.Q, data[i]);
- print_queue("q5", q5);
- }
+ c_drop(IPQue, &q1.get, &minq1.get, &q5.get);
}
diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c
deleted file mode 100644
index 40d0981f..00000000
--- a/misc/examples/gauss1.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include <time.h>
-#include <math.h>
-
-#include <stc/crandom.h>
-#include <stc/cstr.h>
-
-// Declare int -> int hashmap. Uses typetag 'ii' for ints.
-#define i_key int
-#define i_val int
-#define i_tag ii
-#include <stc/cmap.h>
-
-// Declare int vector with entries from the cmap.
-#define i_val cmap_ii_value
-#define i_less(x, y) x->first < y->first
-#define i_tag ii
-#include <stc/cvec.h>
-
-int main()
-{
- enum {N = 10000000};
- const double Mean = -12.0, StdDev = 6.0, Scale = 74;
-
- printf("Demo of gaussian / normal distribution of %d random samples\n", N);
-
- // Setup random engine with normal distribution.
- uint64_t seed = (uint64_t)time(NULL);
- stc64_t rng = stc64_new(seed);
- stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev);
-
- // Create and init histogram vec and map with defered destructors:
- c_auto (cvec_ii, histvec)
- c_auto (cmap_ii, histmap)
- {
- c_forrange (N) {
- int index = (int)round( stc64_normalf(&rng, &dist) );
- cmap_ii_insert(&histmap, index, 0).ref->second += 1;
- }
-
- // Transfer map to vec and sort it by map keys.
- c_foreach (i, cmap_ii, histmap)
- cvec_ii_push(&histvec, (cmap_ii_value){i.ref->first, i.ref->second});
-
- cvec_ii_sort(&histvec);
-
- // Print the gaussian bar chart
- c_foreach (i, cvec_ii, histvec) {
- int n = (int)(i.ref->second * StdDev * Scale * 2.5 / (double)N);
- if (n > 0) {
- printf("%4d ", i.ref->first);
- c_forrange (n) printf("*");
- puts("");
- }
- }
- }
-}
diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c
index c531e5e3..df709d03 100644
--- a/misc/examples/gauss2.c
+++ b/misc/examples/gauss2.c
@@ -1,42 +1,44 @@
#include <stdio.h>
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stc/cstr.h>
// Declare int -> int sorted map.
#define i_key int
-#define i_val size_t
+#define i_val int
#include <stc/csmap.h>
int main()
{
- enum {N = 10000000};
- const double Mean = -12.0, StdDev = 6.0, Scale = 74;
+ enum {N = 5000000};
+ uint64_t seed = (uint64_t)time(NULL);
+ crand_t rng = crand_init(seed);
+ const double Mean = round(crand_f64(&rng)*98.f - 49.f), StdDev = crand_f64(&rng)*10.f + 1.f, Scale = 74.f;
printf("Demo of gaussian / normal distribution of %d random samples\n", N);
+ printf("Mean %f, StdDev %f\n", Mean, StdDev);
// Setup random engine with normal distribution.
- uint64_t seed = (uint64_t)time(NULL);
- stc64_t rng = stc64_new(seed);
- stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev);
+ crand_norm_t dist = crand_norm_init(Mean, StdDev);
// Create and init histogram map with defered destruct
- c_auto (csmap_int, mhist)
- {
- c_forrange (N) {
- int index = (int) round( stc64_normalf(&rng, &dist) );
- csmap_int_insert(&mhist, index, 0).ref->second += 1;
- }
+ csmap_int hist = {0};
+ cstr bar = {0};
+
+ c_forrange (N) {
+ int index = (int)round(crand_norm(&rng, &dist));
+ csmap_int_insert(&hist, index, 0).ref->second += 1;
+ }
- // Print the gaussian bar chart
- c_auto (cstr, bar)
- c_forpair (index, count, csmap_int, mhist) {
- 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));
- }
+ // Print the gaussian bar chart
+ c_forpair (index, count, csmap_int, hist) {
+ int n = (int)round((double)*_.count * StdDev * Scale * 2.5 / (double)N);
+ if (n > 0) {
+ cstr_resize(&bar, n, '*');
+ printf("%4d %s\n", *_.index, cstr_str(&bar));
}
}
+ cstr_drop(&bar);
+ csmap_int_drop(&hist);
}
diff --git a/misc/examples/generator.c b/misc/examples/generator.c
index f83ff3f2..2bccc489 100644
--- a/misc/examples/generator.c
+++ b/misc/examples/generator.c
@@ -20,8 +20,8 @@ bool Triple_next(Triple_iter* it) {
for (t->a = 1; t->a < t->c; ++t->a) {
for (t->b = t->a; t->b < t->c; ++t->b) {
if (t->a*t->a + t->b*t->b == t->c*t->c) {
+ if (t->n-- == 0) cco_return;
cco_yield(true);
- if (t->n-- == 1) cco_return;
}
}
}
diff --git a/misc/examples/hashmap.c b/misc/examples/hashmap.c
index f59ed824..47a3bcff 100644
--- a/misc/examples/hashmap.c
+++ b/misc/examples/hashmap.c
@@ -17,32 +17,33 @@ const char* call(const char* number) {
}
int main(void) {
- c_auto (cmap_str, contacts)
- {
- cmap_str_emplace(&contacts, "Daniel", "798-1364");
- cmap_str_emplace(&contacts, "Ashley", "645-7689");
- cmap_str_emplace(&contacts, "Katie", "435-8291");
- cmap_str_emplace(&contacts, "Robert", "956-1745");
-
- const cmap_str_value* v;
- if ((v = cmap_str_get(&contacts, "Daniel")))
- printf("Calling Daniel: %s\n", call(cstr_str(&v->second)));
- else
- printf("Don't have Daniel's number.");
-
- cmap_str_emplace_or_assign(&contacts, "Daniel", "164-6743");
-
- if ((v = cmap_str_get(&contacts, "Ashley")))
- printf("Calling Ashley: %s\n", call(cstr_str(&v->second)));
- else
- printf("Don't have Ashley's number.");
-
- cmap_str_erase(&contacts, "Ashley");
-
- puts("");
- c_forpair (contact, number, cmap_str, contacts) {
- printf("Calling %s: %s\n", cstr_str(_.contact), call(cstr_str(_.number)));
- }
- puts("");
+ cmap_str contacts = {0};
+
+ cmap_str_emplace(&contacts, "Daniel", "798-1364");
+ cmap_str_emplace(&contacts, "Ashley", "645-7689");
+ cmap_str_emplace(&contacts, "Katie", "435-8291");
+ cmap_str_emplace(&contacts, "Robert", "956-1745");
+
+ const cmap_str_value* v;
+ if ((v = cmap_str_get(&contacts, "Daniel")))
+ printf("Calling Daniel: %s\n", call(cstr_str(&v->second)));
+ else
+ printf("Don't have Daniel's number.");
+
+ cmap_str_emplace_or_assign(&contacts, "Daniel", "164-6743");
+
+ if ((v = cmap_str_get(&contacts, "Ashley")))
+ printf("Calling Ashley: %s\n", call(cstr_str(&v->second)));
+ else
+ printf("Don't have Ashley's number.");
+
+ cmap_str_erase(&contacts, "Ashley");
+
+ puts("");
+ c_forpair (contact, number, cmap_str, contacts) {
+ printf("Calling %s: %s\n", cstr_str(_.contact), call(cstr_str(_.number)));
}
+ puts("");
+
+ cmap_str_drop(&contacts);
}
diff --git a/misc/examples/inits.c b/misc/examples/inits.c
index 3d03ee91..81bcdd3e 100644
--- a/misc/examples/inits.c
+++ b/misc/examples/inits.c
@@ -36,79 +36,73 @@ int main(void)
{
// CVEC FLOAT / PRIORITY QUEUE
- c_auto (cpque_f, floats) {
- const float nums[] = {4.0f, 2.0f, 5.0f, 3.0f, 1.0f};
-
- // PRIORITY QUEUE
- c_forrange (i, c_ARRAYLEN(nums))
- cpque_f_push(&floats, nums[i]);
-
- puts("\npop and show high priorites first:");
- while (! cpque_f_empty(&floats)) {
- printf("%.1f ", *cpque_f_top(&floats));
- cpque_f_pop(&floats);
- }
- puts("\n");
+ cpque_f floats = {0};
+ const float nums[] = {4.0f, 2.0f, 5.0f, 3.0f, 1.0f};
+
+ // PRIORITY QUEUE
+ c_forrange (i, c_arraylen(nums))
+ cpque_f_push(&floats, nums[i]);
+
+ puts("\npop and show high priorites first:");
+ while (! cpque_f_empty(&floats)) {
+ printf("%.1f ", *cpque_f_top(&floats));
+ cpque_f_pop(&floats);
}
+ puts("\n");
+ cpque_f_drop(&floats);
// CMAP ID
int year = 2020;
- c_auto (cmap_id, idnames) {
- cmap_id_emplace(&idnames, 100, "Hello");
- cmap_id_insert(&idnames, 110, cstr_lit("World"));
- cmap_id_insert(&idnames, 120, cstr_from_fmt("Howdy, -%d-", year));
-
- c_foreach (i, cmap_id, idnames)
- printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
- puts("");
- }
+ cmap_id idnames = {0};
+ cmap_id_emplace(&idnames, 100, "Hello");
+ cmap_id_insert(&idnames, 110, cstr_lit("World"));
+ cmap_id_insert(&idnames, 120, cstr_from_fmt("Howdy, -%d-", year));
+
+ c_foreach (i, cmap_id, idnames)
+ printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
+ puts("");
+ cmap_id_drop(&idnames);
// CMAP CNT
- c_auto (cmap_cnt, countries)
- {
- countries = c_make(cmap_cnt, {
- {"Norway", 100},
- {"Denmark", 50},
- {"Iceland", 10},
- {"Belgium", 10},
- {"Italy", 10},
- {"Germany", 10},
- {"Spain", 10},
- {"France", 10},
- });
- cmap_cnt_emplace(&countries, "Greenland", 0).ref->second += 20;
- cmap_cnt_emplace(&countries, "Sweden", 0).ref->second += 20;
- cmap_cnt_emplace(&countries, "Norway", 0).ref->second += 20;
- cmap_cnt_emplace(&countries, "Finland", 0).ref->second += 20;
-
- c_forpair (country, health, cmap_cnt, countries)
- printf("%s: %d\n", cstr_str(_.country), *_.health);
- puts("");
- }
+ cmap_cnt countries = c_make(cmap_cnt, {
+ {"Norway", 100},
+ {"Denmark", 50},
+ {"Iceland", 10},
+ {"Belgium", 10},
+ {"Italy", 10},
+ {"Germany", 10},
+ {"Spain", 10},
+ {"France", 10},
+ });
+ cmap_cnt_emplace(&countries, "Greenland", 0).ref->second += 20;
+ cmap_cnt_emplace(&countries, "Sweden", 0).ref->second += 20;
+ cmap_cnt_emplace(&countries, "Norway", 0).ref->second += 20;
+ cmap_cnt_emplace(&countries, "Finland", 0).ref->second += 20;
+
+ c_forpair (country, health, cmap_cnt, countries)
+ printf("%s: %d\n", cstr_str(_.country), *_.health);
+ puts("");
+ cmap_cnt_drop(&countries);
// CVEC PAIR
- c_auto (cvec_ip, pairs1) {
- pairs1 = c_make(cvec_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ cvec_ip pairs1 = c_make(cvec_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ cvec_ip_sort(&pairs1);
- cvec_ip_sort(&pairs1);
-
- c_foreach (i, cvec_ip, pairs1)
- printf("(%d %d) ", i.ref->x, i.ref->y);
- puts("");
- }
+ c_foreach (i, cvec_ip, pairs1)
+ printf("(%d %d) ", i.ref->x, i.ref->y);
+ puts("");
+ cvec_ip_drop(&pairs1);
// CLIST PAIR
- c_auto (clist_ip, pairs2) {
- pairs2 = c_make(clist_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ clist_ip pairs2 = c_make(clist_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}});
+ clist_ip_sort(&pairs2);
- clist_ip_sort(&pairs2);
-
- c_foreach (i, clist_ip, pairs2)
- printf("(%d %d) ", i.ref->x, i.ref->y);
- puts("");
- }
+ c_foreach (i, clist_ip, pairs2)
+ printf("(%d %d) ", i.ref->x, i.ref->y);
+ puts("");
+ clist_ip_drop(&pairs2);
}
diff --git a/misc/examples/intrusive.c b/misc/examples/intrusive.c
index 5f9f8d07..0d503575 100644
--- a/misc/examples/intrusive.c
+++ b/misc/examples/intrusive.c
@@ -1,55 +1,32 @@
-// Example of intrusive/shared list-nodes by using the node API.
+// Example of clist using the node API.
#include <stdio.h>
-#define i_type Inner
+#define i_type List
#define i_val int
-#define i_extern // implement Inner_sort()
#include <stc/clist.h>
-#define i_type Outer
-#define i_val Inner_node
-#define i_opt c_no_cmp // no elem. comparison
-#include <stc/clist.h>
-
-void printLists(Inner inner, Outer outer) {
- printf(" inner:");
- c_foreach (i, Inner, inner)
- printf(" %d", *i.ref);
-
- printf("\n outer:");
- c_foreach (i, Outer, outer)
- printf(" %d", i.ref->value);
- puts("");
+void printList(List list) {
+ printf("list:");
+ c_foreach (i, List, list)
+ printf(" %d", *i.ref);
+ puts("");
}
-int main()
-{
- c_auto (Outer, outer)
- {
- Inner inner = Inner_init(); // do not destroy, outer will destroy the shared nodes.
-
- c_forlist (i, int, {6, 9, 3, 1, 7, 4, 5, 2, 8}) {
- Inner_node* node = Outer_push_back(&outer, (Inner_node){0});
- node->value = *i.ref;
- }
-
- c_foreach (i, Outer, outer)
- Inner_push_back_node(&inner, i.ref);
-
- printLists(inner, outer);
-
- puts("Sort inner");
- Inner_sort(&inner);
+int main() {
+ List list = {0};
+ c_forlist (i, int, {6, 9, 3, 1, 7, 4, 5, 2, 8})
+ List_push_back_node(&list, c_new(List_node, {0, *i.ref}));
- printLists(inner, outer);
+ printList(list);
- puts("Remove odd numbers from inner list");
+ puts("Sort list");
+ List_sort(&list);
+ printList(list);
- c_foreach (i, Inner, inner)
- if (*i.ref & 1)
- Inner_unlink_after_node(&inner, i.prev);
+ puts("Remove nodes from list");
+ while (!List_empty(&list))
+ c_free(List_unlink_after_node(&list, list.last));
- printLists(inner, outer);
- }
+ printList(list);
}
diff --git a/misc/examples/list.c b/misc/examples/list.c
index b345bd16..363d7fec 100644
--- a/misc/examples/list.c
+++ b/misc/examples/list.c
@@ -1,69 +1,63 @@
#include <stdio.h>
#include <time.h>
+#include <stc/algo/filter.h>
+#include <stc/crand.h>
+#define i_type DList
#define i_val double
-#define i_tag fx
-#define i_extern // include sort function
#include <stc/clist.h>
-#include <stc/crandom.h>
int main() {
- const int n = 1000000;
+ const int n = 3000000;
+ DList list = {0};
- c_auto (clist_fx, list)
- {
- stc64_t rng = stc64_new(1234);
- stc64_uniformf_t dist = stc64_uniformf_new(100.0f, n);
- int m = 0;
- c_forrange (n)
- clist_fx_push_back(&list, stc64_uniformf(&rng, &dist)), ++m;
+ crand_t rng = crand_init(1234567);
+ int m = 0;
+ c_forrange (n)
+ DList_push_back(&list, crand_f64(&rng)*n + 100), ++m;
- double sum = 0.0;
- printf("sumarize %d:\n", m);
- c_foreach (i, clist_fx, list)
- sum += *i.ref;
- printf("sum %f\n\n", sum);
+ double sum = 0.0;
+ printf("sumarize %d:\n", m);
+ c_foreach (i, DList, list)
+ sum += *i.ref;
+ printf("sum %f\n\n", sum);
- c_forwhile (i, clist_fx, clist_fx_begin(&list), i.index < 10)
- printf("%8d: %10f\n", (int)i.index, *i.ref);
+ c_forfilter (i, DList, list, c_flt_take(i, 10))
+ printf("%8d: %10f\n", c_flt_getcount(i), *i.ref);
- puts("sort");
- clist_fx_sort(&list); // mergesort O(n*log n)
- puts("sorted");
+ puts("sort");
+ DList_sort(&list); // qsort O(n*log n)
+ puts("sorted");
- double last = 0;
- c_foreach (i, clist_fx, list) {
- if (*i.ref < last) {printf("ERROR"); exit(-1);}
- last = *i.ref;
- }
+ c_forfilter (i, DList, list, c_flt_take(i, 10))
+ printf("%8d: %10f\n", c_flt_getcount(i), *i.ref);
+ puts("");
- c_forwhile (i, clist_fx, clist_fx_begin(&list), i.index < 10)
- printf("%8d: %10f\n", (int)i.index, *i.ref);
- puts("");
+ DList_drop(&list);
+ list = c_make(DList, {10, 20, 30, 40, 30, 50});
- clist_fx_clear(&list);
- c_forlist (i, int, {10, 20, 30, 40, 30, 50})
- clist_fx_push_back(&list, *i.ref);
+ const double* v = DList_get(&list, 30);
+ printf("found: %f\n", *v);
- const double* v = clist_fx_get(&list, 30);
- printf("found: %f\n", *v);
- c_foreach (i, clist_fx, list)
- printf(" %g", *i.ref);
- puts("");
+ c_foreach (i, DList, list)
+ printf(" %g", *i.ref);
+ puts("");
- clist_fx_remove(&list, 30);
- clist_fx_insert_at(&list, clist_fx_begin(&list), 5); // same as push_front()
- clist_fx_push_back(&list, 500);
- clist_fx_push_front(&list, 1964);
+ DList_remove(&list, 30);
+ DList_insert_at(&list, DList_begin(&list), 5); // same as push_front()
+ DList_push_back(&list, 500);
+ DList_push_front(&list, 1964);
- printf("Full: ");
- c_foreach (i, clist_fx, list)
- printf(" %g", *i.ref);
+ printf("Full: ");
+ c_foreach (i, DList, list)
+ printf(" %g", *i.ref);
- printf("\nSubs: ");
- clist_fx_iter it = clist_fx_begin(&list);
- c_foreach (i, clist_fx, clist_fx_advance(it, 4), clist_fx_end(&list))
- printf(" %g", *i.ref);
- puts("");
- }
+ printf("\nSubs: ");
+ DList_iter it = DList_begin(&list);
+
+ c_foreach (i, DList, DList_advance(it, 4), DList_end(&list))
+ printf(" %g", *i.ref);
+ puts("");
+
+ DList_drop(&list);
}
diff --git a/misc/examples/list_erase.c b/misc/examples/list_erase.c
index 47f56625..0201c2d9 100644
--- a/misc/examples/list_erase.c
+++ b/misc/examples/list_erase.c
@@ -7,23 +7,24 @@
int main ()
{
- c_with (IList L = c_make(IList, {10, 20, 30, 40, 50}), IList_drop(&L))
- {
- c_foreach (x, IList, L)
- printf("%d ", *x.ref);
- puts("");
- // 10 20 30 40 50
- IList_iter it = IList_begin(&L); // ^
- IList_next(&it);
- it = IList_erase_at(&L, it); // 10 30 40 50
- // ^
- IList_iter end = IList_end(&L); //
- IList_next(&it);
- it = IList_erase_range(&L, it, end); // 10 30
- // ^
- printf("list contains:");
- c_foreach (x, IList, L)
- printf(" %d", *x.ref);
- puts("");
- }
+ IList L = c_make(IList, {10, 20, 30, 40, 50});
+
+ c_foreach (x, IList, L)
+ printf("%d ", *x.ref);
+ puts("");
+ // 10 20 30 40 50
+ IList_iter it = IList_begin(&L); // ^
+ IList_next(&it);
+ it = IList_erase_at(&L, it); // 10 30 40 50
+ // ^
+ IList_iter end = IList_end(&L); //
+ IList_next(&it);
+ it = IList_erase_range(&L, it, end); // 10 30
+ // ^
+ printf("list contains:");
+ c_foreach (x, IList, L)
+ printf(" %d", *x.ref);
+ puts("");
+
+ IList_drop(&L);
}
diff --git a/misc/examples/list_splice.c b/misc/examples/list_splice.c
index f2f4946f..baebca29 100644
--- a/misc/examples/list_splice.c
+++ b/misc/examples/list_splice.c
@@ -16,25 +16,24 @@ void print_ilist(const char* s, clist_i list)
int main ()
{
- c_auto (clist_i, list1, list2)
- {
- list1 = c_make(clist_i, {1, 2, 3, 4, 5});
- list2 = c_make(clist_i, {10, 20, 30, 40, 50});
+ clist_i list1 = c_make(clist_i, {1, 2, 3, 4, 5});
+ clist_i list2 = c_make(clist_i, {10, 20, 30, 40, 50});
- print_ilist("list1:", list1);
- print_ilist("list2:", list2);
+ print_ilist("list1:", list1);
+ print_ilist("list2:", list2);
- clist_i_iter it = clist_i_advance(clist_i_begin(&list1), 2);
- it = clist_i_splice(&list1, it, &list2);
+ clist_i_iter it = clist_i_advance(clist_i_begin(&list1), 2);
+ it = clist_i_splice(&list1, it, &list2);
- puts("After splice");
- print_ilist("list1:", list1);
- print_ilist("list2:", list2);
+ puts("After splice");
+ print_ilist("list1:", list1);
+ print_ilist("list2:", list2);
- clist_i_splice_range(&list2, clist_i_begin(&list2), &list1, it, clist_i_end(&list1));
+ clist_i_splice_range(&list2, clist_i_begin(&list2), &list1, it, clist_i_end(&list1));
- puts("After splice_range");
- print_ilist("list1:", list1);
- print_ilist("list2:", list2);
- }
+ puts("After splice_range");
+ print_ilist("list1:", list1);
+ print_ilist("list2:", list2);
+
+ c_drop(clist_i, &list1, &list2);
}
diff --git a/misc/examples/lower_bound.c b/misc/examples/lower_bound.c
index f492ccaa..6ec7544c 100644
--- a/misc/examples/lower_bound.c
+++ b/misc/examples/lower_bound.c
@@ -9,10 +9,9 @@
int main()
{
// TEST SORTED VECTOR
- c_auto (cvec_int, vec)
{
int key, *res;
- vec = c_make(cvec_int, {40, 600, 1, 7000, 2, 500, 30});
+ cvec_int vec = c_make(cvec_int, {40, 600, 1, 7000, 2, 500, 30});
cvec_int_sort(&vec);
@@ -35,13 +34,13 @@ int main()
printf(" %d\n", *i.ref);
puts("");
+ cvec_int_drop(&vec);
}
-
+
// TEST SORTED SET
- c_auto (csset_int, set)
{
int key, *res;
- set = c_make(csset_int, {40, 600, 1, 7000, 2, 500, 30});
+ csset_int set = c_make(csset_int, {40, 600, 1, 7000, 2, 500, 30});
key = 100;
res = csset_int_lower_bound(&set, key).ref;
@@ -60,5 +59,7 @@ int main()
c_foreach (i, csset_int, it1, it2)
printf(" %d\n", *i.ref);
+
+ csset_int_drop(&set);
}
}
diff --git a/misc/examples/mapmap.c b/misc/examples/mapmap.c
index cad5e462..668da5de 100644
--- a/misc/examples/mapmap.c
+++ b/misc/examples/mapmap.c
@@ -7,24 +7,13 @@
#define i_key_str // name
#define i_val_str // email
#define i_keydrop(p) (printf("kdrop: %s\n", cstr_str(p)), cstr_drop(p)) // override
-#include <stc/csmap.h>
+#include <stc/cmap.h>
// Departments: std::map<std::string, People>
#define i_type Departments
#define i_key_str // dep. name
#define i_valclass People
-// i_key_str implies:
-// #define i_tag str
-// #define i_key cstr
-// #define i_keyclone cstr_clone
-// #define i_keydrop cstr_drop
-// #define i_cmp cstr_cmp
-// #define i_hash cstr_hash
-// i_valclass implies:
-// #define i_val People
-// #define i_valclone People_clone
-// #define i_valdrop People_drop
-#include <stc/csmap.h>
+#include <stc/cmap.h>
void add(Departments* deps, const char* name, const char* email, const char* dep)
@@ -44,31 +33,32 @@ int contains(Departments* map, const char* name)
int main(void)
{
- c_auto (Departments, map)
- {
- add(&map, "Anna Kendro", "[email protected]", "Support");
- add(&map, "Terry Dane", "[email protected]", "Development");
- add(&map, "Kik Winston", "[email protected]", "Finance");
- add(&map, "Nancy Drew", "[email protected]", "Development");
- add(&map, "Nick Denton", "[email protected]", "Finance");
- add(&map, "Stan Whiteword", "[email protected]", "Marketing");
- add(&map, "Serena Bath", "[email protected]", "Support");
- add(&map, "Patrick Dust", "[email protected]", "Finance");
- add(&map, "Red Winger", "[email protected]", "Marketing");
- add(&map, "Nick Denton", "[email protected]", "Support");
- add(&map, "Colin Turth", "[email protected]", "Support");
- add(&map, "Dennis Kay", "[email protected]", "Marketing");
- add(&map, "Anne Dickens", "[email protected]", "Development");
+ Departments map = {0};
- c_foreach (i, Departments, map)
- c_forpair (name, email, People, i.ref->second)
- printf("%s: %s - %s\n", cstr_str(&i.ref->first), cstr_str(_.name), cstr_str(_.email));
- puts("");
+ add(&map, "Anna Kendro", "[email protected]", "Support");
+ add(&map, "Terry Dane", "[email protected]", "Development");
+ add(&map, "Kik Winston", "[email protected]", "Finance");
+ add(&map, "Nancy Drew", "[email protected]", "Development");
+ add(&map, "Nick Denton", "[email protected]", "Finance");
+ add(&map, "Stan Whiteword", "[email protected]", "Marketing");
+ add(&map, "Serena Bath", "[email protected]", "Support");
+ add(&map, "Patrick Dust", "[email protected]", "Finance");
+ add(&map, "Red Winger", "[email protected]", "Marketing");
+ add(&map, "Nick Denton", "[email protected]", "Support");
+ add(&map, "Colin Turth", "[email protected]", "Support");
+ add(&map, "Dennis Kay", "[email protected]", "Marketing");
+ add(&map, "Anne Dickens", "[email protected]", "Development");
- printf("found Nick Denton: %d\n", contains(&map, "Nick Denton"));
- printf("found Patrick Dust: %d\n", contains(&map, "Patrick Dust"));
- printf("found Dennis Kay: %d\n", contains(&map, "Dennis Kay"));
- printf("found Serena Bath: %d\n", contains(&map, "Serena Bath"));
- puts("Done");
- }
+ c_foreach (i, Departments, map)
+ c_forpair (name, email, People, i.ref->second)
+ printf("%s: %s - %s\n", cstr_str(&i.ref->first), cstr_str(_.name), cstr_str(_.email));
+ puts("");
+
+ printf("found Nick Denton: %d\n", contains(&map, "Nick Denton"));
+ printf("found Patrick Dust: %d\n", contains(&map, "Patrick Dust"));
+ printf("found Dennis Kay: %d\n", contains(&map, "Dennis Kay"));
+ printf("found Serena Bath: %d\n", contains(&map, "Serena Bath"));
+ puts("Done");
+
+ Departments_drop(&map);
}
diff --git a/misc/examples/mmap.c b/misc/examples/mmap.c
index 3934cf26..0394a2df 100644
--- a/misc/examples/mmap.c
+++ b/misc/examples/mmap.c
@@ -4,14 +4,12 @@
// Multimap entries
#include <stc/cstr.h>
#define i_val_str
-//#define i_valdrop(x) (printf("drop %s\n", cstr_str(x)), cstr_drop(x))
-#define i_extern // define _clist_mergesort() once
#include <stc/clist.h>
// Map of int => clist_str.
#define i_type Multimap
#define i_key int
-#define i_valclass clist_str // uses clist_str as i_val and binds clist_str_clone, clist_str_drop
+#define i_valclass clist_str // set i_val = clist_str, bind clist_str_clone and clist_str_drop
#define i_cmp -c_default_cmp // like std::greater<int>
#include <stc/csmap.h>
@@ -33,40 +31,34 @@ void insert(Multimap* mmap, int key, const char* str)
int main()
{
- c_auto (Multimap, mmap)
- {
- typedef struct {int a; const char* b;} pair;
+ Multimap mmap = {0};
- // list-initialize
- c_forlist (i, pair, {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}})
- insert(&mmap, i.ref->a, i.ref->b);
- print("#1", mmap);
+ // list-initialize
+ typedef struct {int a; const char* b;} pair;
+ c_forlist (i, pair, {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}})
+ insert(&mmap, i.ref->a, i.ref->b);
+ print("#1", mmap);
- // insert using value_type
- insert(&mmap, 5, "pqr");
- print("#2", mmap);
+ // insert using value_type
+ insert(&mmap, 5, "pqr");
+ print("#2", mmap);
- // insert using make_pair
- insert(&mmap, 6, "uvw");
- print("#3", mmap);
+ // insert using make_pair
+ insert(&mmap, 6, "uvw");
+ print("#3", mmap);
- insert(&mmap, 7, "xyz");
- print("#4", mmap);
+ insert(&mmap, 7, "xyz");
+ print("#4", mmap);
- // insert using initialization_list
- c_forlist (i, pair, {{5, "one"}, {5, "two"}})
- insert(&mmap, i.ref->a, i.ref->b);
- print("#5", mmap);
+ // insert using initialization_list
+ c_forlist (i, pair, {{5, "one"}, {5, "two"}})
+ insert(&mmap, i.ref->a, i.ref->b);
+ print("#5", mmap);
- // FOLLOWING NOT IN ORIGINAL EXAMPLE:
- // erase all entries with key 5
- Multimap_erase(&mmap, 5);
- print("+5", mmap);
-
-
- Multimap_clear(&mmap);
- c_forlist (i, pair, {{1, "ä"}, {2, "ё"}, {2, "ö"}, {3, "ü"}})
- insert(&mmap, i.ref->a, i.ref->b);
- print("#6", mmap);
- }
+ // FOLLOWING NOT IN ORIGINAL EXAMPLE:
+ // erase all entries with key 5
+ Multimap_erase(&mmap, 5);
+ print("+5", mmap);
+
+ Multimap_drop(&mmap);
}
diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c
index 1d5d259d..d8981a81 100644
--- a/misc/examples/multimap.c
+++ b/misc/examples/multimap.c
@@ -41,7 +41,6 @@ void OlympicLoc_drop(OlympicLoc* self);
// Create a clist<OlympicLoc>, can be sorted by year.
#define i_valclass OlympicLoc // binds _cmp, _clone and _drop.
#define i_tag OL
-#define i_extern // define _clist_mergesort()
#include <stc/clist.h>
// Create a csmap<cstr, clist_OL> where key is country name
@@ -69,34 +68,34 @@ void OlympicLoc_drop(OlympicLoc* self) {
int main()
{
// Define the multimap with destructor defered to when block is completed.
- c_auto (csmap_OL, multimap)
+ csmap_OL multimap = {0};
+ const clist_OL empty = clist_OL_init();
+
+ for (size_t i = 0; i < c_arraylen(ol_data); ++i)
{
- const clist_OL empty = clist_OL_init();
+ struct OlympicsData* d = &ol_data[i];
+ OlympicLoc loc = {.year = d->year,
+ .city = cstr_from(d->city),
+ .date = cstr_from(d->date)};
+ // Insert an empty list for each new country, and append the entry to the list.
+ // If country already exist in map, its list is returned from the insert function.
+ clist_OL* list = &csmap_OL_emplace(&multimap, d->country, empty).ref->second;
+ clist_OL_push_back(list, loc);
+ }
- for (size_t i = 0; i < c_ARRAYLEN(ol_data); ++i)
- {
- struct OlympicsData* d = &ol_data[i];
- OlympicLoc loc = {.year = d->year,
- .city = cstr_from(d->city),
- .date = cstr_from(d->date)};
- // Insert an empty list for each new country, and append the entry to the list.
- // If country already exist in map, its list is returned from the insert function.
- clist_OL* list = &csmap_OL_emplace(&multimap, d->country, empty).ref->second;
- clist_OL_push_back(list, loc);
- }
- // Sort locations by year for each country.
- c_foreach (country, csmap_OL, multimap)
- clist_OL_sort(&country.ref->second);
+ // Sort locations by year for each country.
+ c_foreach (country, csmap_OL, multimap)
+ clist_OL_sort(&country.ref->second);
- // Print the multimap:
- c_foreach (country, csmap_OL, multimap)
- {
- // Loop the locations for a country sorted by year
- c_foreach (loc, clist_OL, country.ref->second)
- printf("%s: %d, %s, %s\n", cstr_str(&country.ref->first),
- loc.ref->year,
- cstr_str(&loc.ref->city),
- cstr_str(&loc.ref->date));
- }
+ // Print the multimap:
+ c_foreach (country, csmap_OL, multimap)
+ {
+ // Loop the locations for a country sorted by year
+ c_foreach (loc, clist_OL, country.ref->second)
+ printf("%s: %d, %s, %s\n", cstr_str(&country.ref->first),
+ loc.ref->year,
+ cstr_str(&loc.ref->city),
+ cstr_str(&loc.ref->date));
}
+ csmap_OL_drop(&multimap);
}
diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c
index fcd24beb..3714e1d5 100644
--- a/misc/examples/music_arc.c
+++ b/misc/examples/music_arc.c
@@ -11,8 +11,6 @@ typedef struct
int Song_cmp(const Song* x, const Song* y)
{ return cstr_cmp(&x->title, &y->title); }
-uint64_t Song_hash(const Song* x) { return cstr_hash(&x->title); }
-
Song Song_make(const char* artist, const char* title)
{ return (Song){cstr_from(artist), cstr_from(title)}; }
@@ -21,47 +19,45 @@ void Song_drop(Song* s) {
c_drop(cstr, &s->artist, &s->title);
}
-// Define the reference counted type
+// Define the shared pointer:
#define i_type SongArc
#define i_valclass Song
-//#define i_opt c_no_hash
+#define i_opt c_no_hash // arc require hash fn, disable as we don't need it.
#include <stc/carc.h>
-// ... and a vector of it
+// ... and a vector of them
#define i_type SongVec
-#define i_valboxed SongArc
+#define i_valboxed SongArc // use i_valboxed on carc / cbox instead of i_val
#include <stc/cstack.h>
void example3()
{
- c_auto (SongVec, vec1, vec2)
- {
- vec1 = c_make(SongVec, {
- Song_make("Bob Dylan", "The Times They Are A Changing"),
- Song_make("Aretha Franklin", "Bridge Over Troubled Water"),
- Song_make("Thalia", "Entre El Mar y Una Estrella")
- });
+ SongVec vec1 = c_make(SongVec, {
+ Song_make("Bob Dylan", "The Times They Are A Changing"),
+ Song_make("Aretha Franklin", "Bridge Over Troubled Water"),
+ Song_make("Thalia", "Entre El Mar y Una Estrella")
+ });
- // Share all entries in vec with vec2, except Bob Dylan.
- c_foreach (s, SongVec, vec1)
- if (!cstr_equals(&s.ref->get->artist, "Bob Dylan"))
- SongVec_push(&vec2, SongArc_clone(*s.ref));
+ SongVec vec2 = {0};
+ // Share all entries in vec with vec2, except Bob Dylan.
+ c_foreach (s, SongVec, vec1)
+ if (!cstr_equals(&s.ref->get->artist, "Bob Dylan"))
+ SongVec_push(&vec2, SongArc_clone(*s.ref));
- // Add a few more to vec2. We can use emplace when creating new entries
- SongVec_emplace(&vec2, Song_make("Michael Jackson", "Billie Jean"));
- SongVec_emplace(&vec2, Song_make("Rihanna", "Stay"));
- // If we use push, we would need to construct the Arc explicitly (as in c++, make_shared):
- // SongVec_push(&vec2, SongArc_from(Song_make("Rihanna", "Stay")));
+ // Add a few more to vec2. We can use emplace when creating new entries
+ // Emplace calls SongArc_from() on the argument to create the Arc:
+ SongVec_emplace(&vec2, Song_make("Michael Jackson", "Billie Jean"));
+ SongVec_emplace(&vec2, Song_make("Rihanna", "Stay"));
- // We now have two vectors with some shared, some unique entries.
- c_forlist (i, SongVec, {vec1, vec2}) {
- puts("VEC:");
- c_foreach (s, SongVec, *i.ref)
- printf(" %s - %s, REFS: %ld\n", cstr_str(&s.ref->get->artist),
- cstr_str(&s.ref->get->title),
- *s.ref->use_count);
- }
- } // because the shared elem. are ref. counted, they are only dropped once here.
+ // We now have two vectors with some shared, some unique entries.
+ c_forlist (i, SongVec, {vec1, vec2}) {
+ puts("VEC:");
+ c_foreach (s, SongVec, *i.ref)
+ printf(" %s - %s, REFS: %ld\n", cstr_str(&s.ref->get->artist),
+ cstr_str(&s.ref->get->title),
+ *s.ref->use_count);
+ }
+ c_drop(SongVec, &vec1, &vec2);
}
int main()
diff --git a/misc/examples/new_deq.c b/misc/examples/new_deq.c
deleted file mode 100644
index 39149140..00000000
--- a/misc/examples/new_deq.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <stc/cstr.h>
-#include <stc/forward.h>
-
-forward_cdeq(cdeq_i32, int);
-forward_cdeq(cdeq_pnt, struct Point);
-
-struct MyStruct {
- cdeq_i32 intvec;
- cdeq_pnt pntvec;
-} typedef MyStruct;
-
-
-#define i_val int
-#define i_opt c_is_forward
-#define i_tag i32
-#include <stc/cdeq.h>
-
-struct Point { int x, y; } typedef Point;
-int point_cmp(const Point* a, const Point* b) {
- int c = a->x - b->x;
- return c ? c : a->y - b->y;
-}
-
-#define i_val Point
-#define i_cmp point_cmp
-#define i_opt c_is_forward
-#define i_tag pnt
-#include <stc/cdeq.h>
-
-#define i_val float
-#include <stc/cdeq.h>
-
-#define i_val_str
-#include <stc/cdeq.h>
-
-
-int main()
-{
- c_auto (cdeq_i32, vec)
- {
- cdeq_i32_push_back(&vec, 123);
- }
- c_auto (cdeq_float, fvec)
- {
- cdeq_float_push_back(&fvec, 123.3f);
- }
- c_auto (cdeq_pnt, pvec)
- {
- cdeq_pnt_push_back(&pvec, (Point){42, 14});
- cdeq_pnt_push_back(&pvec, (Point){32, 94});
- cdeq_pnt_push_front(&pvec, (Point){62, 81});
- cdeq_pnt_sort(&pvec);
- c_foreach (i, cdeq_pnt, pvec)
- printf(" (%d %d)", i.ref->x, i.ref->y);
- puts("");
- }
- c_auto (cdeq_str, svec)
- {
- cdeq_str_emplace_back(&svec, "Hello, friend");
- }
-}
diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c
index 6dbe80b4..8b291d34 100644
--- a/misc/examples/new_list.c
+++ b/misc/examples/new_list.c
@@ -1,20 +1,20 @@
-#include <stc/cstr.h>
+#include <stdio.h>
+#include <stc/forward.h>
forward_clist(clist_i32, int);
forward_clist(clist_pnt, struct Point);
-struct MyStruct {
+typedef struct {
clist_i32 intlst;
clist_pnt pntlst;
-} typedef MyStruct;
+} MyStruct;
#define i_val int
-#define i_opt c_is_forward
#define i_tag i32
-#define i_extern // define _clist_mergesort()
+#define i_is_forward
#include <stc/clist.h>
-struct Point { int x, y; } typedef Point;
+typedef struct Point { int x, y; } Point;
int point_cmp(const Point* a, const Point* b) {
int c = a->x - b->x;
return c ? c : a->y - b->y;
@@ -22,40 +22,47 @@ int point_cmp(const Point* a, const Point* b) {
#define i_val Point
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/clist.h>
#define i_val float
#include <stc/clist.h>
-#define i_val_str
+void MyStruct_drop(MyStruct* s);
+#define i_type MyList
+#define i_valclass MyStruct // i_valclass uses MyStruct_drop
+#define i_opt c_no_clone|c_no_cmp
#include <stc/clist.h>
+void MyStruct_drop(MyStruct* s) {
+ clist_i32_drop(&s->intlst);
+ clist_pnt_drop(&s->pntlst);
+}
+
int main()
{
- c_auto (clist_i32, lst)
- clist_i32_push_back(&lst, 123);
+ MyStruct my = {0};
+ clist_i32_push_back(&my.intlst, 123);
+ clist_pnt_push_back(&my.pntlst, (Point){123, 456});
+ MyStruct_drop(&my);
+
+ clist_pnt plst = c_make(clist_pnt, {{42, 14}, {32, 94}, {62, 81}});
+ clist_pnt_sort(&plst);
- c_auto (clist_pnt, plst) {
- c_forlist (i, Point, {{42, 14}, {32, 94}, {62, 81}})
- clist_pnt_push_back(&plst, *i.ref);
+ c_foreach (i, clist_pnt, plst)
+ printf(" (%d %d)", i.ref->x, i.ref->y);
+ puts("");
+ clist_pnt_drop(&plst);
- clist_pnt_sort(&plst);
- c_foreach (i, clist_pnt, plst)
- printf(" (%d %d)", i.ref->x, i.ref->y);
- puts("");
- }
+ clist_float flst = c_make(clist_float, {123.3f, 321.2f, -32.2f, 78.2f});
+ clist_float_sort(&flst);
- c_auto (clist_float, flst) {
- c_forlist (i, float, {123.3f, 321.2f, -32.2f, 78.2f})
- clist_float_push_back(&flst, *i.ref);
-
- c_foreach (i, clist_float, flst) printf(" %g", *i.ref);
- }
+ c_foreach (i, clist_float, flst)
+ printf(" %g", *i.ref);
- c_auto (clist_str, slst)
- clist_str_emplace_back(&slst, "Hello, friend");
+ puts("");
+ clist_float_drop(&flst);
}
diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c
index a4d5289c..3a4f934d 100644
--- a/misc/examples/new_map.c
+++ b/misc/examples/new_map.c
@@ -26,7 +26,7 @@ int point_cmp(const Point* a, const Point* b) {
#define i_val int
#define i_cmp point_cmp
#define i_hash c_default_hash
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cmap.h>
@@ -42,33 +42,33 @@ int point_cmp(const Point* a, const Point* b) {
int main()
{
- c_auto (cmap_int, map)
- c_auto (cmap_pnt, pmap)
- c_auto (cmap_str, smap)
- c_auto (cset_str, sset)
- {
- cmap_int_insert(&map, 123, 321);
- cmap_int_insert(&map, 456, 654);
- cmap_int_insert(&map, 789, 987);
-
- 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("");
-
- smap = c_make(cmap_str, {
- {"Hello, friend", "long time no see"},
- {"So long", "see you around"},
- });
-
- sset = c_make(cset_str, {
- "Hello, friend",
- "Nice to see you again",
- "So long",
- });
-
- c_foreach (i, cset_str, sset)
- printf(" %s\n", cstr_str(i.ref));
- }
+ cmap_pnt 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("");
+
+ cmap_str smap = c_make(cmap_str, {
+ {"Hello, friend", "long time no see"},
+ {"So long", "see you around"},
+ });
+
+ cset_str sset = c_make(cset_str, {
+ "Hello, friend",
+ "Nice to see you again",
+ "So long",
+ });
+
+ cmap_int map = {0};
+ cmap_int_insert(&map, 123, 321);
+ cmap_int_insert(&map, 456, 654);
+ cmap_int_insert(&map, 789, 987);
+
+ c_foreach (i, cset_str, sset)
+ printf(" %s\n", cstr_str(i.ref));
+
+ cmap_int_drop(&map);
+ cset_str_drop(&sset);
+ cmap_str_drop(&smap);
+ cmap_pnt_drop(&pmap);
}
diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c
index 57f27dc4..9147e3f2 100644
--- a/misc/examples/new_pque.c
+++ b/misc/examples/new_pque.c
@@ -10,16 +10,13 @@ struct Point { int x, y; } typedef Point;
int main()
{
- c_auto (PointQ, pque)
+ PointQ pque = c_make(PointQ, {{23, 80}, {12, 32}, {54, 74}, {12, 62}});
+ // print
+ for (; !PointQ_empty(&pque); PointQ_pop(&pque))
{
- pque = c_make(PointQ, {{23, 80}, {12, 32}, {54, 74}, {12, 62}});
-
- // print
- for (; !PointQ_empty(&pque); PointQ_pop(&pque))
- {
- const Point *v = PointQ_top(&pque);
- printf(" (%d,%d)", v->x, v->y);
- }
- puts("");
+ const Point *v = PointQ_top(&pque);
+ printf(" (%d,%d)", v->x, v->y);
}
+ puts("");
+ PointQ_drop(&pque);
}
diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c
index 7fae90d2..916f4dbc 100644
--- a/misc/examples/new_queue.c
+++ b/misc/examples/new_queue.c
@@ -1,4 +1,4 @@
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stc/forward.h>
#include <stdio.h>
#include <time.h>
@@ -12,7 +12,7 @@ int point_cmp(const Point* a, const Point* b) {
}
#define i_val Point
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cqueue.h>
@@ -22,25 +22,26 @@ int point_cmp(const Point* a, const Point* b) {
int main() {
int n = 50000000;
- 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, (int)stc64_uniform(&rng, &dist));
-
- // Push or pop on the queue 50 million times
- printf("befor: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
-
- c_forrange (n) {
- int r = (int)stc64_uniform(&rng, &dist);
- if (r & 3)
- IQ_push(&Q, r);
- else
- IQ_pop(&Q);
- }
- printf("after: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
+ crand_t rng = crand_init((uint64_t)time(NULL));
+ crand_unif_t dist = crand_unif_init(0, n);
+
+ IQ Q = {0};
+
+ // Push 50'000'000 random numbers onto the queue.
+ c_forrange (n)
+ IQ_push(&Q, (int)crand_unif(&rng, &dist));
+
+ // Push or pop on the queue 50 million times
+ printf("befor: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
+
+ c_forrange (n) {
+ int r = (int)crand_unif(&rng, &dist);
+ if (r & 3)
+ IQ_push(&Q, r);
+ else
+ IQ_pop(&Q);
}
+
+ printf("after: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
+ IQ_drop(&Q);
}
diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c
index 0870ee3d..d8245b8b 100644
--- a/misc/examples/new_smap.c
+++ b/misc/examples/new_smap.c
@@ -4,15 +4,10 @@
forward_csmap(PMap, struct Point, int);
// Use forward declared PMap in struct
-struct MyStruct {
+typedef struct {
PMap pntmap;
cstr name;
-} typedef MyStruct;
-
-// int => int map
-#define i_key int
-#define i_val int
-#include <stc/csmap.h>
+} MyStruct;
// Point => int map
struct Point { int x, y; } typedef Point;
@@ -25,7 +20,7 @@ int point_cmp(const Point* a, const Point* b) {
#define i_key Point
#define i_val int
#define i_cmp point_cmp
-#define i_opt c_is_forward
+#define i_is_forward
#include <stc/csmap.h>
// cstr => cstr map
@@ -42,36 +37,30 @@ int point_cmp(const Point* a, const Point* b) {
int main()
{
- c_auto (csmap_int, imap) {
- csmap_int_insert(&imap, 123, 321);
- }
-
- c_auto (PMap, pmap) {
- pmap = c_make(PMap, {
- {{42, 14}, 1},
- {{32, 94}, 2},
- {{62, 81}, 3},
- });
+ PMap pmap = c_make(PMap, {
+ {{42, 14}, 1},
+ {{32, 94}, 2},
+ {{62, 81}, 3},
+ });
+ SMap smap = c_make(SMap, {
+ {"Hello, friend", "this is the mapped value"},
+ {"The brown fox", "jumped"},
+ {"This is the time", "for all good things"},
+ });
+ SSet sset = {0};
- c_forpair (p, i, PMap, pmap)
- printf(" (%d,%d: %d)", _.p->x, _.p->y, *_.i);
- puts("");
- }
+ c_forpair (p, i, PMap, pmap)
+ printf(" (%d,%d: %d)", _.p->x, _.p->y, *_.i);
+ puts("");
- c_auto (SMap, smap) {
- smap = c_make(SMap, {
- {"Hello, friend", "this is the mapped value"},
- {"The brown fox", "jumped"},
- {"This is the time", "for all good things"},
- });
+ c_forpair (i, j, SMap, smap)
+ printf(" (%s: %s)\n", cstr_str(_.i), cstr_str(_.j));
- c_forpair (i, j, SMap, smap)
- printf(" (%s: %s)\n", cstr_str(_.i), cstr_str(_.j));
- }
+ SSet_emplace(&sset, "Hello, friend");
+ SSet_emplace(&sset, "Goodbye, foe");
+ printf("Found? %s\n", SSet_contains(&sset, "Hello, friend") ? "true" : "false");
- c_auto (SSet, sset) {
- SSet_emplace(&sset, "Hello, friend");
- SSet_emplace(&sset, "Goodbye, foe");
- printf("Found? %s\n", SSet_contains(&sset, "Hello, friend") ? "true" : "false");
- }
+ PMap_drop(&pmap);
+ SMap_drop(&smap);
+ SSet_drop(&sset);
}
diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c
index 68454970..1b72e4f5 100644
--- a/misc/examples/new_sptr.c
+++ b/misc/examples/new_sptr.c
@@ -31,16 +31,20 @@ uint64_t Person_hash(const Person* p);
Person Person_make(const char* name, const char* last) {
return (Person){.name = cstr_from(name), .last = cstr_from(last)};
}
+
int Person_cmp(const Person* a, const Person* b) {
return cstr_cmp(&a->name, &b->name);
}
+
uint64_t Person_hash(const Person* p) {
return cstr_hash(&p->name);
}
+
Person Person_clone(Person p) {
p.name = cstr_clone(p.name), p.last = cstr_clone(p.last);
return p;
}
+
void Person_drop(Person* p) {
printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last));
c_drop(cstr, &p->name, &p->last);
@@ -48,26 +52,24 @@ void Person_drop(Person* p) {
int main(void) {
- c_auto (PersonArc, p, q, r, s)
- {
- puts("Ex1");
- p = PersonArc_from(Person_make("John", "Smiths"));
- q = PersonArc_clone(p); // share
- r = PersonArc_clone(p);
- s = PersonArc_from(Person_clone(*p.get)); // deep copy
- printf("%s %s: refs %ld\n", cstr_str(&p.get->name), cstr_str(&p.get->last), *p.use_count);
- }
- c_auto (IPStack, vec)
- {
- puts("Ex2");
- IPStack_push(&vec, IPtr_from(10));
- IPStack_push(&vec, IPtr_from(20));
- IPStack_emplace(&vec, 30); // same as IPStack_push(&vec, IPtr_from(30));
- IPStack_push(&vec, IPtr_clone(*IPStack_back(&vec)));
- IPStack_push(&vec, IPtr_clone(*IPStack_front(&vec)));
+ puts("Ex1");
+ PersonArc p = PersonArc_from(Person_make("John", "Smiths"));
+ PersonArc q = PersonArc_clone(p); // share
+ PersonArc r = PersonArc_clone(p);
+ PersonArc s = PersonArc_from(Person_clone(*p.get)); // deep copy
+ printf("%s %s: refs %ld\n", cstr_str(&p.get->name), cstr_str(&p.get->last), *p.use_count);
+ c_drop(PersonArc, &p, &q, &r, &s);
+
+ puts("Ex2");
+ IPStack vec = {0};
+ IPStack_push(&vec, IPtr_from(10));
+ IPStack_push(&vec, IPtr_from(20));
+ IPStack_emplace(&vec, 30); // same as IPStack_push(&vec, IPtr_from(30));
+ IPStack_push(&vec, IPtr_clone(*IPStack_back(&vec)));
+ IPStack_push(&vec, IPtr_clone(*IPStack_front(&vec)));
- c_foreach (i, IPStack, vec)
- printf(" (%d: refs %ld)", *i.ref->get, *i.ref->use_count);
- puts("");
- }
+ c_foreach (i, IPStack, vec)
+ printf(" (%d: refs %ld)", *i.ref->get, *i.ref->use_count);
+ puts("");
+ IPStack_drop(&vec);
}
diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c
index 84e4c7b2..df443b7f 100644
--- a/misc/examples/new_vec.c
+++ b/misc/examples/new_vec.c
@@ -1,4 +1,4 @@
-#include <stc/cstr.h>
+#include <stdio.h>
#include <stc/forward.h>
forward_cvec(cvec_i32, int);
@@ -10,49 +10,33 @@ struct MyStruct {
} typedef MyStruct;
#define i_val int
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag i32
#include <stc/cvec.h>
-struct Point { int x, y; } typedef Point;
-int point_cmp(const Point* a, const Point* b) {
- int c = c_default_cmp(&a->x, &b->x);
- return c ? c : c_default_cmp(&a->y, &b->y);
-}
+typedef struct Point { int x, y; } Point;
#define i_val Point
-//#define i_cmp point_cmp
#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y)
-#define i_opt c_is_forward
+#define i_is_forward
#define i_tag pnt
#include <stc/cvec.h>
-#define i_val float
-#include <stc/cvec.h>
+int main()
+{
+ MyStruct my = {0};
-#define i_val_str
-#include <stc/cvec.h>
+ cvec_pnt_push(&my.pntvec, (Point){42, 14});
+ cvec_pnt_push(&my.pntvec, (Point){32, 94});
+ cvec_pnt_push(&my.pntvec, (Point){62, 81});
+ cvec_pnt_push(&my.pntvec, (Point){32, 91});
+ cvec_pnt_sort(&my.pntvec);
-int main()
-{
- c_auto (cvec_i32, vec)
- c_auto (cvec_float, fvec)
- c_auto (cvec_pnt, pvec)
- c_auto (cvec_str, svec)
- {
- cvec_i32_push(&vec, 123);
- cvec_float_push(&fvec, 123.3f);
-
- cvec_pnt_push(&pvec, (Point){42, 14});
- cvec_pnt_push(&pvec, (Point){32, 94});
- cvec_pnt_push(&pvec, (Point){62, 81});
- cvec_pnt_push(&pvec, (Point){32, 91});
- cvec_pnt_sort(&pvec);
- c_foreach (i, cvec_pnt, pvec)
- printf(" (%d %d)", i.ref->x, i.ref->y);
- puts("");
-
- cvec_str_emplace(&svec, "Hello, friend");
- }
+ c_foreach (i, cvec_pnt, my.pntvec)
+ printf(" (%d %d)", i.ref->x, i.ref->y);
+ puts("");
+
+ cvec_i32_drop(&my.intvec);
+ cvec_pnt_drop(&my.pntvec);
}
diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c
index a7bf2a6f..620d311f 100644
--- a/misc/examples/person_arc.c
+++ b/misc/examples/person_arc.c
@@ -39,13 +39,15 @@ void Person_drop(Person* p) {
int main()
{
- c_auto (Persons, vec)
- c_auto (PSPtr, p, q)
- {
- p = PSPtr_from(Person_make("Laura", "Palmer"));
-
- // We want a deep copy -- PSPtr_clone(p) only shares!
- q = PSPtr_from(Person_clone(*p.get));
+ PSPtr p = PSPtr_from(Person_make("Laura", "Palmer"));
+ PSPtr q = PSPtr_from(Person_clone(*p.get)); // deep copy
+ Persons vec = {0};
+
+ c_defer(
+ PSPtr_drop(&p),
+ PSPtr_drop(&q),
+ Persons_drop(&vec)
+ ){
cstr_assign(&q.get->name, "Leland");
printf("orig: %s %s\n", cstr_str(&p.get->name), cstr_str(&p.get->last));
@@ -65,10 +67,9 @@ int main()
puts("");
// Look-up Audrey!
- c_with (Person a = Person_make("Audrey", "Home"), Person_drop(&a)) {
- const PSPtr *v = Persons_get(&vec, a);
- if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last));
- }
- puts("");
+ Person a = Person_make("Audrey", "Home");
+ const PSPtr *v = Persons_get(&vec, a);
+ if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last));
+ Person_drop(&a);
}
}
diff --git a/misc/examples/phonebook.c b/misc/examples/phonebook.c
index ec9c5876..c0007cb7 100644
--- a/misc/examples/phonebook.c
+++ b/misc/examples/phonebook.c
@@ -38,37 +38,35 @@ void print_phone_book(cmap_str phone_book)
int main(int argc, char **argv)
{
- c_auto (cmap_str, phone_book)
- {
- phone_book = c_make(cmap_str, {
- {"Lilia Friedman", "(892) 670-4739"},
- {"Tariq Beltran", "(489) 600-7575"},
- {"Laiba Juarez", "(303) 885-5692"},
- {"Elliott Mooney", "(945) 616-4482"},
- });
+ cmap_str phone_book = c_make(cmap_str, {
+ {"Lilia Friedman", "(892) 670-4739"},
+ {"Tariq Beltran", "(489) 600-7575"},
+ {"Laiba Juarez", "(303) 885-5692"},
+ {"Elliott Mooney", "(945) 616-4482"},
+ });
- printf("Phone book:\n");
- print_phone_book(phone_book);
+ printf("Phone book:\n");
+ print_phone_book(phone_book);
- cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1880");
- cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1990");
+ cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1880");
+ cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1990");
- printf("\nPhone book after adding Zak Byers:\n");
- print_phone_book(phone_book);
+ printf("\nPhone book after adding Zak Byers:\n");
+ print_phone_book(phone_book);
- if (cmap_str_contains(&phone_book, "Tariq Beltran"))
- printf("\nTariq Beltran is in phone book\n");
+ if (cmap_str_contains(&phone_book, "Tariq Beltran"))
+ printf("\nTariq Beltran is in phone book\n");
- cmap_str_erase(&phone_book, "Tariq Beltran");
- cmap_str_erase(&phone_book, "Elliott Mooney");
+ cmap_str_erase(&phone_book, "Tariq Beltran");
+ cmap_str_erase(&phone_book, "Elliott Mooney");
- printf("\nPhone book after erasing Tariq and Elliott:\n");
- print_phone_book(phone_book);
+ printf("\nPhone book after erasing Tariq and Elliott:\n");
+ print_phone_book(phone_book);
- cmap_str_emplace_or_assign(&phone_book, "Zak Byers", "(555) 396-188");
+ cmap_str_emplace_or_assign(&phone_book, "Zak Byers", "(555) 396-188");
- printf("\nPhone book after update phone of Zak Byers:\n");
- print_phone_book(phone_book);
- }
- puts("done");
+ printf("\nPhone book after update phone of Zak Byers:\n");
+ print_phone_book(phone_book);
+
+ cmap_str_drop(&phone_book);
}
diff --git a/misc/examples/prime.c b/misc/examples/prime.c
index 59ee336c..d0887353 100644
--- a/misc/examples/prime.c
+++ b/misc/examples/prime.c
@@ -30,24 +30,25 @@ int main(void)
printf("Computing prime numbers up to %" c_ZI "\n", n);
clock_t t1 = clock();
- c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) {
- int64_t np = cbits_count(&primes);
- clock_t t2 = clock();
+ cbits primes = sieveOfEratosthenes(n + 1);
+ int64_t np = cbits_count(&primes);
+ clock_t t2 = clock();
- printf("Number of primes: %" c_ZI ", time: %f\n\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)
- if (cbits_test(&primes, i>>1)) printf(" %lld", i);
- puts("\n");
+ printf("Number of primes: %" c_ZI ", time: %f\n\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)
+ if (cbits_test(&primes, i>>1)) printf(" %lld", i);
+ puts("\n");
- puts("Show the last 50 primes using a temporary crange generator:");
- crange R = crange_make(n - 1, 0, -2);
- c_forfilter (i, crange, R
- , cbits_test(&primes, *i.ref>>1)
- && c_flt_take(i, 50)) {
- printf("%lld ", *i.ref);
- if (c_flt_last(i) % 10 == 0) puts("");
- }
+ puts("Show the last 50 primes using a temporary crange generator:");
+ c_forfilter (i, crange, crange_obj(n - 1, 0, -2),
+ cbits_test(&primes, *i.ref/2) &&
+ c_flt_take(i, 50)
+ ){
+ printf("%lld ", *i.ref);
+ if (c_flt_getcount(i) % 10 == 0) puts("");
}
+
+ cbits_drop(&primes);
}
diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c
index 81f6fa14..7459ac77 100644
--- a/misc/examples/printspan.c
+++ b/misc/examples/printspan.c
@@ -16,42 +16,42 @@ using_cspan(intspan, int, 1);
void printMe(intspan container) {
printf("%d:", (int)cspan_size(&container));
- c_foreach (e, intspan, container) printf(" %d", *e.ref);
+ c_foreach (e, intspan, container)
+ printf(" %d", *e.ref);
puts("");
}
int main()
{
- c_auto (cvec_int, vec)
- c_auto (cstack_int, stk)
- c_auto (cdeq_int, deq)
- c_auto (csset_str, set)
- {
- intspan sp1 = cspan_make(intspan, {1, 2});
- printMe( sp1 );
-
- printMe( c_make(intspan, {1, 2, 3}) );
-
- int arr[] = {1, 2, 3, 4, 5, 6};
- intspan sp2 = cspan_from_array(arr);
- printMe( (intspan)cspan_subspan(&sp2, 1, 4) );
-
- c_forlist (i, int, {1, 2, 3, 4, 5})
- cvec_int_push(&vec, *i.ref);
- printMe( (intspan)cspan_from(&vec) );
-
- printMe( sp2 );
-
- stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7});
- printMe( (intspan)cspan_from(&stk) );
-
- deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8});
- printMe( (intspan)cspan_from(&deq) );
-
- set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"});
- printf("%d:", (int)csset_str_size(&set));
- c_foreach (e, csset_str, set)
- printf(" %s", cstr_str(e.ref));
- puts("");
- }
+ intspan sp1 = cspan_make(intspan, {1, 2});
+ printMe( sp1 );
+
+ printMe( c_make(intspan, {1, 2, 3}) );
+
+ int arr[] = {1, 2, 3, 4, 5, 6};
+ intspan sp2 = cspan_from_array(arr);
+ printMe( (intspan)cspan_subspan(&sp2, 1, 4) );
+
+ cvec_int vec = c_make(cvec_int, {1, 2, 3, 4, 5});
+ printMe( (intspan)cspan_from(&vec) );
+
+ printMe( sp2 );
+
+ cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7});
+ printMe( (intspan)cspan_from(&stk) );
+
+ cdeq_int deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8});
+ printMe( (intspan)cspan_from(&deq) );
+
+ csset_str set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"});
+ printf("%d:", (int)csset_str_size(&set));
+ c_foreach (e, csset_str, set)
+ printf(" %s", cstr_str(e.ref));
+ puts("");
+
+ // cleanup
+ cvec_int_drop(&vec);
+ cstack_int_drop(&stk);
+ cdeq_int_drop(&deq);
+ csset_str_drop(&set);
}
diff --git a/misc/examples/priority.c b/misc/examples/priority.c
index 0a1d419b..95dd3183 100644
--- a/misc/examples/priority.c
+++ b/misc/examples/priority.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
#define i_val int64_t
#define i_cmp -c_default_cmp // min-heap (increasing values)
@@ -10,26 +10,28 @@
int main() {
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_ZI " numbers\n", N);
- c_forrange (N)
- cpque_i_push(&heap, stc64_uniform(&rng, &dist));
-
- // push some negative numbers too.
- c_forlist (i, int, {-231, -32, -873, -4, -343})
- cpque_i_push(&heap, *i.ref);
-
- c_forrange (N)
- cpque_i_push(&heap, stc64_uniform(&rng, &dist));
-
- puts("Extract the hundred smallest.");
- c_forrange (100) {
- printf("%" PRId64 " ", *cpque_i_top(&heap));
- cpque_i_pop(&heap);
- }
+ crand_t rng = crand_init((uint64_t)time(NULL));
+ crand_unif_t dist = crand_unif_init(0, N * 10);
+
+ cpque_i heap = {0};
+
+ // Push ten million random numbers to priority queue
+ printf("Push %" c_ZI " numbers\n", N);
+ c_forrange (N)
+ cpque_i_push(&heap, crand_unif(&rng, &dist));
+
+ // push some negative numbers too.
+ c_forlist (i, int, {-231, -32, -873, -4, -343})
+ cpque_i_push(&heap, *i.ref);
+
+ c_forrange (N)
+ cpque_i_push(&heap, crand_unif(&rng, &dist));
+
+ puts("Extract the hundred smallest.");
+ c_forrange (100) {
+ printf("%" PRId64 " ", *cpque_i_top(&heap));
+ cpque_i_pop(&heap);
}
+
+ cpque_i_drop(&heap);
}
diff --git a/misc/examples/queue.c b/misc/examples/queue.c
index 4064cc77..83c18d09 100644
--- a/misc/examples/queue.c
+++ b/misc/examples/queue.c
@@ -1,4 +1,4 @@
-#include <stc/crandom.h>
+#include <stc/crand.h>
#include <stdio.h>
#define i_val int
@@ -7,25 +7,26 @@
int main() {
int n = 100000000;
- stc64_uniform_t dist;
- stc64_t rng = stc64_new(1234);
- dist = stc64_uniform_new(0, n);
+ crand_unif_t dist;
+ crand_t rng = crand_init(1234);
+ dist = crand_unif_init(0, n);
- c_auto (cqueue_i, queue)
- {
- // Push ten million random numbers onto the queue.
- c_forrange (n)
- cqueue_i_push(&queue, (int)stc64_uniform(&rng, &dist));
+ cqueue_i queue = {0};
- // Push or pop on the queue ten million times
- printf("%d\n", n);
- c_forrange (n) { // forrange uses initial n only.
- 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_ZI "\n", n, cqueue_i_size(&queue));
+ // Push ten million random numbers onto the queue.
+ c_forrange (n)
+ cqueue_i_push(&queue, (int)crand_unif(&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 = (int)crand_unif(&rng, &dist);
+ if (r & 1)
+ ++n, cqueue_i_push(&queue, r);
+ else
+ --n, cqueue_i_pop(&queue);
}
+ printf("%d, %" c_ZI "\n", n, cqueue_i_size(&queue));
+
+ cqueue_i_drop(&queue);
}
diff --git a/misc/examples/random.c b/misc/examples/random.c
index e27279a0..ea9c483e 100644
--- a/misc/examples/random.c
+++ b/misc/examples/random.c
@@ -1,12 +1,12 @@
#include <stdio.h>
#include <time.h>
-#include <stc/crandom.h>
+#include <stc/crand.h>
int main()
{
const size_t N = 1000000000;
const uint64_t seed = (uint64_t)time(NULL), range = 1000000;
- stc64_t rng = stc64_new(seed);
+ crand_t rng = crand_init(seed);
int64_t sum;
clock_t diff, before;
@@ -15,28 +15,28 @@ int main()
sum = 0;
before = clock();
c_forrange (N) {
- sum += (uint32_t)stc64_rand(&rng);
+ sum += (uint32_t)crand_u64(&rng);
}
diff = clock() - before;
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);
+ crand_unif_t dist1 = crand_unif_init(0, range);
+ rng = crand_init(seed);
sum = 0;
before = clock();
c_forrange (N) {
- sum += stc64_uniform(&rng, &dist1); // unbiased
+ sum += crand_unif(&rng, &dist1); // unbiased
}
diff = clock() - before;
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);
+ rng = crand_init(seed);
before = clock();
c_forrange (N) {
- sum += (int64_t)(stc64_rand(&rng) % (range + 1)); // biased
+ sum += (int64_t)(crand_u64(&rng) % (range + 1)); // biased
}
diff = clock() - before;
printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZI ", avg: %f\n",
diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c
index 4b3d2056..01bcdc44 100644
--- a/misc/examples/rawptr_elements.c
+++ b/misc/examples/rawptr_elements.c
@@ -2,54 +2,58 @@
#include <stdio.h>
#include <stc/cstr.h>
-// Map of cstr => int64 pointers
-typedef int64_t inttype;
-// Do it without cbox:
+// Create cmap of cstr => long*
#define i_type SIPtrMap
#define i_key_str
-#define i_val inttype*
-#define i_valraw inttype
-#define i_valfrom(raw) c_new(inttype, raw)
+#define i_val long*
+#define i_valraw long
+#define i_valfrom(raw) c_new(long, raw)
#define i_valto(x) **x
-#define i_valclone(x) c_new(inttype, *x)
+#define i_valclone(x) c_new(long, *x)
#define i_valdrop(x) c_free(*x)
#include <stc/cmap.h>
-// With cbox:
+// Alternatively, using cbox:
#define i_type IBox
-#define i_val int
-#include <stc/cbox.h> //<stc/carc.h>
+#define i_val long
+#include <stc/cbox.h> // unique_ptr<long> alike.
+// cmap of cstr => IBox
#define i_type SIBoxMap
#define i_key_str
-#define i_valboxed IBox
+#define i_valboxed IBox // i_valboxed: use properties from IBox automatically
#include <stc/cmap.h>
int main()
{
- c_auto (SIPtrMap, map, m1)
- c_auto (SIBoxMap, m2)
- {
- printf("\nMap with pointer elements:\n");
- SIPtrMap_insert(&map, cstr_from("testing"), c_new(inttype, 1));
- SIPtrMap_insert(&map, cstr_from("done"), c_new(inttype, 2));
-
- // Emplace: implicit key, val construction:
- SIPtrMap_emplace(&map, "hello", 3);
- SIPtrMap_emplace(&map, "goodbye", 4);
-
- m1 = SIPtrMap_clone(map);
-
- c_forpair (name, number, SIPtrMap, m1)
- printf("%s: %" PRId64 "\n", cstr_str(_.name), **_.number);
-
-
- puts("\nIBox map:");
- SIBoxMap_insert(&m2, cstr_from("Hello"), IBox_make(123));
- SIBoxMap_emplace(&m2, "World", 999);
- c_forpair (name, number, SIBoxMap, m2)
- printf("%s: %d\n", cstr_str(_.name), *_.number->get);
- puts("");
- }
+ // These have the same behaviour, except IBox has a get member:
+ SIPtrMap map1 = {0};
+ SIBoxMap map2 = {0};
+
+ printf("\nMap cstr => long*:\n");
+ SIPtrMap_insert(&map1, cstr_from("Test1"), c_new(long, 1));
+ SIPtrMap_insert(&map1, cstr_from("Test2"), c_new(long, 2));
+
+ // Emplace implicitly creates cstr from const char* and an owned long* from long!
+ SIPtrMap_emplace(&map1, "Test3", 3);
+ SIPtrMap_emplace(&map1, "Test4", 4);
+
+ c_forpair (name, number, SIPtrMap, map1)
+ printf("%s: %ld\n", cstr_str(_.name), **_.number);
+
+ puts("\nMap cstr => IBox:");
+ SIBoxMap_insert(&map2, cstr_from("Test1"), IBox_make(1));
+ SIBoxMap_insert(&map2, cstr_from("Test2"), IBox_make(2));
+
+ // Emplace implicitly creates cstr from const char* and IBox from long!
+ SIBoxMap_emplace(&map2, "Test3", 3);
+ SIBoxMap_emplace(&map2, "Test4", 4);
+
+ c_forpair (name, number, SIBoxMap, map2)
+ printf("%s: %ld\n", cstr_str(_.name), *_.number->get);
+ puts("");
+
+ SIPtrMap_drop(&map1);
+ SIBoxMap_drop(&map2);
}
diff --git a/misc/examples/regex1.c b/misc/examples/regex1.c
index c311e455..4a56b8ac 100644
--- a/misc/examples/regex1.c
+++ b/misc/examples/regex1.c
@@ -7,24 +7,26 @@ int main(int argc, char* argv[])
printf("Usage: regex1 -i\n");
return 0;
}
- c_auto (cstr, input)
- c_auto (cregex, float_expr)
+ cstr input = {0};
+ cregex float_expr = {0};
+
+ 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)
{
- 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)
- {
- printf("Enter a double precision number (q for quit): ");
- cstr_getline(&input, stdin);
+ printf("Enter a double precision number (q for quit): ");
+ cstr_getline(&input, stdin);
- // Exit when the user inputs q
- if (cstr_equals(&input, "q"))
- break;
+ // Exit when the user inputs q
+ if (cstr_equals(&input, "q"))
+ break;
- if (cregex_is_match(&float_expr, cstr_str(&input)))
- printf("Input is a float\n");
- else
- printf("Invalid input : Not a float\n");
- }
+ if (cregex_is_match(&float_expr, cstr_str(&input)))
+ printf("Input is a float\n");
+ else
+ printf("Invalid input : Not a float\n");
}
+
+ cstr_drop(&input);
+ cregex_drop(&float_expr);
}
diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c
index 20bd323c..3133f7c2 100644
--- a/misc/examples/regex2.c
+++ b/misc/examples/regex2.c
@@ -15,8 +15,8 @@ int main()
{"\\p{Han}+", "This is Han: 王明:那是杂志吗?"},
};
- c_auto (cregex, re)
- c_forrange (i, c_ARRAYLEN(s))
+ cregex re = {0};
+ c_forrange (i, c_arraylen(s))
{
int res = cregex_compile(&re, s[i].pattern);
if (res < 0) {
@@ -30,4 +30,5 @@ int main()
printf(" submatch %lld: %.*s\n", k, c_SV(j.match[k]));
}
}
+ cregex_drop(&re);
}
diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c
index dcc19c1f..def0ae7a 100644
--- a/misc/examples/regex_match.c
+++ b/misc/examples/regex_match.c
@@ -12,24 +12,25 @@ int main()
" Around 365.25 days a year, and 52 weeks in a year."
" Boltzmann const: 1.38064852E-23, is very small."
" Bohrradius is 5.29177210903e-11, and Avogadros number is 6.02214076e23.";
+ cregex re = {0};
+ cstack_float vec = {0};
- c_auto (cregex, re)
- c_auto (cstack_float, vec)
- c_auto (cstr, nums)
- {
- const char* pattern = "[+-]?([0-9]*\\.)?\\d+([Ee][+-]?\\d+)?";
- int res = cregex_compile(&re, pattern);
- printf("%d: %s\n", res, pattern);
+ const char* pattern = "[+-]?([0-9]*\\.)?\\d+([Ee][+-]?\\d+)?";
+ 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, (float)atof(i.match[0].str));
+ // extract and convert all numbers in str to floats
+ c_formatch (i, &re, str)
+ cstack_float_push(&vec, (float)atof(i.match[0].str));
- c_foreach (i, cstack_float, vec)
- printf(" %g\n", *i.ref);
+ c_foreach (i, cstack_float, vec)
+ printf(" %g\n", *i.ref);
- // extracts the numbers only to a comma separated string.
- nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_R_STRIP);
- printf("\n%s\n", cstr_str(&nums));
- }
+ // extracts the numbers only to a comma separated string.
+ cstr nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_R_STRIP);
+ printf("\n%s\n", cstr_str(&nums));
+
+ cstr_drop(&nums);
+ cregex_drop(&re);
+ cstack_float_drop(&vec);
}
diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c
index ebb57488..d3952f50 100644
--- a/misc/examples/regex_replace.c
+++ b/misc/examples/regex_replace.c
@@ -16,9 +16,13 @@ int main()
{
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";
+ cstr str = {0};
+ cregex re = {0};
- c_auto (cstr, str)
- {
+ c_defer(
+ cregex_drop(&re),
+ cstr_drop(&str)
+ ){
printf("INPUT: %s\n", input);
/* replace with a fixed string, extended all-in-one call: */
@@ -34,17 +38,17 @@ int main()
printf("brack: %s\n", cstr_str(&str));
/* Shows how to compile RE separately */
- c_with (cregex re = cregex_from(pattern), cregex_drop(&re)) {
- if (cregex_captures(&re) == 0)
- continue; /* break c_with */
- /* European date format. */
- cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
- printf("euros: %s\n", cstr_str(&str));
-
- /* Strip out everything but the matches */
- cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP));
- printf("strip: %s\n", cstr_str(&str));
- }
+ re = cregex_from(pattern);
+ if (cregex_captures(&re) == 0)
+ continue; /* break c_defer */
+
+ /* European date format. */
+ cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
+ printf("euros: %s\n", cstr_str(&str));
+
+ /* Strip out everything but the matches */
+ cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP));
+ printf("strip: %s\n", cstr_str(&str));
/* Wrap all words in ${} */
cstr_take(&str, cregex_replace_pattern("[a-z]+", "52 apples and 31 mangoes", "$${$0}"));
diff --git a/misc/examples/replace.c b/misc/examples/replace.c
index c22c71ff..cf5b45cb 100644
--- a/misc/examples/replace.c
+++ b/misc/examples/replace.c
@@ -8,27 +8,28 @@ int main ()
// replace signatures used in the same order as described above:
- // Ustring positions: 0123456789*123456789*12345
- cstr s = cstr_from(base); // "this is a test string."
+ // Ustring positions: 0123456789*123456789*12345
+ cstr s = cstr_from(base); // "this is a test string."
cstr m = cstr_clone(s);
- c_defer (cstr_drop(&s), cstr_drop(&m)) {
- cstr_append(&m, cstr_str(&m));
- cstr_append(&m, cstr_str(&m));
- printf("%s\n", cstr_str(&m));
- cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1)
- printf("(1) %s\n", cstr_str(&s));
+ cstr_append(&m, cstr_str(&m));
+ cstr_append(&m, cstr_str(&m));
+ printf("%s\n", cstr_str(&m));
- cstr_replace_at_sv(&s, 19, 6, c_sv(s3+7, 6)); // "this is an example phrase." (2)
- printf("(2) %s\n", cstr_str(&s));
+ cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1)
+ printf("(1) %s\n", cstr_str(&s));
- cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3)
- printf("(3) %s\n", cstr_str(&s));
+ cstr_replace_at_sv(&s, 19, 6, c_sv(s3+7, 6)); // "this is an example phrase." (2)
+ printf("(2) %s\n", cstr_str(&s));
- cstr_replace_at_sv(&s, 8, 6, c_sv("a shorty", 7)); // "this is a short phrase." (4)
- printf("(4) %s\n", cstr_str(&s));
+ cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3)
+ printf("(3) %s\n", cstr_str(&s));
- cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5)
- printf("(5) %s\n", cstr_str(&s));
- }
+ cstr_replace_at_sv(&s, 8, 6, c_sv("a shorty", 7)); // "this is a short phrase." (4)
+ printf("(4) %s\n", cstr_str(&s));
+
+ cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5)
+ printf("(5) %s\n", cstr_str(&s));
+
+ c_drop(cstr, &s, &m);
}
diff --git a/misc/examples/shape.c b/misc/examples/shape.c
index d290fb4d..d7116039 100644
--- a/misc/examples/shape.c
+++ b/misc/examples/shape.c
@@ -4,7 +4,7 @@
#include <stdio.h>
#include <stc/ccommon.h>
-#define c_dyn_cast(T, s) \
+#define DYN_CAST(T, s) \
(&T##_api == (s)->api ? (T*)(s) : (T*)0)
// Shape definition
@@ -53,15 +53,14 @@ typedef struct {
extern struct ShapeAPI Triangle_api;
-Triangle Triangle_from(Point a, Point b, Point c)
-{
- Triangle t = {.shape={.api=&Triangle_api}, .p={a, b, c}};
+Triangle Triangle_from(Point a, Point b, Point c) {
+ Triangle t = {{&Triangle_api}, {a, b, c}};
return t;
}
static void Triangle_draw(const Shape* shape)
{
- const Triangle* self = c_dyn_cast(Triangle, shape);
+ const Triangle* self = DYN_CAST(Triangle, shape);
printf("Triangle : (%g,%g), (%g,%g), (%g,%g)\n",
self->p[0].x, self->p[0].y,
self->p[1].x, self->p[1].y,
@@ -88,9 +87,8 @@ typedef struct {
extern struct ShapeAPI Polygon_api;
-Polygon Polygon_init(void)
-{
- Polygon p = {.shape={.api=&Polygon_api}, .points=PointVec_init()};
+Polygon Polygon_init(void) {
+ Polygon p = {{&Polygon_api}, {0}};
return p;
}
@@ -101,15 +99,14 @@ void Polygon_addPoint(Polygon* self, Point p)
static void Polygon_drop(Shape* shape)
{
- Polygon* self = c_dyn_cast(Polygon, shape);
+ Polygon* self = DYN_CAST(Polygon, shape);
printf("poly destructed\n");
PointVec_drop(&self->points);
- Shape_drop(shape);
}
static void Polygon_draw(const Shape* shape)
{
- const Polygon* self = c_dyn_cast(Polygon, shape);
+ const Polygon* self = DYN_CAST(Polygon, shape);
printf("Polygon :");
c_foreach (i, PointVec, self->points)
printf(" (%g,%g)", i.ref->x, i.ref->y);
@@ -138,23 +135,24 @@ void testShape(const Shape* shape)
int main(void)
{
- c_auto (Shapes, shapes)
- {
- Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20}));
- Polygon* pol1 = c_new(Polygon, Polygon_init());
- Polygon* pol2 = c_new(Polygon, Polygon_init());
-
- c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}})
- Polygon_addPoint(pol1, *i.ref);
-
- c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}})
- Polygon_addPoint(pol2, *i.ref);
-
- Shapes_push(&shapes, &tri1->shape);
- Shapes_push(&shapes, &pol1->shape);
- Shapes_push(&shapes, &pol2->shape);
-
- c_foreach (i, Shapes, shapes)
- testShape(*i.ref);
- }
+ Shapes shapes = {0};
+
+ Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20}));
+ Polygon* pol1 = c_new(Polygon, Polygon_init());
+ Polygon* pol2 = c_new(Polygon, Polygon_init());
+
+ c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}})
+ Polygon_addPoint(pol1, *i.ref);
+
+ c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}})
+ Polygon_addPoint(pol2, *i.ref);
+
+ Shapes_push(&shapes, &tri1->shape);
+ Shapes_push(&shapes, &pol1->shape);
+ Shapes_push(&shapes, &pol2->shape);
+
+ c_foreach (i, Shapes, shapes)
+ testShape(*i.ref);
+
+ Shapes_drop(&shapes);
}
diff --git a/misc/examples/sidebyside.cpp b/misc/examples/sidebyside.cpp
index 80c934a4..a7c1008c 100644
--- a/misc/examples/sidebyside.cpp
+++ b/misc/examples/sidebyside.cpp
@@ -24,9 +24,8 @@ int main() {
std::cout << i.first << ", " << i.second << std::endl;
std::cout << std::endl;
}
-
- c_auto (IIMap, hist)
- {
+ {
+ IIMap hist = {0};
IIMap_insert(&hist, 12, 100).ref->second += 1;
IIMap_insert(&hist, 13, 100).ref->second += 1;
IIMap_insert(&hist, 12, 100).ref->second += 1;
@@ -34,6 +33,7 @@ int main() {
c_foreach (i, IIMap, hist)
printf("%d, %d\n", i.ref->first, i.ref->second);
puts("");
+ IIMap_drop(&hist);
}
// ===================================================
{
@@ -44,14 +44,14 @@ int main() {
std::cout << i.first << ", " << i.second << std::endl;
std::cout << std::endl;
}
-
- c_auto (SIMap, food)
{
+ SIMap food = {0};
c_forlist (i, SIMap_raw, {{"burger", 5}, {"pizza", 12}, {"steak", 15}})
- SIMap_emplace(&food, c_PAIR(i.ref));
+ SIMap_emplace(&food, i.ref->first, i.ref->second);
c_foreach (i, SIMap, food)
printf("%s, %d\n", cstr_str(&i.ref->first), i.ref->second);
puts("");
+ SIMap_drop(&food);
}
}
diff --git a/misc/examples/sorted_map.c b/misc/examples/sorted_map.c
index c4a05c76..ae9b45a4 100644
--- a/misc/examples/sorted_map.c
+++ b/misc/examples/sorted_map.c
@@ -9,8 +9,11 @@ int main()
{
// empty map containers
- c_auto (csmap_int, gquiz1, gquiz2)
- {
+ csmap_int gquiz1 = {0}, gquiz2 = {0};
+ c_defer(
+ csmap_int_drop(&gquiz1),
+ csmap_int_drop(&gquiz2)
+ ){
// insert elements in random order
csmap_int_insert(&gquiz1, 2, 30);
csmap_int_insert(&gquiz1, 4, 20);
diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c
index 5bf02d42..2bc6fc07 100644
--- a/misc/examples/splitstr.c
+++ b/misc/examples/splitstr.c
@@ -10,10 +10,11 @@ int main()
c_fortoken (i, "Hello World C99!", " ")
printf("'%.*s'\n", c_SV(i.token));
-
puts("\nSplit with c_formatch (regex):");
- c_with (cregex re = cregex_from("[^ ]+"), cregex_drop(&re))
- c_formatch (i, &re, " Hello World C99! ")
- printf("'%.*s'\n", c_SV(i.match[0]));
+ cregex re = cregex_from("[^ ]+");
+ c_formatch (i, &re, " Hello World C99! ")
+ printf("'%.*s'\n", c_SV(i.match[0]));
+
+ cregex_drop(&re);
}
diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c
index 128cf50d..70450e21 100644
--- a/misc/examples/sso_map.c
+++ b/misc/examples/sso_map.c
@@ -5,13 +5,14 @@
int main()
{
- c_auto (cmap_str, m) {
- cmap_str_emplace(&m, "Test short", "This is a short string");
- cmap_str_emplace(&m, "Test long ", "This is a longer string");
+ cmap_str m = {0};
+ cmap_str_emplace(&m, "Test short", "This is a short string");
+ cmap_str_emplace(&m, "Test long ", "This is a longer string");
- c_forpair (k, v, cmap_str, m)
- 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");
- }
+ c_forpair (k, v, cmap_str, m)
+ 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");
+
+ cmap_str_drop(&m);
}
diff --git a/misc/examples/stack.c b/misc/examples/stack.c
index 50dc8eb7..c817e1ae 100644
--- a/misc/examples/stack.c
+++ b/misc/examples/stack.c
@@ -11,20 +11,22 @@
#include <stc/cstack.h>
int main() {
- c_auto (cstack_i, stack)
- c_auto (cstack_c, chars)
- {
- c_forrange (i, 101)
- cstack_i_push(&stack, (int)(i*i));
-
- printf("%d\n", *cstack_i_top(&stack));
-
- c_forrange (i, 90)
- cstack_i_pop(&stack);
-
- c_foreach (i, cstack_i, stack)
- printf(" %d", *i.ref);
- puts("");
- printf("top: %d\n", *cstack_i_top(&stack));
- }
+ cstack_i stack = {0};
+ cstack_c chars = {0};
+
+ c_forrange (i, 101)
+ cstack_i_push(&stack, (int)(i*i));
+
+ printf("%d\n", *cstack_i_top(&stack));
+
+ c_forrange (i, 90)
+ cstack_i_pop(&stack);
+
+ c_foreach (i, cstack_i, stack)
+ printf(" %d", *i.ref);
+ puts("");
+ printf("top: %d\n", *cstack_i_top(&stack));
+
+ cstack_i_drop(&stack);
+ cstack_c_drop(&chars);
}
diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c
index 18d547f8..31a28e51 100644
--- a/misc/examples/sview_split.c
+++ b/misc/examples/sview_split.c
@@ -12,8 +12,7 @@ int main()
printf("%.*s, %.*s, %.*s\n", c_SV(year), c_SV(month), c_SV(day));
- c_auto (cstr, y, m, d) {
- y = cstr_from_sv(year), m = cstr_from_sv(month), d = cstr_from_sv(day);
- printf("%s, %s, %s\n", cstr_str(&y), cstr_str(&m), cstr_str(&d));
- }
+ cstr y = cstr_from_sv(year), m = cstr_from_sv(month), d = cstr_from_sv(day);
+ printf("%s, %s, %s\n", cstr_str(&y), cstr_str(&m), cstr_str(&d));
+ c_drop(cstr, &y, &m, &d);
}
diff --git a/misc/examples/triples.c b/misc/examples/triples.c
index 4783d603..520bf012 100644
--- a/misc/examples/triples.c
+++ b/misc/examples/triples.c
@@ -4,12 +4,12 @@
#include <stdio.h>
void triples_vanilla(int n) {
- for (int i = 1, c = 1;; ++c) {
+ for (int c = 5; n; ++c) {
for (int a = 1; a < c; ++a) {
- for (int b = a; b < c; ++b) {
- if (a*a + b*b == c*c) {
- printf("{%d, %d, %d},\n", a, b, c);
- if (++i > n) goto done;
+ for (int b = a + 1; b < c; ++b) {
+ if ((int64_t)a*a + (int64_t)b*b == (int64_t)c*c) {
+ printf("{%d, %d, %d}\n", a, b, c);
+ if (--n == 0) goto done;
}
}
}
@@ -25,20 +25,29 @@ struct triples {
bool triples_next(struct triples* I) {
cco_begin(I);
- for (I->c = 1;; ++I->c) {
+ for (I->c = 5; I->n; ++I->c) {
for (I->a = 1; I->a < I->c; ++I->a) {
- for (I->b = I->a; I->b < I->c; ++I->b) {
- if (I->a*I->a + I->b*I->b == I->c*I->c) {
- if (I->n-- == 0) cco_return;
+ for (I->b = I->a + 1; I->b < I->c; ++I->b) {
+ if ((int64_t)I->a*I->a + (int64_t)I->b*I->b == (int64_t)I->c*I->c) {
cco_yield(true);
+ if (--I->n == 0) cco_return;
}
}
}
}
cco_final:
+ puts("done");
cco_end(false);
}
+int gcd(int a, int b) {
+ while (b) {
+ int t = a % b;
+ a = b;
+ b = t;
+ }
+ return a;
+}
int main()
{
@@ -47,8 +56,14 @@ int main()
puts("\nCoroutine triples:");
struct triples t = {INT32_MAX};
+ int n = 0;
+
while (triples_next(&t)) {
- if (t.c < 100) printf("{%d, %d, %d},\n", t.a, t.b, t.c);
- else cco_stop(&t);
+ if (gcd(t.a, t.b) > 1)
+ continue;
+ if (t.c < 100)
+ printf("%d: {%d, %d, %d}\n", ++n, t.a, t.b, t.c);
+ else
+ cco_stop(&t);
}
}
diff --git a/misc/examples/unordered_set.c b/misc/examples/unordered_set.c
index f9221b21..61f9cc1f 100644
--- a/misc/examples/unordered_set.c
+++ b/misc/examples/unordered_set.c
@@ -7,8 +7,10 @@
int main()
{
// declaring set for storing string data-type
- c_auto (cset_str, stringSet)
- {
+ cset_str stringSet = {0};
+ c_defer(
+ cset_str_drop(&stringSet)
+ ){
// inserting various string, same string will be stored
// once in set
cset_str_emplace(&stringSet, "code");
diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c
index b697efd8..3cde8701 100644
--- a/misc/examples/utf8replace_c.c
+++ b/misc/examples/utf8replace_c.c
@@ -2,24 +2,23 @@
int main()
{
- c_auto (cstr, hello, str)
- {
- hello = cstr_lit("hell😀 w😀rld");
- printf("%s\n", cstr_str(&hello));
+ cstr hello = cstr_lit("hell😀 w😀rld");
+ printf("%s\n", cstr_str(&hello));
- /* replace second smiley at utf8 codepoint pos 7 */
- cstr_u8_replace_at(&hello,
- cstr_u8_to_pos(&hello, 7),
- 1,
- c_sv("🐨")
- );
- printf("%s\n", cstr_str(&hello));
+ /* replace second smiley at utf8 codepoint pos 7 */
+ cstr_u8_replace_at(&hello,
+ cstr_u8_to_pos(&hello, 7),
+ 1,
+ c_sv("🐨")
+ );
+ printf("%s\n", cstr_str(&hello));
- c_foreach (c, cstr, hello)
- printf("%.*s,", c_SV(c.u8.chr));
-
- str = cstr_lit("scooby, dooby doo");
- cstr_replace(&str, "oo", "00");
- printf("\n%s\n", cstr_str(&str));
- }
+ c_foreach (c, cstr, hello)
+ printf("%.*s,", c_SV(c.u8.chr));
+
+ cstr str = cstr_lit("scooby, dooby doo");
+ cstr_replace(&str, "oo", "00");
+ printf("\n%s\n", cstr_str(&str));
+
+ c_drop(cstr, &hello, &str);
}
diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c
index 7a21d0a5..abb909c3 100644
--- a/misc/examples/vikings.c
+++ b/misc/examples/vikings.c
@@ -39,28 +39,20 @@ static inline RViking Viking_toraw(const Viking* vp) {
#define i_hash(rp) cstrhash(rp->name) ^ cstrhash(rp->country)
#define i_val int // mapped type
#include <stc/cmap.h>
-/*
- i_keyclass implies these defines, unless they are already defined:
- i_cmp => RViking_cmp
- //i_hash => RViking_hash // already defined.
- //i_keyclone => Viking_clone // not used, because of c_no_clone
- i_keyto => Viking_toraw // because i_rawclass is defined
- i_keydrop => Viking_drop
-*/
int main()
{
- c_auto (Vikings, vikings) {
- Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20);
- Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24);
- Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12);
- Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10);
+ Vikings vikings = {0};
+ Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20);
+ Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24);
+ Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12);
+ Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10);
- Vikings_value* v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"});
- v->second += 3; // add 3 hp points to Einar
+ Vikings_value* v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"});
+ v->second += 3; // add 3 hp points to Einar
- c_forpair (vk, hp, Vikings, vikings) {
- printf("%s of %s has %d hp\n", cstr_str(&_.vk->name), cstr_str(&_.vk->country), *_.hp);
- }
+ c_forpair (vk, hp, Vikings, vikings) {
+ printf("%s of %s has %d hp\n", cstr_str(&_.vk->name), cstr_str(&_.vk->country), *_.hp);
}
+ Vikings_drop(&vikings);
}
diff --git a/misc/examples/words.c b/misc/examples/words.c
deleted file mode 100644
index f097a991..00000000
--- a/misc/examples/words.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <math.h>
-#include <stc/cstr.h>
-
-#define i_val_str
-#include <stc/cvec.h>
-
-#define i_key_str
-#define i_val int
-#include <stc/cmap.h>
-
-int main1()
-{
- c_auto (cvec_str, words)
- c_auto (cmap_str, word_map)
- {
- words = c_make(cvec_str, {
- "this", "sentence", "is", "not", "a", "sentence",
- "this", "sentence", "is", "a", "hoax"
- });
-
- c_foreach (w, cvec_str, words) {
- cmap_str_emplace(&word_map, cstr_str(w.ref), 0).ref->second += 1;
- }
-
- c_foreach (i, cmap_str, word_map) {
- printf("%d occurrences of word '%s'\n",
- i.ref->second, cstr_str(&i.ref->first));
- }
- }
- return 0;
-}
-
-#ifdef __cplusplus
-#include <string>
-#include <iostream>
-#include <vector>
-#include <unordered_map>
-
-int main2()
-{
- std::vector<std::string> words = {
- "this", "sentence", "is", "not", "a", "sentence",
- "this", "sentence", "is", "a", "hoax"
- };
-
- std::unordered_map<std::string, size_t> word_map;
- for (const auto &w : words) {
- word_map[w] += 1;
- }
-
- for (const auto &pair : word_map) {
- std::cout << pair.second
- << " occurrences of word '"
- << pair.first << "'\n";
- }
- return 0;
-}
-
-int main() {
- main1();
- puts("");
- main2();
-}
-#else
-int main() {
- main1();
-}
-#endif
diff --git a/misc/tests/cregex_test.c b/misc/tests/cregex_test.c
index b3cc9f0a..aa4b2a65 100644
--- a/misc/tests/cregex_test.c
+++ b/misc/tests/cregex_test.c
@@ -248,8 +248,12 @@ CTEST(cregex, replace)
{
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) {
+ cstr str = {0};
+ cregex re = {0};
+ c_defer(
+ cstr_drop(&str),
+ cregex_drop(&re)
+ ){
// replace with a fixed string, extended all-in-one call:
cstr_take(&str, cregex_replace_pattern(pattern, input, "YYYY-MM-DD"));
ASSERT_STREQ(cstr_str(&str), "start date: YYYY-MM-DD, end date: YYYY-MM-DD");
@@ -267,16 +271,15 @@ CTEST(cregex, replace)
ASSERT_STREQ(cstr_str(&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);
+ re = cregex_from(pattern);
+ ASSERT_EQ(cregex_captures(&re), 4);
- // European date format.
- cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
- ASSERT_STREQ(cstr_str(&str), "start date: 31.12.2015, end date: 28.02.2022");
+ // European date format.
+ cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
+ ASSERT_STREQ(cstr_str(&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_STREQ(cstr_str(&str), "31.12.2015;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_STREQ(cstr_str(&str), "31.12.2015;28.02.2022;");
}
}
diff --git a/src/checkauto.l b/src/checkauto.l
index ab71403c..a8f14abb 100644
--- a/src/checkauto.l
+++ b/src/checkauto.l
@@ -35,20 +35,15 @@ c_foreach |
c_forpair |
c_forrange |
c_forfilter |
-c_forwhile |
c_formatch |
c_fortoken |
for |
while |
switch { block_type |= LOOP; state = BRACES; }
do { block_type |= LOOP; state = BRACESDONE; }
-c_with |
-c_scope |
c_defer |
-c_auto |
-c_with |
c_scope |
-c_defer |
+c_with |
c_auto { block_type = AUTO; state = BRACES; }
\( { if (state == BRACES) ++braces_lev; }
\) { if (state == BRACES && --braces_lev == 0) {
diff --git a/src/singleupdate.sh b/src/singleupdate.sh
new file mode 100644
index 00000000..d9a16568
--- /dev/null
+++ b/src/singleupdate.sh
@@ -0,0 +1,27 @@
+d=$(git rev-parse --show-toplevel)
+mkdir -p $d/../stcsingle/c11 $d/../stcsingle/stc
+python singleheader.py $d/include/c11/print.h > $d/../stcsingle/c11/print.h
+python singleheader.py $d/include/stc/calgo.h > $d/../stcsingle/stc/calgo.h
+python singleheader.py $d/include/stc/carc.h > $d/../stcsingle/stc/carc.h
+python singleheader.py $d/include/stc/cbits.h > $d/../stcsingle/stc/cbits.h
+python singleheader.py $d/include/stc/cbox.h > $d/../stcsingle/stc/cbox.h
+python singleheader.py $d/include/stc/ccommon.h > $d/../stcsingle/stc/ccommon.h
+python singleheader.py $d/include/stc/cdeq.h > $d/../stcsingle/stc/cdeq.h
+python singleheader.py $d/include/stc/clist.h > $d/../stcsingle/stc/clist.h
+python singleheader.py $d/include/stc/cmap.h > $d/../stcsingle/stc/cmap.h
+python singleheader.py $d/include/stc/coption.h > $d/../stcsingle/stc/coption.h
+python singleheader.py $d/include/stc/cpque.h > $d/../stcsingle/stc/cpque.h
+python singleheader.py $d/include/stc/cqueue.h > $d/../stcsingle/stc/cqueue.h
+python singleheader.py $d/include/stc/crand.h > $d/../stcsingle/stc/crand.h
+python singleheader.py $d/include/stc/cregex.h > $d/../stcsingle/stc/cregex.h
+python singleheader.py $d/include/stc/cset.h > $d/../stcsingle/stc/cset.h
+python singleheader.py $d/include/stc/csmap.h > $d/../stcsingle/stc/csmap.h
+python singleheader.py $d/include/stc/cspan.h > $d/../stcsingle/stc/cspan.h
+python singleheader.py $d/include/stc/csset.h > $d/../stcsingle/stc/csset.h
+python singleheader.py $d/include/stc/cstack.h > $d/../stcsingle/stc/cstack.h
+python singleheader.py $d/include/stc/cstr.h > $d/../stcsingle/stc/cstr.h
+python singleheader.py $d/include/stc/csview.h > $d/../stcsingle/stc/csview.h
+python singleheader.py $d/include/stc/cvec.h > $d/../stcsingle/stc/cvec.h
+python singleheader.py $d/include/stc/extend.h > $d/../stcsingle/stc/extend.h
+python singleheader.py $d/include/stc/forward.h > $d/../stcsingle/stc/forward.h
+echo "stcsingle headers updated" \ No newline at end of file
diff --git a/src/utf8code.c b/src/utf8code.c
index ecfdd24d..496f5eef 100644
--- a/src/utf8code.c
+++ b/src/utf8code.c
@@ -142,7 +142,7 @@ 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((int)c) != 0;
- for (int j=0; j < c_ARRAYLEN(groups); ++j)
+ for (int j=0; j < c_arraylen(groups); ++j)
if (utf8_isgroup(groups[j], c))
return true;
return false;