From 1ac8bb4ff664baa838b44ed6bf62225766f000c5 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 10 Mar 2023 18:36:28 +0100 Subject: Added short names by default to c11/fmt.h print, println and printd. c_forwhile() now takes container not start iter: may be removed! Cleanup in filter.h --- include/stc/ccommon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index d163b4ab..de230910 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -178,9 +178,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) \ +#define c_forwhile(i, C, cnt, cond) \ for (struct {C##_iter it; C##_value *ref; intptr_t index;} \ - i = {.it=start, .ref=i.it.ref}; i.it.ref && (cond) \ + i = {.it=C##_begin(&cnt), .ref=i.it.ref}; i.it.ref && (cond) \ ; C##_next(&i.it), i.ref = i.it.ref, ++i.index) #define c_forpair(key, val, C, cnt) /* structured binding */ \ -- cgit v1.2.3 From c9be5f66a481bd040b36a25314f6589dd939daa5 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 12 Mar 2023 13:30:15 +0100 Subject: Safer state machine in coroutine.h (internal). Removed c_forwhile() macro. Redundant, use c_forfilter(). Removed find and eq in cspan (use general c_find_if() instead for search). --- README.md | 1 - docs/ccommon_api.md | 16 ++++++++-------- include/stc/algo/coroutine.h | 9 +++++++-- include/stc/algo/crange.h | 6 +++--- include/stc/algo/filter.h | 13 ++++++++----- include/stc/ccommon.h | 5 ----- include/stc/cspan.h | 21 +++------------------ include/stc/priv/altnames.h | 1 - misc/examples/forfilter.c | 36 ++++++++++++++++++------------------ misc/examples/forloops.c | 20 ++++++++++---------- misc/examples/list.c | 11 ++++++----- misc/examples/prime.c | 6 +++--- src/checkauto.l | 1 - 13 files changed, 66 insertions(+), 80 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/README.md b/README.md index f74ee916..c214413b 100644 --- a/README.md +++ b/README.md @@ -547,7 +547,6 @@ STC is generally very memory efficient. Type sizes: ## 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: diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 8dcb2ff3..ff75d83d 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -176,7 +176,7 @@ Iterate containers with stop-criteria and 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 | +| `c_forfilter_it (it, ctype, startit, filter)` | Filter from startit position | | Built-in filter | Description | |:----------------------------------|:-------------------------------------| @@ -203,10 +203,10 @@ int main() { crange R = crange_make(1001, INT32_MAX, 2); 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, 24) && + c_flt_count(i) % 15 == 1 && + c_flt_take(i, 10)) printf(" %lld", *i.ref); puts(""); } @@ -237,9 +237,9 @@ c_forfilter (i, crange, r1, isPrime(*i.ref)) // 2. The 11 first primes: printf("2"); -c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2) - , isPrime(*i.ref) - && c_flt_take(10)) +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 ``` diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index 1c849d49..1dd82720 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -68,12 +68,11 @@ enum { #define cco_begin(ctx) \ int *_state = &(ctx)->cco_state; \ switch (*_state) { \ - case cco_state_done: \ case 0: #define cco_end(retval) \ *_state = cco_state_done; break; \ - default: goto _cco_final_; /* never happens */ \ + default: assert(0); goto _cco_final_; \ } \ return retval @@ -109,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_final) *_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/filter.h b/include/stc/algo/filter.h index a5e11b64..5e3125b1 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -35,10 +35,10 @@ int main() 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 + 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(""); } @@ -57,8 +57,11 @@ int main() #define c_flt_last(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.it.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 diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index de230910..33446982 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -178,11 +178,6 @@ 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, cnt, cond) \ - for (struct {C##_iter it; C##_value *ref; intptr_t index;} \ - i = {.it=C##_begin(&cnt), .ref=i.it.ref}; i.it.ref && (cond) \ - ; C##_next(&i.it), i.ref = i.it.ref, ++i.index) - #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)} \ ; _.it.ref && (_.key = &_.it.ref->first, _.val = &_.it.ref->second) \ diff --git a/include/stc/cspan.h b/include/stc/cspan.h index 00313540..d5482200 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -48,9 +48,9 @@ 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 +65,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 +96,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/priv/altnames.h b/include/stc/priv/altnames.h index b10c7a11..8fa326f1 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 diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 2be975a6..cd6d59cc 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -32,13 +32,13 @@ void demo1(void) 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 + 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); @@ -65,10 +65,10 @@ 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)) + 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); @@ -97,7 +97,7 @@ void demo3(void) SVec_push(&words, *w.ref); c_forfilter (w, SVec, words, - csview_contains(*w.ref, "i")) + csview_contains(*w.ref, "i")) SVec_push(&words_containing_i, *w.ref); puts("demo3:"); @@ -127,12 +127,12 @@ void demo5(void) #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(""); } diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 707e8285..144ec637 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -60,20 +60,20 @@ int main() 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) + puts("\n\nc_forfilter 1:"); + c_forfilter (i, IVec, vec, c_flt_take(i, 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)) + puts("\n\nc_forfilter 2:"); + 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 diff --git a/misc/examples/list.c b/misc/examples/list.c index b345bd16..c12d67e9 100644 --- a/misc/examples/list.c +++ b/misc/examples/list.c @@ -1,11 +1,12 @@ #include #include +#include +#include #define i_val double #define i_tag fx #define i_extern // include sort function #include -#include int main() { const int n = 1000000; @@ -24,8 +25,8 @@ int main() { 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, clist_fx, list, c_flt_take(i, 10)) + printf("%8d: %10f\n", c_flt_last(i), *i.ref); puts("sort"); clist_fx_sort(&list); // mergesort O(n*log n) @@ -37,8 +38,8 @@ int main() { last = *i.ref; } - c_forwhile (i, clist_fx, clist_fx_begin(&list), i.index < 10) - printf("%8d: %10f\n", (int)i.index, *i.ref); + c_forfilter (i, clist_fx, list, c_flt_take(i, 10)) + printf("%8d: %10f\n", c_flt_last(i), *i.ref); puts(""); clist_fx_clear(&list); diff --git a/misc/examples/prime.c b/misc/examples/prime.c index 59ee336c..16a59774 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -43,9 +43,9 @@ int main(void) 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)) { + 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(""); } diff --git a/src/checkauto.l b/src/checkauto.l index ab71403c..349da70b 100644 --- a/src/checkauto.l +++ b/src/checkauto.l @@ -35,7 +35,6 @@ c_foreach | c_forpair | c_forrange | c_forfilter | -c_forwhile | c_formatch | c_fortoken | for | -- cgit v1.2.3 From 5ef0986e98ef021e5ce2f46cdaba244c2c51bc4c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 13 Mar 2023 12:40:07 +0100 Subject: Fixed bug and improved generic c_eraseremove_if(). --- include/stc/ccommon.h | 10 ++++++---- misc/examples/triples.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 14 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 33446982..ad6063e4 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -254,10 +254,12 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, #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); \ + C##_iter it = C##_begin(_cnt), _i; \ + while (it.ref && !(pred)) \ + C##_next(&it); \ + for (_i = it; it.ref; C##_next(&it)) \ + if (pred) C##_value_drop(it.ref), ++_n; \ + else *_i.ref = *it.ref, C##_next(&_i); \ _cnt->_len -= _n; \ } while (0) diff --git a/misc/examples/triples.c b/misc/examples/triples.c index 4783d603..aac7967a 100644 --- a/misc/examples/triples.c +++ b/misc/examples/triples.c @@ -4,12 +4,12 @@ #include void triples_vanilla(int n) { - for (int i = 1, c = 1;; ++c) { + for (int i = 5, c = 1;; ++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) { + if (i++ == n) goto done; + printf("{%d, %d, %d}\n", a, b, c); } } } @@ -25,10 +25,10 @@ struct triples { bool triples_next(struct triples* I) { cco_begin(I); - for (I->c = 1;; ++I->c) { + for (I->c = 5;; ++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) { + 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) { if (I->n-- == 0) cco_return; cco_yield(true); } @@ -36,9 +36,18 @@ bool triples_next(struct triples* I) { } } 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 < 1000) + printf("%d: {%d, %d, %d}\n", ++n, t.a, t.b, t.c); + else + cco_stop(&t); } } -- cgit v1.2.3 From e6a25eaaf4687ff99d0d719d0b32ad512156039e Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Mar 2023 17:32:21 +0100 Subject: Added c_foreach_r() macro for reverse iter of cvec, cdeq, cstack. Moved c_find_if, c_erase_if, c_eraseremove_if to algo/filter.h Internals. --- docs/ccommon_api.md | 15 +++++++------- include/stc/algo/filter.h | 44 ++++++++++++++++++++++++++++++++++++++++ include/stc/ccommon.h | 48 ++++++++------------------------------------ include/stc/cmap.h | 4 ++-- include/stc/forward.h | 2 +- misc/examples/arcvec_erase.c | 4 ++-- misc/examples/csmap_find.c | 2 +- misc/examples/csset_erase.c | 2 +- misc/examples/demos.c | 2 +- misc/examples/forloops.c | 11 +++++----- 10 files changed, 74 insertions(+), 60 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index ff75d83d..64daad42 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -94,13 +94,14 @@ int main() ``` ## 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 | +### c_foreach, c_foreach_r, c_forpair + +| Usage | Description | +|:-----------------------------------------|:----------------------------------------| +| `c_foreach (it, ctype, container)` | Iteratate all elements | +| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) | +| `c_foreach_r (it, ctype, container)` | Iteratate in reverse (cstack,cvec,cdeq) | +| `c_forpair (key, val, ctype, container)` | Iterate with structured binding | ```c #define i_key int diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index 5e3125b1..1978ea43 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -49,6 +49,8 @@ int main() #include +// c_forfilter: + #define c_flt_skip(i, n) (c_flt_count(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) @@ -65,6 +67,48 @@ int main() 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, 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 it = C##_begin(_cnt), _i; \ + while (it.ref && !(pred)) \ + C##_next(&it); \ + for (_i = it; it.ref; C##_next(&it)) \ + 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 diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index ad6063e4..b822b9f8 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -178,6 +178,10 @@ 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_foreach_r(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)} \ ; _.it.ref && (_.key = &_.it.ref->first, _.val = &_.it.ref->second) \ @@ -193,8 +197,8 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, ; (_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 @@ -224,44 +228,8 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, 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 it = C##_begin(_cnt), _i; \ - while (it.ref && !(pred)) \ - C##_next(&it); \ - for (_i = it; it.ref; C##_next(&it)) \ - if (pred) C##_value_drop(it.ref), ++_n; \ - else *_i.ref = *it.ref, C##_next(&_i); \ - _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/cmap.h b/include/stc/cmap.h index bc3b5546..d9081ae0 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -224,7 +224,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 +235,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 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/misc/examples/arcvec_erase.c b/misc/examples/arcvec_erase.c index 38f11097..9c85d3ab 100644 --- a/misc/examples/arcvec_erase.c +++ b/misc/examples/arcvec_erase.c @@ -30,12 +30,12 @@ int main() 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) + if (it.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) + if (it.ref) Vec_erase_at(&vec, it); printf("vec after erase :"); diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c index fe5558e2..863cdea0 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."); diff --git a/misc/examples/csset_erase.c b/misc/examples/csset_erase.c index e8f2fec5..cf94156c 100644 --- a/misc/examples/csset_erase.c +++ b/misc/examples/csset_erase.c @@ -23,7 +23,7 @@ int main() puts(""); printf("Erase values >= %d:\n", val); - while (it.ref != csset_int_end(&set).ref) + while (it.ref) it = csset_int_erase_at(&set, it); c_foreach (k, csset_int, set) diff --git a/misc/examples/demos.c b/misc/examples/demos.c index d5336cbf..2a7f3888 100644 --- a/misc/examples/demos.c +++ b/misc/examples/demos.c @@ -152,7 +152,7 @@ void mapdemo2() 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)) + 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: diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 144ec637..2fe21c8b 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -35,11 +35,8 @@ 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 (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}) @@ -51,8 +48,12 @@ int main() puts("\n\nc_foreach:"); c_foreach (i, IVec, vec) printf(" %d", *i.ref); - puts(""); + puts("\n\nc_foreach_r: reverse"); + c_foreach_r (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); -- cgit v1.2.3 From eb85069b669e754836b9d4587ba03d3af1a5e975 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 26 Mar 2023 00:27:45 +0100 Subject: 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. --- README.md | 169 ++++++++++++---------- docs/carc_api.md | 96 ++++++------- docs/cbox_api.md | 11 +- docs/ccommon_api.md | 195 +++++++++++++------------- docs/clist_api.md | 23 ++- docs/cmap_api.md | 191 ++++++++++++------------- docs/coption_api.md | 2 - docs/cpque_api.md | 34 ++--- docs/cset_api.md | 50 ++++--- docs/csmap_api.md | 109 +++++++-------- docs/cspan_api.md | 19 ++- docs/csset_api.md | 49 ++++--- docs/cstr_api.md | 7 +- docs/csview_api.md | 28 ++-- docs/cvec_api.md | 46 +++--- include/c11/fmt.h | 272 ------------------------------------ include/c11/print.h | 272 ++++++++++++++++++++++++++++++++++++ include/stc/ccommon.h | 29 +--- include/stc/priv/raii.h | 27 ++++ misc/benchmarks/various/rust_cmap.c | 68 ++++----- misc/examples/arc_containers.c | 11 +- misc/examples/arc_demo.c | 65 ++++----- misc/examples/arcvec_erase.c | 66 +++++---- misc/examples/astar.c | 45 +++--- misc/examples/birthday.c | 44 +++--- misc/examples/bits.c | 51 ++++--- misc/examples/books.c | 6 +- misc/examples/box.c | 46 +++--- misc/examples/box2.c | 34 ++--- misc/examples/city.c | 92 ------------ misc/examples/complex.c | 37 +++-- misc/examples/convert.c | 15 +- misc/examples/csmap_erase.c | 113 ++++++++------- misc/examples/csmap_find.c | 46 +++--- misc/examples/csmap_insert.c | 134 +++++++++--------- misc/examples/csset_erase.c | 69 +++++---- misc/examples/cstr_match.c | 32 +++-- misc/examples/demos.c | 196 +++++++++++++------------- misc/examples/forfilter.c | 129 ++++++++--------- misc/examples/forloops.c | 82 +++++------ misc/examples/functor.c | 23 ++- misc/examples/gauss1.c | 40 +++--- misc/examples/gauss2.c | 29 ++-- misc/examples/hashmap.c | 55 ++++---- misc/examples/inits.c | 112 +++++++-------- misc/examples/intrusive.c | 63 +++------ misc/examples/list.c | 91 ++++++------ misc/examples/list_erase.c | 39 +++--- misc/examples/list_splice.c | 31 ++-- misc/examples/lower_bound.c | 11 +- misc/examples/mapmap.c | 51 +++---- misc/examples/mmap.c | 58 ++++---- misc/examples/multimap.c | 52 +++---- misc/examples/music_arc.c | 58 ++++---- misc/examples/new_deq.c | 41 ++---- misc/examples/new_list.c | 67 +++++---- misc/examples/new_map.c | 58 ++++---- misc/examples/new_pque.c | 17 +-- misc/examples/new_queue.c | 35 ++--- misc/examples/new_smap.c | 59 ++++---- misc/examples/new_sptr.c | 44 +++--- misc/examples/new_vec.c | 48 +++---- misc/examples/person_arc.c | 25 ++-- misc/examples/phonebook.c | 48 +++---- misc/examples/prime.c | 35 ++--- misc/examples/printspan.c | 36 ++--- misc/examples/priority.c | 40 +++--- misc/examples/queue.c | 31 ++-- misc/examples/rawptr_elements.c | 10 +- misc/examples/regex1.c | 34 ++--- misc/examples/regex2.c | 3 +- misc/examples/regex_match.c | 33 ++--- misc/examples/regex_replace.c | 30 ++-- misc/examples/shape.c | 3 +- misc/examples/sidebyside.cpp | 9 +- misc/examples/sorted_map.c | 7 +- misc/examples/sso_map.c | 17 +-- misc/examples/stack.c | 34 ++--- misc/examples/sview_split.c | 7 +- misc/examples/unordered_set.c | 6 +- misc/examples/utf8replace_c.c | 35 +++-- misc/examples/vikings.c | 28 ++-- misc/examples/words.c | 68 --------- 83 files changed, 2225 insertions(+), 2406 deletions(-) delete mode 100644 include/c11/fmt.h create mode 100644 include/c11/print.h create mode 100644 include/stc/priv/raii.h delete mode 100644 misc/examples/city.c delete mode 100644 misc/examples/words.c (limited to 'include/stc/ccommon.h') diff --git a/README.md b/README.md index cfab70ad..8d816bc6 100644 --- a/README.md +++ b/README.md @@ -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 +#include // "instantiate" the desired container type +#include 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 // Use a sorted set instead +#include + 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 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 +#include -#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 -... -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 #include struct Point { float x, y; }; -int Point_cmp(const struct Point* a, const struct Point* b); #define i_key int #include // 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 // cvec_pnt: vector of struct Point +#include // cvec_pnt: vector of struct Point #define i_val int -#include // cdeq_int: deque of int +#include // cdeq_int: deque of int #define i_val int -#include // clist_int: singly linked list +#include // clist_int: singly linked list #define i_val int -#include +#include // cstack_int #define i_key int #define i_val int -#include // 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 // 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 // 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. 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 64daad42..010ea204 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -2,96 +2,6 @@ The following macros are recommended to use, and they safe/have no side-effects. -## 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. - -| 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 -#include - -#define i_val_str -#include - -// 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_foreach_r, c_forpair @@ -165,10 +75,6 @@ c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} }) // string literals pushed to a stack of cstr: c_forlist (i, const char*, {"Hello", "crazy", "world"}) cstack_str_emplace(&stk, *i.ref); - -// reverse the list: -c_forlist (i, int, {1, 2, 3}) - cvec_i_push_back(&vec, i.data[i.size - 1 - i.index]); ``` ### c_forfilter @@ -297,13 +203,18 @@ 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 +### c_swap, c_drop, c_const_cast ```c // Safe macro for swapping internals of two objects of same type: c_swap(cmap_int, &map1, &map2); // Drop multiple containers of same type: c_drop(cvec_i, &vec1, &vec2, &vec3); + +// 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! ``` ### General predefined template parameter functions @@ -329,7 +240,99 @@ int array[] = {1, 2, 3, 4}; intptr_t n = c_arraylen(array); ``` -## The **checkauto** utility program (for RAII) +## 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. + +| 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 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 +#include + +#define i_val_str +#include + +// 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)); +} +``` + +### 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 be6949ec..a1dbe105 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -193,21 +193,20 @@ Splice `[30, 40]` from *L2* into *L1* before `3`: #include 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..71e00265 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -125,27 +125,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 +160,33 @@ The HEX of color BLACK is:[#000000] This example uses a cmap with cstr as mapped value. ```c #include - +#define i_type IDMap #define i_key int #define i_val_str -#define i_tag id #include 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 +211,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 +245,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 +301,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 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 +377,22 @@ static inline RViking Viking_toraw(const Viking* vp) { #define i_hash(rp) (cstrhash(rp->name) ^ cstrhash(rp->country)) #define i_val int #include -/* - 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 @@ -65,7 +65,5 @@ int main(int argc, char *argv[]) { for (int i = opt.ind; i < argc; ++i) printf(" %s", argv[i]); putchar('\n'); -} - return 0; } ``` diff --git a/docs/cpque_api.md b/docs/cpque_api.md index 991623d7..b3a1a9ec 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -75,24 +75,24 @@ int main() 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); - } + // Define heap + cpque_i heap = {0}; + + // 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); } + cpque_i_drop(&heap); } ``` Output: diff --git a/docs/cset_api.md b/docs/cset_api.md index 287f7636..a0af357f 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -80,37 +80,35 @@ cset_X_value cset_X_value_clone(cset_X_value val); ## Example ```c #include - +#define i_type Strset #define i_key_str #include 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..da0e6915 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -112,27 +112,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: @@ -149,32 +148,29 @@ This example uses a csmap with cstr as mapped value. ```c #include +#define i_type IDSMap #define i_key int #define i_val_str -#define i_tag id #include 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: @@ -205,16 +201,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: @@ -238,17 +235,17 @@ typedef struct { int x, y, z; } Vec3i; 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); - } + csmap_iv imap = {0}; + + csmap_iv_insert(&imap, 1, (Vec3i){100, 0, 0}); + csmap_iv_insert(&imap, 2, (Vec3i){0, 100, 0}); + csmap_iv_insert(&imap, 3, (Vec3i){0, 0, 100}); + csmap_iv_insert(&imap, 4, (Vec3i){100, 100, 100}); + + c_forpair (n, v, csmap_iv, imap) + printf("%d: { %3d, %3d, %3d }\n", *_.n, _.v->x, _.v->y, _.v->z); + + csmap_iv_drop(&imap); } ``` Output: 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 +#include #include 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..0989fd9b 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -80,33 +80,38 @@ csset_X_value csset_X_value_clone(csset_X_value val); ```c #include +#define i_type SSet #define i_key_str #include 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 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 @@ -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 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/include/c11/fmt.h b/include/c11/fmt.h deleted file mode 100644 index 193520b1..00000000 --- a/include/c11/fmt.h +++ /dev/null @@ -1,272 +0,0 @@ -#ifndef FMT_H_INCLUDED -#define FMT_H_INCLUDED -/* -VER 2.0: NEW API: - -void fmt_print(fmt, ...); -void fmt_println(fmt, ...); -void fmt_printd(dest, fmt, ...); -void fmt_destroy(fmt_buffer* buf); - - dest - destination, one of: - FILE* fp Write to a file - char* strbuf Write to a pre-allocated string buffer - fmt_buffer* buf Auto realloc the needed memory (safe). - Set buf->stream=1 for stream-mode. - Call fmt_destroy(buf) after usage. - - fmt - format string - {} Auto-detected format. If :MOD is not specified, - float will use ".8g" format, and double ".16g". - {:MOD} Format modifiers: < left align (replaces -), default for char*, char. - > right align, default for numbers. - Other than that MOD can be normal printf format modifiers. - {{, }} Print chars {, and }. (note: a single % prints %). - -* C11 or higher required. -* MAX 255 chars fmt string by default. MAX 12 arguments after fmt string. -* Static linking by default, shared symbols by defining FMT_HEADER / FMT_IMPLEMENT. -* (c) operamint, 2022, MIT License. ------------------------------------------------------------------------------------ -#include "c11/fmt.h" - -int main() { - const double pi = 3.141592653589793; - const size_t x = 1234567890; - const char* string = "Hello world"; - const wchar_t* wstr = L"The whole"; - const char z = 'z'; - _Bool flag = 1; - 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); - - 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); - fmt_destroy(out); -} -*/ -#include -#include -#include - -#define fmt_OVERLOAD(name, ...) \ - fmt_JOIN(name, fmt_NUMARGS(__VA_ARGS__))(__VA_ARGS__) -#define fmt_CONCAT(a, b) a ## b -#define fmt_JOIN(a, b) fmt_CONCAT(a, b) -#define fmt_EXPAND(...) __VA_ARGS__ -#define fmt_NUMARGS(...) _fmt_APPLY_ARG_N((__VA_ARGS__, _fmt_RSEQ_N)) - -#define _fmt_APPLY_ARG_N(args) fmt_EXPAND(_fmt_ARG_N args) -#define _fmt_RSEQ_N 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -#define _fmt_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \ - _14, _15, _16, N, ...) N - -#if defined FMT_HEADER || defined FMT_IMPLEMENT -# define FMT_API -#else -# define FMT_API static inline -#endif -#if defined FMT_NDEBUG || defined NDEBUG -# define fmt_OK(exp) (void)(exp) -#else -# define fmt_OK(exp) assert(exp) -#endif - -typedef struct { - char* data; - intptr_t cap, len; - _Bool stream; -} fmt_buffer; - -FMT_API void fmt_destroy(fmt_buffer* buf); -FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...); -FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...); - -#ifndef FMT_MAX -#define FMT_MAX 256 -#endif - -#ifndef FMT_NOSHORTS -#define print(...) fmt_printd(stdout, __VA_ARGS__) -#define println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__) -#define printd fmt_printd -#endif - -#define fmt_print(...) fmt_printd(stdout, __VA_ARGS__) -#define fmt_println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__) -#define fmt_printd(...) fmt_OVERLOAD(fmt_printd, __VA_ARGS__) - -/* Primary function. */ -#define fmt_printd2(to, fmt) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 0, fmt); \ - fmt_OK(_n == 0); _fmt_fn(to)(to, fmt); } while (0) -#define fmt_printd3(to, fmt, c) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 1, fmt, _fc(c)); \ - fmt_OK(_n == 1); _fmt_fn(to)(to, _fs, c); } while (0) -#define fmt_printd4(to, fmt, c, d) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 2, fmt, _fc(c), _fc(d)); \ - fmt_OK(_n == 2); _fmt_fn(to)(to, _fs, c, d); } while (0) -#define fmt_printd5(to, fmt, c, d, e) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 3, fmt, _fc(c), _fc(d), _fc(e)); \ - fmt_OK(_n == 3); _fmt_fn(to)(to, _fs, c, d, e); } while (0) -#define fmt_printd6(to, fmt, c, d, e, f) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 4, fmt, _fc(c), _fc(d), _fc(e), _fc(f)); \ - fmt_OK(_n == 4); _fmt_fn(to)(to, _fs, c, d, e, f); } while (0) -#define fmt_printd7(to, fmt, c, d, e, f, g) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 5, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g)); \ - fmt_OK(_n == 5); _fmt_fn(to)(to, _fs, c, d, e, f, g); } while (0) -#define fmt_printd8(to, fmt, c, d, e, f, g, h) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 6, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h)); \ - fmt_OK(_n == 6); _fmt_fn(to)(to, _fs, c, d, e, f, g, h); } while (0) -#define fmt_printd9(to, fmt, c, d, e, f, g, h, i) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 7, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), _fc(i)); \ - fmt_OK(_n == 7); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i); } while (0) -#define fmt_printd10(to, fmt, c, d, e, f, g, h, i, j) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 8, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ - _fc(i), _fc(j)); \ - fmt_OK(_n == 8); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j); } while (0) -#define fmt_printd11(to, fmt, c, d, e, f, g, h, i, j, k) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 9, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ - _fc(i), _fc(j), _fc(k)); \ - fmt_OK(_n == 9); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k); } while (0) -#define fmt_printd12(to, fmt, c, d, e, f, g, h, i, j, k, m) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 10, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ - _fc(i), _fc(j), _fc(k), _fc(m)); \ - fmt_OK(_n == 10); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m); } while (0) -#define fmt_printd13(to, fmt, c, d, e, f, g, h, i, j, k, m, n) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 11, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ - _fc(i), _fc(j), _fc(k), _fc(m), _fc(n)); \ - fmt_OK(_n == 11); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n); } while (0) -#define fmt_printd14(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o) \ - do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 12, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ - _fc(i), _fc(j), _fc(k), _fc(m), _fc(n), _fc(o)); \ - fmt_OK(_n == 12); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n, o); } while (0) - -#define _fmt_fn(x) _Generic ((x), \ - FILE*: fprintf, \ - char*: sprintf, \ - fmt_buffer*: _fmt_bprint) - -#if defined(_MSC_VER) && !defined(__clang__) -# define _signed_char_hhd -#else -# define _signed_char_hhd signed char: "hhd", -#endif - -#define _fc(x) _Generic (x, \ - _Bool: "d", \ - unsigned char: "hhu", \ - _signed_char_hhd \ - char: "c", \ - short: "hd", \ - unsigned short: "hu", \ - int: "d", \ - unsigned: "u", \ - long: "ld", \ - unsigned long: "lu", \ - long long: "lld", \ - unsigned long long: "llu", \ - float: "g", \ - double: "@g", \ - long double: "@Lg", \ - char*: "s", \ - wchar_t*: "ls", \ - void*: "p", \ - const char*: "s", \ - const wchar_t*: "ls", \ - const void*: "p") - -#if defined FMT_IMPLEMENT || !(defined FMT_HEADER || defined FMT_IMPLEMENT) - -#include -#include -#include - -FMT_API void fmt_destroy(fmt_buffer* buf) { - free(buf->data); -} - -FMT_API void _fmt_bprint(fmt_buffer* buf, const char* fmt, ...) { - va_list args, args2; - va_start(args, fmt); - if (buf == NULL) { - vprintf(fmt, args); putchar('\n'); - goto done1; - } - va_copy(args2, args); - const int n = vsnprintf(NULL, 0U, fmt, args); - if (n < 0) goto done2; - const intptr_t pos = buf->stream ? buf->len : 0; - buf->len = pos + n; - if (buf->len > buf->cap) { - buf->cap = buf->len + buf->cap/2; - buf->data = (char*)realloc(buf->data, (size_t)buf->cap + 1U); - } - vsprintf(buf->data + pos, fmt, args2); - done2: va_end(args2); - done1: va_end(args); -} - -FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...) { - char *arg, *p0, ch; - int n = 0, empty; - va_list args; - va_start(args, fmt); - do { - switch ((ch = *fmt)) { - case '%': - *p++ = '%'; - break; - case '}': - if (*++fmt == '}') break; /* ok */ - n = 99; - continue; - case '{': - if (*++fmt == '{') break; /* ok */ - if (++n > nargs) continue; - if (*fmt != ':' && *fmt != '}') n = 99; - fmt += (*fmt == ':'); - empty = *fmt == '}'; - arg = va_arg(args, char *); - *p++ = '%', p0 = p; - while (1) switch (*fmt) { - case '\0': n = 99; /* nobreak */ - case '}': goto done; - case '<': *p++ = '-', ++fmt; break; - case '>': p0 = NULL; /* nobreak */ - case '-': ++fmt; break; - case '*': if (++n <= nargs) arg = va_arg(args, char *); /* nobreak */ - default: *p++ = *fmt++; - } - done: - switch (*arg) { - case 'g': if (empty) memcpy(p, ".8", 2), p += 2; break; - case '@': ++arg; if (empty) memcpy(p, ".16", 3), p += 3; break; - } - if (!strchr("csdioxXufFeEaAgGnp", fmt[-1])) - while (*arg) *p++ = *arg++; - if (p0 && (p[-1] == 's' || p[-1] == 'c')) /* left-align str */ - memmove(p0 + 1, p0, (size_t)(p++ - p0)), *p0 = '-'; - fmt += *fmt == '}'; - continue; - } - *p++ = *fmt++; - } while (ch); - va_end(args); - return n; -} -#endif -#endif diff --git a/include/c11/print.h b/include/c11/print.h new file mode 100644 index 00000000..1302d9cc --- /dev/null +++ b/include/c11/print.h @@ -0,0 +1,272 @@ +#ifndef FMT_H_INCLUDED +#define FMT_H_INCLUDED +/* +VER 2.0: NEW API: + +void fmt_print(fmt, ...); +void fmt_println(fmt, ...); +void fmt_printd(dest, fmt, ...); +void fmt_destroy(fmt_buffer* buf); + + dest - destination, one of: + FILE* fp Write to a file + char* strbuf Write to a pre-allocated string buffer + fmt_buffer* buf Auto realloc the needed memory (safe). + Set buf->stream=1 for stream-mode. + Call fmt_destroy(buf) after usage. + + fmt - format string + {} Auto-detected format. If :MOD is not specified, + float will use ".8g" format, and double ".16g". + {:MOD} Format modifiers: < left align (replaces -), default for char*, char. + > right align, default for numbers. + Other than that MOD can be normal printf format modifiers. + {{, }} Print chars {, and }. (note: a single % prints %). + +* C11 or higher required. +* MAX 255 chars fmt string by default. MAX 12 arguments after fmt string. +* Static linking by default, shared symbols by defining FMT_HEADER / FMT_IMPLEMENT. +* (c) operamint, 2022, MIT License. +----------------------------------------------------------------------------------- +#include "c11/print.h" + +int main() { + const double pi = 3.141592653589793; + const size_t x = 1234567890; + const char* string = "Hello world"; + const wchar_t* wstr = L"The whole"; + const char z = 'z'; + _Bool flag = 1; + 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); + + 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); + fmt_destroy(out); +} +*/ +#include +#include +#include + +#define fmt_OVERLOAD(name, ...) \ + fmt_JOIN(name, fmt_NUMARGS(__VA_ARGS__))(__VA_ARGS__) +#define fmt_CONCAT(a, b) a ## b +#define fmt_JOIN(a, b) fmt_CONCAT(a, b) +#define fmt_EXPAND(...) __VA_ARGS__ +#define fmt_NUMARGS(...) _fmt_APPLY_ARG_N((__VA_ARGS__, _fmt_RSEQ_N)) + +#define _fmt_APPLY_ARG_N(args) fmt_EXPAND(_fmt_ARG_N args) +#define _fmt_RSEQ_N 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define _fmt_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \ + _14, _15, _16, N, ...) N + +#if defined FMT_HEADER || defined FMT_IMPLEMENT +# define FMT_API +#else +# define FMT_API static inline +#endif +#if defined FMT_NDEBUG || defined NDEBUG +# define fmt_OK(exp) (void)(exp) +#else +# define fmt_OK(exp) assert(exp) +#endif + +typedef struct { + char* data; + intptr_t cap, len; + _Bool stream; +} fmt_buffer; + +FMT_API void fmt_destroy(fmt_buffer* buf); +FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...); +FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...); + +#ifndef FMT_MAX +#define FMT_MAX 256 +#endif + +#ifndef FMT_NOSHORTS +#define print(...) fmt_printd(stdout, __VA_ARGS__) +#define println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__) +#define printd fmt_printd +#endif + +#define fmt_print(...) fmt_printd(stdout, __VA_ARGS__) +#define fmt_println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__) +#define fmt_printd(...) fmt_OVERLOAD(fmt_printd, __VA_ARGS__) + +/* Primary function. */ +#define fmt_printd2(to, fmt) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 0, fmt); \ + fmt_OK(_n == 0); _fmt_fn(to)(to, fmt); } while (0) +#define fmt_printd3(to, fmt, c) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 1, fmt, _fc(c)); \ + fmt_OK(_n == 1); _fmt_fn(to)(to, _fs, c); } while (0) +#define fmt_printd4(to, fmt, c, d) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 2, fmt, _fc(c), _fc(d)); \ + fmt_OK(_n == 2); _fmt_fn(to)(to, _fs, c, d); } while (0) +#define fmt_printd5(to, fmt, c, d, e) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 3, fmt, _fc(c), _fc(d), _fc(e)); \ + fmt_OK(_n == 3); _fmt_fn(to)(to, _fs, c, d, e); } while (0) +#define fmt_printd6(to, fmt, c, d, e, f) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 4, fmt, _fc(c), _fc(d), _fc(e), _fc(f)); \ + fmt_OK(_n == 4); _fmt_fn(to)(to, _fs, c, d, e, f); } while (0) +#define fmt_printd7(to, fmt, c, d, e, f, g) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 5, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g)); \ + fmt_OK(_n == 5); _fmt_fn(to)(to, _fs, c, d, e, f, g); } while (0) +#define fmt_printd8(to, fmt, c, d, e, f, g, h) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 6, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h)); \ + fmt_OK(_n == 6); _fmt_fn(to)(to, _fs, c, d, e, f, g, h); } while (0) +#define fmt_printd9(to, fmt, c, d, e, f, g, h, i) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 7, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), _fc(i)); \ + fmt_OK(_n == 7); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i); } while (0) +#define fmt_printd10(to, fmt, c, d, e, f, g, h, i, j) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 8, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ + _fc(i), _fc(j)); \ + fmt_OK(_n == 8); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j); } while (0) +#define fmt_printd11(to, fmt, c, d, e, f, g, h, i, j, k) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 9, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ + _fc(i), _fc(j), _fc(k)); \ + fmt_OK(_n == 9); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k); } while (0) +#define fmt_printd12(to, fmt, c, d, e, f, g, h, i, j, k, m) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 10, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ + _fc(i), _fc(j), _fc(k), _fc(m)); \ + fmt_OK(_n == 10); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m); } while (0) +#define fmt_printd13(to, fmt, c, d, e, f, g, h, i, j, k, m, n) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 11, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ + _fc(i), _fc(j), _fc(k), _fc(m), _fc(n)); \ + fmt_OK(_n == 11); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n); } while (0) +#define fmt_printd14(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o) \ + do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 12, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ + _fc(i), _fc(j), _fc(k), _fc(m), _fc(n), _fc(o)); \ + fmt_OK(_n == 12); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n, o); } while (0) + +#define _fmt_fn(x) _Generic ((x), \ + FILE*: fprintf, \ + char*: sprintf, \ + fmt_buffer*: _fmt_bprint) + +#if defined(_MSC_VER) && !defined(__clang__) +# define _signed_char_hhd +#else +# define _signed_char_hhd signed char: "hhd", +#endif + +#define _fc(x) _Generic (x, \ + _Bool: "d", \ + unsigned char: "hhu", \ + _signed_char_hhd \ + char: "c", \ + short: "hd", \ + unsigned short: "hu", \ + int: "d", \ + unsigned: "u", \ + long: "ld", \ + unsigned long: "lu", \ + long long: "lld", \ + unsigned long long: "llu", \ + float: "g", \ + double: "@g", \ + long double: "@Lg", \ + char*: "s", \ + wchar_t*: "ls", \ + void*: "p", \ + const char*: "s", \ + const wchar_t*: "ls", \ + const void*: "p") + +#if defined FMT_IMPLEMENT || !(defined FMT_HEADER || defined FMT_IMPLEMENT) + +#include +#include +#include + +FMT_API void fmt_destroy(fmt_buffer* buf) { + free(buf->data); +} + +FMT_API void _fmt_bprint(fmt_buffer* buf, const char* fmt, ...) { + va_list args, args2; + va_start(args, fmt); + if (buf == NULL) { + vprintf(fmt, args); putchar('\n'); + goto done1; + } + va_copy(args2, args); + const int n = vsnprintf(NULL, 0U, fmt, args); + if (n < 0) goto done2; + const intptr_t pos = buf->stream ? buf->len : 0; + buf->len = pos + n; + if (buf->len > buf->cap) { + buf->cap = buf->len + buf->cap/2; + buf->data = (char*)realloc(buf->data, (size_t)buf->cap + 1U); + } + vsprintf(buf->data + pos, fmt, args2); + done2: va_end(args2); + done1: va_end(args); +} + +FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...) { + char *arg, *p0, ch; + int n = 0, empty; + va_list args; + va_start(args, fmt); + do { + switch ((ch = *fmt)) { + case '%': + *p++ = '%'; + break; + case '}': + if (*++fmt == '}') break; /* ok */ + n = 99; + continue; + case '{': + if (*++fmt == '{') break; /* ok */ + if (++n > nargs) continue; + if (*fmt != ':' && *fmt != '}') n = 99; + fmt += (*fmt == ':'); + empty = *fmt == '}'; + arg = va_arg(args, char *); + *p++ = '%', p0 = p; + while (1) switch (*fmt) { + case '\0': n = 99; /* nobreak */ + case '}': goto done; + case '<': *p++ = '-', ++fmt; break; + case '>': p0 = NULL; /* nobreak */ + case '-': ++fmt; break; + case '*': if (++n <= nargs) arg = va_arg(args, char *); /* nobreak */ + default: *p++ = *fmt++; + } + done: + switch (*arg) { + case 'g': if (empty) memcpy(p, ".8", 2), p += 2; break; + case '@': ++arg; if (empty) memcpy(p, ".16", 3), p += 3; break; + } + if (!strchr("csdioxXufFeEaAgGnp", fmt[-1])) + while (*arg) *p++ = *arg++; + if (p0 && (p[-1] == 's' || p[-1] == 'c')) /* left-align str */ + memmove(p0 + 1, p0, (size_t)(p++ - p0)), *p0 = '-'; + fmt += *fmt == '}'; + continue; + } + *p++ = *fmt++; + } while (ch); + va_end(args); + return n; +} +#endif +#endif diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index b822b9f8..5e163875 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -30,6 +30,7 @@ #include #include #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 @@ -123,7 +125,10 @@ #define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a]) #define c_litstrlen(literal) (c_sizeof("" literal) - 1) +// 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,7 +137,6 @@ 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) { @@ -195,6 +199,7 @@ 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* ref; int size, index;} \ @@ -207,26 +212,6 @@ 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))) #define c_drop(C, ...) \ do { c_forlist (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0) 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/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/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..88555177 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 9c85d3ab..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_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 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..6c850b08 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); @@ -120,18 +124,18 @@ astar(cstr* maze, int width) point current = goal; while (!point_equal(¤t, &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..2b52cc48 100644 --- a/misc/examples/birthday.c +++ b/misc/examples/birthday.c @@ -18,16 +18,15 @@ static void test_repeats(void) 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)); - } + + cmap_ic m = cmap_ic_with_capacity(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)); } + cmap_ic_drop(&m); } #define i_key uint32_t @@ -42,22 +41,23 @@ void test_distribution(void) stc64_t rng = stc64_new(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 = stc64_rand(&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..e43c0bc3 100644 --- a/misc/examples/books.c +++ b/misc/examples/books.c @@ -8,8 +8,10 @@ // would be `HashMap` in this example). int main() { - c_auto (cmap_str, book_reviews) - { + cmap_str book_reviews = {0}; + c_defer( + cmap_str_drop(&book_reviews) + ){ // Review some books. cmap_str_emplace(&book_reviews, "Adventures of Huckleberry Finn", 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 - -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 -//#include // try instead of cbox.h - -#define i_type Cities -#define i_keyboxed CityArc -#include - -#define i_type CityMap -#define i_key int -#define i_valboxed CityArc -#include - - -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/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 863cdea0..c417567a 100644 --- a/misc/examples/csmap_find.c +++ b/misc/examples/csmap_find.c @@ -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 - // 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 +#include #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 cf94156c..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) - 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 ? "" : 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 ? "" : 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 2a7f3888..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 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_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 cd6d59cc..fdf8be6f 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -21,30 +21,28 @@ 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 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_drop(&vec); } @@ -62,18 +60,19 @@ fn main() { 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: @@ -91,42 +90,45 @@ fn main() { */ 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)) && @@ -134,14 +136,15 @@ void demo5(void) 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 2fe21c8b..54b49485 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,48 +34,43 @@ int main() printf(" %s", *i.ref); puts(""); + 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_r (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); + + puts("\n\nc_forfilter 1:"); + c_forfilter (i, IVec, vec, c_flt_take(i, 3)) + printf(" %d", *i.ref); + + #define isOdd(i) (*i.ref & 1) + + puts("\n\nc_forfilter 2:"); + 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 - 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("\n\nc_foreach_r: reverse"); - c_foreach_r (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); - - puts("\n\nc_forfilter 1:"); - c_forfilter (i, IVec, vec, c_flt_take(i, 3)) - printf(" %d", *i.ref); - - #define isOdd(i) (*i.ref & 1) - - puts("\n\nc_forfilter 2:"); - 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_drop(&vec); + IMap_drop(&map); } diff --git a/misc/examples/functor.c b/misc/examples/functor.c index 6d42c4f8..8952c710 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -51,18 +51,17 @@ int main() 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); + c_forrange (i, n) + ipque_push(&q1.Q, data[i]); + print_queue("q1", q1); - c_forrange (i, n) - ipque_push(&minq1.Q, 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.Q, data[i]); - print_queue("q5", q5); - } + c_forrange (i, n) + ipque_push(&q5.Q, data[i]); + print_queue("q5", q5); + + c_drop(ipque, &q1.Q, &minq1.Q, &q5.Q); } diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c index 40d0981f..67871aa9 100644 --- a/misc/examples/gauss1.c +++ b/misc/examples/gauss1.c @@ -29,28 +29,30 @@ int main() 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; - } + cvec_ii histvec = {0}; + cmap_ii histmap = {0}; + + 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}); + // 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); + 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(""); - } + // 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(""); } } + + cvec_ii_drop(&histvec); + cmap_ii_drop(&histmap); } diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c index c531e5e3..79397f0c 100644 --- a/misc/examples/gauss2.c +++ b/misc/examples/gauss2.c @@ -22,21 +22,22 @@ int main() stc64_normalf_t dist = stc64_normalf_new(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 mhist = {0}; + cstr bar = {0}; + + c_forrange (N) { + int index = (int) round( stc64_normalf(&rng, &dist) ); + csmap_int_insert(&mhist, 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, 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)); } } + cstr_drop(&bar); + csmap_int_drop(&mhist); } 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..7530dd08 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..093cb36e 100644 --- a/misc/examples/intrusive.c +++ b/misc/examples/intrusive.c @@ -1,55 +1,34 @@ -// Example of intrusive/shared list-nodes by using the node API. +// Example of clist using the node API. #include -#define i_type Inner +#define i_type List #define i_val int -#define i_extern // implement Inner_sort() #include -#define i_type Outer -#define i_val Inner_node -#define i_opt c_no_cmp // no elem. comparison -#include - -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 odd numbers from list list"); + c_foreach (i, List, list) + if (*i.ref & 1) + List_unlink_after_node(&list, i.prev); + printList(list); - printLists(inner, outer); - } + List_drop(&list); } diff --git a/misc/examples/list.c b/misc/examples/list.c index 027c5adc..9f0b2504 100644 --- a/misc/examples/list.c +++ b/misc/examples/list.c @@ -1,69 +1,64 @@ #include #include -#include +#include #include +#define i_type DList #define i_val double -#define i_tag fx #include int main() { const int n = 3000000; + DList list = {0}; - c_auto (clist_fx, list) - { - stc64_t rng = stc64_new(1234567); - 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; + stc64_t rng = stc64_new(1234567); + stc64_uniformf_t dist = stc64_uniformf_new(100.0f, n); + int m = 0; + c_forrange (n) + DList_push_back(&list, stc64_uniformf(&rng, &dist)), ++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_forfilter (i, clist_fx, list, c_flt_take(i, 10)) - printf("%8d: %10f\n", c_flt_last(i), *i.ref); + c_forfilter (i, DList, list, c_flt_take(i, 10)) + printf("%8d: %10f\n", c_flt_last(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_last(i), *i.ref); + puts(""); - c_forfilter (i, clist_fx, list, c_flt_take(i, 10)) - printf("%8d: %10f\n", c_flt_last(i), *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..8fc307ab 100644 --- a/misc/examples/mapmap.c +++ b/misc/examples/mapmap.c @@ -44,31 +44,32 @@ int contains(Departments* map, const char* name) int main(void) { - c_auto (Departments, map) - { - add(&map, "Anna Kendro", "Anna@myplace.com", "Support"); - add(&map, "Terry Dane", "Terry@myplace.com", "Development"); - add(&map, "Kik Winston", "Kik@myplace.com", "Finance"); - add(&map, "Nancy Drew", "Nancy@live.com", "Development"); - add(&map, "Nick Denton", "Nick@myplace.com", "Finance"); - add(&map, "Stan Whiteword", "Stan@myplace.com", "Marketing"); - add(&map, "Serena Bath", "Serena@myplace.com", "Support"); - add(&map, "Patrick Dust", "Patrick@myplace.com", "Finance"); - add(&map, "Red Winger", "Red@gmail.com", "Marketing"); - add(&map, "Nick Denton", "Nick@yahoo.com", "Support"); - add(&map, "Colin Turth", "Colin@myplace.com", "Support"); - add(&map, "Dennis Kay", "Dennis@mail.com", "Marketing"); - add(&map, "Anne Dickens", "Anne@myplace.com", "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", "Anna@myplace.com", "Support"); + add(&map, "Terry Dane", "Terry@myplace.com", "Development"); + add(&map, "Kik Winston", "Kik@myplace.com", "Finance"); + add(&map, "Nancy Drew", "Nancy@live.com", "Development"); + add(&map, "Nick Denton", "Nick@myplace.com", "Finance"); + add(&map, "Stan Whiteword", "Stan@myplace.com", "Marketing"); + add(&map, "Serena Bath", "Serena@myplace.com", "Support"); + add(&map, "Patrick Dust", "Patrick@myplace.com", "Finance"); + add(&map, "Red Winger", "Red@gmail.com", "Marketing"); + add(&map, "Nick Denton", "Nick@yahoo.com", "Support"); + add(&map, "Colin Turth", "Colin@myplace.com", "Support"); + add(&map, "Dennis Kay", "Dennis@mail.com", "Marketing"); + add(&map, "Anne Dickens", "Anne@myplace.com", "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 #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 // 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 #include @@ -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 1b72fb67..9c37db6c 100644 --- a/misc/examples/multimap.c +++ b/misc/examples/multimap.c @@ -68,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 -// ... 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 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 index 39149140..467fd4e5 100644 --- a/misc/examples/new_deq.c +++ b/misc/examples/new_deq.c @@ -27,35 +27,20 @@ int point_cmp(const Point* a, const Point* b) { #define i_tag pnt #include -#define i_val float -#include - -#define i_val_str -#include - 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"); - } + cdeq_pnt pvec = {0}; + + 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(""); + + cdeq_pnt_drop(&pvec); } diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c index 23709a64..eae4b8f5 100644 --- a/misc/examples/new_list.c +++ b/misc/examples/new_list.c @@ -1,19 +1,20 @@ -#include +#include +#include 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_opt c_is_forward #include -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; @@ -28,34 +29,40 @@ int point_cmp(const Point* a, const Point* b) { #define i_val float #include -#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 +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); - - c_auto (clist_pnt, plst) { - c_forlist (i, Point, {{42, 14}, {32, 94}, {62, 81}}) - clist_pnt_push_back(&plst, *i.ref); - - clist_pnt_sort(&plst); - - c_foreach (i, clist_pnt, plst) - printf(" (%d %d)", i.ref->x, i.ref->y); - puts(""); - } - - c_auto (clist_float, flst) { - c_forlist (i, float, {123.3f, 321.2f, -32.2f, 78.2f}) - clist_float_push_back(&flst, *i.ref); - - clist_float_sort(&flst); - c_foreach (i, clist_float, flst) printf(" %g", *i.ref); - } - - c_auto (clist_str, slst) - clist_str_emplace_back(&slst, "Hello, friend"); + 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_foreach (i, clist_pnt, plst) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + clist_pnt_drop(&plst); + + + clist_float flst = c_make(clist_float, {123.3f, 321.2f, -32.2f, 78.2f}); + clist_float_sort(&flst); + + c_foreach (i, clist_float, flst) + printf(" %g", *i.ref); + + puts(""); + clist_float_drop(&flst); } diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c index a4d5289c..4b02c46a 100644 --- a/misc/examples/new_map.c +++ b/misc/examples/new_map.c @@ -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..f7887ffb 100644 --- a/misc/examples/new_queue.c +++ b/misc/examples/new_queue.c @@ -25,22 +25,23 @@ int main() { 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)); + IQ Q = {0}; + + // 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)); + IQ_drop(&Q); } diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c index 0870ee3d..d85d5c75 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 +} MyStruct; // Point => int map struct Point { int x, y; } typedef Point; @@ -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..988b78d9 100644 --- a/misc/examples/new_vec.c +++ b/misc/examples/new_vec.c @@ -1,4 +1,4 @@ -#include +#include #include forward_cvec(cvec_i32, int); @@ -14,45 +14,29 @@ struct MyStruct { #define i_tag i32 #include -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_tag pnt #include -#define i_val float -#include +int main() +{ + MyStruct my = {0}; -#define i_val_str -#include + 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 16a59774..18bf3490 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:"); + 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(""); } + + cbits_drop(&primes); } diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index 81f6fa14..127b07b9 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -22,22 +22,26 @@ void printMe(intspan container) { 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); + 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; + cstack_int stk; + cdeq_int deq; + csset_str set; + c_defer( + cvec_int_drop(&vec), + cstack_int_drop(&stk), + cdeq_int_drop(&deq), + csset_str_drop(&set) + ) { + vec = c_make(cvec_int, {1, 2, 3, 4, 5}); printMe( (intspan)cspan_from(&vec) ); printMe( sp2 ); diff --git a/misc/examples/priority.c b/misc/examples/priority.c index 0a1d419b..d3d0283e 100644 --- a/misc/examples/priority.c +++ b/misc/examples/priority.c @@ -12,24 +12,26 @@ 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); - } + + 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, 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); } + + cpque_i_drop(&heap); } diff --git a/misc/examples/queue.c b/misc/examples/queue.c index 4064cc77..0f387d52 100644 --- a/misc/examples/queue.c +++ b/misc/examples/queue.c @@ -11,21 +11,22 @@ int main() { stc64_t rng = stc64_new(1234); dist = stc64_uniform_new(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)stc64_uniform(&rng, &dist)); + + // Push or pop on the queue ten million times + printf("%d\n", n); + c_forrange (n) { // forrange uses initial n only. + int r = (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)); + + cqueue_i_drop(&queue); } diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c index 4b3d2056..f46a7f5e 100644 --- a/misc/examples/rawptr_elements.c +++ b/misc/examples/rawptr_elements.c @@ -28,9 +28,13 @@ typedef int64_t inttype; int main() { - c_auto (SIPtrMap, map, m1) - c_auto (SIBoxMap, m2) - { + SIPtrMap map = {0}, m1; + SIBoxMap m2 = {0}; + c_defer( + SIPtrMap_drop(&map), + SIPtrMap_drop(&m1), + SIBoxMap_drop(&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)); 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..883dd112 100644 --- a/misc/examples/regex2.c +++ b/misc/examples/regex2.c @@ -15,7 +15,7 @@ int main() {"\\p{Han}+", "This is Han: 王明:那是杂志吗?"}, }; - c_auto (cregex, re) + cregex re = {0}; c_forrange (i, c_ARRAYLEN(s)) { int res = cregex_compile(&re, s[i].pattern); @@ -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/shape.c b/misc/examples/shape.c index d290fb4d..2aabdcc2 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -138,7 +138,8 @@ void testShape(const Shape* shape) int main(void) { - c_auto (Shapes, shapes) + Shapes shapes = {0}; + c_defer (Shapes_drop(&shapes)) { Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); Polygon* pol1 = c_new(Polygon, Polygon_init()); diff --git a/misc/examples/sidebyside.cpp b/misc/examples/sidebyside.cpp index 80c934a4..a817b5a5 100644 --- a/misc/examples/sidebyside.cpp +++ b/misc/examples/sidebyside.cpp @@ -25,8 +25,8 @@ int main() { std::cout << std::endl; } - c_auto (IIMap, hist) - { + IIMap hist = {0}; + c_defer (IIMap_drop(&hist)) { IIMap_insert(&hist, 12, 100).ref->second += 1; IIMap_insert(&hist, 13, 100).ref->second += 1; IIMap_insert(&hist, 12, 100).ref->second += 1; @@ -45,10 +45,11 @@ int main() { std::cout << std::endl; } - c_auto (SIMap, food) + SIMap food = {0}; + c_defer (SIMap_drop(&food)) { 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); 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/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 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/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 -/* - 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 -#include - -#define i_val_str -#include - -#define i_key_str -#define i_val int -#include - -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 -#include -#include -#include - -int main2() -{ - std::vector words = { - "this", "sentence", "is", "not", "a", "sentence", - "this", "sentence", "is", "a", "hoax" - }; - - std::unordered_map 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 -- cgit v1.2.3 From 9a88ddd9cbf4c33664de258bcb5bcef6a746149a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 29 Mar 2023 18:23:54 +0200 Subject: Some optimizations in hash func. --- include/stc/ccommon.h | 22 +++---- include/stc/crand.h | 105 +++++++++++++++------------------- misc/benchmarks/shootout_hashmaps.cpp | 1 + 3 files changed, 58 insertions(+), 70 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 5e163875..362b09ce 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -140,20 +140,20 @@ typedef const char* crawstr; #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; - } - switch (len &= 7) { - case 0: return h; - case 4: memcpy(&u4, x, 4); - return h + u4*0xc6a4a7935bd1e99d; + h += u8*0xc6a4a7935bd1e99d; } - h += *x++; - while (--len) h = (h << 10) - h + *x++; + while (len--) h = (h << 10) - h - *x++; return c_ROTL(h, 26) ^ h; } diff --git a/include/stc/crand.h b/include/stc/crand.h index 4ebc402d..f46f2bd5 100644 --- a/include/stc/crand.h +++ b/include/stc/crand.h @@ -30,15 +30,13 @@ int main() { uint64_t seed = 123456789; - crand_t rng = crand_from(seed); - crand_unif_t dist1 = crand_unif_from(1, 6); - crandf_unif_t dist2 = crandf_unif_from(1.0, 10.0); - crandf_norm_t dist3 = crandf_norm_from(1.0, 10.0); + 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_r(&rng); + uint64_t i = crand_u64(&rng); int64_t iu = crand_unif(&rng, &dist1); - double xu = crandf_unif(&rng, &dist2); - double xn = crandf_norm(&rng, &dist3); + double xn = crand_norm(&rng, &dist3); } */ #include @@ -46,8 +44,7 @@ int main() { 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 crandf_unif { double lower, range; } crandf_unif_t; -typedef struct crandf_norm { double mean, stddev, next; int has_next; } crandf_norm_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. @@ -61,23 +58,25 @@ typedef struct crandf_norm { double mean, stddev, next; int has_next; } crandf_n */ /* Global crand_t PRNGs */ -STC_API void csrand(uint64_t seed); +STC_API void csrand(uint64_t seed); STC_API uint64_t crand(void); -STC_API double crandf(void); +STC_API double crandf(void); /* Init crand_t prng with a seed */ -STC_API crand_t crand_from(uint64_t seed); +STC_API crand_t crand_init(uint64_t seed); /* Unbiased bounded uniform distribution. range [low, high] */ -STC_API crand_unif_t crand_unif_from(int64_t low, int64_t 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 distribution PRNG */ -STC_API double crandf_norm(crand_t* rng, crandf_norm_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_r(crand_t* rng) { +STC_INLINE uint64_t crand_u64(crand_t* rng) { enum {LR=24, RS=11, LS=3}; uint64_t *s = rng->state; const uint64_t out = (s[0] ^ (s[3] += s[4])) + s[1]; s[0] = s[1] ^ (s[1] >> RS); @@ -87,26 +86,11 @@ STC_INLINE uint64_t crand_r(crand_t* rng) { } /* Float64 random number in range [0.0, 1.0). */ -STC_INLINE double crandf_r(crand_t* rng) { - union {uint64_t i; double f;} u = {0x3FF0000000000000U | (crand_r(rng) >> 12)}; +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; } -/* Float64 uniform distributed RNG, range [low, high). */ -STC_INLINE double crandf_unif(crand_t* rng, crandf_unif_t* dist) { - return crandf_r(rng)*dist->range + dist->lower; -} - -/* Init uniform distributed float64 RNG, range [low, high). */ -STC_INLINE crandf_unif_t crandf_unif_from(double low, double high) { - return c_LITERAL(crandf_unif_t){low, high - low}; -} - -/* Marsaglia polar method for gaussian/normal distribution, float64. */ -STC_INLINE crandf_norm_t crandf_norm_from(double mean, double stddev) { - return c_LITERAL(crandf_norm_t){mean, stddev, 0.0, 0}; -} - /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) @@ -117,29 +101,34 @@ static crand_t crand_global = {{ 0x6a09e667a754166b }}; -STC_DEF void csrand(uint64_t seed) { - crand_global = crand_from(seed); -} +STC_DEF void csrand(uint64_t seed) + { crand_global = crand_init(seed); } -STC_DEF uint64_t crand(void) { - return crand_r(&crand_global); -} +STC_DEF uint64_t crand(void) + { return crand_u64(&crand_global); } + +STC_DEF double crandf(void) + { return crand_f64(&crand_global); } -STC_DEF double crandf(void) { - return crandf_r(&crand_global); +STC_INLINE uint64_t splitmix64(uint64_t s[1]) { + uint64_t z = (s[0] += 0x9e3779b97f4a7c15); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) * 0x94d049bb133111eb; + return z ^ (z >> 31); } -/* rng.state[4] must be odd */ -STC_DEF crand_t crand_from(uint64_t seed) { +STC_DEF crand_t crand_init(uint64_t seed) { + /* rng.state[4] must be odd */ crand_t rng = {{seed + 0x26aa069ea2fb1a4d, seed*0x9e3779b97f4a7c15 + 0x70c72c95cd592d04, seed + 0x504f333d3aa0b359, - seed*0x6a09e667a754166b, seed<<1 | 1}}; + seed, seed<<1 | 1}}; + crand_u64(&rng); return rng; } /* Init unbiased uniform uint RNG with bounds [low, high] */ -STC_DEF crand_unif_t crand_unif_from(int64_t low, int64_t 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; @@ -157,32 +146,30 @@ STC_DEF crand_unif_t crand_unif_from(int64_t low, int64_t high) { asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b)) #endif -/* Int uniform distributed RNG, range [low, high]. */ +/* Int64 uniform distributed RNG, range [low, high]. */ STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) { -#ifdef c_umul128 uint64_t lo, hi; - do { c_umul128(crand_r(rng), d->range, &lo, &hi); } while (lo < d->threshold); - return d->lower + (int64_t)hi; +#ifdef c_umul128 + do { c_umul128(crand_u64(rng), d->range, &lo, &hi); } while (lo < d->threshold); #else - uint64_t x, r; - do { x = crand_r(rng); r = x % d->range; } while (x - r > -d->range); - return d->lower + r; + do { lo = crand_u64(rng); hi = lo % d->range; } while (lo - hi > -d->range); #endif + return d->lower + (int64_t)hi; } -/* Normal distribution PRNG */ -STC_DEF double crandf_norm(crand_t* rng, crandf_norm_t* dist) { +/* 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; + return dist->next*dist->stddev + dist->mean; do { - u1 = 2.0 * crandf_r(rng) - 1.0; - u2 = 2.0 * crandf_r(rng) - 1.0; + 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; + dist->next = u2*m; + return (u1*m)*dist->stddev + dist->mean; } #endif diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp index 39ad1786..947a35b4 100644 --- a/misc/benchmarks/shootout_hashmaps.cpp +++ b/misc/benchmarks/shootout_hashmaps.cpp @@ -35,6 +35,7 @@ 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 -- cgit v1.2.3 From 701b7af4aaf9fe3965c656c500d9200dd7c4831d Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Fri, 7 Apr 2023 22:51:45 +0200 Subject: More docs updating. --- README.md | 67 +++++++-------- docs/ccommon_api.md | 208 +++++++++++++++++++++++++---------------------- include/stc/ccommon.h | 2 +- include/stc/extend.h | 2 +- misc/examples/forloops.c | 2 +- misc/examples/functor.c | 2 +- 6 files changed, 148 insertions(+), 135 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/README.md b/README.md index 224e7cb3..6f07f8ff 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ STC - Smart Template Containers for C ===================================== -### [Version 4.2](#version-history) +### [Version 4.2 RC](#version-history) --- Description @@ -35,13 +35,13 @@ Containers Algorithms ---------- -- [***common*** Generic container algorithms](docs/ccommon_api.md#algorithms) -- [***filter*** - Ranges-like filtering](docs/ccommon_api.md#c_forfilter) -- [***coroutine*** - Tiny, fast and portable coroutine implementation](docs/ccommon_api.md#coroutines) -- [***cregex*** - Regular expressions based on Rob Pike's regexp9](docs/cregex_api.md) -- [***crange*** - Generalized iota integer generator](docs/ccommon_api.md#crange) -- [***crand*** - A novel very fast *PRNG* based on ***sfc64***](docs/crandom_api.md) -- [***coption*** - A ***getopt***-alike command line argument parser](docs/coption_api.md) +- [***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, etc.](docs/ccommon_api.md#generic-algorithms) +- [***Coroutines*** - Simon Tatham's coroutines done right](docs/ccommon_api.md#coroutines) +- [***Regular expressions*** - modernized Rob Pike's Plan-9 regexp](docs/cregex_api.md) +- [***Random numbers*** - a novel very fast *PRNG* based on *SFC64*](docs/crandom_api.md) +- [***Command line argument parser*** - similar to *getopt()*](docs/coption_api.md) --- List of contents @@ -49,7 +49,7 @@ List of contents - [Highlights](#highlights) - [STC is unique!](#stc-is-unique) - [Performance](#performance) -- [STC naming conventions](#stc-naming-conventions) +- [Naming conventions](#naming-conventions) - [Usage](#usage) - [Installation](#installation) - [Specifying template parameters](#specifying-template-parameters) @@ -57,19 +57,19 @@ List of contents - [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) +- [Per container-instance customization](#per-container-instance-customization) - [Memory efficiency](#memory-efficiency) --- ## Highlights -- **No boilerplate code** - Minimal code is needed to setup containers with any element type. Specify only what is needed, e.g. ***cmp***- and/or ***clone***-, ***drop***- functions, and leave the rest as defaults. +- **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. +- **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** - 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** - Uniform and intuitive method/type names and 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 for this reason. +- **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*** and ***cbox***. +- **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. @@ -87,7 +87,8 @@ that the elements are of basic types. For more complex types, additional templat 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 construction of a `cstr` (which may allocate memory) for the lookup *is not needed*. Hence, the alt. lookup -key does not need to be destroyed after use, as it is normally a POD type. Finally, the alternative +key does not need to be destroyed after use as it is normally a POD type. Finally, the alternative +key does not need to be destroyed after use as it is normally a POD type. Finally, the alternative lookup type may be passed to an ***emplace***-function. E.g. instead of calling `cvec_str_push(&vec, cstr_from("Hello"))`, you may call `cvec_str_emplace(&vec, "Hello")`, which is functionally identical, but more convenient. @@ -100,7 +101,7 @@ same element access syntax. E.g.: --- ## Performance -STC is a fast and memory efficient library, and code compiles very fast: +STC is a fast and memory efficient library, and code compiles fast: ![Benchmark](misc/benchmarks/pics/benchmark.gif) @@ -114,7 +115,7 @@ Benchmark notes: - **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 naming 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`. @@ -144,10 +145,10 @@ Benchmark notes: --- ## Usage -The functionality of STC containers is similar to C++ STL standard containers. All containers except for a few, +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 done, so containers are type-safe like -templated types in C++. However, the specification of template parameters are naturally different. Here is -a basic usage example: +templated types in C++. However, the specification of template parameters are naturally different. In STC, +you specify template parameters by `#define` before including the container: ```c #define i_type Floats // Container type name; unless defined name would be cvec_float #define i_val float // Container element type @@ -166,7 +167,7 @@ int main(void) Floats_sort(&nums); - c_foreach (i, Floats, nums) // Alternative and recommended way to iterate nums. + c_foreach (i, Floats, nums) // Alternative and recommended way to iterate. printf(" %g", *i.ref); // i.ref is a pointer to the current element. Floats_drop(&nums); // cleanup memory @@ -181,7 +182,7 @@ You may switch to a different container type, e.g. a sorted set (csset): int main() { - Floats nums = c_make(Floats, {30.f, 10.f, 20.f}); // Initialize nums 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); @@ -192,11 +193,11 @@ int main() Floats_drop(&nums); } ``` -For user-defined struct elements, `i_cmp` compare function should be defined, as the default `<` and `==` +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.* -Let's make a vector of vectors that can be cloned. All of its element vectors will be destroyed when destroying the Vec2D. +Let's make a vector of vectors, which can be cloned. All of its element vectors will be destroyed when destroying the Vec2D. ```c #include @@ -206,7 +207,7 @@ Let's make a vector of vectors that can be cloned. All of its element vectors wi #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 // However, disable search/sort for Vec2D because Vec_cmp() is not defined. +#define i_opt c_no_cmp // Disable cmp (search/sort) for Vec2D because Vec_cmp() is not defined. #include int main(void) @@ -542,11 +543,11 @@ typedef struct Dataset { ``` --- -## Per-container-instance customization -Sometimes it is useful to extend a container type to hold extra data, e.g. a comparison -or allocator function pointer or some context that the function pointers can use. Most -libraries solve this by adding an opaque pointer (void*) or some function pointer(s) into -the data structure for the user to manage. This solution has a few disadvantages, e.g. the +## 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" @@ -564,10 +565,10 @@ the by inclusion of ``. #define i_allocator pgs #define i_no_clone -#define i_extend MemoryContext memctx +#define i_extend MemoryContext memctx; #include ``` -Define both `i_type` and `i_con` (the container type) before including the custom header: +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 diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index af27bd1d..21eaf884 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -2,16 +2,17 @@ The following macros are recommended to use, and they safe/have no side-effects. -## Loop abstraction macros +--- +## Ranged for-loops -### c_foreach, c_foreach_r, c_forpair +### c_foreach, c_foreach_rv, c_forpair -| Usage | Description | -|:-----------------------------------------|:----------------------------------------| -| `c_foreach (it, ctype, container)` | Iteratate all elements | -| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) | -| `c_foreach_r (it, ctype, container)` | Iteratate in reverse (cstack,cvec,cdeq) | -| `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 @@ -40,6 +41,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. @@ -61,24 +81,38 @@ 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); +crange& crange_object(...) // 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); -// insert in existing map -c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} }) - cmap_ii_insert(&map, i.ref->first, i.ref->second); +// 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 -// string literals pushed to a stack of cstr: -c_forlist (i, const char*, {"Hello", "crazy", "world"}) - cstack_str_emplace(&stk, *i.ref); +// 2. The first 11 primes: +printf("2"); +c_forfilter (i, crange, crange_object(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 | |:----------------------------------------------------|:---------------------------------------| @@ -122,46 +156,14 @@ int main() { ``` Note that `c_flt_take()` and `c_flt_takewhile()` breaks the loop on false. -## Generators - -### 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_object(...) // 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 - -// 2. The first 11 primes: -printf("2"); -c_forfilter (i, crange, crange_object(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 +--- +## Generic algorithms -### c_make, c_new, c_delete +### c_make, c_drop -- *c_make(C, {...})*: Make any container from an initializer list. Example: +Make any container from an initializer list: ```c -#define i_val_str // owned cstr string value type -//#define i_valclass crawstr // non-owning const char* values with strcmp/cstrhash -//#define i_val const char* // non-owning const char* values with pointer cmp/hash. +#define i_val_str // owned cstr string value type #include #define i_key int @@ -170,26 +172,21 @@ c_forfilter (i, crange, crange_object(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 - -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; @@ -208,51 +205,66 @@ 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, c_const_cast +### 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 +#include + +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 +Memory allocator wrappers that uses signed sizes. + +### c_arraylen +Return number of elements in an array. array must not be a pointer! +```c +int array[] = {1, 2, 3, 4}; +intptr_t n = c_arraylen(array); +``` + +### c_swap, c_const_cast ```c // Safe macro for swapping internals of two objects of same type: c_swap(cmap_int, &map1, &map2); -// Drop multiple containers of same type: -c_drop(cvec_i, &vec1, &vec2, &vec3); - // 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! ``` -### General predefined template parameter functions +### Predefined template parameter functions +**crawstr** - Non-owned `const char*` "class" element type: `#define i_valclass crawstr` ```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 - 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); ``` - -### c_malloc, c_calloc, c_realloc, c_free: customizable allocators -Memory allocator wrappers that uses signed sizes. - -### c_arraylen -Return number of elements in an array. array must not be a pointer! +Default implementations ```c -int array[] = {1, 2, 3, 4}; -intptr_t n = c_arraylen(array); +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 an improved implementation of Simon Tatham's classic C code, which utilizes the *Duff's device* trick. However, Tatham's implementation is not typesafe, -and it always allocates the coroutine's internal state dynamically. Also, -it does not let the coroutine do self-cleanup on early finish, i.e. it -just frees the dynamically allocated memory. +and it always allocates the coroutine's internal state dynamically. But most 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 some struct pointer as parameter, which must contain the member `int cco_state;` @@ -260,8 +272,8 @@ 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 main user-loop -skips the triples which are upscaled version of smaller ones, by checking -the gcd() function, and breaks when diagonal length >= 100: +skips the triples which are upscaled version of smaller ones by checking +the gcd() function, and breaks when the diagonal size >= 100: ```c #include @@ -271,14 +283,14 @@ struct triples { 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) { +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; + if (--i->n == 0) cco_return; } } } diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 362b09ce..24ad59f9 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -182,7 +182,7 @@ 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_foreach_r(it, C, cnt) \ +#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) diff --git a/include/stc/extend.h b/include/stc/extend.h index a8cb5f5b..cbfc4a12 100644 --- a/include/stc/extend.h +++ b/include/stc/extend.h @@ -50,7 +50,7 @@ #endif typedef struct { - i_extend; + i_extend i_type get; } c_PASTE(i_type, Ext); diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 82126456..1fc00614 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -42,7 +42,7 @@ int main() printf(" %d", *i.ref); puts("\n\nc_foreach_r: reverse"); - c_foreach_r (i, IVec, vec) + c_foreach_rv (i, IVec, vec) printf(" %d", *i.ref); puts("\n\nc_foreach in map:"); diff --git a/misc/examples/functor.c b/misc/examples/functor.c index 7cc770d0..7417080b 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -9,7 +9,7 @@ #define i_type IPQue #define i_val int -#define i_extend bool (*less)(const int*, const int*) +#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 -- cgit v1.2.3 From d92ffe3da29b3352c90b2d356e395914ba5b3f52 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Sat, 8 Apr 2023 11:02:39 +0200 Subject: More docs updates, and a change in stc/extend.h. --- README.md | 51 +++++++++++++++++++++++++++-------------------- docs/ccommon_api.md | 33 +++++++++++++++--------------- include/stc/algo/crange.h | 4 ++-- include/stc/ccommon.h | 3 ++- include/stc/extend.h | 4 ++-- misc/examples/forfilter.c | 2 +- misc/examples/functor.c | 10 +++++----- misc/examples/prime.c | 2 +- 8 files changed, 59 insertions(+), 50 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/README.md b/README.md index 6f07f8ff..220349b3 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,10 @@ STC - Smart Template Containers for C --- Description ----------- -STC is a *modern*, *fully typesafe*, *fast* and *compact* container and algorithm library for C99. +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 let you store and manage trivial and highly complex data in a variety of -containers with ease. It is optimized for speed, usage ergonomics, consistency, -and it creates small binaries. +The library handles everything from trivial to highly complex data using *templates*, and it +supports a variety of containers. Containers ---------- @@ -80,18 +79,18 @@ List of contents ## 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 more complex 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 construction of a `cstr` (which may allocate memory) for the lookup *is not needed*. Hence, the alt. lookup -key does not need to be destroyed after use as it is normally a POD type. Finally, the alternative -key does not need to be destroyed after use as it is normally a POD type. Finally, the alternative -lookup type may be passed to an ***emplace***-function. E.g. instead of calling -`cvec_str_push(&vec, cstr_from("Hello"))`, you may call `cvec_str_emplace(&vec, "Hello")`, -which is functionally identical, but more convenient. +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 @@ -146,9 +145,9 @@ Benchmark notes: --- ## 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 done, so containers are type-safe like -templated types in C++. However, the specification of template parameters are naturally different. In STC, -you specify template parameters by `#define` before including the container: +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 Floats // Container type name; unless defined name would be cvec_float #define i_val float // Container element type @@ -576,10 +575,10 @@ To use it, define both `i_type` and `i_con` (the container type) before includin #define i_con csmap #include "stcpgs.h" -// Note the wrapper struct type is IMapExt. IMap is accessed by .get +// Note the wrapper struct type is IMap_ext. IMap is accessed by .get void maptest() { - IMapExt map = {.memctx=CurrentMemoryContext}; + IMap_ext map = {.memctx=CurrentMemoryContext}; c_forrange (i, 1, 16) IMap_insert(&map.get, i*i, i); @@ -605,9 +604,17 @@ STC is generally very memory efficient. Memory usage for the different container --- # Version History +## Version 4.2 +- Much improved documentation +- Added Coroutines + documentation +- Added `c_const_cast()` typesafe macro. +- 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)` +- Removed c_PAIR ## Version 4.1.1 -I am happy to finally announce a new release! Major changes: +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). diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 21eaf884..90191e40 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -84,7 +84,7 @@ c_forrange (i, 30, 0, -5) printf(" %lld", i); ### 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_object(...) // create a compound literal crange object +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 @@ -102,7 +102,7 @@ c_forfilter (i, crange, r1, isPrime(*i.ref)) // 2. The first 11 primes: printf("2"); -c_forfilter (i, crange, crange_object(3, INT64_MAX, 2), +c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2), isPrime(*i.ref) && c_flt_take(10) ){ @@ -260,22 +260,23 @@ void c_default_drop(Type* p); // does nothing --- ## Coroutines -This is an improved implementation of Simon Tatham's classic C code, which utilizes -the *Duff's device* trick. However, Tatham's implementation is not typesafe, -and it always allocates the coroutine's internal state dynamically. But most crucially, +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 some struct pointer as parameter, which must contain the member `int cco_state;` +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 main user-loop -skips the triples which are upscaled version of smaller ones by checking -the gcd() function, and breaks when the diagonal size >= 100: +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: ```c -#include +#include struct triples { int n; // input: max number of triples to be generated. @@ -311,8 +312,7 @@ int gcd(int a, int b) { // greatest common denominator int main() { - puts("\nCoroutine triples:"); - struct triples t = {INT32_MAX}; + struct triples t = {.n=INT32_MAX}; int n = 0; while (triples_next(&t)) { @@ -324,12 +324,13 @@ int main() if (t.c < 100) printf("%d: {%d, %d, %d}\n", ++n, t.a, t.b, t.c); else - cco_stop(&t); // make sure coroutine cleanup is done + 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. +**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 | |:----------|:-------------------------------------|:----------------------------------------| @@ -340,7 +341,7 @@ int main() | `void` | `cco_begin(ctx)` | Begin coroutine block | | `rettype` | `cco_end(retval)` | End coroutine block with return value | | `rettype` | `cco_end()` | End coroutine block with (void) | -| `rettype` | `cco_yield(retval)` | Yield a value | +| `rettype` | `cco_yield(retval)` | Return a value and suspend execution | | `rettype` | `cco_yield(corocall2, ctx2, retval)` | Yield from another coroutine and return val | | `rettype` | `cco_yield(corocall2, ctx2)` | Yield from another coroutine (void) | | | From the caller side: | | diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index 91ffdd56..ca06c258 100644 --- a/include/stc/algo/crange.h +++ b/include/stc/algo/crange.h @@ -34,7 +34,7 @@ int main() // use a temporary crange object. int a = 100, b = INT32_MAX; - c_forfilter (i, crange, crange_object(a, b, 8), + c_forfilter (i, crange, crange_obj(a, b, 8), c_flt_skip(i, 10) && c_flt_take(i, 3)) printf(" %lld", *i.ref); @@ -46,7 +46,7 @@ int main() #include -#define crange_object(...) \ +#define crange_obj(...) \ (*(crange[]){crange_make(__VA_ARGS__)}) typedef long long crange_value; diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 24ad59f9..1a2b3c3f 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -122,8 +122,9 @@ #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) (c_ARRAYLEN(a) + c_static_assert(sizeof(a) != sizeof(uintptr_t))) +#define c_ARRAYLEN(a) (intptr_t)(sizeof(a)/sizeof 0[a]) // Non-owning c-string typedef const char* crawstr; diff --git a/include/stc/extend.h b/include/stc/extend.h index cbfc4a12..66b3ebd1 100644 --- a/include/stc/extend.h +++ b/include/stc/extend.h @@ -52,9 +52,9 @@ typedef struct { i_extend i_type get; -} c_PASTE(i_type, Ext); +} c_PASTE(i_type, _ext); -#define c_getcon(cptr) c_container_of(cptr, _cx_memb(Ext), get) +#define c_getcon(cptr) c_container_of(cptr, _cx_memb(_ext), get) #define i_is_forward #define _i_inc diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index daea68b9..fbb7280f 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -54,7 +54,7 @@ fn main() { void demo2(void) { IVec vector = {0}; - c_forfilter (x, crange, crange_object(INT64_MAX), + c_forfilter (x, crange, crange_obj(INT64_MAX), c_flt_skipwhile(x, *x.ref != 11) && (*x.ref % 2) != 0 && c_flt_take(x, 5) diff --git a/misc/examples/functor.c b/misc/examples/functor.c index 7417080b..c0a4f8e8 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -14,10 +14,10 @@ #define i_con cpque #include -void print_queue(const char* name, IPQueExt 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. - IPQueExt copy = {q.less, IPQue_clone(q.get)}; + IPQue_ext copy = {q.less, IPQue_clone(q.get)}; for (printf("%s: \t", name); !IPQue_empty(©.get); IPQue_pop(©.get)) printf("%d ", *IPQue_top(©.get)); @@ -38,9 +38,9 @@ int main() printf("%d ", data[i]); puts(""); - IPQueExt q1 = {int_less}; // Max priority queue - IPQueExt minq1 = {int_greater}; // Min priority queue - IPQueExt q5 = {int_lambda}; // Using lambda to compare elements. + 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]); diff --git a/misc/examples/prime.c b/misc/examples/prime.c index a576a85c..d0887353 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -42,7 +42,7 @@ int main(void) puts("\n"); puts("Show the last 50 primes using a temporary crange generator:"); - c_forfilter (i, crange, crange_object(n - 1, 0, -2), + c_forfilter (i, crange, crange_obj(n - 1, 0, -2), cbits_test(&primes, *i.ref/2) && c_flt_take(i, 50) ){ -- cgit v1.2.3 From 6426ac05eb8c4dc1ab22aae2eb4139f9671981b7 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Sat, 8 Apr 2023 22:30:46 +0200 Subject: Reverted c_arraylen(), removed c_ARRAYLEN() --- README.md | 3 +++ include/stc/ccommon.h | 3 +-- include/stc/cspan.h | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include/stc/ccommon.h') diff --git a/README.md b/README.md index 220349b3..4be378a0 100644 --- a/README.md +++ b/README.md @@ -608,9 +608,12 @@ STC is generally very memory efficient. Memory usage for the different container - Much improved documentation - Added Coroutines + documentation - Added `c_const_cast()` typesafe macro. +- Added crand.h header: new API for crandom.h, which is deprecated. - 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() +- Renamed deprecated c_ARGSV => c_SV - Removed c_PAIR ## Version 4.1.1 diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 1a2b3c3f..d5508807 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -123,8 +123,7 @@ C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw)) #define c_litstrlen(literal) (c_sizeof("" literal) - 1) -#define c_arraylen(a) (c_ARRAYLEN(a) + c_static_assert(sizeof(a) != sizeof(uintptr_t))) -#define c_ARRAYLEN(a) (intptr_t)(sizeof(a)/sizeof 0[a]) +#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a]) // Non-owning c-string typedef const char* crawstr; diff --git a/include/stc/cspan.h b/include/stc/cspan.h index ce3c33ce..ac3e9206 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -129,10 +129,10 @@ typedef struct { int32_t d[6]; } cspan_idx6; {.data=(container)->data, .shape={(int32_t)(container)->_len}} #define cspan_from_array(array) \ - {.data=(array) + c_static_assert(sizeof(array) != sizeof(void*)), .shape={c_ARRAYLEN(array)}} + {.data=(array) + c_static_assert(sizeof(array) != sizeof(void*)), .shape={c_arraylen(array)}} #define cspan_size(self) _cspan_size((self)->shape, cspan_rank(self)) -#define cspan_rank(self) c_ARRAYLEN((self)->shape) +#define cspan_rank(self) c_arraylen((self)->shape) #define cspan_index(self, ...) c_PASTE(cspan_idx_, c_NUMARGS(__VA_ARGS__))(self, __VA_ARGS__) #define cspan_idx_1 cspan_idx_4 -- cgit v1.2.3