diff options
| author | Tyge Løvset <[email protected]> | 2022-09-25 14:51:35 +0200 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2022-09-25 15:09:23 +0200 |
| commit | 2093b18689383286915df511167a12dc5d7bc75f (patch) | |
| tree | 174779ae7e7b4f6d10ec8be300ea9574e2395729 | |
| parent | 756120e349a892ef1b7655fc777f28ec13845300 (diff) | |
| download | STC-modified-2093b18689383286915df511167a12dc5d7bc75f.tar.gz STC-modified-2093b18689383286915df511167a12dc5d7bc75f.zip | |
Added: crange number generator type. (similar to c++ std::iota). Fixed c_forfilter again. Cleanups. Docs added.
| -rw-r--r-- | docs/ccommon_api.md | 90 | ||||
| -rw-r--r-- | docs/cdeq_api.md | 2 | ||||
| -rw-r--r-- | docs/cstr_api.md | 2 | ||||
| -rw-r--r-- | docs/csview_api.md | 2 | ||||
| -rw-r--r-- | docs/cvec_api.md | 2 | ||||
| -rw-r--r-- | examples/city.c | 8 | ||||
| -rw-r--r-- | examples/forfilter.c | 63 | ||||
| -rw-r--r-- | examples/new_deq.c | 2 | ||||
| -rw-r--r-- | examples/new_vec.c | 2 | ||||
| -rw-r--r-- | include/stc/ccommon.h | 42 | ||||
| -rw-r--r-- | include/stc/cdeq.h | 2 | ||||
| -rw-r--r-- | include/stc/cstack.h | 2 | ||||
| -rw-r--r-- | include/stc/cstr.h | 4 | ||||
| -rw-r--r-- | include/stc/csview.h | 4 | ||||
| -rw-r--r-- | include/stc/cvec.h | 2 |
15 files changed, 170 insertions, 59 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index c45dadc1..8938f0d2 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -149,9 +149,9 @@ c_forlist (i, int, {1, 2, 3}) c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} }) cmap_ii_insert(&map, i.ref->first, i.ref->second); -// even string literals +// even string literals pushed to a stack of cstr: c_forlist (i, const char*, {"Hello", "crazy", "world"}) - cstack_s_push(&stk, *i.ref); + cstack_str_emplace(&stk, *i.ref); ``` ### c_foreach, c_forpair @@ -168,7 +168,7 @@ c_forlist (i, const char*, {"Hello", "crazy", "world"}) #define i_tag ii #include <stc/csmap.h> ... -c_forlist (i, csmap_ii_value, { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} }) +c_forlist (i, csmap_ii_raw, { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} }) csmap_ii_insert(&map, i.ref->first, i.ref->second); c_foreach (i, csmap_ii, map) @@ -186,7 +186,7 @@ c_forpair (id, count, csmap_ii, map) ``` ### c_forrange -Declare an iterator and specify a range to iterate with a for loop. Like python's ***for i in range()*** loop: +Abstaction for iterating sequence of numbers. Like python's ***for i in range()*** loop. | Usage | Python equivalent | |:----------------------------------------------|:-------------------------------------| @@ -207,6 +207,88 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i); // 30 25 20 15 10 5 ``` +### c_forwhile, c_forfilter +Iterate containers with stop-criteria and chained range filtering. + +| Usage | Description | +|:-----------------------------------------------------------|:-------------------------------------| +| `c_forwhile (it, ctype, container, whilepred)` | Iterate as long as whilepred is true | +| `c_forfilter (it, ctype, container, filter(s))` | Filter out items in chain | +| `c_forfilter (it, ctype, container, filter(s), whilepred)` | Adds a "takewhile" filter argument | + +| Built-in filter | Description | +|:----------------------------------|:-------------------------------------| +| `c_flt_drop(it, numItems)` | Drop numItems | +| `c_flt_dropwhile(it, predicate)` | Drop items until predicate is false | +| `c_flt_take(it, numItems)` | Take numItems | + +`it.index` holds the current item index. +```c +#define i_type IVec +#define i_val int +#include <stc/cstack.h> +#include <stdio.h> + +bool flt_prime(int i) { + for (int j=2; j*j <= i; ++j){ + if (i % j == 0) return false; + } + return true; +} +#define flt_odd(i) ((i) & 1) + +int main() { + c_auto (IVec, vec) { + c_forrange (i, 1000) IVec_push(&vec, 1000000 + i); + + c_forfilter (i, IVec, vec, + flt_odd(*i.ref) + && c_flt_drop(i, 100) // built-in + && flt_prime(*i.ref) + , c_flt_take(i, 10)) { // breaks loop on false. + printf(" %d", *i.ref); + } + puts(""); + } +} +// Out: 1000211 1000213 1000231 1000249 1000253 1000273 1000289 1000291 1000303 1000313 +``` +Note that `c_flt_take()` is given as an optional argument, which makes the loop stop when it becomes false (for efficiency). Chaining it after `flt_prime()` instead will give same result, but the full input is processed. + +### crange +**crange** is a number sequence generator type. The **crange_value** type is `intmax_t`. Below, *start*, *end*, *step* are of *crange_type*. +```c +crange crange_init(void); // will generate 0, 1, 2, ... +crange crange_from(start); // will generate start, start+1, ... +crange crange_from(start, end); // will generate start, start+1, ... end-1 +crange crange_from(start, end, step); // will generate start, start+step, ... upto-not-including end + // note that step may be negative. +crange_iter crange_begin(crange* self); +crange_iter crange_end(crange* self); +void crange_next(crange_iter* it); + +// Example usage: + +bool isPrime(int i) { + for (int j=2; j*j <= i; ++j) if (i % j == 0) return false; + return true; +} + +crange r1 = crange_from(3, 32, 2); +printf("1 2"); +c_forfilter (i, crange, r1, + isPrime(*i.ref)) + printf(" %lld", *i.ref); +// 1 2 3 5 7 11 13 17 19 23 29 31 + +crange r2 = crange_from(3, INTMAX_MAX, 2); +printf("1 2"); +c_forfilter (i, crange, r2, + isPrime(*i.ref) + , c_flt_take(10)) + printf(" %lld", *i.ref); +// 1 2 3 5 7 11 13 17 19 23 29 31 +``` ### c_find_if, c_find_in, c_erase_if Find or erase linearily in containers using a predicate ```c diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 969cecc2..cfd5565e 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -81,7 +81,7 @@ void cdeq_X_sort_range(cdeq_X_iter i1, cdeq_X_iter i2, cdeq_X_iter cdeq_X_begin(const cdeq_X* self); cdeq_X_iter cdeq_X_end(const cdeq_X* self); void cdeq_X_next(cdeq_X_iter* it); -cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, isize_t n); +cdeq_X_iter cdeq_X_advance(cdeq_X_iter it, intptr_t n); cdeq_X_raw cdeq_X_value_toraw(cdeq_X_value* pval); cdeq_X_value cdeq_X_value_clone(cdeq_X_value val); diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 53850e04..439faca7 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -108,7 +108,7 @@ void cstr_u8_erase(cstr* self, size_t bytepos, size_t u8len); // erase u cstr_iter cstr_begin(const cstr* self); cstr_iter cstr_end(const cstr* self); void cstr_next(cstr_iter* it); -cstr_iter cstr_advance(cstr_iter it, isize_t n); +cstr_iter cstr_advance(cstr_iter it, intptr_t n); // utf8 functions requires linking with src/utf8code.c symbols: bool cstr_valid_utf8(const cstr* self); // check if str is valid utf8 diff --git a/docs/csview_api.md b/docs/csview_api.md index 37ebf79a..70587911 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -55,7 +55,7 @@ bool csview_valid_utf8(csview sv); // requires csview_iter csview_begin(const csview* self); csview_iter csview_end(const csview* self); void csview_next(csview_iter* it); // utf8 codepoint step, not byte! -csview_iter csview_advance(csview_iter it, isize_t n); +csview_iter csview_advance(csview_iter it, intptr_t n); // from utf8.h size_t utf8_size(const char *s); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index dca273aa..c9442bb1 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -92,7 +92,7 @@ void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2, cvec_X_iter cvec_X_begin(const cvec_X* self); cvec_X_iter cvec_X_end(const cvec_X* self); void cvec_X_next(cvec_X_iter* iter); -cvec_X_iter cvec_X_advance(cvec_X_iter it, isize_t n); +cvec_X_iter cvec_X_advance(cvec_X_iter it, intptr_t n); cvec_X_raw cvec_X_value_toraw(cvec_X_value* pval); cvec_X_value cvec_X_value_clone(cvec_X_value val); diff --git a/examples/city.c b/examples/city.c index c98d3098..80bfbb12 100644 --- a/examples/city.c +++ b/examples/city.c @@ -52,10 +52,10 @@ int main(void) c_auto (CityMap, map) { c_forlist (i, City, { - {cstr_new("New York"), cstr_new("US"), 4.3, 23.2, 9000000}, - {cstr_new("Paris"), cstr_new("France"), 4.3, 23.2, 9000000}, - {cstr_new("Berlin"), cstr_new("Germany"), 4.3, 23.2, 9000000}, - {cstr_new("London"), cstr_new("UK"), 4.3, 23.2, 9000000}, + {cstr_new("New York"), cstr_new("US"), 4.3f, 23.2f, 9000000}, + {cstr_new("Paris"), cstr_new("France"), 4.3f, 23.2f, 9000000}, + {cstr_new("Berlin"), cstr_new("Germany"), 4.3f, 23.2f, 9000000}, + {cstr_new("London"), cstr_new("UK"), 4.3f, 23.2f, 9000000}, }) Cities_emplace(&cities, *i.ref); copy = Cities_clone(cities); // share each element! diff --git a/examples/forfilter.c b/examples/forfilter.c index 46e59562..29128836 100644 --- a/examples/forfilter.c +++ b/examples/forfilter.c @@ -14,6 +14,7 @@ // filters and transforms: #define flt_remove(i, x) (*i.ref != (x)) #define flt_even(i) ((*i.ref & 1) == 0) +#define flt_odd(i) (*i.ref & 1) #define trf_square(i) (*i.ref * *i.ref) void demo1(void) @@ -22,21 +23,24 @@ void demo1(void) 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_remove(i, 80)) printf(" %d", *i.ref); puts(""); int res, sum = 0; - c_forfilter (i, IVec, vec, c_flt_drop(i, 3) - && flt_even(i) - && flt_remove(i, 80) - //&& c_flt_take(i, 5) - , c_flt_take(i, 5) + c_forfilter (i, IVec, vec, + c_flt_dropwhile(i, *i.ref != 80) + && c_flt_drop(i, 1) + && c_flt_dropwhile(i, *i.ref != 80) + && flt_even(i) + && flt_remove(i, 80) + , c_flt_take(i, 5) // takewhile ){ sum += res = trf_square(i); - printf(" %d:%d", *i.ref, res); + printf(" %d", res); } - printf("\nsum: %d\n", sum); + printf("\n sum: %d\n", sum); } } @@ -55,11 +59,13 @@ fn main() { void demo2(void) { c_auto (IVec, vector) { - int n = 0; - for (size_t x=1;; ++x) - if (n == 5) break; - else if (x & 1) ++n, IVec_push(&vector, x*x); + crange rv = crange_from(1); + c_forfilter (x, crange, rv, + flt_odd(x) + , c_flt_take(x, 5)) + IVec_push(&vector, trf_square(x)); + puts("demo2:"); c_foreach (i, IVec, vector) printf(" %d", *i.ref); puts(""); } @@ -89,6 +95,7 @@ void demo3(void) csview_contains(*w.ref, c_sv("i"))) SVec_push(&words_containing_i, *w.ref); + puts("demo3:"); c_foreach (w, SVec, words_containing_i) printf(" %.*s", c_ARGsv(*w.ref)); puts(""); @@ -97,18 +104,33 @@ void demo3(void) void demo4(void) { - csview s = c_sv("ab123cReAghNGnΩoEp"); - cstr out = cstr_null; - - c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) { - char buf[4]; - utf8_encode(buf, utf8_tolower(utf8_peek(i.ref))); - cstr_push(&out, buf); + 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)); } - - printf("%s\n", cstr_str(&out)); } +void demo5(void) +{ + #define flt_even(i) ((*i.ref & 1) == 0) + #define flt_mid_decade(i) ((*i.ref % 10) != 0) + puts("demo5:"); + crange r1 = crange_from(1963); + c_forfilter (i, crange, r1, + c_flt_drop(i,15) + && c_flt_dropwhile(i, flt_mid_decade(i)) + && c_flt_drop(i,30) + && flt_even(i) + , c_flt_take(i,10)) + printf(" %lld", *i.ref); + puts(""); +} int main(void) { @@ -116,6 +138,7 @@ int main(void) demo2(); demo3(); demo4(); + demo5(); } #include "../src/utf8code.c" diff --git a/examples/new_deq.c b/examples/new_deq.c index 5f7c357f..dd6f04c0 100644 --- a/examples/new_deq.c +++ b/examples/new_deq.c @@ -42,7 +42,7 @@ int main() } c_auto (cdeq_float, fvec) { - cdeq_float_push_back(&fvec, 123.3); + cdeq_float_push_back(&fvec, 123.3f); } c_auto (cdeq_pnt, pvec) { diff --git a/examples/new_vec.c b/examples/new_vec.c index 9ae2ccf1..e0fa79ae 100644 --- a/examples/new_vec.c +++ b/examples/new_vec.c @@ -41,7 +41,7 @@ int main() c_auto (cvec_str, svec) { cvec_i32_push_back(&vec, 123); - cvec_float_push_back(&fvec, 123.3); + cvec_float_push_back(&fvec, 123.3f); cvec_pnt_push_back(&pvec, (Point){42, 14}); cvec_pnt_push_back(&pvec, (Point){32, 94}); diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index ac55b3e9..4ed3ebf8 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -30,14 +30,6 @@ #include <string.h> #include <assert.h> -#if SIZE_MAX == UINT32_MAX - typedef int32_t isize_t; -# define ISIZE_MAX INT32_MAX -#elif SIZE_MAX == UINT64_MAX - typedef int64_t isize_t; -# define ISIZE_MAX INT64_MAX -#endif - #if defined(_MSC_VER) # pragma warning(disable: 4116 4996) // unnamed type definition in parentheses # define STC_FORCE_INLINE static __forceinline @@ -171,27 +163,25 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, ; it.ref != (C##_value*)_endref; C##_next(&it)) #ifndef c_FLT_STACK -#define c_FLT_STACK 4 +#define c_FLT_STACK 20 #endif - -#define c_flt_drop(i, n) (++(i).dropped[(i).dn++] > (n)) -#define c_flt_dropwhile(i, pred) ((i).dropwhile |= !(pred)) -#define c_flt_take(i, n) (++(i).taken[(i).tn++] <= (n)) +#define c_flt_take(i, n) (++(i).stack[(i).top++] <= (n)) +#define c_flt_drop(i, n) (++(i).stack[(i).top++] > (n)) +#define c_flt_dropwhile(i, pred) ((i).stack[(i).top++] |= !(pred)) #define c_forfilter(...) c_MACRO_OVERLOAD(c_forfilter, __VA_ARGS__) #define c_forfilter4(it, C, cnt, filter) \ c_forfilter_s(it, C, C##_begin(&cnt), filter) -#define c_forfilter5(it, C, cnt, filter, loopwhile) \ - c_forfilter_s(it, C, C##_begin(&cnt), filter) if (!(loopwhile)) break; else +#define c_forfilter5(it, C, cnt, filter, takewhile) \ + c_forfilter_s(it, C, C##_begin(&cnt), filter) if (!(takewhile)) break; else #define c_forfilter_s(it, C, start, filter) \ c_foreach_s(it, C, start) if (!(filter)) ; else #define c_foreach_s(i, C, start) \ for (struct {C##_iter it; C##_value *ref; \ - uint32_t index, taken[c_FLT_STACK+1], dropped[c_FLT_STACK]; \ - int8_t dn, tn; bool dropwhile;} \ + uint32_t index, top, stack[c_FLT_STACK];} \ i = {.it=start, .ref=i.it.ref}; i.ref \ - ; C##_next(&i.it), i.ref = i.it.ref, ++i.index, i.dn=0, i.tn=0) + ; C##_next(&i.it), i.ref = i.it.ref, ++i.index, i.top=0) #define c_forwhile(i, C, cnt, cond) \ for (struct {C##_iter it; C##_value *ref; size_t index;} \ @@ -213,6 +203,22 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, for (itype i=start, _inc=step, _end=(stop) - (_inc > 0) \ ; (_inc > 0) ^ (i > _end); i += _inc) +typedef intmax_t crange_value; +struct {crange_value val, end, step; } typedef crange; +struct {crange_value *ref, end, step; } typedef crange_iter; +#define crange_from(...) c_MACRO_OVERLOAD(crange_from, __VA_ARGS__) +#define crange_init() crange_from3(0, INTMAX_MAX, 1) +#define crange_from1(start) crange_from3(start, INTMAX_MAX, 1) +#define crange_from2(start, end) crange_from3(start, end, 1) +STC_INLINE crange crange_from3(crange_value start, crange_value finish, crange_value step) + { crange r = {start, finish - (step > 0), step}; return r; } +STC_INLINE crange_iter crange_begin(crange* self) + { crange_iter it = {&self->val, self->end, self->step}; return it; } +STC_INLINE crange_iter crange_end(crange* self) + { crange_iter it = {NULL}; return it; } +STC_INLINE void crange_next(crange_iter* it) + { *it->ref += it->step; if ((it->step > 0) == (*it->ref > it->end)) it->ref = NULL; } + #define c_forlist(it, T, ...) \ for (struct {T* data; T* ref; size_t index;} \ it = {.data=(T[])__VA_ARGS__, .ref=it.data} \ diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index 423464ac..2b8513e1 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -110,7 +110,7 @@ STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) STC_INLINE void _cx_memb(_next)(_cx_iter* it) { if (++it->ref == it->end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, isize_t n) +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } #if !defined _i_queue diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 9126cdef..2f9b2626 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -180,7 +180,7 @@ STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) STC_INLINE void _cx_memb(_next)(_cx_iter* it) { if (++it->ref == it->end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, isize_t n) +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { if ((it.ref += n) >= it.end) it.ref = NULL ; return it; } #include "template.h" diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 961ca344..7b382085 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -48,7 +48,7 @@ enum { cstr_s_cap = sizeof(cstr_buf) - 1 }; #define cstr_s_size(s) ((size_t)(cstr_s_cap - (s)->sml.last)) -#define cstr_s_set_size(s, len) ((s)->sml.last = cstr_s_cap - (len), (s)->sml.data[len] = 0) +#define cstr_s_set_size(s, len) ((s)->sml.last = (uint8_t)(cstr_s_cap - (len)), (s)->sml.data[len] = 0) #define cstr_s_data(s) (s)->sml.data #define cstr_s_end(s) ((s)->sml.data + cstr_s_size(s)) @@ -237,7 +237,7 @@ STC_INLINE void cstr_next(cstr_iter* it) { it->u8.chr.size = utf8_chr_size(it->ref); if (!*it->ref) it->ref = NULL; } -STC_INLINE cstr_iter cstr_advance(cstr_iter it, isize_t pos) { +STC_INLINE cstr_iter cstr_advance(cstr_iter it, intptr_t pos) { int inc = -1; if (pos > 0) pos = -pos, inc = 1; while (pos && *it.ref) pos += (*(it.ref += inc) & 0xC0) != 0x80; diff --git a/include/stc/csview.h b/include/stc/csview.h index 3bb8a542..2be30cb0 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -86,7 +86,7 @@ STC_INLINE void csview_next(csview_iter* it) { it->u8.chr.size = utf8_chr_size(it->ref); if (it->ref == it->u8.end) it->ref = NULL; } -STC_INLINE csview_iter csview_advance(csview_iter it, isize_t pos) { +STC_INLINE csview_iter csview_advance(csview_iter it, intptr_t pos) { int inc = -1; if (pos > 0) pos = -pos, inc = 1; while (pos && it.ref != it.u8.end) pos += (*(it.ref += inc) & 0xC0) != 0x80; @@ -145,7 +145,7 @@ STC_INLINE csview cstr_u8_substr(const cstr* self , size_t bytepos, size_t u8len STC_INLINE int csview_cmp(const csview* x, const csview* y) { size_t n = x->size < y->size ? x->size : y->size; int c = memcmp(x->str, y->str, n); - return c ? c : x->size - y->size; + return c ? c : (int)(x->size - y->size); } STC_INLINE int csview_icmp(const csview* x, const csview* y) diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 4419f4a8..aeb17e1a 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -207,7 +207,7 @@ STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) STC_INLINE void _cx_memb(_next)(_cx_iter* it) { if (++it->ref == it->end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, isize_t n) +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } STC_INLINE size_t _cx_memb(_index)(const _cx_self* cx, _cx_iter it) |
