diff options
| author | Tyge Løvset <[email protected]> | 2023-04-08 22:37:06 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-04-08 22:37:06 +0200 |
| commit | 43120f2863a67db416ec3b379eb820e2704cafb7 (patch) | |
| tree | f3b9917940f94c1582bc39ea6f56b735295ec861 /include/stc | |
| parent | e8be14dfc894eeac859f0287d4d5b4f4745c0585 (diff) | |
| parent | 6426ac05eb8c4dc1ab22aae2eb4139f9671981b7 (diff) | |
| download | STC-modified-43120f2863a67db416ec3b379eb820e2704cafb7.tar.gz STC-modified-43120f2863a67db416ec3b379eb820e2704cafb7.zip | |
Merge pull request #53 from tylov/dev42
Version 4.2 RC
Diffstat (limited to 'include/stc')
| -rw-r--r-- | include/stc/algo/coroutine.h | 10 | ||||
| -rw-r--r-- | include/stc/algo/csort.h | 6 | ||||
| -rw-r--r-- | include/stc/algo/filter.h | 36 | ||||
| -rw-r--r-- | include/stc/carc.h | 20 | ||||
| -rw-r--r-- | include/stc/cbits.h | 40 | ||||
| -rw-r--r-- | include/stc/cbox.h | 20 | ||||
| -rw-r--r-- | include/stc/ccommon.h | 55 | ||||
| -rw-r--r-- | include/stc/cdeq.h | 13 | ||||
| -rw-r--r-- | include/stc/clist.h | 12 | ||||
| -rw-r--r-- | include/stc/cmap.h | 54 | ||||
| -rw-r--r-- | include/stc/cpque.h | 14 | ||||
| -rw-r--r-- | include/stc/cqueue.h | 10 | ||||
| -rw-r--r-- | include/stc/crand.h | 174 | ||||
| -rw-r--r-- | include/stc/csmap.h | 54 | ||||
| -rw-r--r-- | include/stc/cspan.h | 8 | ||||
| -rw-r--r-- | include/stc/cstack.h | 4 | ||||
| -rw-r--r-- | include/stc/cvec.h | 15 | ||||
| -rw-r--r-- | include/stc/extend.h | 66 | ||||
| -rw-r--r-- | include/stc/priv/altnames.h | 3 | ||||
| -rw-r--r-- | include/stc/priv/raii.h | 27 | ||||
| -rw-r--r-- | include/stc/priv/template.h | 74 | ||||
| -rw-r--r-- | include/stc/priv/template2.h | 78 |
22 files changed, 522 insertions, 271 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index d29b2cef..b0ecd6b7 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -83,16 +83,16 @@ enum { case __LINE__:; \ } while (0) -#define cco_yield_2(corocall, ctx) \ - cco_yield_3(corocall, ctx,) +#define cco_yield_2(corocall2, ctx2) \ + cco_yield_3(corocall2, ctx2, ) -#define cco_yield_3(corocall, ctx, retval) \ +#define cco_yield_3(corocall2, ctx2, retval) \ do { \ *_state = __LINE__; \ do { \ - corocall; if (cco_suspended(ctx)) return retval; \ + corocall2; if (cco_suspended(ctx2)) return retval; \ case __LINE__:; \ - } while (cco_alive(ctx)); \ + } while (cco_alive(ctx2)); \ } while (0) #define cco_final \ diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h index c452064f..53fe9fcc 100644 --- a/include/stc/algo/csort.h +++ b/include/stc/algo/csort.h @@ -20,8 +20,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include <stc/ccommon.h> -#include <stc/priv/template.h> +#include "../ccommon.h" +#include "../priv/template.h" /* Generic Quicksort in C, performs as fast as c++ std::sort(). template params: @@ -86,4 +86,4 @@ static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi static inline void c_PASTE(csort_, i_tag)(i_val arr[], intptr_t n) { c_PASTE(cqsort_, i_tag)(arr, 0, n - 1); } -#include <stc/priv/template.h> +#include "../priv/template2.h" diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index 7729799f..e133577c 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -24,24 +24,24 @@ #include <stdio.h> #define i_val int #include <stc/cstack.h> -#include <stc/algo/filter.h> +#include <stc/calgo.h> int main() { - c_with (cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7, 8, 9}), - cstack_int_drop(&stk)) - { - c_foreach (i, cstack_int, stk) - printf(" %d", *i.ref); - puts(""); - - c_forfilter (i, cstack_int, stk, - c_flt_skipwhile(i, *i.ref < 3) && - (*i.ref & 1) == 0 && // even only - c_flt_take(i, 2)) // break after 2 - printf(" %d", *i.ref); - puts(""); - } + cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7, 8, 9}); + + c_foreach (i, cstack_int, stk) + printf(" %d", *i.ref); + puts(""); + + c_forfilter (i, cstack_int, stk, + c_flt_skipwhile(i, *i.ref < 3) && + (*i.ref & 1) == 0 && // even only + c_flt_take(i, 2)) // break after 2 + printf(" %d", *i.ref); + puts(""); + + cstack_int_drop(&stk); } */ #ifndef STC_FILTER_H_INCLUDED @@ -51,12 +51,12 @@ int main() // c_forfilter: -#define c_flt_skip(i, n) (c_flt_count(i) > (n)) +#define c_flt_skip(i, n) (c_flt_counter(i) > (n)) #define c_flt_skipwhile(i, pred) ((i).b.s2[(i).b.s2top++] |= !(pred)) #define c_flt_take(i, n) _flt_take(&(i).b, n) #define c_flt_takewhile(i, pred) _flt_takewhile(&(i).b, pred) -#define c_flt_count(i) ++(i).b.s1[(i).b.s1top++] -#define c_flt_last(i) (i).b.s1[(i).b.s1top - 1] +#define c_flt_counter(i) ++(i).b.s1[(i).b.s1top++] +#define c_flt_getcount(i) (i).b.s1[(i).b.s1top - 1] #define c_forfilter(i, C, cnt, filter) \ c_forfilter_it(i, C, C##_begin(&cnt), filter) diff --git a/include/stc/carc.h b/include/stc/carc.h index 02bbaf52..8ef80b12 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -90,7 +90,7 @@ typedef i_keyraw _cx_raw; #define _i_atomic_inc(v) (void)(++*(v)) #define _i_atomic_dec_and_test(v) !(--*(v)) #endif -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_carc_types, _cx_self, i_key); #endif struct _cx_memb(_rep_) { catomic_long counter; i_key value; }; @@ -177,8 +177,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) { STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry) { return i_cmp(rx, ry); } -STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { - _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get); +STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) { + _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get); return i_cmp((&rx), (&ry)); } #endif @@ -187,27 +187,27 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) { return i_eq(rx, ry); } -STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get); +STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get); return i_eq((&rx), (&ry)); } #elif !defined i_no_cmp STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) { return i_cmp(rx, ry) == 0; } -STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) - { return _cx_memb(_cmp)(x, y) == 0; } +STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) + { return _cx_memb(_cmp)(self, other) == 0; } #endif #ifndef i_no_hash STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx) { return i_hash(rx); } -STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) - { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); } +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self) + { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); } #endif #undef _i_eq #undef _i_atomic_inc #undef _i_atomic_dec_and_test -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/cbits.h b/include/stc/cbits.h index fa0da665..826df847 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -27,26 +27,26 @@ Similar to boost::dynamic_bitset / std::bitset #include "cbits.h" int main() { - c_with (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) - { - cbits_reset(&bset, 9); - cbits_resize(&bset, 43, false); - - printf("%4zu: ", cbits_size(&bset)); - c_forrange (i, cbits_size(&bset)) - printf("%d", cbits_at(&bset, i)); - puts(""); - cbits_set(&bset, 28); - cbits_resize(&bset, 77, true); - cbits_resize(&bset, 93, false); - cbits_resize(&bset, 102, true); - cbits_set_value(&bset, 99, false); - - printf("%4zu: ", cbits_size(&bset)); - c_forrange (i, cbits_size(&bset)) - printf("%d", cbits_at(&bset, i)); - puts(""); - } + cbits bset = cbits_with_size(23, true); + cbits_reset(&bset, 9); + cbits_resize(&bset, 43, false); + + printf("%4zu: ", cbits_size(&bset)); + c_forrange (i, cbits_size(&bset)) + printf("%d", cbits_at(&bset, i)); + puts(""); + cbits_set(&bset, 28); + cbits_resize(&bset, 77, true); + cbits_resize(&bset, 93, false); + cbits_resize(&bset, 102, true); + cbits_set_value(&bset, 99, false); + + printf("%4zu: ", cbits_size(&bset)); + c_forrange (i, cbits_size(&bset)) + printf("%d", cbits_at(&bset, i)); + puts(""); + + cbits_drop(&bset); } */ #ifndef CBITS_H_INCLUDED diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 641fcbfc..ca88fc66 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -76,7 +76,7 @@ int main() { #include "priv/template.h" typedef i_keyraw _cx_raw; -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_cbox_types, _cx_self, i_key); #endif @@ -163,8 +163,8 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* moved) { STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry) { return i_cmp(rx, ry); } -STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { - _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get); +STC_INLINE int _cx_memb(_cmp)(const _cx_self* self, const _cx_self* other) { + _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get); return i_cmp((&rx), (&ry)); } #endif @@ -173,25 +173,25 @@ STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) { STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) { return i_eq(rx, ry); } -STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - _cx_raw rx = i_keyto(x->get), ry = i_keyto(y->get); +STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + _cx_raw rx = i_keyto(self->get), ry = i_keyto(other->get); return i_eq((&rx), (&ry)); } #elif !defined i_no_cmp STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) { return i_cmp(rx, ry) == 0; } -STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) - { return _cx_memb(_cmp)(x, y) == 0; } +STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) + { return _cx_memb(_cmp)(self, other) == 0; } #endif #ifndef i_no_hash STC_INLINE uint64_t _cx_memb(_raw_hash)(const _cx_raw* rx) { return i_hash(rx); } -STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) - { _cx_raw rx = i_keyto(x->get); return i_hash((&rx)); } +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* self) + { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); } #endif #undef _i_eq -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index b822b9f8..d5508807 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -30,6 +30,7 @@ #include <string.h> #include <assert.h> #include "priv/altnames.h" +#include "priv/raii.h" #define c_NPOS INTPTR_MAX #define c_ZI PRIiPTR @@ -81,7 +82,8 @@ #define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); free(_tp); } while (0) #define c_static_assert(b) ((int)(0*sizeof(int[(b) ? 1 : -1]))) -#define c_container_of(p, T, m) ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m))) +#define c_container_of(p, C, m) ((C*)((char*)(1 ? (p) : &((C*)0)->m) - offsetof(C, m))) +#define c_const_cast(T, p) ((T)(p) + 0*sizeof((T)0 == (p))) #define c_swap(T, xp, yp) do { T *_xp = xp, *_yp = yp, \ _tv = *_xp; *_xp = *_yp; *_yp = _tv; } while (0) #define c_sizeof (intptr_t)sizeof @@ -120,10 +122,13 @@ #define c_make(C, ...) \ C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw)) -#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a]) #define c_litstrlen(literal) (c_sizeof("" literal) - 1) +#define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a]) +// Non-owning c-string typedef const char* crawstr; +#define crawstr_clone(s) (s) +#define crawstr_drop(p) ((void)p) #define crawstr_cmp(xp, yp) strcmp(*(xp), *(yp)) #define crawstr_hash(p) cstrhash(*(p)) @@ -132,24 +137,23 @@ typedef const char* crawstr; #define c_sv_2(str, n) (c_LITERAL(csview){str, n}) #define c_SV(sv) (int)(sv).size, (sv).str // print csview: use format "%.*s" -#define c_PAIR(ref) (ref)->first, (ref)->second #define c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) { - const uint8_t *x = (const uint8_t*) key; - uint64_t u8, h = 1; intptr_t n = len >> 3; - uint32_t u4; + uint32_t u4; uint64_t u8; + switch (len) { + case 8: memcpy(&u8, key, 8); return u8*0xc6a4a7935bd1e99d; + case 4: memcpy(&u4, key, 4); return u4*0xc6a4a7935bd1e99d; + case 0: return 1; + } + const uint8_t *x = (const uint8_t*)key; + uint64_t h = *x, n = (uint64_t)len >> 3; + len &= 7; while (n--) { memcpy(&u8, x, 8), x += 8; - h += (c_ROTL(u8, 26) ^ u8)*0xc6a4a7935bd1e99d; + h += u8*0xc6a4a7935bd1e99d; } - switch (len &= 7) { - case 0: return h; - case 4: memcpy(&u4, x, 4); - return h + u4*0xc6a4a7935bd1e99d; - } - h += *x++; - while (--len) h = (h << 10) - h + *x++; + while (len--) h = (h << 10) - h - *x++; return c_ROTL(h, 26) ^ h; } @@ -178,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) @@ -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/cdeq.h b/include/stc/cdeq.h index c4f84a1b..ff6e744f 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -36,7 +36,7 @@ #endif #include "priv/template.h" -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_cdeq_types, _cx_self, i_key); #endif typedef i_keyraw _cx_raw; @@ -196,11 +196,10 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw) { return (_cx_value *) _cx_memb(_get)(self, raw); } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - if (x->_len != y->_len) return false; - _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y); - for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) { - const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref); +_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + if (self->_len != other->_len) return false; + for (intptr_t i = 0; i < self->_len; ++i) { + const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i); if (!(i_eq((&_rx), (&_ry)))) return false; } return true; @@ -443,5 +442,5 @@ _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { #endif // !c_no_cmp #endif // !_i_queue #endif // IMPLEMENTATION -#include "priv/template.h" #define CDEQ_H_INCLUDED +#include "priv/template2.h" diff --git a/include/stc/clist.h b/include/stc/clist.h index eb72b888..f7fb4152 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -26,7 +26,7 @@ it also support both push_back() and push_front(), unlike std::forward_list: #include <stdio.h> - #include <stc/crandom.h> + #include <stc/crand.h> #define i_key int64_t #define i_tag ix @@ -38,7 +38,7 @@ { int n; for (int i = 0; i < 1000000; ++i) // one million - clist_ix_push_back(&list, crandom() >> 32); + clist_ix_push_back(&list, crand() >> 32); n = 0; c_foreach (i, clist_ix, list) if (++n % 10000 == 0) printf("%8d: %10zu\n", n, *i.ref); @@ -82,7 +82,7 @@ #endif #include "priv/template.h" -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_clist_types, _cx_self, i_key); #endif _cx_deftypes(_c_clist_complete_types, _cx_self, dummy); @@ -204,8 +204,8 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw val) { return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val).ref; } -STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y); +STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + _cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other); for (; i.ref && j.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) { const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref); if (!(i_eq((&_rx), (&_ry)))) return false; @@ -404,4 +404,4 @@ STC_DEF bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, co #endif // !c_no_cmp #endif // i_implement #define CLIST_H_INCLUDED -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/cmap.h b/include/stc/cmap.h index d9081ae0..9a503367 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -31,20 +31,20 @@ #include <stc/cmap.h> int main(void) { - c_with (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m)) - { - cmap_ichar_emplace(&m, 5, 'a'); - cmap_ichar_emplace(&m, 8, 'b'); - cmap_ichar_emplace(&m, 12, 'c'); - - cmap_ichar_value* v = cmap_ichar_get(&m, 10); // NULL - char val = *cmap_ichar_at(&m, 5); // 'a' - cmap_ichar_emplace_or_assign(&m, 5, 'd'); // update - cmap_ichar_erase(&m, 8); - - c_foreach (i, cmap_ichar, m) - printf("map %d: %c\n", i.ref->first, i.ref->second); - } + cmap_ichar m = {0}; + cmap_ichar_emplace(&m, 5, 'a'); + cmap_ichar_emplace(&m, 8, 'b'); + cmap_ichar_emplace(&m, 12, 'c'); + + cmap_ichar_value* v = cmap_ichar_get(&m, 10); // NULL + char val = *cmap_ichar_at(&m, 5); // 'a' + cmap_ichar_emplace_or_assign(&m, 5, 'd'); // update + cmap_ichar_erase(&m, 8); + + c_foreach (i, cmap_ichar, m) + printf("map %d: %c\n", i.ref->first, i.ref->second); + + cmap_ichar_drop(&m); } */ #include "ccommon.h" @@ -82,13 +82,7 @@ typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t; #define _i_size i_ssize #endif #include "priv/template.h" -#ifndef i_hash_functor - #define i_hash_functor(self, x) i_hash(x) -#endif -#ifndef i_eq_functor - #define i_eq_functor(self, x, y) i_eq(x, y) -#endif -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY); #endif @@ -283,11 +277,11 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* m1, const _cx_self* m2) { - if (_cx_memb(_size)(m1) != _cx_memb(_size)(m2)) return false; - for (_cx_iter i = _cx_memb(_begin)(m1); i.ref; _cx_memb(_next)(&i)) { +_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false; + for (_cx_iter i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i)) { const _cx_rawkey _raw = i_keyto(_i_keyref(i.ref)); - if (!_cx_memb(_contains)(m2, _raw)) return false; + if (!_cx_memb(_contains)(other, _raw)) return false; } return true; } @@ -371,14 +365,14 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { STC_DEF chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { - const uint64_t _hash = i_hash_functor(self, rkeyptr); + const uint64_t _hash = i_hash(rkeyptr); int64_t _cap = self->bucket_count; chash_bucket_t b = {c_PASTE(fastrange_,_i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; const uint8_t* _hx = self->_hashx; while (_hx[b.idx]) { if (_hx[b.idx] == b.hx) { const _cx_rawkey _raw = i_keyto(_i_keyref(self->table + b.idx)); - if (i_eq_functor(self, (&_raw), rkeyptr)) + if (i_eq((&_raw), rkeyptr)) break; } if (++b.idx == _cap) @@ -469,7 +463,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! _hashx[j]) break; const _cx_rawkey _raw = i_keyto(_i_keyref(_slot + j)); - k = (i_ssize)c_PASTE(fastrange_,_i_expandby)(i_hash_functor(self, (&_raw)), (uint64_t)_cap); + k = (i_ssize)c_PASTE(fastrange_,_i_expandby)(i_hash((&_raw)), (uint64_t)_cap); if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ _slot[i] = _slot[j], _hashx[i] = _hashx[j], i = j; } @@ -479,8 +473,6 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { #endif // i_implement #undef i_max_load_factor -#undef i_hash_functor -#undef i_eq_functor #undef _i_size #undef _i_isset #undef _i_ismap @@ -489,4 +481,4 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { #undef _i_MAP_ONLY #undef _i_SET_ONLY #define CMAP_H_INCLUDED -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 4955f2e0..b95b5020 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -32,10 +32,7 @@ #endif #include "priv/template.h" -#ifndef i_less_functor - #define i_less_functor(self, x, y) i_less(x, y) -#endif -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_cpque_types, _cx_self, i_key); #endif typedef i_keyraw _cx_raw; @@ -120,8 +117,8 @@ STC_DEF void _cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) { _cx_value t, *arr = self->data - 1; for (intptr_t r = idx, c = idx*2; c <= n; c *= 2) { - c += i_less_functor(self, (&arr[c]), (&arr[c + (c < n)])); - if (!(i_less_functor(self, (&arr[r]), (&arr[c])))) return; + c += i_less((&arr[c]), (&arr[c + (c < n)])); + if (!(i_less((&arr[r]), (&arr[c])))) return; t = arr[r], arr[r] = arr[c], arr[r = c] = t; } } @@ -156,12 +153,11 @@ _cx_memb(_push)(_cx_self* self, _cx_value value) { _cx_memb(_reserve)(self, self->_len*3/2 + 4); _cx_value *arr = self->data - 1; /* base 1 */ intptr_t c = ++self->_len; - for (; c > 1 && (i_less_functor(self, (&arr[c/2]), (&value))); c /= 2) + for (; c > 1 && (i_less((&arr[c/2]), (&value))); c /= 2) arr[c] = arr[c/2]; arr[c] = value; } #endif #define CPQUE_H_INCLUDED -#undef i_less_functor -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 67909f8e..1934305a 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -22,7 +22,7 @@ */ // STC queue /* -#include <stc/crandom.h> +#include <stc/crand.h> #include <stdio.h> #define i_key int @@ -30,19 +30,19 @@ int main() { int n = 10000000; - stc64_t rng = stc64_new(1234); - stc64_uniform_t dist = stc64_uniform_new(0, n); + crand_t rng = crand_init(1234); + crand_unif_t dist = crand_unif_init(0, n); c_auto (cqueue_int, Q) { // Push ten million random numbers onto the queue. for (int i=0; i<n; ++i) - cqueue_int_push(&Q, stc64_uniform(&rng, &dist)); + cqueue_int_push(&Q, crand_unif(&rng, &dist)); // Push or pop on the queue ten million times printf("before: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q)); for (int i=n; i>0; --i) { - int r = stc64_uniform(&rng, &dist); + int r = crand_unif(&rng, &dist); if (r & 1) ++n, cqueue_int_push(&Q, r); else diff --git a/include/stc/crand.h b/include/stc/crand.h new file mode 100644 index 00000000..a1b7250d --- /dev/null +++ b/include/stc/crand.h @@ -0,0 +1,174 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ccommon.h" + +#ifndef CRAND_H_INCLUDED +#define CRAND_H_INCLUDED +/* +// crand: Pseudo-random number generator +#include "stc/crand.h" + +int main() { + uint64_t seed = 123456789; + crand_t rng = crand_init(seed); + crand_unif_t dist1 = crand_unif_init(1, 6); + crand_norm_t dist3 = crand_norm_init(1.0, 10.0); + + uint64_t i = crand_u64(&rng); + int64_t iu = crand_unif(&rng, &dist1); + double xn = crand_norm(&rng, &dist3); +} +*/ +#include <string.h> +#include <math.h> + +typedef struct crand { uint64_t state[5]; } crand_t; +typedef struct crand_unif { int64_t lower; uint64_t range, threshold; } crand_unif_t; +typedef struct crand_norm { double mean, stddev, next; int has_next; } crand_norm_t; + +/* PRNG crand_t. + * Very fast PRNG suited for parallel usage with Weyl-sequence parameter. + * 320-bit state, 256 bit is mutable. + * Noticable faster than xoshiro and pcg, slighly slower than wyrand64 and + * Romu, but these have restricted capacity for larger parallel jobs or unknown minimum periods. + * crand_t supports 2^63 unique threads with a minimum 2^64 period lengths each. + * Passes all statistical tests, e.g PractRand and correlation tests, i.e. interleaved + * streams with one-bit diff state. Even the 16-bit version (LR=6, RS=5, LS=3) passes + * PractRand to multiple TB input. + */ + +/* Global crand_t PRNGs */ +STC_API void csrand(uint64_t seed); +STC_API uint64_t crand(void); +STC_API double crandf(void); + +/* Init crand_t prng with a seed */ +STC_API crand_t crand_init(uint64_t seed); + +/* Unbiased bounded uniform distribution. range [low, high] */ +STC_API crand_unif_t crand_unif_init(int64_t low, int64_t high); +STC_API int64_t crand_unif(crand_t* rng, crand_unif_t* dist); + +/* Normal/gaussian distribution. */ +STC_INLINE crand_norm_t crand_norm_init(double mean, double stddev) + { crand_norm_t r = {mean, stddev, 0.0, 0}; return r; } + +STC_API double crand_norm(crand_t* rng, crand_norm_t* dist); + +/* Main crand_t prng */ +STC_INLINE uint64_t crand_u64(crand_t* rng) { + uint64_t *s = rng->state; + const uint64_t result = (s[0] ^ (s[3] += s[4])) + s[1]; + s[0] = s[1] ^ (s[1] >> 11); + s[1] = s[2] + (s[2] << 3); + s[2] = ((s[2] << 24) | (s[2] >> (64 - 24))) + result; + return result; +} + +/* Float64 random number in range [0.0, 1.0). */ +STC_INLINE double crand_f64(crand_t* rng) { + union {uint64_t i; double f;} u = {0x3FF0000000000000U | (crand_u64(rng) >> 12)}; + return u.f - 1.0; +} + +/* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined(i_implement) + +/* Global random() */ +static crand_t crand_global = {{ + 0x26aa069ea2fb1a4d, 0x70c72c95cd592d04, + 0x504f333d3aa0b359, 0x9e3779b97f4a7c15, + 0x6a09e667a754166b +}}; + +STC_DEF void csrand(uint64_t seed) + { crand_global = crand_init(seed); } + +STC_DEF uint64_t crand(void) + { return crand_u64(&crand_global); } + +STC_DEF double crandf(void) + { return crand_f64(&crand_global); } + +STC_DEF crand_t crand_init(uint64_t seed) { + crand_t rng; uint64_t* s = rng.state; + s[0] = seed + 0x9e3779b97f4a7c15; + s[1] = (s[0] ^ (s[0] >> 30))*0xbf58476d1ce4e5b9; + s[2] = (s[1] ^ (s[1] >> 27))*0x94d049bb133111eb; + s[3] = (s[2] ^ (s[2] >> 31)); + s[4] = ((seed + 0x6aa069ea2fb1a4d) << 1) | 1; + return rng; +} + +/* Init unbiased uniform uint RNG with bounds [low, high] */ +STC_DEF crand_unif_t crand_unif_init(int64_t low, int64_t high) { + crand_unif_t dist = {low, (uint64_t) (high - low + 1)}; + dist.threshold = (uint64_t)(0 - dist.range) % dist.range; + return dist; +} + +#if defined(__SIZEOF_INT128__) + #define c_umul128(a, b, lo, hi) \ + do { __uint128_t _z = (__uint128_t)(a)*(b); \ + *(lo) = (uint64_t)_z, *(hi) = (uint64_t)(_z >> 64U); } while(0) +#elif defined(_MSC_VER) && defined(_WIN64) + #include <intrin.h> + #define c_umul128(a, b, lo, hi) ((void)(*(lo) = _umul128(a, b, hi))) +#elif defined(__x86_64__) + #define c_umul128(a, b, lo, hi) \ + asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b)) +#endif + +/* Int64 uniform distributed RNG, range [low, high]. */ +STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) { + uint64_t lo, hi; +#ifdef c_umul128 + do { c_umul128(crand_u64(rng), d->range, &lo, &hi); } while (lo < d->threshold); +#else + do { lo = crand_u64(rng); hi = lo % d->range; } while (lo - hi > -d->range); +#endif + return d->lower + (int64_t)hi; +} + +/* Normal distribution PRNG. Marsaglia polar method */ +STC_DEF double crand_norm(crand_t* rng, crand_norm_t* dist) { + double u1, u2, s, m; + if (dist->has_next++ & 1) + return dist->next*dist->stddev + dist->mean; + do { + u1 = 2.0 * crand_f64(rng) - 1.0; + u2 = 2.0 * crand_f64(rng) - 1.0; + s = u1*u1 + u2*u2; + } while (s >= 1.0 || s == 0.0); + m = sqrt(-2.0 * log(s) / s); + dist->next = u2*m; + return (u1*m)*dist->stddev + dist->mean; +} + +#endif +#endif +#undef i_opt +#undef i_static +#undef i_header +#undef i_implement +#undef i_extern diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 0f72ca2d..22607196 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -32,25 +32,22 @@ #include <stc/csmap.h> int main(void) { - c_with (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) - { - csmap_sx_emplace(&m, "Testing one", 1.234); - csmap_sx_emplace(&m, "Testing two", 12.34); - csmap_sx_emplace(&m, "Testing three", 123.4); - - csmap_sx_value *v = csmap_sx_get(&m, "Testing five"); // NULL - double num = *csmap_sx_at(&m, "Testing one"); - csmap_sx_emplace_or_assign(&m, "Testing three", 1000.0); // update - csmap_sx_erase(&m, "Testing two"); - - c_foreach (i, csmap_sx, m) - printf("map %s: %g\n", cstr_str(&i.ref->first), i.ref->second); - } + csmap_sx m = {0}; + csmap_sx_emplace(&m, "Testing one", 1.234); + csmap_sx_emplace(&m, "Testing two", 12.34); + csmap_sx_emplace(&m, "Testing three", 123.4); + + csmap_sx_value *v = csmap_sx_get(&m, "Testing five"); // NULL + double num = *csmap_sx_at(&m, "Testing one"); + csmap_sx_emplace_or_assign(&m, "Testing three", 1000.0); // update + csmap_sx_erase(&m, "Testing two"); + + c_foreach (i, csmap_sx, m) + printf("map %s: %g\n", cstr_str(&i.ref->first), i.ref->second); + + csmap_sx_drop(&m); } */ -#ifdef STC_CSMAP_V1 -#include "alt/csmap.h" -#else #include "ccommon.h" #ifndef CSMAP_H_INCLUDED @@ -80,10 +77,7 @@ int main(void) { #define _i_size i_ssize #endif #include "priv/template.h" -#ifndef i_cmp_functor - #define i_cmp_functor(self, x, y) i_cmp(x, y) -#endif -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY); #endif @@ -222,12 +216,12 @@ _cx_memb(_advance)(_cx_iter it, size_t n) { } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* m1, const _cx_self* m2) { - if (_cx_memb(_size)(m1) != _cx_memb(_size)(m2)) return false; - _cx_iter i = _cx_memb(_begin)(m1), j = _cx_memb(_begin)(m2); +_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false; + _cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other); for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) { const _cx_rawkey _rx = i_keyto(_i_keyref(i.ref)), _ry = i_keyto(_i_keyref(j.ref)); - if ((i_cmp_functor(m1, (&_rx), (&_ry))) != 0) return false; + if (!(i_eq((&_rx), (&_ry)))) return false; } return true; } @@ -357,7 +351,7 @@ _cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out) { out->_top = 0; while (tn) { int c; const _cx_rawkey _raw = i_keyto(_i_keyref(&d[tn].value)); - if ((c = i_cmp_functor(self, (&_raw), (&rkey))) < 0) + if ((c = i_cmp((&_raw), (&rkey))) < 0) tn = d[tn].link[1]; else if (c > 0) { out->_st[out->_top++] = tn; tn = d[tn].link[0]; } @@ -425,7 +419,7 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, i_ssize tn, const _cx_rawkey* rkey, _ while (tx) { up[top++] = tx; const _cx_rawkey _raw = i_keyto(_i_keyref(&d[tx].value)); - if (!(c = i_cmp_functor(self, (&_raw), rkey))) + if (!(c = i_cmp((&_raw), rkey))) { _res->ref = &d[tx].value; return tn; } dir = (c < 0); tx = d[tx].link[dir]; @@ -464,7 +458,7 @@ _cx_memb(_erase_r_)(_cx_self *self, i_ssize tn, const _cx_rawkey* rkey, int *era if (tn == 0) return 0; _cx_rawkey raw = i_keyto(_i_keyref(&d[tn].value)); - i_ssize tx; int c = i_cmp_functor(self, (&raw), rkey); + i_ssize tx; int c = i_cmp((&raw), rkey); if (c != 0) d[tn].link[c < 0] = _cx_memb(_erase_r_)(self, d[tn].link[c < 0], rkey, erased); else { @@ -594,7 +588,6 @@ _cx_memb(_drop)(_cx_self* self) { } #endif // i_implement -#undef i_cmp_functor #undef _i_size #undef _i_isset #undef _i_ismap @@ -602,5 +595,4 @@ _cx_memb(_drop)(_cx_self* self) { #undef _i_MAP_ONLY #undef _i_SET_ONLY #define CSMAP_H_INCLUDED -#include "priv/template.h" -#endif // !STC_CSMAP_V1 +#include "priv/template2.h" diff --git a/include/stc/cspan.h b/include/stc/cspan.h index d5482200..ac3e9206 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -48,10 +48,12 @@ int demo2() { puts(""); c_forfilter (i, Intspan, span, - c_flt_skipwhile(i, *i.ref < 25) && - (*i.ref & 1) == 0 && // even only - c_flt_take(i, 2)) // break after 2 + c_flt_skipwhile(i, *i.ref < 25) && + (*i.ref & 1) == 0 && // even only + c_flt_take(i, 2) // break after 2 + ){ printf(" %d", *i.ref); + } puts(""); } */ diff --git a/include/stc/cstack.h b/include/stc/cstack.h index f0c930e5..c2792358 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -33,7 +33,7 @@ #endif #include "priv/template.h" -#if !c_option(c_is_forward) +#ifndef i_is_forward #ifdef i_capacity #define i_no_clone _cx_deftypes(_c_cstack_fixed, _cx_self, i_key, i_capacity); @@ -189,4 +189,4 @@ STC_INLINE void _cx_memb(_next)(_cx_iter* it) STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) { if ((it.ref += n) >= it.end) it.ref = NULL ; return it; } -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 91cdb25c..a1aa74b2 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -39,7 +39,7 @@ struct MyStruct { #include <stc/cvec.h> #define i_key int -#define i_opt c_is_forward // forward declared +#define i_is_forward // forward declared #define i_tag i32 #include <stc/cvec.h> @@ -73,7 +73,7 @@ int main() { #endif #include "priv/template.h" -#if !c_option(c_is_forward) +#ifndef i_is_forward _cx_deftypes(_c_cvec_types, _cx_self, i_key); #endif typedef i_keyraw _cx_raw; @@ -234,11 +234,10 @@ _cx_memb(_get_mut)(const _cx_self* self, _cx_raw raw) { return (_cx_value*) _cx_memb(_get)(self, raw); } STC_INLINE bool -_cx_memb(_eq)(const _cx_self* x, const _cx_self* y) { - if (x->_len != y->_len) return false; - _cx_iter i = _cx_memb(_begin)(x), j = _cx_memb(_begin)(y); - for (; i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) { - const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref); +_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { + if (self->_len != other->_len) return false; + for (intptr_t i = 0; i < self->_len; ++i) { + const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i); if (!(i_eq((&_rx), (&_ry)))) return false; } return true; @@ -439,4 +438,4 @@ STC_DEF int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { #endif // !c_no_cmp #endif // i_implement #define CVEC_H_INCLUDED -#include "priv/template.h" +#include "priv/template2.h" diff --git a/include/stc/extend.h b/include/stc/extend.h new file mode 100644 index 00000000..66b3ebd1 --- /dev/null +++ b/include/stc/extend.h @@ -0,0 +1,66 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include <stc/ccommon.h> +#include <stc/forward.h> + +#ifdef i_key_str + #define _i_key cstr +#elif defined i_keyclass + #define _i_key i_keyclass +#elif defined i_keyboxed + #define _i_key i_keyboxed +#elif defined i_key + #define _i_key i_key +#endif + +#ifdef i_val_str + #define _i_val cstr +#elif defined i_valclass + #define _i_val i_valclass +#elif defined i_valboxed + #define _i_val i_valboxed +#elif defined i_val + #define _i_val i_val +#endif + +#ifdef _i_key + c_PASTE(forward_, i_con)(i_type, _i_key, _i_val); +#else + c_PASTE(forward_, i_con)(i_type, _i_val); +#endif + +typedef struct { + i_extend + i_type get; +} c_PASTE(i_type, _ext); + +#define c_getcon(cptr) c_container_of(cptr, _cx_memb(_ext), get) + +#define i_is_forward +#define _i_inc <stc/i_con.h> +#include _i_inc +#undef _i_inc +#undef _i_key +#undef _i_val +#undef i_con +#undef i_extend diff --git a/include/stc/priv/altnames.h b/include/stc/priv/altnames.h index 8fa326f1..723b6a66 100644 --- a/include/stc/priv/altnames.h +++ b/include/stc/priv/altnames.h @@ -32,6 +32,3 @@ #define c_WITH c_with #define c_SCOPE c_scope #define c_DEFER c_defer -#define c_NEW c_new -#define c_ARRAYLEN c_arraylen -#define c_ARGSV c_SV // [deprecated] diff --git a/include/stc/priv/raii.h b/include/stc/priv/raii.h new file mode 100644 index 00000000..bb41e0d1 --- /dev/null +++ b/include/stc/priv/raii.h @@ -0,0 +1,27 @@ +#define c_defer(...) \ + for (int _i = 1; _i; _i = 0, __VA_ARGS__) + +#define c_with(...) c_MACRO_OVERLOAD(c_with, __VA_ARGS__) +#define c_with_2(declvar, drop) \ + for (declvar, *_i, **_ip = &_i; _ip; _ip = 0, drop) +#define c_with_3(declvar, pred, drop) \ + for (declvar, *_i, **_ip = &_i; _ip && (pred); _ip = 0, drop) + +#define c_scope(...) c_MACRO_OVERLOAD(c_scope, __VA_ARGS__) +#define c_scope_2(init, drop) \ + for (int _i = (init, 1); _i; _i = 0, drop) +#define c_scope_3(init, pred, drop) \ + for (int _i = (init, 1); _i && (pred); _i = 0, drop) + +#define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) +#define c_auto_2(C, a) \ + c_with_2(C a = C##_init(), C##_drop(&a)) +#define c_auto_3(C, a, b) \ + c_with_2(c_EXPAND(C a = C##_init(), b = C##_init()), \ + (C##_drop(&b), C##_drop(&a))) +#define c_auto_4(C, a, b, c) \ + c_with_2(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init()), \ + (C##_drop(&c), C##_drop(&b), C##_drop(&a))) +#define c_auto_5(C, a, b, c, d) \ + c_with_2(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ + (C##_drop(&d), C##_drop(&c), C##_drop(&b), C##_drop(&a))) diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index e352f488..250a3dda 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -20,12 +20,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _i_template +#ifdef _i_template + #error template.h already included +#endif #define _i_template #ifndef STC_TEMPLATE_H_INCLUDED #define STC_TEMPLATE_H_INCLUDED - #define _cx_self c_PASTE(_i_prefix, i_tag) + #define _cx_self i_type #define _cx_memb(name) c_PASTE(_cx_self, name) #define _cx_deftypes(macro, SELF, ...) c_EXPAND(macro(SELF, __VA_ARGS__)) #define _cx_value _cx_memb(_value) @@ -38,10 +40,8 @@ #define _cx_node _cx_memb(_node) #endif -#ifdef i_type - #define i_tag i_type - #undef _i_prefix - #define _i_prefix +#ifndef i_type + #define i_type c_PASTE(_i_prefix, i_tag) #endif #ifndef i_ssize @@ -96,6 +96,9 @@ #endif #endif +#if c_option(c_is_forward) + #define i_is_forward +#endif #if c_option(c_no_cmp) #define i_no_cmp #endif @@ -289,62 +292,3 @@ #ifndef _i_has_from #define i_no_emplace #endif - -#else // ============================================================ - -#undef i_type -#undef i_tag -#undef i_imp -#undef i_opt -#undef i_less -#undef i_cmp -#undef i_eq -#undef i_hash -#undef i_rawclass -#undef i_capacity -#undef i_ssize - -#undef i_val -#undef i_val_str -#undef i_val_ssv -#undef i_valboxed -#undef i_valclass -#undef i_valraw -#undef i_valclone -#undef i_valfrom -#undef i_valto -#undef i_valdrop - -#undef i_key -#undef i_key_str -#undef i_key_ssv -#undef i_keyboxed -#undef i_keyclass -#undef i_keyraw -#undef i_keyclone -#undef i_keyfrom -#undef i_keyto -#undef i_keydrop - -#undef i_header -#undef i_implement -#undef i_static -#undef i_extern - -#undef i_allocator -#undef i_malloc -#undef i_calloc -#undef i_realloc -#undef i_free - -#undef i_no_cmp -#undef i_no_hash -#undef i_no_clone -#undef i_no_emplace - -#undef _i_prefix -#undef _i_expandby -#undef _i_has_from -#undef _i_has_eq -#undef _i_template -#endif diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h new file mode 100644 index 00000000..27c6a890 --- /dev/null +++ b/include/stc/priv/template2.h @@ -0,0 +1,78 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#undef i_type +#undef i_tag +#undef i_imp +#undef i_opt +#undef i_less +#undef i_cmp +#undef i_eq +#undef i_hash +#undef i_rawclass +#undef i_capacity +#undef i_ssize + +#undef i_val +#undef i_val_str +#undef i_val_ssv +#undef i_valboxed +#undef i_valclass +#undef i_valraw +#undef i_valclone +#undef i_valfrom +#undef i_valto +#undef i_valdrop + +#undef i_key +#undef i_key_str +#undef i_key_ssv +#undef i_keyboxed +#undef i_keyclass +#undef i_keyraw +#undef i_keyclone +#undef i_keyfrom +#undef i_keyto +#undef i_keydrop + +#undef i_header +#undef i_implement +#undef i_static +#undef i_extern + +#undef i_allocator +#undef i_malloc +#undef i_calloc +#undef i_realloc +#undef i_free + +#undef i_no_cmp +#undef i_no_hash +#undef i_no_clone +#undef i_no_emplace +#undef i_is_forward + +#undef _i_prefix +#undef _i_expandby +#undef _i_has_from +#undef _i_has_eq +#undef _i_template |
