diff options
| author | Tyge Løvset <[email protected]> | 2023-03-26 00:27:45 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-03-26 00:27:45 +0100 |
| commit | eb85069b669e754836b9d4587ba03d3af1a5e975 (patch) | |
| tree | 45c9a0d3fe40c59a8b33ae8ecd2e7aa78bef6240 /README.md | |
| parent | e8be14dfc894eeac859f0287d4d5b4f4745c0585 (diff) | |
| download | STC-modified-eb85069b669e754836b9d4587ba03d3af1a5e975.tar.gz STC-modified-eb85069b669e754836b9d4587ba03d3af1a5e975.zip | |
development branch for 4.2
Removed uses of c_auto and c_with in documentation examples and code examples. Still using c_defer a few places.
Renamed c11/fmt.h to c11/print.h.
Some additions in ccommon.h, e.g. c_const_cast(T, x).
Improved docs.
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 169 |
1 files changed, 99 insertions, 70 deletions
@@ -3,7 +3,7 @@ STC - Smart Template Containers for C ===================================== -News: Version 4.1.1 Released (Feb 2023) +News: Version 4.2 Released (2023-03-26) ------------------------------------------------ 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). @@ -148,108 +148,138 @@ The usage of the containers is similar to the c++ standard containers in STL, so are familiar with them. All containers are generic/templated, except for **cstr** and **cbits**. No casting is used, so containers are type-safe like templates in c++. A basic usage example: ```c -#define i_type FVec // Container type name; if not defined, it would be cvec_float +#define i_type Floats // Container type name; if not defined, it 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 = Floats_init(); + Floats_push(&nums, 30.f); + Floats_push(&nums, 10.f); + Floats_push(&nums, 20.f); - for (intptr_t i = 0; i < FVec_size(vec); ++i) - printf(" %g", vec.data[i]); + for (int i = 0; i < Floats_size(&nums); ++i) + printf(" %g", nums.data[i]); + + Floats_sort(&nums); - FVec_drop(&vec); // cleanup memory + c_foreach (i, Floats, nums) // Alternative way to iterate nums. + printf(" %g", *i.ref); // i.ref is a pointer to the current element. + + 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: +To switch to a different container type is easy when using `c_foreach`: ```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 = c_make(Floats, {30.f, 10.f, 20.f}); // Initialize with a list of floats. + Floats_push(&nums, 50.f); + Floats_push(&nums, 40.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 + // print the sorted 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 that can be cloned. All of its element vectors will be destroyed when destroying the Vec2D. ```c -#define i_val struct One -#define i_opt c_no_cmp -#define i_tag one +#define i_type Vec +#define i_val float #include <stc/cvec.h> +#include <stdio.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 "member" functions Vec_clone(), Vec_drop() and Vec_cmp(). +#define i_opt c_no_cmp // Disable 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(); -``` -An example using six different container types: +int main(void) +{ + Vec* v; + Vec2D vec = {0}; // All containers in STC can be initialized with {0}. + v = Vec2D_push(&vec, Vec_init()); // 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. +} +``` +Here is an example of using six different container types: ```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 #define i_val struct Point -#define i_cmp Point_cmp +// Define a i_less template parameter (alternative to i_cmp) for Point. +#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 +#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/cdeq.h> // cdeq_int: deque of int #define i_val int -#include <stc/clist.h> // clist_int: singly linked list +#include <stc/clist.h> // clist_int: singly linked list #define i_val int -#include <stc/cstack.h> +#include <stc/cstack.h> // cstack_int #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) - { + // Define six empty containers + cset_int set = {0}; + cvec_pnt vec = {0}; + cdeq_int deq = {0}; + clist_int lst = {0}; + cstack_int stk = {0}; + csmap_int map = {0}; + + c_defer( // Drop the containers after the scope is executed + cset_int_drop(&set), + cvec_pnt_drop(&vec), + cdeq_int_drop(&deq), + clist_int_drop(&lst), + cstack_int_drop(&stk), + csmap_int_drop(&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} }; - /* Add some elements to each container */ + // Add some elements to each container for (int i = 0; i < 4; ++i) { cset_int_insert(&set, nums[i]); cvec_pnt_push(&vec, pts[i]); @@ -259,7 +289,7 @@ int main(void) csmap_int_insert(&map, pairs[i][0], pairs[i][1]); } - /* Find an element in each container (except cstack) */ + // Find an element in each container (except cstack) 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); @@ -270,7 +300,7 @@ int main(void) *i1.ref, i2.ref->x, i2.ref->y, *i3.ref, *i4.ref, i5.ref->first, i5.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); @@ -446,17 +476,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_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_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. + +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 @@ -552,9 +584,6 @@ STC is generally very memory efficient. Type sizes: - 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. |
