summaryrefslogtreecommitdiffhomepage
path: root/include/stc
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-04-08 22:37:06 +0200
committerGitHub <[email protected]>2023-04-08 22:37:06 +0200
commit43120f2863a67db416ec3b379eb820e2704cafb7 (patch)
treef3b9917940f94c1582bc39ea6f56b735295ec861 /include/stc
parente8be14dfc894eeac859f0287d4d5b4f4745c0585 (diff)
parent6426ac05eb8c4dc1ab22aae2eb4139f9671981b7 (diff)
downloadSTC-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.h10
-rw-r--r--include/stc/algo/csort.h6
-rw-r--r--include/stc/algo/filter.h36
-rw-r--r--include/stc/carc.h20
-rw-r--r--include/stc/cbits.h40
-rw-r--r--include/stc/cbox.h20
-rw-r--r--include/stc/ccommon.h55
-rw-r--r--include/stc/cdeq.h13
-rw-r--r--include/stc/clist.h12
-rw-r--r--include/stc/cmap.h54
-rw-r--r--include/stc/cpque.h14
-rw-r--r--include/stc/cqueue.h10
-rw-r--r--include/stc/crand.h174
-rw-r--r--include/stc/csmap.h54
-rw-r--r--include/stc/cspan.h8
-rw-r--r--include/stc/cstack.h4
-rw-r--r--include/stc/cvec.h15
-rw-r--r--include/stc/extend.h66
-rw-r--r--include/stc/priv/altnames.h3
-rw-r--r--include/stc/priv/raii.h27
-rw-r--r--include/stc/priv/template.h74
-rw-r--r--include/stc/priv/template2.h78
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