From a913490c248f6cfdca3481d81d6d344f4d066cb9 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 18 Apr 2023 17:48:47 +0200 Subject: Removed unneeded custom size type in maps and bits.h. Prepared for possible robin-hood impl. Improved sso_bench.c testing string hash - twice as fast as m.ankeln robin impl !?. --- include/stc/cmap.h | 77 +++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 14782b71..cfed5540 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -73,17 +73,12 @@ typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t; #ifndef i_max_load_factor #define i_max_load_factor 0.85f #endif -#ifndef i_ssize - #define i_ssize int32_t - #define _i_size intptr_t - #define _i_expandby 1 -#else - #define _i_expandby 2 - #define _i_size i_ssize +#ifndef i_expandby + #define i_expandby 1 #endif #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, i_ssize, _i_MAP_ONLY, _i_SET_ONLY); + _cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); #endif _i_MAP_ONLY( struct _cx_value { @@ -98,25 +93,25 @@ typedef _i_SET_ONLY( i_keyraw ) i_valraw second; } ) _cx_raw; -STC_API _cx_self _cx_memb(_with_capacity)(_i_size cap); +STC_API _cx_self _cx_memb(_with_capacity)(intptr_t cap); #if !defined i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self map); #endif STC_API void _cx_memb(_drop)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, _i_size capacity); +STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t capacity); STC_API chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr); STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val); STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self map = {0}; return map; } -STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, self->size); } +STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, (intptr_t)self->size); } STC_INLINE float _cx_memb(_max_load_factor)(const _cx_self* self) { return (float)(i_max_load_factor); } STC_INLINE bool _cx_memb(_empty)(const _cx_self* map) { return !map->size; } -STC_INLINE _i_size _cx_memb(_size)(const _cx_self* map) { return map->size; } -STC_INLINE _i_size _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } -STC_INLINE _i_size _cx_memb(_capacity)(const _cx_self* map) - { return (_i_size)((float)map->bucket_count * (i_max_load_factor)); } +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* map) { return (intptr_t)map->size; } +STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket.count; } +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) + { return (intptr_t)((float)map->bucket.count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } @@ -197,7 +192,7 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { return _res; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, _i_size n) { +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { while (n--) #if defined _i_isset && defined i_no_emplace _cx_memb(_insert)(self, *raw++); @@ -210,11 +205,11 @@ STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, _i_size n) #endif } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, _i_size n) +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->table, self->table+self->bucket_count, self->_hashx}; + _cx_iter it = {self->table, self->table+self->bucket.count, self->_hashx}; if (it._hx) while (*it._hx == 0) ++it.ref, ++it._hx; @@ -243,7 +238,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) { int64_t idx; if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx]) return c_LITERAL(_cx_iter){self->table + idx, - self->table + self->bucket_count, + self->table + self->bucket.count, self->_hashx + idx}; return _cx_memb(_end)(self); } @@ -306,7 +301,7 @@ STC_INLINE uint64_t next_power_of_2(uint64_t n) { #endif // CMAP_H_INCLUDED STC_DEF _cx_self -_cx_memb(_with_capacity)(const _i_size cap) { +_cx_memb(_with_capacity)(const intptr_t cap) { _cx_self h = {0}; _cx_memb(_reserve)(&h, cap); return h; @@ -315,7 +310,7 @@ _cx_memb(_with_capacity)(const _i_size cap) { STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { if (self->size == 0) return; - _cx_value* e = self->table, *end = e + self->bucket_count; + _cx_value* e = self->table, *end = e + self->bucket.count; uint8_t *hx = self->_hashx; for (; e != end; ++e) if (*hx++) @@ -331,7 +326,7 @@ STC_DEF void _cx_memb(_drop)(_cx_self* self) { STC_DEF void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_wipe_)(self); self->size = 0; - c_memset(self->_hashx, 0, self->bucket_count); + c_memset(self->_hashx, 0, self->bucket.count); } #ifndef _i_isset @@ -366,8 +361,8 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { STC_DEF chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* 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)}; + 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) { @@ -384,8 +379,8 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { STC_DEF _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; - if (self->size + 2 > (i_ssize)((float)self->bucket_count * (i_max_load_factor))) - if (!_cx_memb(_reserve)(self, self->size*3/2)) + if (self->size + 2 > (intptr_t)((float)self->bucket.count * (i_max_load_factor))) + if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2))) return res; chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); @@ -401,11 +396,11 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { STC_DEF _cx_self _cx_memb(_clone)(_cx_self m) { if (m.table) { - _cx_value *t = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket_count), - *dst = t, *m_end = m.table + m.bucket_count; - uint8_t *h = (uint8_t *)c_memcpy(i_malloc(m.bucket_count + 1), m._hashx, m.bucket_count + 1); + _cx_value *t = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket.count), + *dst = t, *m_end = m.table + m.bucket.count; + uint8_t *h = (uint8_t *)c_memcpy(i_malloc(m.bucket.count + 1), m._hashx, m.bucket.count + 1); if (!(t && h)) - { i_free(t), i_free(h), t = 0, h = 0, m.bucket_count = 0; } + { i_free(t), i_free(h), t = 0, h = 0, m.bucket.count = 0; } else for (; m.table != m_end; ++m.table, ++m._hashx, ++dst) if (*m._hashx) @@ -417,27 +412,27 @@ _cx_memb(_clone)(_cx_self m) { #endif STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const _i_size newcap) { - const i_ssize _oldbuckets = self->bucket_count, _newcap = (i_ssize)newcap; +_cx_memb(_reserve)(_cx_self* self, const intptr_t newcap) { + const intptr_t _oldbuckets = self->bucket.count, _newcap = newcap; if (_newcap != self->size && _newcap <= _oldbuckets) return true; - i_ssize _nbuckets = (i_ssize)((float)_newcap / (i_max_load_factor)) + 4; - #if _i_expandby == 2 - _nbuckets = (i_ssize)next_power_of_2(_nbuckets); + uintptr_t _nbuckets = (uintptr_t)((float)_newcap / (i_max_load_factor)) + 4; + #if i_expandby == 2 + _nbuckets = (intptr_t)next_power_of_2(_nbuckets); #else _nbuckets |= 1; #endif _cx_self m = { (_cx_value *)i_malloc(c_sizeof(_cx_value)*_nbuckets), (uint8_t *)i_calloc(_nbuckets + 1, 1), - self->size, _nbuckets, + self->size, {_nbuckets & ((1ULL << 48) - 1)} }; bool ok = m.table && m._hashx; if (ok) { /* Rehash: */ m._hashx[_nbuckets] = 0xff; const _cx_value* e = self->table; const uint8_t* h = self->_hashx; - for (i_ssize i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { + for (intptr_t i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { _cx_keyraw r = i_keyto(_i_keyref(e)); chash_bucket_t b = _cx_memb(_bucket_)(&m, &r); m.table[b.idx] = *e; @@ -452,8 +447,8 @@ _cx_memb(_reserve)(_cx_self* self, const _i_size newcap) { STC_DEF void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { - i_ssize i = (i_ssize)(_val - self->table), j = i, k; - const i_ssize _cap = self->bucket_count; + intptr_t i = (intptr_t)(_val - self->table), j = i, k; + const intptr_t _cap = self->bucket.count; _cx_value* _slot = self->table; uint8_t* _hashx = self->_hashx; _cx_memb(_value_drop)(_val); @@ -463,7 +458,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! _hashx[j]) break; const _cx_keyraw _raw = i_keyto(_i_keyref(_slot + j)); - k = (i_ssize)c_PASTE(fastrange_,_i_expandby)(i_hash((&_raw)), (uint64_t)_cap); + k = (intptr_t)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; } @@ -473,7 +468,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { #endif // i_implement #undef i_max_load_factor -#undef _i_size +#undef i_expandby #undef _i_isset #undef _i_ismap #undef _i_ishash -- cgit v1.2.3 From 25679f9af707818df02a71ef7c996b2a806dae28 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 19 Apr 2023 20:25:32 +0200 Subject: Internal refactoring in cmap. Should be easy to convert to robinhood hash from here. --- include/stc/cmap.h | 140 +++++++++++++++++++++++++------------------------- include/stc/forward.h | 6 +-- 2 files changed, 74 insertions(+), 72 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index cfed5540..4b970c86 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -53,7 +53,8 @@ int main(void) { #include "forward.h" #include #include -typedef struct { int64_t idx; uint8_t hx; } chash_bucket_t; +typedef struct { int64_t idx; uint8_t hashx; } chash_bucket; +typedef struct chash_slot { uint8_t hashx/*, psl*/; } chash_slot; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -100,7 +101,7 @@ STC_API _cx_self _cx_memb(_clone)(_cx_self map); STC_API void _cx_memb(_drop)(_cx_self* self); STC_API void _cx_memb(_clear)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t capacity); -STC_API chash_bucket_t _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr); +STC_API chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr); STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val); @@ -113,7 +114,7 @@ STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->buc STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) { return (intptr_t)((float)map->bucket.count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) - { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } + { return self->size && self->slot[_cx_memb(_bucket_)(self, &rkey).idx].hashx; } #ifndef _i_isset STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); @@ -123,9 +124,9 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rke STC_INLINE const _cx_mapped* _cx_memb(_at)(const _cx_self* self, _cx_keyraw rkey) { - chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); - assert(self->_hashx[b.idx]); - return &self->table[b.idx].second; + chash_bucket b = _cx_memb(_bucket_)(self, &rkey); + assert(self->slot[b.idx].hashx); + return &self->data[b.idx].second; } STC_INLINE _cx_mapped* _cx_memb(_at_mut)(_cx_self* self, _cx_keyraw rkey) @@ -134,7 +135,7 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rke #if !defined i_no_clone STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { - if (self->table == other->table) + if (self->data == other->data) return; _cx_memb(_drop)(self); *self = _cx_memb(_clone)(*other); @@ -209,10 +210,10 @@ STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->table, self->table+self->bucket.count, self->_hashx}; - if (it._hx) - while (*it._hx == 0) - ++it.ref, ++it._hx; + _cx_iter it = {self->data, self->data+self->bucket.count, self->slot}; + if (it.spos) + while (it.spos->hashx == 0) + ++it.ref, ++it.spos; if (it.ref == it._end) it.ref = NULL; return it; } @@ -223,7 +224,7 @@ _cx_memb(_end)(const _cx_self* self) STC_INLINE void _cx_memb(_next)(_cx_iter* it) { - while ((++it->ref, *++it->_hx == 0)) ; + while ((++it->ref, (++it->spos)->hashx == 0)) ; if (it->ref == it->_end) it->ref = NULL; } @@ -236,18 +237,18 @@ _cx_memb(_advance)(_cx_iter it, size_t n) { STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) { int64_t idx; - if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx]) - return c_LITERAL(_cx_iter){self->table + idx, - self->table + self->bucket.count, - self->_hashx + idx}; + if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) + return c_LITERAL(_cx_iter){self->data + idx, + self->data + self->bucket.count, + self->slot + idx}; return _cx_memb(_end)(self); } STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) { int64_t idx; - if (self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx]) - return self->table + idx; + if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) + return self->data + idx; return NULL; } @@ -259,14 +260,14 @@ STC_INLINE int _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { if (self->size == 0) return 0; - chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); - return self->_hashx[b.idx] ? _cx_memb(_erase_entry)(self, self->table + b.idx), 1 : 0; + chash_bucket b = _cx_memb(_bucket_)(self, &rkey); + return self->slot[b.idx].hashx ? _cx_memb(_erase_entry)(self, self->data + b.idx), 1 : 0; } STC_INLINE _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { _cx_memb(_erase_entry)(self, it.ref); - if (*it._hx == 0) + if (it.spos->hashx == 0) _cx_memb(_next)(&it); return it; } @@ -310,23 +311,23 @@ _cx_memb(_with_capacity)(const intptr_t cap) { STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { if (self->size == 0) return; - _cx_value* e = self->table, *end = e + self->bucket.count; - uint8_t *hx = self->_hashx; - for (; e != end; ++e) - if (*hx++) - _cx_memb(_value_drop)(e); + _cx_value* d = self->data, *_end = d + self->bucket.count; + chash_slot *_slot = self->slot; + for (; d != _end; ++d) + if ((_slot++)->hashx) + _cx_memb(_value_drop)(d); } STC_DEF void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_wipe_)(self); - i_free(self->_hashx); - i_free((void *) self->table); + i_free(self->slot); + i_free(self->data); } STC_DEF void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_wipe_)(self); self->size = 0; - c_memset(self->_hashx, 0, self->bucket.count); + c_memset(self->slot, 0, sizeof(chash_slot)*self->bucket.count); } #ifndef _i_isset @@ -358,15 +359,15 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { #endif // !i_no_emplace #endif // !_i_isset -STC_DEF chash_bucket_t +STC_DEF chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* 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_keyraw _raw = i_keyto(_i_keyref(self->table + b.idx)); + chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; + const chash_slot* _slot = self->slot; + while (_slot[b.idx].hashx) { + if (_slot[b.idx].hashx == b.hashx) { + const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + b.idx)); if (i_eq((&_raw), rkeyptr)) break; } @@ -383,10 +384,10 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2))) return res; - chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); - res.ref = &self->table[b.idx]; - if ((res.inserted = !self->_hashx[b.idx])) { - self->_hashx[b.idx] = b.hx; + chash_bucket b = _cx_memb(_bucket_)(self, &rkey); + res.ref = &self->data[b.idx]; + if ((res.inserted = !self->slot[b.idx].hashx)) { + self->slot[b.idx].hashx = b.hashx; ++self->size; } return res; @@ -395,17 +396,18 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { #if !defined i_no_clone STC_DEF _cx_self _cx_memb(_clone)(_cx_self m) { - if (m.table) { - _cx_value *t = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket.count), - *dst = t, *m_end = m.table + m.bucket.count; - uint8_t *h = (uint8_t *)c_memcpy(i_malloc(m.bucket.count + 1), m._hashx, m.bucket.count + 1); - if (!(t && h)) - { i_free(t), i_free(h), t = 0, h = 0, m.bucket.count = 0; } + if (m.data) { + _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket.count), + *_dst = d, *_end = m.data + m.bucket.count; + const intptr_t _mem = c_sizeof(chash_slot)*(m.bucket.count + 1); + chash_slot *_slot = (chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); + if (!(d && _slot)) + { i_free(d), i_free(_slot), d = 0, _slot = 0, m.bucket.count = 0; } else - for (; m.table != m_end; ++m.table, ++m._hashx, ++dst) - if (*m._hashx) - *dst = _cx_memb(_value_clone)(*m.table); - m.table = t, m._hashx = h; + for (; m.data != _end; ++m.data, ++m.slot, ++_dst) + if (m.slot->hashx) + *_dst = _cx_memb(_value_clone)(*m.data); + m.data = d, m.slot = _slot; } return m; } @@ -424,45 +426,45 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t newcap) { #endif _cx_self m = { (_cx_value *)i_malloc(c_sizeof(_cx_value)*_nbuckets), - (uint8_t *)i_calloc(_nbuckets + 1, 1), + (chash_slot *)i_calloc(_nbuckets + 1, sizeof(chash_slot)), self->size, {_nbuckets & ((1ULL << 48) - 1)} }; - bool ok = m.table && m._hashx; - if (ok) { /* Rehash: */ - m._hashx[_nbuckets] = 0xff; - const _cx_value* e = self->table; - const uint8_t* h = self->_hashx; - for (intptr_t i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { - _cx_keyraw r = i_keyto(_i_keyref(e)); - chash_bucket_t b = _cx_memb(_bucket_)(&m, &r); - m.table[b.idx] = *e; - m._hashx[b.idx] = b.hx; + bool ok = m.data && m.slot; + if (ok) { // Rehash: + m.slot[_nbuckets].hashx = 0xff; + const _cx_value* d = self->data; + const chash_slot* _slot = self->slot; + for (intptr_t i = 0; i < _oldbuckets; ++i, ++d) if ((_slot++)->hashx) { + _cx_keyraw r = i_keyto(_i_keyref(d)); + chash_bucket b = _cx_memb(_bucket_)(&m, &r); + m.data[b.idx] = *d; // move + m.slot[b.idx].hashx = b.hashx; } c_swap(_cx_self, self, &m); } - i_free(m._hashx); - i_free(m.table); + i_free(m.slot); + i_free(m.data); return ok; } STC_DEF void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { - intptr_t i = (intptr_t)(_val - self->table), j = i, k; + _cx_value* d = self->data; + chash_slot* _slot = self->slot; + intptr_t i = (intptr_t)(_val - d), j = i, k; const intptr_t _cap = self->bucket.count; - _cx_value* _slot = self->table; - uint8_t* _hashx = self->_hashx; _cx_memb(_value_drop)(_val); for (;;) { /* delete without leaving tombstone */ if (++j == _cap) j = 0; - if (! _hashx[j]) + if (! _slot[j].hashx) break; - const _cx_keyraw _raw = i_keyto(_i_keyref(_slot + j)); + const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); k = (intptr_t)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; + d[i] = d[j], _slot[i] = _slot[j], i = j; } - _hashx[i] = 0; + _slot[i].hashx = 0; --self->size; } diff --git a/include/stc/forward.h b/include/stc/forward.h index e543b94a..e79be580 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -116,12 +116,12 @@ typedef union { \ typedef struct { \ SELF##_value *ref, *_end; \ - uint8_t* _hx; \ + struct chash_slot* spos; \ } SELF##_iter; \ \ typedef struct SELF { \ - SELF##_value* table; \ - uint8_t* _hashx; \ + SELF##_value* data; \ + struct chash_slot* slot; \ intptr_t size; \ struct { uint64_t count: 48, maxdist: 16; } bucket; \ } SELF -- cgit v1.2.3 From 119de13b8506e5f13d7b4d5ba3edbd394b6f3218 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 20 Apr 2023 09:31:57 +0200 Subject: Minor internal cmap updates. --- include/stc/cmap.h | 61 +++++++++++++++++++++++++-------------------------- include/stc/forward.h | 8 ++++--- 2 files changed, 35 insertions(+), 34 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 4b970c86..e5a810a9 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -54,7 +54,6 @@ int main(void) { #include #include typedef struct { int64_t idx; uint8_t hashx; } chash_bucket; -typedef struct chash_slot { uint8_t hashx/*, psl*/; } chash_slot; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -211,9 +210,9 @@ STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { _cx_iter it = {self->data, self->data+self->bucket.count, self->slot}; - if (it.spos) - while (it.spos->hashx == 0) - ++it.ref, ++it.spos; + if (it.sref) + while (it.sref->hashx == 0) + ++it.ref, ++it.sref; if (it.ref == it._end) it.ref = NULL; return it; } @@ -224,7 +223,7 @@ _cx_memb(_end)(const _cx_self* self) STC_INLINE void _cx_memb(_next)(_cx_iter* it) { - while ((++it->ref, (++it->spos)->hashx == 0)) ; + while ((++it->ref, (++it->sref)->hashx == 0)) ; if (it->ref == it->_end) it->ref = NULL; } @@ -267,7 +266,7 @@ _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { STC_INLINE _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { _cx_memb(_erase_entry)(self, it.ref); - if (it.spos->hashx == 0) + if (it.sref->hashx == 0) _cx_memb(_next)(&it); return it; } @@ -312,9 +311,9 @@ STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { if (self->size == 0) return; _cx_value* d = self->data, *_end = d + self->bucket.count; - chash_slot *_slot = self->slot; + chash_slot* s = self->slot; for (; d != _end; ++d) - if ((_slot++)->hashx) + if ((s++)->hashx) _cx_memb(_value_drop)(d); } @@ -364,9 +363,9 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); int64_t _cap = self->bucket.count; chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; - const chash_slot* _slot = self->slot; - while (_slot[b.idx].hashx) { - if (_slot[b.idx].hashx == b.hashx) { + const chash_slot* s = self->slot; + while (s[b.idx].hashx) { + if (s[b.idx].hashx == b.hashx) { const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + b.idx)); if (i_eq((&_raw), rkeyptr)) break; @@ -400,41 +399,41 @@ _cx_memb(_clone)(_cx_self m) { _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket.count), *_dst = d, *_end = m.data + m.bucket.count; const intptr_t _mem = c_sizeof(chash_slot)*(m.bucket.count + 1); - chash_slot *_slot = (chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); - if (!(d && _slot)) - { i_free(d), i_free(_slot), d = 0, _slot = 0, m.bucket.count = 0; } + chash_slot *s = (chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); + if (!(d && s)) + { i_free(d), i_free(s), d = 0, s = 0, m.bucket.count = 0; } else for (; m.data != _end; ++m.data, ++m.slot, ++_dst) if (m.slot->hashx) *_dst = _cx_memb(_value_clone)(*m.data); - m.data = d, m.slot = _slot; + m.data = d, m.slot = s; } return m; } #endif STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t newcap) { - const intptr_t _oldbuckets = self->bucket.count, _newcap = newcap; - if (_newcap != self->size && _newcap <= _oldbuckets) +_cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { + const intptr_t _oldbucks = self->bucket.count; + if (_newcap != self->size && _newcap <= _oldbucks) return true; - uintptr_t _nbuckets = (uintptr_t)((float)_newcap / (i_max_load_factor)) + 4; + uintptr_t _newbucks = (uintptr_t)((float)_newcap / (i_max_load_factor)) + 4; #if i_expandby == 2 - _nbuckets = (intptr_t)next_power_of_2(_nbuckets); + _newbucks = (intptr_t)next_power_of_2(_newbucks); #else - _nbuckets |= 1; + _newbucks |= 1; #endif _cx_self m = { - (_cx_value *)i_malloc(c_sizeof(_cx_value)*_nbuckets), - (chash_slot *)i_calloc(_nbuckets + 1, sizeof(chash_slot)), - self->size, {_nbuckets & ((1ULL << 48) - 1)} + (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), + (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), + self->size, {_newbucks & ((1ULL << 48) - 1)} }; bool ok = m.data && m.slot; if (ok) { // Rehash: - m.slot[_nbuckets].hashx = 0xff; + m.slot[_newbucks].hashx = 0xff; const _cx_value* d = self->data; - const chash_slot* _slot = self->slot; - for (intptr_t i = 0; i < _oldbuckets; ++i, ++d) if ((_slot++)->hashx) { + const chash_slot* s = self->slot; + for (intptr_t i = 0; i < _oldbucks; ++i, ++d) if ((s++)->hashx) { _cx_keyraw r = i_keyto(_i_keyref(d)); chash_bucket b = _cx_memb(_bucket_)(&m, &r); m.data[b.idx] = *d; // move @@ -450,21 +449,21 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t newcap) { STC_DEF void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { _cx_value* d = self->data; - chash_slot* _slot = self->slot; + chash_slot* s = self->slot; intptr_t i = (intptr_t)(_val - d), j = i, k; const intptr_t _cap = self->bucket.count; _cx_memb(_value_drop)(_val); for (;;) { /* delete without leaving tombstone */ if (++j == _cap) j = 0; - if (! _slot[j].hashx) + if (! s[j].hashx) break; const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); k = (intptr_t)c_PASTE(fastrange_,i_expandby)(i_hash((&_raw)), (uint64_t)_cap); if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ - d[i] = d[j], _slot[i] = _slot[j], i = j; + d[i] = d[j], s[i] = s[j], i = j; } - _slot[i].hashx = 0; + s[i].hashx = 0; --self->size; } diff --git a/include/stc/forward.h b/include/stc/forward.h index e79be580..78ec23a2 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -101,6 +101,8 @@ typedef union { SELF##_node *last; \ } SELF +typedef struct { uint8_t hashx/*, psl*/; } chash_slot; + #define _c_chash_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ typedef VAL SELF##_mapped; \ @@ -116,14 +118,14 @@ typedef union { \ typedef struct { \ SELF##_value *ref, *_end; \ - struct chash_slot* spos; \ + chash_slot* sref; \ } SELF##_iter; \ \ typedef struct SELF { \ SELF##_value* data; \ - struct chash_slot* slot; \ + chash_slot* slot; \ intptr_t size; \ - struct { uint64_t count: 48, maxdist: 16; } bucket; \ + struct { uint64_t count: 48, maxpsl: 16; } bucket; \ } SELF #define _c_aatree_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ -- cgit v1.2.3 From 4375640bdf856866fa2a1e7010103736077b9738 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 20 Apr 2023 21:33:49 +0200 Subject: cmap Updates to dev43 standard. --- include/stc/cmap.h | 38 +++++++++++++++++------------------ include/stc/forward.h | 5 ++--- misc/benchmarks/shootout_hashmaps.cpp | 6 +++--- 3 files changed, 24 insertions(+), 25 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index e5a810a9..d0ad7886 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -53,7 +53,7 @@ int main(void) { #include "forward.h" #include #include -typedef struct { int64_t idx; uint8_t hashx; } chash_bucket; +typedef struct { intptr_t idx; uint8_t hashx; } chash_bucket; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -109,9 +109,9 @@ STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_res STC_INLINE float _cx_memb(_max_load_factor)(const _cx_self* self) { return (float)(i_max_load_factor); } STC_INLINE bool _cx_memb(_empty)(const _cx_self* map) { return !map->size; } STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* map) { return (intptr_t)map->size; } -STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket.count; } +STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) - { return (intptr_t)((float)map->bucket.count * (i_max_load_factor)); } + { return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) { return self->size && self->slot[_cx_memb(_bucket_)(self, &rkey).idx].hashx; } @@ -209,7 +209,7 @@ STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->data, self->data+self->bucket.count, self->slot}; + _cx_iter it = {self->data, self->data+self->bucket_count, self->slot}; if (it.sref) while (it.sref->hashx == 0) ++it.ref, ++it.sref; @@ -235,17 +235,17 @@ _cx_memb(_advance)(_cx_iter it, size_t n) { STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) { - int64_t idx; + intptr_t idx; if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) return c_LITERAL(_cx_iter){self->data + idx, - self->data + self->bucket.count, + self->data + self->bucket_count, self->slot + idx}; return _cx_memb(_end)(self); } STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) { - int64_t idx; + intptr_t idx; if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) return self->data + idx; return NULL; @@ -310,7 +310,7 @@ _cx_memb(_with_capacity)(const intptr_t cap) { STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { if (self->size == 0) return; - _cx_value* d = self->data, *_end = d + self->bucket.count; + _cx_value* d = self->data, *_end = d + self->bucket_count; chash_slot* s = self->slot; for (; d != _end; ++d) if ((s++)->hashx) @@ -326,7 +326,7 @@ STC_DEF void _cx_memb(_drop)(_cx_self* self) { STC_DEF void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_wipe_)(self); self->size = 0; - c_memset(self->slot, 0, sizeof(chash_slot)*self->bucket.count); + c_memset(self->slot, 0, c_sizeof(chash_slot)*self->bucket_count); } #ifndef _i_isset @@ -361,7 +361,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { STC_DEF chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); - int64_t _cap = self->bucket.count; + intptr_t _cap = self->bucket_count; chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; const chash_slot* s = self->slot; while (s[b.idx].hashx) { @@ -379,7 +379,7 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { STC_DEF _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; - if (self->size + 2 > (intptr_t)((float)self->bucket.count * (i_max_load_factor))) + if (self->size + 2 > (intptr_t)((float)self->bucket_count * (i_max_load_factor))) if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2))) return res; @@ -396,12 +396,12 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { STC_DEF _cx_self _cx_memb(_clone)(_cx_self m) { if (m.data) { - _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket.count), - *_dst = d, *_end = m.data + m.bucket.count; - const intptr_t _mem = c_sizeof(chash_slot)*(m.bucket.count + 1); + _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket_count), + *_dst = d, *_end = m.data + m.bucket_count; + const intptr_t _mem = c_sizeof(chash_slot)*(m.bucket_count + 1); chash_slot *s = (chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); if (!(d && s)) - { i_free(d), i_free(s), d = 0, s = 0, m.bucket.count = 0; } + { i_free(d), i_free(s), d = 0, s = 0, m.bucket_count = 0; } else for (; m.data != _end; ++m.data, ++m.slot, ++_dst) if (m.slot->hashx) @@ -414,10 +414,10 @@ _cx_memb(_clone)(_cx_self m) { STC_DEF bool _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { - const intptr_t _oldbucks = self->bucket.count; + const intptr_t _oldbucks = self->bucket_count; if (_newcap != self->size && _newcap <= _oldbucks) return true; - uintptr_t _newbucks = (uintptr_t)((float)_newcap / (i_max_load_factor)) + 4; + intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; #if i_expandby == 2 _newbucks = (intptr_t)next_power_of_2(_newbucks); #else @@ -426,7 +426,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), - self->size, {_newbucks & ((1ULL << 48) - 1)} + self->size, _newbucks }; bool ok = m.data && m.slot; if (ok) { // Rehash: @@ -451,7 +451,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { _cx_value* d = self->data; chash_slot* s = self->slot; intptr_t i = (intptr_t)(_val - d), j = i, k; - const intptr_t _cap = self->bucket.count; + const intptr_t _cap = self->bucket_count; _cx_memb(_value_drop)(_val); for (;;) { /* delete without leaving tombstone */ if (++j == _cap) diff --git a/include/stc/forward.h b/include/stc/forward.h index 78ec23a2..ae49dc31 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -101,7 +101,7 @@ typedef union { SELF##_node *last; \ } SELF -typedef struct { uint8_t hashx/*, psl*/; } chash_slot; +typedef struct { uint8_t hashx; } chash_slot; #define _c_chash_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ @@ -124,8 +124,7 @@ typedef struct { uint8_t hashx/*, psl*/; } chash_slot; typedef struct SELF { \ SELF##_value* data; \ chash_slot* slot; \ - intptr_t size; \ - struct { uint64_t count: 48, maxpsl: 16; } bucket; \ + intptr_t size, bucket_count; \ } SELF #define _c_aatree_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp index 05ec33e7..886bb345 100644 --- a/misc/benchmarks/shootout_hashmaps.cpp +++ b/misc/benchmarks/shootout_hashmaps.cpp @@ -2,7 +2,7 @@ #include #include -#define MAX_LOAD_FACTOR 85 +#define MAX_LOAD_FACTOR 80 #ifdef __cplusplus #include @@ -335,8 +335,8 @@ int main(int argc, char* argv[]) printf("\nT1: Insert %g mill. random keys range [0, 2^%u): map[rnd] = i;\n", N1/1000000.0, keybits); RUN_TEST(1) - //printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0); - //RUN_TEST(2) + printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0); + RUN_TEST(2) printf("\nT3: Erase all elements by lookup (%u mill. random inserts), key range [0, 2^%u)\n", n_mill*2, keybits); RUN_TEST(3) -- cgit v1.2.3 From feea8547482d8822a288977201e08eded1551e59 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 21 Apr 2023 14:41:47 +0200 Subject: Householding. --- include/stc/ccommon.h | 11 ++++++ include/stc/cmap.h | 67 +++++++++++++++-------------------- include/stc/crand.h | 13 ------- misc/benchmarks/shootout_hashmaps.cpp | 6 ++-- 4 files changed, 43 insertions(+), 54 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 0735e855..2453143c 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -216,6 +216,17 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, #define c_drop(C, ...) \ do { c_forlist (_i, C*, {__VA_ARGS__}) C##_drop(*_i.ref); } while(0) +#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 + #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 #endif // CCOMMON_H_INCLUDED #undef STC_API diff --git a/include/stc/cmap.h b/include/stc/cmap.h index d0ad7886..3fea78f0 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -53,7 +53,7 @@ int main(void) { #include "forward.h" #include #include -typedef struct { intptr_t idx; uint8_t hashx; } chash_bucket; +typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -71,10 +71,10 @@ typedef struct { intptr_t idx; uint8_t hashx; } chash_bucket; #endif #define _i_ishash #ifndef i_max_load_factor - #define i_max_load_factor 0.85f + #define i_max_load_factor 0.82f #endif -#ifndef i_expandby - #define i_expandby 1 +#ifndef i_sizebits + #define i_sizebits 32 #endif #include "priv/template.h" #ifndef i_is_forward @@ -113,7 +113,7 @@ STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->buc STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) { return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) - { return self->size && self->slot[_cx_memb(_bucket_)(self, &rkey).idx].hashx; } + { return _cx_memb(_bucket_)(self, &rkey).found; } #ifndef _i_isset STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); @@ -124,7 +124,7 @@ STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rke STC_INLINE const _cx_mapped* _cx_memb(_at)(const _cx_self* self, _cx_keyraw rkey) { chash_bucket b = _cx_memb(_bucket_)(self, &rkey); - assert(self->slot[b.idx].hashx); + assert(b.found); return &self->data[b.idx].second; } STC_INLINE _cx_mapped* @@ -235,19 +235,19 @@ _cx_memb(_advance)(_cx_iter it, size_t n) { STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) { - intptr_t idx; - if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) - return c_LITERAL(_cx_iter){self->data + idx, + chash_bucket b; + if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) + return c_LITERAL(_cx_iter){self->data + b.idx, self->data + self->bucket_count, - self->slot + idx}; + self->slot + b.idx}; return _cx_memb(_end)(self); } STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) { - intptr_t idx; - if (self->size && self->slot[idx = _cx_memb(_bucket_)(self, &rkey).idx].hashx) - return self->data + idx; + chash_bucket b; + if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) + return self->data + b.idx; return NULL; } @@ -257,10 +257,10 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_keyraw rkey) STC_INLINE int _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { - if (self->size == 0) - return 0; - chash_bucket b = _cx_memb(_bucket_)(self, &rkey); - return self->slot[b.idx].hashx ? _cx_memb(_erase_entry)(self, self->data + b.idx), 1 : 0; + chash_bucket b = {0}; + if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) + _cx_memb(_erase_entry)(self, self->data + b.idx); + return b.found; } STC_INLINE _cx_iter @@ -285,18 +285,12 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #if defined(i_implement) #ifndef CMAP_H_INCLUDED -STC_INLINE int64_t fastrange_1(uint64_t x, uint64_t n) - { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^32 - -STC_INLINE int64_t fastrange_2(uint64_t x, uint64_t n) - { return (int64_t)(x & (n - 1)); } // n power of 2. - -STC_INLINE uint64_t next_power_of_2(uint64_t n) { - n--; - n |= n >> 1, n |= n >> 2; - n |= n >> 4, n |= n >> 8; - n |= n >> 16, n |= n >> 32; - return n + 1; +STC_INLINE int64_t fastrange_32(uint64_t x, uint64_t n) + { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^31 + +STC_INLINE int64_t fastrange_64(uint64_t x, uint64_t n) { + uint64_t lo, hi; c_umul128(x, n, &lo, &hi); + return (int64_t)hi; } #endif // CMAP_H_INCLUDED @@ -362,13 +356,13 @@ STC_DEF chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); intptr_t _cap = self->bucket_count; - chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; + chash_bucket b = {c_PASTE(fastrange_,i_sizebits)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; const chash_slot* s = self->slot; while (s[b.idx].hashx) { if (s[b.idx].hashx == b.hashx) { const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + b.idx)); if (i_eq((&_raw), rkeyptr)) - break; + {b.found = true; break;} } if (++b.idx == _cap) b.idx = 0; @@ -385,7 +379,8 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { chash_bucket b = _cx_memb(_bucket_)(self, &rkey); res.ref = &self->data[b.idx]; - if ((res.inserted = !self->slot[b.idx].hashx)) { + if (!b.found) { + res.inserted = true; self->slot[b.idx].hashx = b.hashx; ++self->size; } @@ -418,11 +413,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { if (_newcap != self->size && _newcap <= _oldbucks) return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; - #if i_expandby == 2 - _newbucks = (intptr_t)next_power_of_2(_newbucks); - #else _newbucks |= 1; - #endif _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), @@ -459,7 +450,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! s[j].hashx) break; const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); - k = (intptr_t)c_PASTE(fastrange_,i_expandby)(i_hash((&_raw)), (uint64_t)_cap); + k = (intptr_t)c_PASTE(fastrange_,i_sizebits)(i_hash((&_raw)), (uint64_t)_cap); if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ d[i] = d[j], s[i] = s[j], i = j; } @@ -469,7 +460,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { #endif // i_implement #undef i_max_load_factor -#undef i_expandby +#undef i_sizebits #undef _i_isset #undef _i_ismap #undef _i_ishash diff --git a/include/stc/crand.h b/include/stc/crand.h index a1b7250d..f566c1cf 100644 --- a/include/stc/crand.h +++ b/include/stc/crand.h @@ -127,18 +127,6 @@ STC_DEF crand_unif_t crand_unif_init(int64_t low, int64_t high) { 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 - #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; @@ -164,7 +152,6 @@ STC_DEF double crand_norm(crand_t* rng, crand_norm_t* dist) { dist->next = u2*m; return (u1*m)*dist->stddev + dist->mean; } - #endif #endif #undef i_opt diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp index 886bb345..8eb36b34 100644 --- a/misc/benchmarks/shootout_hashmaps.cpp +++ b/misc/benchmarks/shootout_hashmaps.cpp @@ -35,7 +35,7 @@ KHASH_MAP_INIT_INT64(ii, IValue) // cmap template expansion #define i_key IKey #define i_val IValue -#define i_expandby 2 // enable 2^K buckets like the rest. +//#define i_sizebits 64 // more than 2.2 billion elements? #define i_tag ii #define i_max_load_factor MAX_LOAD_FACTOR / 100.0f #include @@ -335,8 +335,8 @@ int main(int argc, char* argv[]) printf("\nT1: Insert %g mill. random keys range [0, 2^%u): map[rnd] = i;\n", N1/1000000.0, keybits); RUN_TEST(1) - printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0); - RUN_TEST(2) + //printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0); + //RUN_TEST(2) printf("\nT3: Erase all elements by lookup (%u mill. random inserts), key range [0, 2^%u)\n", n_mill*2, keybits); RUN_TEST(3) -- cgit v1.2.3 From e78f0ed961c3d0f34b63e113247194fc9eafa636 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sat, 22 Apr 2023 22:47:53 +0200 Subject: Fixed a regression bug in cmap_X_contains()- --- include/stc/cmap.h | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 3fea78f0..986771e5 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -113,7 +113,7 @@ STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->buc STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) { return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) - { return _cx_memb(_bucket_)(self, &rkey).found; } + { return self->size && _cx_memb(_bucket_)(self, &rkey).found; } #ifndef _i_isset STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); @@ -361,11 +361,12 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { while (s[b.idx].hashx) { if (s[b.idx].hashx == b.hashx) { const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + b.idx)); - if (i_eq((&_raw), rkeyptr)) - {b.found = true; break;} + if (i_eq((&_raw), rkeyptr)) { + b.found = true; + break; + } } - if (++b.idx == _cap) - b.idx = 0; + if (++b.idx == _cap) b.idx = 0; } return b; } @@ -380,8 +381,8 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { chash_bucket b = _cx_memb(_bucket_)(self, &rkey); res.ref = &self->data[b.idx]; if (!b.found) { - res.inserted = true; self->slot[b.idx].hashx = b.hashx; + res.inserted = true; ++self->size; } return res; @@ -427,8 +428,8 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { for (intptr_t i = 0; i < _oldbucks; ++i, ++d) if ((s++)->hashx) { _cx_keyraw r = i_keyto(_i_keyref(d)); chash_bucket b = _cx_memb(_bucket_)(&m, &r); - m.data[b.idx] = *d; // move m.slot[b.idx].hashx = b.hashx; + m.data[b.idx] = *d; // move } c_swap(_cx_self, self, &m); } @@ -441,18 +442,20 @@ STC_DEF void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { _cx_value* d = self->data; chash_slot* s = self->slot; - intptr_t i = (intptr_t)(_val - d), j = i, k; + intptr_t i = _val - d, j = i, k; const intptr_t _cap = self->bucket_count; _cx_memb(_value_drop)(_val); - for (;;) { /* delete without leaving tombstone */ - if (++j == _cap) - j = 0; + for (;;) { // delete without leaving tombstone + if (++j == _cap) j = 0; if (! s[j].hashx) break; const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); k = (intptr_t)c_PASTE(fastrange_,i_sizebits)(i_hash((&_raw)), (uint64_t)_cap); - if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ - d[i] = d[j], s[i] = s[j], i = j; + if ((j < i) ^ (k <= i) ^ (k > j)) { // is k outside (i, j]? + d[i] = d[j]; + s[i] = s[j]; + i = j; + } } s[i].hashx = 0; --self->size; -- cgit v1.2.3 From ee619c6ef061c4adb2b13985ebb7d2c67551c84a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 23 Apr 2023 20:02:29 +0200 Subject: Tuned cmap.h and hash function. --- include/stc/ccommon.h | 6 ++-- include/stc/cmap.h | 40 +++++++++++++-------- misc/benchmarks/shootout_hashmaps.cpp | 1 - misc/benchmarks/various/sso_bench.cpp | 67 +++++++++++++++++++++-------------- 4 files changed, 68 insertions(+), 46 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 2453143c..bac25fb1 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -147,13 +147,13 @@ STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) { case 0: return 1; } const uint8_t *x = (const uint8_t*)key; - uint64_t h = *x*0x811c9dc5ULL, n = (uint64_t)len >> 3; + uint64_t h = *x | (*x << 15), n = (uint64_t)len >> 3; len &= 7; while (n--) { memcpy(&u8, x, 8), x += 8; - h = (h ^ u8)*0x01000193ULL; + h = (h ^ u8)*0x9e3779b97f4a7c15; } - while (len--) h = (h ^ *x++)*0x01000193ULL; + while (len--) h = (h ^ *x++)*0xbf58476d1ce4e5b9; return h; } diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 986771e5..1aeb63df 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -71,10 +71,10 @@ typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif #define _i_ishash #ifndef i_max_load_factor - #define i_max_load_factor 0.82f + #define i_max_load_factor 0.80f #endif -#ifndef i_sizebits - #define i_sizebits 32 +#ifndef i_expandby + #define i_expandby 1 #endif #include "priv/template.h" #ifndef i_is_forward @@ -285,20 +285,26 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #if defined(i_implement) #ifndef CMAP_H_INCLUDED -STC_INLINE int64_t fastrange_32(uint64_t x, uint64_t n) - { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^31 - -STC_INLINE int64_t fastrange_64(uint64_t x, uint64_t n) { - uint64_t lo, hi; c_umul128(x, n, &lo, &hi); - return (int64_t)hi; +STC_INLINE int64_t fastrange_1(uint64_t x, uint64_t n) + { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^32 + +STC_INLINE int64_t fastrange_2(uint64_t x, uint64_t n) + { return (int64_t)(x & (n - 1)); } // n power of 2. + +STC_INLINE uint64_t next_power_of_2(uint64_t n) { + n--; + n |= n >> 1, n |= n >> 2; + n |= n >> 4, n |= n >> 8; + n |= n >> 16, n |= n >> 32; + return n + 1; } #endif // CMAP_H_INCLUDED STC_DEF _cx_self _cx_memb(_with_capacity)(const intptr_t cap) { - _cx_self h = {0}; - _cx_memb(_reserve)(&h, cap); - return h; + _cx_self map = {0}; + _cx_memb(_reserve)(&map, cap); + return map; } STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { @@ -356,7 +362,7 @@ STC_DEF chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); intptr_t _cap = self->bucket_count; - chash_bucket b = {c_PASTE(fastrange_,i_sizebits)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; + chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; const chash_slot* s = self->slot; while (s[b.idx].hashx) { if (s[b.idx].hashx == b.hashx) { @@ -414,7 +420,11 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { if (_newcap != self->size && _newcap <= _oldbucks) return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; + #if i_expandby == 2 + _newbucks = (intptr_t)next_power_of_2(_newbucks); + #else _newbucks |= 1; + #endif _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), @@ -450,7 +460,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! s[j].hashx) break; const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); - k = (intptr_t)c_PASTE(fastrange_,i_sizebits)(i_hash((&_raw)), (uint64_t)_cap); + k = (intptr_t)c_PASTE(fastrange_,i_expandby)(i_hash((&_raw)), (uint64_t)_cap); if ((j < i) ^ (k <= i) ^ (k > j)) { // is k outside (i, j]? d[i] = d[j]; s[i] = s[j]; @@ -463,7 +473,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { #endif // i_implement #undef i_max_load_factor -#undef i_sizebits +#undef i_expandby #undef _i_isset #undef _i_ismap #undef _i_ishash diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp index 8eb36b34..54680402 100644 --- a/misc/benchmarks/shootout_hashmaps.cpp +++ b/misc/benchmarks/shootout_hashmaps.cpp @@ -35,7 +35,6 @@ KHASH_MAP_INIT_INT64(ii, IValue) // cmap template expansion #define i_key IKey #define i_val IValue -//#define i_sizebits 64 // more than 2.2 billion elements? #define i_tag ii #define i_max_load_factor MAX_LOAD_FACTOR / 100.0f #include diff --git a/misc/benchmarks/various/sso_bench.cpp b/misc/benchmarks/various/sso_bench.cpp index 9841c296..71d123e8 100644 --- a/misc/benchmarks/various/sso_bench.cpp +++ b/misc/benchmarks/various/sso_bench.cpp @@ -9,19 +9,32 @@ #define i_val_str #include -#define i_type StcSet -#define i_expandby 2 -#define i_val_str -#include - #include using StdVec = std::vector; -//#include "../external/ankerl/robin_hood.h" -//using StdSet = robin_hood::unordered_flat_set; #include -using StdSet = std::unordered_set; +#include "../external/ankerl/robin_hood.h" + +struct string_hash { + using is_transparent = void; + [[nodiscard]] size_t operator()(const char *txt) const { + return std::hash{}(txt); + } + [[nodiscard]] size_t operator()(std::string_view txt) const { + return std::hash{}(txt); + } + [[nodiscard]] size_t operator()(const std::string &txt) const { + return std::hash{}(txt); + } +}; +using StdSet = robin_hood::unordered_flat_set>; +//using StdSet = std::unordered_set; + +#define i_type StcSet +#define i_val_str +//#define i_hash(txtp) std::hash{}(*txtp) +#include static const int BENCHMARK_SIZE = 250000; @@ -43,28 +56,28 @@ static inline const char* randomString(int strsize) { -static inline void addRandomString(StdVec& vec, int strsize) { - vec.push_back(randomString(strsize)); +static inline void addRandomString(StdVec& vec, const char* str) { + vec.push_back(str); } -static inline void addRandomString(StcVec& vec, int strsize) { - StcVec_emplace(&vec, randomString(strsize)); +static inline void addRandomString(StcVec& vec, const char* str) { + StcVec_emplace(&vec, str); } -static inline void addRandomString(StdSet& set, int strsize) { - set.insert(randomString(strsize)); +static inline void addRandomString(StdSet& set, const char* str) { + set.insert(str); } -static inline void addRandomString(StcSet& set, int strsize) { - StcSet_emplace(&set, randomString(strsize)); +static inline void addRandomString(StcSet& set, const char* str) { + StcSet_emplace(&set, str); } -static inline bool getRandomString(const StdSet& set, int strsize) { - return set.find(randomString(strsize)) != set.end(); +static inline bool getRandomString(const StdSet& set, const char* str) { + return set.find(str) != set.end(); } -static inline bool getRandomString(const StcSet& set, int strsize) { - return StcSet_contains(&set, randomString(strsize)); +static inline bool getRandomString(const StcSet& set, const char* str) { + return StcSet_contains(&set, str); } @@ -73,7 +86,7 @@ int benchmark(C& container, const int n, const int strsize) { time_point t1 = std::chrono::high_resolution_clock::now(); for (int i = 0; i < n; i++) - addRandomString(container, strsize); + addRandomString(container, randomString(strsize)); time_point t2 = std::chrono::high_resolution_clock::now(); const auto duration = std::chrono::duration_cast(t2 - t1).count(); @@ -84,12 +97,12 @@ int benchmark(C& container, const int n, const int strsize) { template int benchmark_lookup(C& container, const int n, const int strsize) { for (int i = 0; i < n; i++) - addRandomString(container, strsize); + addRandomString(container, randomString(strsize)); time_point t1 = std::chrono::high_resolution_clock::now(); int found = 0; for (int i = 0; i < n; i++) - found += (int)getRandomString(container, strsize); + found += (int)getRandomString(container, randomString(strsize)); time_point t2 = std::chrono::high_resolution_clock::now(); const auto duration = std::chrono::duration_cast(t2 - t1).count(); @@ -97,9 +110,9 @@ int benchmark_lookup(C& container, const int n, const int strsize) { return (int)duration; } - +#include int main() { - uint64_t seed = 4321; + uint64_t seed = time(NULL); // 4321; int sum, n; // VECTOR WITH STRINGS @@ -154,7 +167,7 @@ int main() { csrand(seed); sum = 0, n = 0; std::cerr << "\nstrsize\tmsecs\tfind: robin_hood::unordered_flat_set, size=" << BENCHMARK_SIZE/2 << "\n"; - for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) { + for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) { StdSet set; set.reserve(BENCHMARK_SIZE/2); sum += benchmark_lookup(set, BENCHMARK_SIZE/2, strsize), ++n; std::cout << '\t' << *set.begin() << '\n'; @@ -164,7 +177,7 @@ int main() { csrand(seed); sum = 0, n = 0; std::cerr << "\nstrsize\tmsecs\tfind: cset, size=" << BENCHMARK_SIZE/2 << "\n"; - for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 4) { + for (int strsize = 1; strsize <= MAX_STRING_SIZE; strsize += 2) { StcSet set = StcSet_with_capacity(BENCHMARK_SIZE/2); sum += benchmark_lookup(set, BENCHMARK_SIZE/2, strsize), ++n; std::cout << '\t' << cstr_str(StcSet_begin(&set).ref) << '\n'; -- cgit v1.2.3 From 3139f550e2af86003e08f0795e395690c120d63e Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 24 Apr 2023 06:38:10 +0200 Subject: Set i_expandby 2 by default. --- include/stc/cmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 1aeb63df..34a9ec79 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -74,7 +74,7 @@ typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #define i_max_load_factor 0.80f #endif #ifndef i_expandby - #define i_expandby 1 + #define i_expandby 2 #endif #include "priv/template.h" #ifndef i_is_forward -- cgit v1.2.3 From 38aab1d6ae8f929084ae6c67256a87760cc07705 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 24 Apr 2023 08:52:15 +0200 Subject: Fixed another cmap issue --- include/stc/ccommon.h | 2 +- include/stc/cmap.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index bac25fb1..121bc566 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -147,7 +147,7 @@ STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) { case 0: return 1; } const uint8_t *x = (const uint8_t*)key; - uint64_t h = *x | (*x << 15), n = (uint64_t)len >> 3; + uint64_t h = (*x << 15) - *x, n = (uint64_t)len >> 3; len &= 7; while (n--) { memcpy(&u8, x, 8), x += 8; diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 34a9ec79..533e8a16 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -380,8 +380,8 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { STC_DEF _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; - if (self->size + 2 > (intptr_t)((float)self->bucket_count * (i_max_load_factor))) - if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2))) + if (self->size >= (intptr_t)((float)self->bucket_count * (i_max_load_factor))) + if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2 + 2))) return res; chash_bucket b = _cx_memb(_bucket_)(self, &rkey); -- cgit v1.2.3 From 9d5766ae528595050dcfe0db4c1c3c0c058b186c Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Wed, 26 Apr 2023 13:13:47 +0200 Subject: Internal. --- include/stc/cmap.h | 1 + include/stc/forward.h | 2 +- misc/benchmarks/plotbench/run_clang.sh | 10 +++++----- misc/benchmarks/plotbench/run_gcc.sh | 10 +++++----- 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 533e8a16..65e4a544 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -53,6 +53,7 @@ int main(void) { #include "forward.h" #include #include +struct chash_slot { uint8_t hashx; }; typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif // CMAP_H_INCLUDED diff --git a/include/stc/forward.h b/include/stc/forward.h index ae49dc31..b534e48b 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -101,7 +101,7 @@ typedef union { SELF##_node *last; \ } SELF -typedef struct { uint8_t hashx; } chash_slot; +typedef struct chash_slot chash_slot; #define _c_chash_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ diff --git a/misc/benchmarks/plotbench/run_clang.sh b/misc/benchmarks/plotbench/run_clang.sh index 096e71be..c9dbac31 100644 --- a/misc/benchmarks/plotbench/run_clang.sh +++ b/misc/benchmarks/plotbench/run_clang.sh @@ -1,10 +1,10 @@ exe='' if [ "$OS" = "Windows_NT" ] ; then exe=".exe" ; fi -clang++ -I../include -O3 -o cdeq_benchmark$exe cdeq_benchmark.cpp -clang++ -I../include -O3 -o clist_benchmark$exe clist_benchmark.cpp -clang++ -I../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp -clang++ -I../include -O3 -o csmap_benchmark$exe csmap_benchmark.cpp -clang++ -I../include -O3 -o cvec_benchmark$exe cvec_benchmark.cpp +clang++ -I../../include -O3 -o cdeq_benchmark$exe cdeq_benchmark.cpp +clang++ -I../../include -O3 -o clist_benchmark$exe clist_benchmark.cpp +clang++ -I../../include -O3 -o cmap_benchmark$exe cmap_benchmark.cpp +clang++ -I../../include -O3 -o csmap_benchmark$exe csmap_benchmark.cpp +clang++ -I../../include -O3 -o cvec_benchmark$exe cvec_benchmark.cpp c='Win-Clang-14.0.1' ./cdeq_benchmark$exe $c diff --git a/misc/benchmarks/plotbench/run_gcc.sh b/misc/benchmarks/plotbench/run_gcc.sh index 5249ed1e..14d89b9a 100644 --- a/misc/benchmarks/plotbench/run_gcc.sh +++ b/misc/benchmarks/plotbench/run_gcc.sh @@ -1,8 +1,8 @@ -g++ -I../include -O3 -o cdeq_benchmark cdeq_benchmark.cpp -g++ -I../include -O3 -o clist_benchmark clist_benchmark.cpp -g++ -I../include -O3 -o cmap_benchmark cmap_benchmark.cpp -g++ -I../include -O3 -o csmap_benchmark csmap_benchmark.cpp -g++ -I../include -O3 -o cvec_benchmark cvec_benchmark.cpp +g++ -I../../include -O3 -o cdeq_benchmark cdeq_benchmark.cpp +g++ -I../../include -O3 -o clist_benchmark clist_benchmark.cpp +g++ -I../../include -O3 -o cmap_benchmark cmap_benchmark.cpp +g++ -I../../include -O3 -o csmap_benchmark csmap_benchmark.cpp +g++ -I../../include -O3 -o cvec_benchmark cvec_benchmark.cpp c='Mingw-g++-11.3.0' ./cdeq_benchmark $c -- cgit v1.2.3 From ba3f2284731e50100d249cf1d825b8d24efad658 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 27 Apr 2023 12:41:24 +0200 Subject: removing compiler warning ++. --- README.md | 2 +- docs/cmap_api.md | 4 ++-- include/stc/algo/filter.h | 9 ++++----- include/stc/ccommon.h | 2 +- include/stc/cmap.h | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/README.md b/README.md index 65d00324..f571c280 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ STC - Smart Template Containers =============================== -### [Version 4.2](#version-history) +### [Version 4.3 beta](#version-history) --- Description diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 94f1c54e..cdb57534 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -9,8 +9,8 @@ hashing (aka open addressing) with linear probing, and without leaving tombstone ***Iterator invalidation***: References and iterators are invalidated after erase. No iterators are invalidated after insert, unless the hash-table need to be extended. The hash table size can be reserved prior to inserts if the total max size is known. -The order of elements is preserved after erase and insert. This makes it possible to erase individual elements while iterating -through the container by using the returned iterator from *erase_at()*, which references the next element. +The order of elements may not be preserved after erase. It is still possible to erase elements when iterating through +the container by setting the iterator to the value returned from *erase_at()*, which references the next element. Note that a small number of elements may be visited twice when doing this, but all elements will be visited. See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_map) for a functional description. diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index e133577c..db076ae4 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -89,8 +89,7 @@ int main() // Use with: clist, cmap, cset, csmap, csset: #define c_erase_if(it, C, cnt, pred) do { \ C* _cnt = &cnt; \ - intptr_t _index = 0; \ - for (C##_iter it = C##_begin(_cnt); it.ref; ++_index) { \ + for (C##_iter it = C##_begin(_cnt); it.ref; ) { \ if (pred) it = C##_erase_at(_cnt, it); \ else C##_next(&it); \ } \ @@ -100,11 +99,11 @@ int main() // Use with: cstack, cvec, cdeq, cqueue: #define c_eraseremove_if(it, C, cnt, pred) do { \ C* _cnt = &cnt; \ - intptr_t _n = 0, _index = 0; \ + intptr_t _n = 0; \ C##_iter it = C##_begin(_cnt), _i; \ while (it.ref && !(pred)) \ - C##_next(&it), ++_index; \ - for (_i = it; it.ref; C##_next(&it), ++_index) \ + C##_next(&it); \ + for (_i = it; it.ref; C##_next(&it)) \ if (pred) C##_value_drop(it.ref), ++_n; \ else *_i.ref = *it.ref, C##_next(&_i); \ _cnt->_len -= _n; \ diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 4f9fa398..73a3d5ef 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -147,7 +147,7 @@ STC_INLINE uint64_t cfasthash(const void* key, intptr_t len) { case 0: return 1; } const uint8_t *x = (const uint8_t*)key; - uint64_t h = *x << 7, n = (uint64_t)len >> 3; + uint64_t h = (uint64_t)*x << 7, n = (uint64_t)len >> 3; len &= 7; while (n--) { memcpy(&u8, x, 8), x += 8; diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 65e4a544..9f21b811 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -422,7 +422,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; #if i_expandby == 2 - _newbucks = (intptr_t)next_power_of_2(_newbucks); + _newbucks = (intptr_t)next_power_of_2((uint64_t)_newbucks); #else _newbucks |= 1; #endif -- cgit v1.2.3 From a922157394a9a3e0cffe26a5fa4d29c9d78ecc06 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 27 Apr 2023 17:55:31 +0200 Subject: Reshuffled code in csmap.h and cmap.h --- include/stc/cmap.h | 81 ++++++++++++++++++++-------------------- include/stc/csmap.h | 105 ++++++++++++++++++++++++++-------------------------- 2 files changed, 94 insertions(+), 92 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 9f21b811..cd8878ea 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -70,13 +70,6 @@ typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #define _i_SET_ONLY c_false #define _i_keyref(vp) (&(vp)->first) #endif -#define _i_ishash -#ifndef i_max_load_factor - #define i_max_load_factor 0.80f -#endif -#ifndef i_expandby - #define i_expandby 2 -#endif #include "priv/template.h" #ifndef i_is_forward _cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); @@ -104,15 +97,14 @@ STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t capacity); STC_API chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr); STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val); +STC_API float _cx_memb(_max_load_factor)(const _cx_self* self); +STC_API intptr_t _cx_memb(_capacity)(const _cx_self* map); STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self map = {0}; return map; } STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, (intptr_t)self->size); } -STC_INLINE float _cx_memb(_max_load_factor)(const _cx_self* self) { return (float)(i_max_load_factor); } STC_INLINE bool _cx_memb(_empty)(const _cx_self* map) { return !map->size; } STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* map) { return (intptr_t)map->size; } STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* map) - { return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) { return self->size && _cx_memb(_bucket_)(self, &rkey).found; } @@ -161,14 +153,12 @@ _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmappe } #endif // !i_no_emplace -STC_INLINE _cx_raw -_cx_memb(_value_toraw)(const _cx_value* val) { +STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { return _i_SET_ONLY( i_keyto(val) ) _i_MAP_ONLY( c_LITERAL(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); } -STC_INLINE void -_cx_memb(_value_drop)(_cx_value* _val) { +STC_INLINE void _cx_memb(_value_drop)(_cx_value* _val) { i_keydrop(_i_keyref(_val)); _i_MAP_ONLY( i_valdrop((&_val->second)); ) } @@ -183,14 +173,13 @@ _cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { return _res; } -STC_INLINE _cx_result -_cx_memb(_push)(_cx_self* self, _cx_value _val) { +STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value _val) { _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); if (_res.inserted) *_res.ref = _val; else _cx_memb(_value_drop)(&_val); - return _res; + return _res.ref; } STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { @@ -209,27 +198,17 @@ STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->data, self->data+self->bucket_count, self->slot}; - if (it.sref) - while (it.sref->hashx == 0) - ++it.ref, ++it.sref; - if (it.ref == it._end) it.ref = NULL; - return it; -} +STC_API _cx_iter _cx_memb(_begin)(const _cx_self* self); -STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) +STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) { return c_LITERAL(_cx_iter){NULL}; } -STC_INLINE void -_cx_memb(_next)(_cx_iter* it) { +STC_INLINE void _cx_memb(_next)(_cx_iter* it) { while ((++it->ref, (++it->sref)->hashx == 0)) ; if (it->ref == it->_end) it->ref = NULL; } -STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) { while (n-- && it.ref) _cx_memb(_next)(&it); return it; } @@ -284,13 +263,19 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) +#ifndef i_max_load_factor + #define i_max_load_factor 0.80f +#endif +#ifndef i_expandby + #define i_expandby 2 +#endif #ifndef CMAP_H_INCLUDED -STC_INLINE int64_t fastrange_1(uint64_t x, uint64_t n) - { return (int64_t)((uint32_t)x*n >> 32); } // n < 2^32 +STC_INLINE intptr_t fastrange_1(uint64_t x, uint64_t n) + { return (intptr_t)((uint32_t)x*n >> 32); } // n < 2^32 -STC_INLINE int64_t fastrange_2(uint64_t x, uint64_t n) - { return (int64_t)(x & (n - 1)); } // n power of 2. +STC_INLINE intptr_t fastrange_2(uint64_t x, uint64_t n) + { return (intptr_t)(x & (n - 1)); } // n power of 2. STC_INLINE uint64_t next_power_of_2(uint64_t n) { n--; @@ -301,8 +286,24 @@ STC_INLINE uint64_t next_power_of_2(uint64_t n) { } #endif // CMAP_H_INCLUDED -STC_DEF _cx_self -_cx_memb(_with_capacity)(const intptr_t cap) { +STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) { + _cx_iter it = {self->data, self->data+self->bucket_count, self->slot}; + if (it.sref) + while (it.sref->hashx == 0) + ++it.ref, ++it.sref; + if (it.ref == it._end) it.ref = NULL; + return it; +} + +STC_DEF float _cx_memb(_max_load_factor)(const _cx_self* self) { + return (float)(i_max_load_factor); +} + +STC_DEF intptr_t _cx_memb(_capacity)(const _cx_self* map) { + return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); +} + +STC_DEF _cx_self _cx_memb(_with_capacity)(const intptr_t cap) { _cx_self map = {0}; _cx_memb(_reserve)(&map, cap); return map; @@ -471,13 +472,13 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { s[i].hashx = 0; --self->size; } - -#endif // i_implement #undef i_max_load_factor #undef i_expandby +#elif defined i_max_load_factor || defined i_expandby +#error i_max_load_factor and i_expandby may only be defined for the implementation. +#endif // i_implement #undef _i_isset #undef _i_ismap -#undef _i_ishash #undef _i_keyref #undef _i_MAP_ONLY #undef _i_SET_ONLY diff --git a/include/stc/csmap.h b/include/stc/csmap.h index dc0387f7..cd7c1d95 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -97,8 +97,6 @@ STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MA #if !defined i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self tree); #endif // !i_no_clone -STC_API _cx_result _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)); -STC_API _cx_result _cx_memb(_push)(_cx_self* self, _cx_value _val); STC_API void _cx_memb(_drop)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap); STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out); @@ -108,6 +106,7 @@ STC_API _cx_value* _cx_memb(_back)(const _cx_self* self); STC_API int _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey); STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); +STC_API _cx_iter _cx_memb(_begin)(const _cx_self* self); STC_API void _cx_memb(_next)(_cx_iter* it); STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self tree = {0}; return tree; } @@ -184,17 +183,6 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } #endif // !_i_isset -STC_INLINE _cx_iter -_cx_memb(_begin)(const _cx_self* self) { - _cx_iter it; - it.ref = NULL; - it._d = self->nodes, it._top = 0; - it._tn = self->root; - if (it._tn) - _cx_memb(_next)(&it); - return it; -} - STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) { (void)self; @@ -220,7 +208,30 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { return true; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { +static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); + +STC_INLINE _cx_result +_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { + _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); + if (_res.inserted) + { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} + else + { i_keydrop((&_key)); _i_MAP_ONLY( i_valdrop((&_mapped)); )} + return _res; +} + +STC_INLINE _cx_value* +_cx_memb(_push)(_cx_self* self, _cx_value _val) { + _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); + if (_res.inserted) + *_res.ref = _val; + else + _cx_memb(_value_drop)(&_val); + return _res.ref; +} + +STC_INLINE void +_cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { while (n--) #if defined _i_isset && defined i_no_emplace _cx_memb(_insert)(self, *raw++); @@ -233,12 +244,39 @@ STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) #endif } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) +STC_INLINE _cx_self +_cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) +STC_DEF void +_cx_memb(_next)(_cx_iter *it) { + int32_t tn = it->_tn; + if (it->_top || tn) { + while (tn) { + it->_st[it->_top++] = tn; + tn = it->_d[tn].link[0]; + } + tn = it->_st[--it->_top]; + it->_tn = it->_d[tn].link[1]; + it->ref = &it->_d[tn].value; + } else + it->ref = NULL; +} + +STC_DEF _cx_iter +_cx_memb(_begin)(const _cx_self* self) { + _cx_iter it; + it.ref = NULL; + it._d = self->nodes, it._top = 0; + it._tn = self->root; + if (it._tn) + _cx_memb(_next)(&it); + return it; +} + STC_DEF bool _cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { if (cap <= self->cap) @@ -287,28 +325,6 @@ _cx_memb(_new_node_)(_cx_self* self, int level) { return tn; } -static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); - -STC_DEF _cx_result -_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); - if (_res.inserted) - { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} - else - { i_keydrop((&_key)); _i_MAP_ONLY( i_valdrop((&_mapped)); )} - return _res; -} - -STC_DEF _cx_result -_cx_memb(_push)(_cx_self* self, _cx_value _val) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); - if (_res.inserted) - *_res.ref = _val; - else - _cx_memb(_value_drop)(&_val); - return _res; -} - #ifndef _i_isset STC_DEF _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped) { @@ -367,21 +383,6 @@ _cx_memb(_lower_bound)(const _cx_self* self, _cx_keyraw rkey) { return it; } -STC_DEF void -_cx_memb(_next)(_cx_iter *it) { - int32_t tn = it->_tn; - if (it->_top || tn) { - while (tn) { - it->_st[it->_top++] = tn; - tn = it->_d[tn].link[0]; - } - tn = it->_st[--it->_top]; - it->_tn = it->_d[tn].link[1]; - it->ref = &it->_d[tn].value; - } else - it->ref = NULL; -} - STC_DEF int32_t _cx_memb(_skew_)(_cx_node *d, int32_t tn) { if (tn && d[d[tn].link[0]].level == d[tn].level) { -- cgit v1.2.3 From 49e7d9cc0a888b0b19aa4e737d55a2bc33bec824 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 28 Apr 2023 17:01:58 +0200 Subject: Removed crandom.h and altnames.h. Housholding. --- README.md | 8 +- include/stc/algo/crange.h | 4 +- include/stc/algo/csort.h | 20 ++--- include/stc/carc.h | 2 - include/stc/cbox.h | 2 - include/stc/ccommon.h | 1 - include/stc/clist.h | 2 - include/stc/cmap.h | 21 ++--- include/stc/cpque.h | 3 - include/stc/cqueue.h | 2 - include/stc/crandom.h | 197 -------------------------------------------- include/stc/cset.h | 3 - include/stc/csmap.h | 13 ++- include/stc/csset.h | 3 - include/stc/cstack.h | 2 - include/stc/cvec.h | 2 - include/stc/priv/altnames.h | 34 -------- 17 files changed, 33 insertions(+), 286 deletions(-) delete mode 100644 include/stc/crandom.h delete mode 100644 include/stc/priv/altnames.h (limited to 'include/stc/cmap.h') diff --git a/README.md b/README.md index f571c280..74c2238f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ STC - Smart Template Containers =============================== -### [Version 4.3 beta](#version-history) +### [Version 4.3 RC](#version-history) --- Description @@ -611,6 +611,12 @@ STC is generally very memory efficient. Memory usage for the different container --- # Version History + +## Version 4.3 +- Removed deprecated uppercase flow-control macro names. +- Removed deprecated crandom.h. Use crand.h with new API. +- Improved default string hash function. + ## Version 4.2 - New home! And online single headers for https://godbolt.org - Library: https://github.com/stclib/STC diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index ca06c258..56c317da 100644 --- a/include/stc/algo/crange.h +++ b/include/stc/algo/crange.h @@ -63,10 +63,10 @@ STC_INLINE crange crange_make_3(crange_value start, crange_value stop, crange_va STC_INLINE crange_iter crange_begin(crange* self) { self->value = self->start; crange_iter it = {&self->value, self->end, self->step}; return it; } -STC_INLINE crange_iter crange_end(crange* self) +STC_INLINE crange_iter crange_end(crange* self) { crange_iter it = {NULL}; return it; } -STC_INLINE void crange_next(crange_iter* it) +STC_INLINE void crange_next(crange_iter* it) { *it->ref += it->step; if ((it->step > 0) == (*it->ref > it->end)) it->ref = NULL; } #endif diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h index 53fe9fcc..e01a2893 100644 --- a/include/stc/algo/csort.h +++ b/include/stc/algo/csort.h @@ -20,9 +20,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "../ccommon.h" -#include "../priv/template.h" - /* Generic Quicksort in C, performs as fast as c++ std::sort(). template params: #define i_val - value type [required] @@ -44,10 +41,13 @@ int main() { puts(""); } */ +#include "../ccommon.h" +#define _i_prefix csort_ +#include "../priv/template.h" -typedef i_val c_PASTE(c_CONCAT(csort_, i_tag), _value); +typedef i_val _cx_value; -static inline void c_PASTE(cisort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi) { +static inline void _cx_memb(_insertion)(i_val arr[], intptr_t lo, intptr_t hi) { for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) { i_val key = arr[i]; while (j >= 0 && (i_less((&key), (&arr[j])))) { @@ -58,7 +58,7 @@ static inline void c_PASTE(cisort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi } } -static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi) { +static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) { intptr_t i = lo, j; while (lo < hi) { i_val pivot = arr[lo + (hi - lo)*7/16]; @@ -77,13 +77,13 @@ static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t lo, intptr_t hi c_swap(intptr_t, &hi, &j); } - if (j - lo > 64) c_PASTE(cqsort_, i_tag)(arr, lo, j); - else if (j > lo) c_PASTE(cisort_, i_tag)(arr, lo, j); + if (j - lo > 64) _cx_memb(_quicksort)(arr, lo, j); + else if (j > lo) _cx_memb(_insertion)(arr, lo, j); lo = i; } } -static inline void c_PASTE(csort_, i_tag)(i_val arr[], intptr_t n) - { c_PASTE(cqsort_, i_tag)(arr, 0, n - 1); } +static inline void _cx_self(i_val arr[], intptr_t n) + { _cx_memb(_quicksort)(arr, 0, n - 1); } #include "../priv/template2.h" diff --git a/include/stc/carc.h b/include/stc/carc.h index 8ef80b12..74205caf 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -74,9 +74,7 @@ int main() { #define carc_NULL {NULL, NULL} #endif // CARC_H_INCLUDED -#ifndef _i_prefix #define _i_prefix carc_ -#endif #ifdef i_eq #define _i_eq #endif diff --git a/include/stc/cbox.h b/include/stc/cbox.h index ca88fc66..393b904b 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -67,9 +67,7 @@ int main() { #define cbox_NULL {NULL} #endif // CBOX_H_INCLUDED -#ifndef _i_prefix #define _i_prefix cbox_ -#endif #ifdef i_eq #define _i_eq #endif diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 73a3d5ef..1882646c 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -29,7 +29,6 @@ #include #include #include -#include "priv/altnames.h" #include "priv/raii.h" #define c_NPOS INTPTR_MAX diff --git a/include/stc/clist.h b/include/stc/clist.h index f7fb4152..65a1ac87 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -77,9 +77,7 @@ #endif // CLIST_H_INCLUDED -#ifndef _i_prefix #define _i_prefix clist_ -#endif #include "priv/template.h" #ifndef i_is_forward diff --git a/include/stc/cmap.h b/include/stc/cmap.h index cd8878ea..ec3238f6 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -58,17 +58,16 @@ typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif // CMAP_H_INCLUDED #ifndef _i_prefix -#define _i_prefix cmap_ -#endif -#ifdef _i_isset - #define _i_MAP_ONLY c_false - #define _i_SET_ONLY c_true - #define _i_keyref(vp) (vp) -#else + #define _i_prefix cmap_ #define _i_ismap #define _i_MAP_ONLY c_true #define _i_SET_ONLY c_false #define _i_keyref(vp) (&(vp)->first) +#else + #define _i_isset + #define _i_MAP_ONLY c_false + #define _i_SET_ONLY c_true + #define _i_keyref(vp) (vp) #endif #include "priv/template.h" #ifndef i_is_forward @@ -421,11 +420,9 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { const intptr_t _oldbucks = self->bucket_count; if (_newcap != self->size && _newcap <= _oldbucks) return true; - intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; + intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) | 1; #if i_expandby == 2 _newbucks = (intptr_t)next_power_of_2((uint64_t)_newbucks); - #else - _newbucks |= 1; #endif _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), @@ -472,11 +469,9 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { s[i].hashx = 0; --self->size; } +#endif // i_implement #undef i_max_load_factor #undef i_expandby -#elif defined i_max_load_factor || defined i_expandby -#error i_max_load_factor and i_expandby may only be defined for the implementation. -#endif // i_implement #undef _i_isset #undef _i_ismap #undef _i_keyref diff --git a/include/stc/cpque.h b/include/stc/cpque.h index b95b5020..c76621cd 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -27,10 +27,7 @@ #include "forward.h" #endif -#ifndef _i_prefix #define _i_prefix cpque_ -#endif - #include "priv/template.h" #ifndef i_is_forward _cx_deftypes(_c_cpque_types, _cx_self, i_key); diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 1934305a..254bc834 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -53,9 +53,7 @@ int main() { } */ -#ifndef _i_prefix #define _i_prefix cqueue_ -#endif #define _i_queue #define _pop_front _pop diff --git a/include/stc/crandom.h b/include/stc/crandom.h deleted file mode 100644 index a9374602..00000000 --- a/include/stc/crandom.h +++ /dev/null @@ -1,197 +0,0 @@ -/* 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 CRANDOM_H_INCLUDED -#define CRANDOM_H_INCLUDED -/* -// crandom: Pseudo-random number generator -#include "stc/crandom.h" -int main() { - uint64_t seed = 123456789; - stc64_t rng = stc64_new(seed); - stc64_uniform_t dist1 = stc64_uniform_new(1, 6); - stc64_uniformf_t dist2 = stc64_uniformf_new(1.0, 10.0); - stc64_normalf_t dist3 = stc64_normalf_new(1.0, 10.0); - - uint64_t i = stc64_rand(&rng); - int64_t iu = stc64_uniform(&rng, &dist1); - double xu = stc64_uniformf(&rng, &dist2); - double xn = stc64_normalf(&rng, &dist3); -} -*/ -#include -#include - -typedef struct stc64 { uint64_t state[5]; } stc64_t; -typedef struct stc64_uniform { int64_t lower; uint64_t range, threshold; } stc64_uniform_t; -typedef struct stc64_uniformf { double lower, range; } stc64_uniformf_t; -typedef struct stc64_normalf { double mean, stddev, next; int has_next; } stc64_normalf_t; - -/* PRNG stc64. - * 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. - * stc64 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 stc64 PRNGs */ -STC_API void csrandom(uint64_t seed); -STC_API uint64_t crandom(void); -STC_API double crandomf(void); - -/* Init stc64 prng with and without sequence number */ -STC_API stc64_t stc64_with_seq(uint64_t seed, uint64_t seq); -STC_INLINE stc64_t stc64_new(uint64_t seed) - { return stc64_with_seq(seed, seed + 0x3504f333d3aa0b37); } - -/* Unbiased bounded uniform distribution. range [low, high] */ -STC_API stc64_uniform_t stc64_uniform_new(int64_t low, int64_t high); -STC_API int64_t stc64_uniform(stc64_t* rng, stc64_uniform_t* dist); - -/* Normal distribution PRNG */ -STC_API double stc64_normalf(stc64_t* rng, stc64_normalf_t* dist); - - -/* Main stc64 prng */ -STC_INLINE uint64_t stc64_rand(stc64_t* rng) { - uint64_t *s = rng->state; enum {LR=24, RS=11, LS=3}; - const uint64_t result = (s[0] ^ (s[3] += s[4])) + s[1]; - s[0] = s[1] ^ (s[1] >> RS); - s[1] = s[2] + (s[2] << LS); - s[2] = ((s[2] << LR) | (s[2] >> (64 - LR))) + result; - return result; -} - -/* Float64 random number in range [0.0, 1.0). */ -STC_INLINE double stc64_randf(stc64_t* rng) { - union {uint64_t i; double f;} u = {0x3FF0000000000000ull | (stc64_rand(rng) >> 12)}; - return u.f - 1.0; -} - -/* Float64 uniform distributed RNG, range [low, high). */ -STC_INLINE double stc64_uniformf(stc64_t* rng, stc64_uniformf_t* dist) { - return stc64_randf(rng)*dist->range + dist->lower; -} - -/* Init uniform distributed float64 RNG, range [low, high). */ -STC_INLINE stc64_uniformf_t stc64_uniformf_new(double low, double high) { - return c_LITERAL(stc64_uniformf_t){low, high - low}; -} - -/* Marsaglia polar method for gaussian/normal distribution, float64. */ -STC_INLINE stc64_normalf_t stc64_normalf_new(double mean, double stddev) { - return c_LITERAL(stc64_normalf_t){mean, stddev, 0.0, 0}; -} - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) - -/* Global random() */ -static stc64_t stc64_global = {{ - 0x26aa069ea2fb1a4d, 0x70c72c95cd592d04, - 0x504f333d3aa0b359, 0x9e3779b97f4a7c15, - 0x6a09e667a754166b -}}; - -STC_DEF void csrandom(uint64_t seed) { - stc64_global = stc64_new(seed); -} - -STC_DEF uint64_t crandom(void) { - return stc64_rand(&stc64_global); -} - -STC_DEF double crandomf(void) { - return stc64_randf(&stc64_global); -} - -/* rng.state[4] must be odd */ -STC_DEF stc64_t stc64_with_seq(uint64_t seed, uint64_t seq) { - stc64_t rng = {{seed+0x26aa069ea2fb1a4d, seed+0x70c72c95cd592d04, - seed+0x504f333d3aa0b359, seed, seq<<1 | 1}}; - for (int i = 0; i < 6; ++i) stc64_rand(&rng); - return rng; -} - -/* Init unbiased uniform uint RNG with bounds [low, high] */ -STC_DEF stc64_uniform_t stc64_uniform_new(int64_t low, int64_t high) { - stc64_uniform_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 - #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 - -/* Int uniform distributed RNG, range [low, high]. */ -STC_DEF int64_t stc64_uniform(stc64_t* rng, stc64_uniform_t* d) { -#ifdef c_umul128 - uint64_t lo, hi; - do { c_umul128(stc64_rand(rng), d->range, &lo, &hi); } while (lo < d->threshold); - return d->lower + (int64_t)hi; -#else - uint64_t x, r; - do { - x = stc64_rand(rng); - r = x % d->range; - } while (x - r > -d->range); - return d->lower + r; -#endif -} - -/* Normal distribution PRNG */ -STC_DEF double stc64_normalf(stc64_t* rng, stc64_normalf_t* dist) { - double u1, u2, s, m; - if (dist->has_next++ & 1) - return dist->next * dist->stddev + dist->mean; - do { - u1 = 2.0 * stc64_randf(rng) - 1.0; - u2 = 2.0 * stc64_randf(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/cset.h b/include/stc/cset.h index 58cbeb3e..c89a144d 100644 --- a/include/stc/cset.h +++ b/include/stc/cset.h @@ -39,8 +39,5 @@ int main(void) { } */ -#ifndef _i_prefix #define _i_prefix cset_ -#endif -#define _i_isset #include "cmap.h" diff --git a/include/stc/csmap.h b/include/stc/csmap.h index cd7c1d95..6b8475eb 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -58,17 +58,16 @@ int main(void) { #endif // CSMAP_H_INCLUDED #ifndef _i_prefix -#define _i_prefix csmap_ -#endif -#ifdef _i_isset - #define _i_MAP_ONLY c_false - #define _i_SET_ONLY c_true - #define _i_keyref(vp) (vp) -#else + #define _i_prefix csmap_ #define _i_ismap #define _i_MAP_ONLY c_true #define _i_SET_ONLY c_false #define _i_keyref(vp) (&(vp)->first) +#else + #define _i_isset + #define _i_MAP_ONLY c_false + #define _i_SET_ONLY c_true + #define _i_keyref(vp) (vp) #endif #include "priv/template.h" #ifndef i_is_forward diff --git a/include/stc/csset.h b/include/stc/csset.h index c14d2a6a..29810c7c 100644 --- a/include/stc/csset.h +++ b/include/stc/csset.h @@ -42,8 +42,5 @@ int main(void) { } */ -#ifndef _i_prefix #define _i_prefix csset_ -#endif -#define _i_isset #include "csmap.h" diff --git a/include/stc/cstack.h b/include/stc/cstack.h index c2792358..87ef9405 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -28,9 +28,7 @@ #include "forward.h" #endif // CSTACK_H_INCLUDED -#ifndef _i_prefix #define _i_prefix cstack_ -#endif #include "priv/template.h" #ifndef i_is_forward diff --git a/include/stc/cvec.h b/include/stc/cvec.h index a1aa74b2..3cbd90b7 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -68,9 +68,7 @@ int main() { #define _it_ptr(it) (it.ref ? it.ref : it.end) #endif // CVEC_H_INCLUDED -#ifndef _i_prefix #define _i_prefix cvec_ -#endif #include "priv/template.h" #ifndef i_is_forward diff --git a/include/stc/priv/altnames.h b/include/stc/priv/altnames.h deleted file mode 100644 index 723b6a66..00000000 --- a/include/stc/priv/altnames.h +++ /dev/null @@ -1,34 +0,0 @@ -/* 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. - */ -#define c_FORLIST c_forlist -#define c_FORRANGE c_forrange -#define c_FOREACH c_foreach -#define c_FORPAIR c_forpair -#define c_FORFILTER c_forfilter -#define c_FORMATCH c_formatch -#define c_FORTOKEN c_fortoken -#define c_FORTOKEN_SV c_fortoken_sv -#define c_AUTO c_auto -#define c_WITH c_with -#define c_SCOPE c_scope -#define c_DEFER c_defer -- cgit v1.2.3 From 50a16934dde8e65bbcf628d6342c1649f7e09365 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Thu, 18 May 2023 11:49:31 +0200 Subject: Huge update: cqueue and cdeq completely rewritten. cvec and cdeq API harmonized. Docs update/improved. --- README.md | 2 +- docs/ccommon_api.md | 2 +- docs/cdeq_api.md | 45 ++-- docs/clist_api.md | 10 +- docs/cqueue_api.md | 9 +- docs/csmap_api.md | 3 +- docs/cstack_api.md | 3 +- docs/cvec_api.md | 20 +- include/stc/algo/csort.h | 89 ------- include/stc/algo/sort.h | 100 ++++++++ include/stc/ccommon.h | 10 + include/stc/cdeq.h | 453 ++++++++-------------------------- include/stc/clist.h | 9 +- include/stc/cmap.h | 9 +- include/stc/cqueue.h | 226 ++++++++++++++--- include/stc/cvec.h | 121 ++++----- include/stc/forward.h | 13 +- include/stc/priv/template.h | 8 +- include/stc/priv/template2.h | 5 + misc/benchmarks/various/csort_bench.c | 44 ++-- misc/benchmarks/various/cspan_bench.c | 2 +- misc/examples/printspan.c | 6 - src/cregex.c | 2 +- 23 files changed, 550 insertions(+), 641 deletions(-) delete mode 100644 include/stc/algo/csort.h create mode 100644 include/stc/algo/sort.h (limited to 'include/stc/cmap.h') diff --git a/README.md b/README.md index 74c2238f..3b9cf90f 100644 --- a/README.md +++ b/README.md @@ -642,7 +642,7 @@ Major changes: - Algorithms: - [crange](docs/ccommon_api.md#crange) - similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html) integer range generator. - [c_forfilter](docs/ccommon_api.md#c_forfilter) - ranges-like view filtering. - - [csort](include/stc/algo/csort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison. + - [csort](include/stc/algo/sort.h) - [fast quicksort](misc/benchmarks/various/csort_bench.c) with custom inline comparison. - Renamed `c_ARGSV()` => `c_SV()`: **csview** print arg. Note `c_sv()` is shorthand for *csview_from()*. - Support for [uppercase flow-control](include/stc/priv/altnames.h) macro names in ccommon.h. - Some API changes in **cregex** and **cstr**. diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index e4c881dd..e37a1463 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -212,7 +212,7 @@ You may customize `i_tag` and the comparison function `i_cmp` or `i_less`. There is a [benchmark/test file here](../misc/benchmarks/various/csort_bench.c). ```c #define i_val int -#include +#include int main() { int array[] = {5, 3, 5, 9, 7, 4, 7, 2, 4, 9, 3, 1, 2, 6, 4}; diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index fc11fe66..91022a5c 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -1,7 +1,9 @@ # STC [cdeq](../include/stc/cdeq.h): Double Ended Queue ![Deque](pics/deque.jpg) -A **cdeq** is an indexed sequence container that allows fast insertion and deletion at both its beginning and its end. Note that this container is implemented similar to a vector, but has the same performance profile for both *push_back()* and *push_front()* as *cdeq_X_push_back()*. Iterators may be invalidated after push-operations. +A **cdeq** is an indexed sequence container that allows fast insertion and deletion at both +its beginning and its end, but has also fast random access to elements. The container is +implemented as a circular dynamic buffer. Iterators may be invalidated after push-operations. See the c++ class [std::deque](https://en.cppreference.com/w/cpp/container/deque) for a functional description. @@ -32,20 +34,20 @@ cdeq_X cdeq_X_clone(cdeq_X deq); void cdeq_X_clear(cdeq_X* self); void cdeq_X_copy(cdeq_X* self, const cdeq_X* other); -cdeq_X_iter cdeq_X_copy_range(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2); bool cdeq_X_reserve(cdeq_X* self, intptr_t cap); void cdeq_X_shrink_to_fit(cdeq_X* self); -void cdeq_X_drop(cdeq_X* self); // destructor +void cdeq_X_drop(cdeq_X* self); // destructor bool cdeq_X_empty(const cdeq_X* self); intptr_t cdeq_X_size(const cdeq_X* self); intptr_t cdeq_X_capacity(const cdeq_X* self); const cdeq_X_value* cdeq_X_at(const cdeq_X* self, intptr_t idx); -const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found -cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get +cdeq_X_value* cdeq_X_at_mut(cdeq_X* self, intptr_t idx); +const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found +cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get cdeq_X_iter cdeq_X_find(const cdeq_X* self, i_valraw raw); -cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found +cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found cdeq_X_value* cdeq_X_front(const cdeq_X* self); cdeq_X_value* cdeq_X_back(const cdeq_X* self); @@ -55,38 +57,31 @@ cdeq_X_value* cdeq_X_emplace_front(cdeq_X* self, i_valraw raw); void cdeq_X_pop_front(cdeq_X* self); cdeq_X_value* cdeq_X_push_back(cdeq_X* self, i_val value); -cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back() +cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back() cdeq_X_value* cdeq_X_emplace_back(cdeq_X* self, i_valraw raw); -cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back() +cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back() void cdeq_X_pop_back(cdeq_X* self); -cdeq_X_iter cdeq_X_insert(cdeq_X* self, intptr_t idx, i_val value); // move value -cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move arr values -cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value -cdeq_X_iter cdeq_X_insert_range(cdeq_X* self, i_val* pos, - const i_val* p1, const i_val* p2); - -cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); // clone values +cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move values +cdeq_X_iter cdeq_X_insert(cdeq_X* self, intptr_t idx, i_val value); // move value +cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value +cdeq_X_iter cdeq_X_insert_uninit(cdeq_X* self, intptr_t idx, intptr_t n); // uninitialized data + // copy values: +cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); cdeq_X_iter cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw); -cdeq_X_iter cdeq_X_emplace_range(cdeq_X* self, i_val* pos, - const i_valraw* p1, const i_valraw* p2); -cdeq_X_iter cdeq_X_erase_n(cdeq_X* self, intptr_t idx, intptr_t n); +void cdeq_X_erase_n(cdeq_X* self, intptr_t idx, intptr_t n); cdeq_X_iter cdeq_X_erase_at(cdeq_X* self, cdeq_X_iter it); cdeq_X_iter cdeq_X_erase_range(cdeq_X* self, cdeq_X_iter it1, cdeq_X_iter it2); -cdeq_X_iter cdeq_X_erase_range_p(cdeq_X* self, i_val* p1, i_val* p2); - -void cdeq_X_sort(cdeq_X* self); -void cdeq_X_sort_range(cdeq_X_iter i1, cdeq_X_iter i2, - int(*cmp)(const i_val*, const i_val*)); 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, size_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); +cdeq_X_raw cdeq_X_value_toraw(const cdeq_X_value* pval); +void cdeq_X_value_drop(cdeq_X_value* pval); ``` ## Types diff --git a/docs/clist_api.md b/docs/clist_api.md index a1dbe105..44c3bb7c 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -84,19 +84,21 @@ void clist_X_sort(clist_X* self); void clist_X_sort_with(clist_X* self, int(*cmp)(const clist_X_value*, const clist_X_value*)); // Node API -clist_X_node* clist_X_get_node(clist_X_value* val); // get the enclosing node +clist_X_node* clist_X_get_node(clist_X_value* val); // get enclosing node clist_X_value* clist_X_push_back_node(clist_X* self, clist_X_node* node); clist_X_value* clist_X_insert_after_node(clist_X* self, clist_X_node* ref, clist_X_node* node); -clist_X_node* clist_X_unlink_after_node(clist_X* self, clist_X_node* ref); // return the unlinked node +clist_X_node* clist_X_unlink_after_node(clist_X* self, clist_X_node* ref); // return unlinked node +clist_X_node* clist_X_unlink_front_node(clist_X* self); // return unlinked node void clist_X_erase_after_node(clist_X* self, clist_X_node* node); clist_X_iter clist_X_begin(const clist_X* self); clist_X_iter clist_X_end(const clist_X* self); void clist_X_next(clist_X_iter* it); -clist_X_iter clist_X_advance(clist_X_iter it, size_t n); // return n elements ahead. +clist_X_iter clist_X_advance(clist_X_iter it, size_t n); // return n elements ahead. -clist_X_raw clist_X_value_toraw(clist_X_value* pval); clist_X_value clist_X_value_clone(clist_X_value val); +clist_X_raw clist_X_value_toraw(const clist_X_value* pval); +void clist_X_value_drop(clist_X_value* pval); ``` ## Types diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index 9ea4b148..7d8d4e5c 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -26,27 +26,34 @@ See the c++ class [std::queue](https://en.cppreference.com/w/cpp/container/queue ```c cqueue_X cqueue_X_init(void); +cqueue_X cqueue_X_with_capacity(intptr_t size); cqueue_X cqueue_X_clone(cqueue_X q); void cqueue_X_clear(cqueue_X* self); void cqueue_X_copy(cqueue_X* self, const cqueue_X* other); +bool cqueue_X_reserve(cqueue_X* self, intptr_t cap); +void cqueue_X_shrink_to_fit(cqueue_X* self); void cqueue_X_drop(cqueue_X* self); // destructor intptr_t cqueue_X_size(const cqueue_X* self); +intptr_t cqueue_X_capacity(const cqueue_X* self); bool cqueue_X_empty(const cqueue_X* self); + cqueue_X_value* cqueue_X_front(const cqueue_X* self); cqueue_X_value* cqueue_X_back(const cqueue_X* self); cqueue_X_value* cqueue_X_push(cqueue_X* self, i_val value); cqueue_X_value* cqueue_X_emplace(cqueue_X* self, i_valraw raw); - void cqueue_X_pop(cqueue_X* self); cqueue_X_iter cqueue_X_begin(const cqueue_X* self); cqueue_X_iter cqueue_X_end(const cqueue_X* self); void cqueue_X_next(cqueue_X_iter* it); +cqueue_X_iter cqueue_X_advance(cqueue_X_iter it, intptr_t n); i_val cqueue_X_value_clone(i_val value); +cqueue_X_raw cqueue_X_value_toraw(const cqueue_X_value* pval); +void cqueue_X_value_drop(cqueue_X_value* pval); ``` ## Types diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 3e643cee..8c2048c0 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -83,7 +83,8 @@ void csmap_X_next(csmap_X_iter* iter); csmap_X_iter csmap_X_advance(csmap_X_iter it, intptr_t n); csmap_X_value csmap_X_value_clone(csmap_X_value val); -csmap_X_raw csmap_X_value_toraw(csmap_X_value* pval); +csmap_X_raw csmap_X_value_toraw(const csmap_X_value* pval); +void csmap_X_value_drop(csmap_X_value* pval); ``` ## Types diff --git a/docs/cstack_api.md b/docs/cstack_api.md index b1371f4e..c20de7d1 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -54,8 +54,9 @@ cstack_X_iter cstack_X_begin(const cstack_X* self); cstack_X_iter cstack_X_end(const cstack_X* self); void cstack_X_next(cstack_X_iter* it); -i_valraw cstack_X_value_toraw(cvec_X_value* pval); i_val cstack_X_value_clone(i_val value); +i_valraw cstack_X_value_toraw(const cvec_X_value* pval); +void cstack_X_value_drop(cvec_X_value* pval); ``` ## Types diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 5879bc1f..194d48e1 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -37,10 +37,9 @@ cvec_X cvec_X_clone(cvec_X vec); void cvec_X_clear(cvec_X* self); void cvec_X_copy(cvec_X* self, const cvec_X* other); -cvec_X_iter cvec_X_copy_range(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2); +cvec_X_iter cvec_X_copy_n(cvec_X* self, intptr_t idx, const i_val* arr, intptr_t n); bool cvec_X_reserve(cvec_X* self, intptr_t cap); bool cvec_X_resize(cvec_X* self, intptr_t size, i_val null); -cvec_X_iter cvec_X_insert_uninit(cvec_X* self, i_val* pos, intptr_t n); // return pos iter void cvec_X_shrink_to_fit(cvec_X* self); void cvec_X_drop(cvec_X* self); // destructor @@ -50,8 +49,8 @@ intptr_t cvec_X_capacity(const cvec_X* self); const cvec_X_value* cvec_X_at(const cvec_X* self, intptr_t idx); const cvec_X_value* cvec_X_get(const cvec_X* self, i_valraw raw); // return NULL if not found -cvec_X_value* cvec_X_at_mut(cvec_X* self, intptr_t idx); -cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // find mutable value, return value ptr +cvec_X_value* cvec_X_at_mut(cvec_X* self, intptr_t idx); // return mutable at idx +cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // find mutable value cvec_X_iter cvec_X_find(const cvec_X* self, i_valraw raw); cvec_X_iter cvec_X_find_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw); // return cvec_X_end() if not found // On sorted vectors: @@ -72,20 +71,16 @@ void cvec_X_pop(cvec_X* self); void cvec_X_pop_back(cvec_X* self); // alias for pop cvec_X_iter cvec_X_insert(cvec_X* self, intptr_t idx, i_val value); // move value -cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move n values +cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val arr[], intptr_t n); // move values cvec_X_iter cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value -cvec_X_iter cvec_X_insert_range(cvec_X* self, i_val* pos, - const i_val* p1, const i_val* p2); +cvec_X_iter cvec_X_insert_uninit(cvec_X* self, intptr_t idx, intptr_t n); // return iter at idx -cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); // clone values +cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_valraw raw[], intptr_t n); cvec_X_iter cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw); -cvec_X_iter cvec_X_emplace_range(cvec_X* self, i_val* pos, - const i_valraw* p1, const i_valraw* p2); cvec_X_iter cvec_X_erase_n(cvec_X* self, intptr_t idx, intptr_t n); cvec_X_iter cvec_X_erase_at(cvec_X* self, cvec_X_iter it); cvec_X_iter cvec_X_erase_range(cvec_X* self, cvec_X_iter it1, cvec_X_iter it2); -cvec_X_iter cvec_X_erase_range_p(cvec_X* self, i_val* p1, i_val* p2); void cvec_X_sort(cvec_X* self); void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2, @@ -96,8 +91,9 @@ 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, size_t n); -cvec_X_raw cvec_X_value_toraw(cvec_X_value* pval); cvec_X_value cvec_X_value_clone(cvec_X_value val); +cvec_X_raw cvec_X_value_toraw(const cvec_X_value* pval); +cvec_X_raw cvec_X_value_drop(cvec_X_value* pval); ``` ## Types diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h deleted file mode 100644 index e01a2893..00000000 --- a/include/stc/algo/csort.h +++ /dev/null @@ -1,89 +0,0 @@ -/* 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. - */ -/* Generic Quicksort in C, performs as fast as c++ std::sort(). -template params: -#define i_val - value type [required] -#define i_less - less function. default: *x < *y -#define i_tag NAME - define csort_NAME(). default {i_val} - -// test: -#include -#define i_val int -#include - -int main() { - int arr[] = {23, 321, 5434, 25, 245, 1, 654, 33, 543, 21}; - - csort_int(arr, c_arraylen(arr)); - - for (int i = 0; i < c_arraylen(arr); i++) - printf(" %d", arr[i]); - puts(""); -} -*/ -#include "../ccommon.h" -#define _i_prefix csort_ -#include "../priv/template.h" - -typedef i_val _cx_value; - -static inline void _cx_memb(_insertion)(i_val arr[], intptr_t lo, intptr_t hi) { - for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) { - i_val key = arr[i]; - while (j >= 0 && (i_less((&key), (&arr[j])))) { - arr[j + 1] = arr[j]; - --j; - } - arr[j + 1] = key; - } -} - -static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) { - intptr_t i = lo, j; - while (lo < hi) { - i_val pivot = arr[lo + (hi - lo)*7/16]; - j = hi; - - while (i <= j) { - while (i_less((&arr[i]), (&pivot))) ++i; - while (i_less((&pivot), (&arr[j]))) --j; - if (i <= j) { - c_swap(i_val, arr+i, arr+j); - ++i; --j; - } - } - if (j - lo > hi - i) { - c_swap(intptr_t, &lo, &i); - c_swap(intptr_t, &hi, &j); - } - - if (j - lo > 64) _cx_memb(_quicksort)(arr, lo, j); - else if (j > lo) _cx_memb(_insertion)(arr, lo, j); - lo = i; - } -} - -static inline void _cx_self(i_val arr[], intptr_t n) - { _cx_memb(_quicksort)(arr, 0, n - 1); } - -#include "../priv/template2.h" diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h new file mode 100644 index 00000000..20b7e1b3 --- /dev/null +++ b/include/stc/algo/sort.h @@ -0,0 +1,100 @@ +/* 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. + */ +/* Generic Quicksort in C, performs as fast as c++ std::sort(). +template params: +#define i_val - value type [required] +#define i_less - less function. default: *x < *y +#define i_tag name - define namearray_qsort(). i_tag defaults {i_val} + +// test: +#include +#define i_val int +#include + +int main() { + int arr[] = {23, 321, 5434, 25, 245, 1, 654, 33, 543, 21}; + + intarray_qsort(arr, c_arraylen(arr)); + + for (int i = 0; i < c_arraylen(arr); i++) + printf(" %d", arr[i]); + puts(""); +} +*/ +#include "../ccommon.h" +#ifndef i_type + #define i_at(arr, idx) (&arr[idx]) + #ifndef i_tag + #define i_tag i_val + #endif + #define i_type c_PASTE(i_tag, array) + typedef i_val i_type; +#endif +#ifndef i_at + #define i_at(arr, idx) _cx_memb(_at_mut)(arr, idx) +#endif +#include "../priv/template.h" + + +static inline void _cx_memb(_insertsort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) { + for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) { + i_val key = *i_at(arr, i); + while (j >= 0 && (i_less((&key), i_at(arr, j)))) { + *i_at(arr, j + 1) = *i_at(arr, j); + --j; + } + *i_at(arr, j + 1) = key; + } +} + +static inline void _cx_memb(_sort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) { + intptr_t i = lo, j; + while (lo < hi) { + i_val pivot = *i_at(arr, lo + (hi - lo)*7/16); + j = hi; + + while (i <= j) { + while (i_less(i_at(arr, i), (&pivot))) ++i; + while (i_less((&pivot), i_at(arr, j))) --j; + if (i <= j) { + c_swap(i_val, i_at(arr, i), i_at(arr, j)); + ++i; --j; + } + } + if (j - lo > hi - i) { + c_swap(intptr_t, &lo, &i); + c_swap(intptr_t, &hi, &j); + } + + if (j - lo > 64) _cx_memb(_sort_ij)(arr, lo, j); + else if (j > lo) _cx_memb(_insertsort_ij)(arr, lo, j); + lo = i; + } +} + +static inline void _cx_memb(_sort_n)(_cx_self* arr, intptr_t len) { + _cx_memb(_sort_ij)(arr, 0, len - 1); +} + +#include "../priv/template2.h" +#undef i_at diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index fd673696..07c72e2f 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -171,6 +171,16 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, return NULL; } +STC_INLINE intptr_t cnextpow2(intptr_t n) { + n--; + n |= n >> 1, n |= n >> 2; + n |= n >> 4, n |= n >> 8; + n |= n >> 16; + #if INTPTR_SIZE == INT64_SIZE + n |= n >> 32; + #endif + return n + 1; +} /* Control block macros */ #define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__) diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index ff6e744f..80dd1dbe 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -20,166 +20,82 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ccommon.h" - -#ifndef CDEQ_H_INCLUDED -#include "forward.h" -#include -#include - -#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref) -#define _it_ptr(it) (it.ref ? it.ref : it.end) -#endif // CDEQ_H_INCLUDED - -#ifndef _i_prefix #define _i_prefix cdeq_ +#define _pop _pop_front +#ifdef i_more + #include "cqueue.h" + #define i_more +#else + #define i_more + #include "cqueue.h" #endif -#include "priv/template.h" - -#ifndef i_is_forward -_cx_deftypes(_c_cdeq_types, _cx_self, i_key); -#endif -typedef i_keyraw _cx_raw; - -STC_API _cx_self _cx_memb(_init)(void); -STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n); -STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n); -STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); -STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } -STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); } -#if !defined _i_queue -#if !defined i_no_emplace -STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); -#endif // i_no_emplace - -#if !defined i_no_cmp || defined _i_has_eq -STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); -#endif -#ifndef i_no_cmp -STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); -#endif -STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); -STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -#endif // !_i_queue +#undef _pop -#if !defined i_no_emplace -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } -#endif +STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); +STC_API _cx_iter _cx_memb(_insert_n)(_cx_self* self, intptr_t idx, const _cx_value* arr, intptr_t n); +STC_API _cx_iter _cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw* raw, intptr_t n); +STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n); +STC_API void _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n); -#if !defined i_no_clone -#if !defined _i_queue -STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_INLINE const _cx_value* +_cx_memb(_at)(const _cx_self* self, intptr_t idx) + { return self->data + _cdeq_topos(self, idx); } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { - if (self->data == other->data) return; - _cx_memb(_clear)(self); - _cx_memb(_copy_range)(self, self->data, - other->data, other->data + other->_len); - } -#endif // !_i_queue -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_INLINE i_key _cx_memb(_value_clone)(i_key val) - { return i_keyclone(val); } -#endif // !i_no_clone -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; } -STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) - { return self->data + self->_len - 1; } -STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _i_queue - { i_keydrop(self->data); ++self->data; --self->_len; } +STC_INLINE _cx_value* +_cx_memb(_at_mut)(_cx_self* self, intptr_t idx) + { return self->data + _cdeq_topos(self, idx); } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - intptr_t n = self->_len; - return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n}; +STC_INLINE _cx_value* +_cx_memb(_push_back)(_cx_self* self, _cx_value val) { + return _cx_memb(_push)(self, val); } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; } - -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, size_t n) - { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } - -#if !defined _i_queue - -STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) - { return (it.ref - self->data); } -STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) - { _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } - -STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const intptr_t idx) { - assert(idx < self->_len); return self->data + idx; -} -STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) { - assert(idx < self->_len); return self->data + idx; +STC_INLINE void +_cx_memb(_pop_back)(_cx_self* self) { + assert(!_cx_memb(_empty)(self)); + self->end = (self->end - 1) & self->capmask; + i_keydrop((self->data + self->end)); } -STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { - return _cx_memb(_push)(self, value); -} -STC_INLINE _cx_iter -_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) { - return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); -} -STC_INLINE _cx_iter -_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { - return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); -} STC_INLINE _cx_iter -_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); +_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const _cx_value val) { + intptr_t idx = _cdeq_toidx(self, it.pos); + return _cx_memb(_insert_n)(self, idx, &val, 1); } -STC_INLINE _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { - return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); -} STC_INLINE _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); + _cx_memb(_erase_n)(self, _cdeq_toidx(self, it.pos), 1); + if (it.pos == self->end) it.ref = NULL; + return it; } + STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { - return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { + intptr_t idx1 = _cdeq_toidx(self, it1.pos); + intptr_t idx2 = _cdeq_toidx(self, it2.pos); + _cx_memb(_erase_n)(self, idx1, idx2 - idx1); + if (it1.pos == self->end) it1.ref = NULL; + return it1; } #if !defined i_no_emplace STC_INLINE _cx_value* -_cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) { - return _cx_memb(_push_front)(self, i_keyfrom(raw)); -} +_cx_memb(_emplace_front)(_cx_self* self, const _cx_raw raw) + { return _cx_memb(_push_front)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { - return _cx_memb(_push)(self, i_keyfrom(raw)); -} +STC_INLINE _cx_value* +_cx_memb(_emplace_back)(_cx_self* self, const _cx_raw raw) + { return _cx_memb(_push)(self, i_keyfrom(raw)); } STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) { - return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); -} -STC_INLINE _cx_iter -_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); -} -#endif // !i_no_emplace +_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, const _cx_raw raw) + { return _cx_memb(_insert_at)(self, it, i_keyfrom(raw)); } +#endif -#if !defined i_no_cmp || defined _i_has_eq +#if defined _i_has_eq || defined _i_has_cmp +STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); +STC_API bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other); STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_raw raw) { @@ -194,253 +110,88 @@ _cx_memb(_get)(const _cx_self* self, _cx_raw raw) { STC_INLINE _cx_value* _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* 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; -} #endif -#ifndef i_no_cmp - -STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { - qsort(i1.ref, (size_t)(_it2_ptr(i1, i2) - i1.ref), sizeof *i1.ref, - (int(*)(const void*, const void*)) cmp); -} - -STC_INLINE void -_cx_memb(_sort)(_cx_self* self) { - _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); -} -#endif // !c_no_cmp -#endif // _i_queue /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) -#define _cdeq_nfront(self) ((self)->data - (self)->_base) - -STC_DEF _cx_self -_cx_memb(_init)(void) { - _cx_self cx = {NULL}; - return cx; -} - -STC_DEF void -_cx_memb(_clear)(_cx_self* self) { - if (self->_cap) { - for (_cx_value *p = self->data, *q = p + self->_len; p != q; ) - { --q; i_keydrop(q); } - self->_len = 0; - self->data = self->_base; - } -} - -STC_DEF void -_cx_memb(_shrink_to_fit)(_cx_self *self) { - if (self->_len != self->_cap) { - c_memmove(self->_base, self->data, self->_len*c_sizeof(i_key)); - _cx_value* d = (_cx_value*)i_realloc(self->_base, self->_len*c_sizeof(i_key)); - if (d) { - self->_base = d; - self->_cap = self->_len; - } - self->data = self->_base; - } -} - -STC_DEF void -_cx_memb(_drop)(_cx_self* self) { - if (self->_base) { - _cx_memb(_clear)(self); - i_free(self->_base); - } -} - -static intptr_t -_cx_memb(_realloc_)(_cx_self* self, const intptr_t n) { - const intptr_t cap = (intptr_t)((float)self->_len*1.7f) + n + 7; - const intptr_t nfront = _cdeq_nfront(self); - _cx_value* d = (_cx_value*)i_realloc(self->_base, cap*c_sizeof(i_key)); - if (!d) - return 0; - self->_cap = cap; - self->_base = d; - self->data = d + nfront; - return cap; -} - -static bool -_cx_memb(_expand_right_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) { - const intptr_t sz = self->_len, cap = self->_cap; - const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; - if (nback >= n || (intptr_t)((float)sz*1.3f) + n > cap) { - if (!_cx_memb(_realloc_)(self, n)) - return false; - c_memmove(self->data + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); - } else { -#if !defined _i_queue - const intptr_t unused = cap - (sz + n); - const intptr_t pos = (nfront*2 < unused) ? nfront : unused/2; -#else - const intptr_t pos = 0; -#endif - c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key)); - c_memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); - self->data = self->_base + pos; - } - return true; -} - -STC_DEF _cx_self -_cx_memb(_with_capacity)(const intptr_t n) { - _cx_self cx = _cx_memb(_init)(); - _cx_memb(_expand_right_half_)(&cx, 0, n); - return cx; -} - -STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t n) { - const intptr_t sz = self->_len; - return n <= sz || _cx_memb(_expand_right_half_)(self, sz, n - sz); -} STC_DEF _cx_value* -_cx_memb(_push)(_cx_self* self, i_key value) { - if (_cdeq_nfront(self) + self->_len == self->_cap) - _cx_memb(_expand_right_half_)(self, self->_len, 1); - _cx_value *v = self->data + self->_len++; +_cx_memb(_push_front)(_cx_self* self, i_key value) { + intptr_t start = (self->start - 1) & self->capmask; + if (start == self->end) { // full + _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand + start = (self->start - 1) & self->capmask; + } + _cx_value *v = self->data + start; + self->start = start; *v = value; return v; } -#if !defined i_no_clone -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - _cx_self out = _cx_memb(_with_capacity)(cx._len); - if (out._base) - for (intptr_t i = 0; i < cx._len; ++i) - out.data[i] = i_keyclone(cx.data[i]); - return out; -} -#endif - -#if !defined _i_queue - -static void -_cx_memb(_expand_left_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) { - intptr_t cap = self->_cap; - const intptr_t sz = self->_len; - const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; - if (nfront >= n) { - self->data = (_cx_value *)c_memmove(self->data - n, self->data, idx*c_sizeof(i_key)); - } else { - if ((intptr_t)((float)sz*1.3f) + n > cap) - cap = _cx_memb(_realloc_)(self, n); - const intptr_t unused = cap - (sz + n); - const intptr_t pos = (nback*2 < unused) ? unused - nback : unused/2; - c_memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key)); - self->data = (_cx_value *)c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key)); - } -} - -static _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) { - if (n) { - if (!pos) pos = self->data + self->_len; - const intptr_t idx = (pos - self->data); - if (idx*2 < self->_len) - _cx_memb(_expand_left_half_)(self, idx, n); - else - _cx_memb(_expand_right_half_)(self, idx, n); - self->_len += n; - pos = self->data + idx; - } - return c_LITERAL(_cx_iter){pos, self->data + self->_len}; -} - -STC_DEF _cx_value* -_cx_memb(_push_front)(_cx_self* self, i_key value) { - if (self->data == self->_base) - _cx_memb(_expand_left_half_)(self, 0, 1); - else - --self->data; - ++self->_len; - *self->data = value; - return self->data; +STC_DEF void +_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { + const intptr_t len = _cx_memb(_size)(self); + for (intptr_t i = idx + n - 1; i >= idx; --i) + i_keydrop(_cx_memb(_at_mut)(self, i)); + for (intptr_t i = idx, j = i + n; j < len; ++i, ++j) + *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j); + self->end = (self->end - n) & self->capmask; } STC_DEF _cx_iter -_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); - if (it.ref) - c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1); +_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { + const intptr_t len = _cx_memb(_size)(self); + _cx_iter it = {._s=self}; + if (len + n > self->capmask) + if (!_cx_memb(_reserve)(self, len + n)) + return it; + for (intptr_t j = len - 1, i = j + n; j >= idx; --j, --i) + *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j); + self->end = (self->end + n) & self->capmask; + it.pos = _cdeq_topos(self, idx); + it.ref = self->data + it.pos; return it; } STC_DEF _cx_iter -_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { - assert(p1 && p2); - intptr_t len = p2 - p1; - _cx_value* p = p1, *end = self->data + self->_len; - for (; p != p2; ++p) - { i_keydrop(p); } - c_memmove(p1, p2, (end - p2)*c_sizeof *p1); - self->_len -= len; - return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len}; -} - -#if !defined i_no_clone -STC_DEF _cx_iter -_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); - if (it.ref) - for (_cx_value* p = it.ref; p1 != p2; ++p1) - *p++ = i_keyclone((*p1)); +_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value* arr, const intptr_t n) { + _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); + for (intptr_t i = idx, j = 0; j < n; ++i, ++j) + *_cx_memb(_at_mut)(self, i) = arr[j]; return it; } -#endif // !i_no_clone -#if !defined i_no_emplace STC_DEF _cx_iter -_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); - if (it.ref) - for (_cx_value* p = it.ref; p1 != p2; ++p1) - *p++ = i_keyfrom((*p1)); +_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw* raw, const intptr_t n) { + _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); + for (intptr_t i = idx, j = 0; j < n; ++i, ++j) + *_cx_memb(_at_mut)(self, i) = i_keyfrom(raw[j]); return it; } -#endif // !i_no_emplace -#if !defined i_no_cmp || defined _i_has_eq +#if defined _i_has_eq || defined _i_has_cmp STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - const _cx_value* p2 = _it2_ptr(i1, i2); - for (; i1.ref != p2; ++i1.ref) { + for (; i1.ref; _cx_memb(_next)(&i1)) { const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) - return i1; + break; } - i2.ref = NULL; - return i2; + return i1; } -#endif -#ifndef i_no_cmp -STC_DEF int -_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { - const _cx_raw rx = i_keyto(x); - const _cx_raw ry = i_keyto(y); - return i_cmp((&rx), (&ry)); + +STC_DEF bool +_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), j = _cx_memb(_begin)(other); + i.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; + } + return true; } -#endif // !c_no_cmp -#endif // !_i_queue +#endif #endif // IMPLEMENTATION #define CDEQ_H_INCLUDED #include "priv/template2.h" diff --git a/include/stc/clist.h b/include/stc/clist.h index 65a1ac87..128e848d 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -109,8 +109,9 @@ STC_API _cx_value* _cx_memb(_push_back_node)(_cx_self* self, _cx_node* node STC_API _cx_value* _cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node); STC_API _cx_node* _cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref); STC_API void _cx_memb(_erase_after_node)(_cx_self* self, _cx_node* ref); -STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* vp) { return _clist_tonode(vp); } - +STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* pval) { return _clist_tonode(pval); } +STC_INLINE _cx_node* _cx_memb(_unlink_front_node)(_cx_self* self) + { return _cx_memb(_unlink_after_node)(self, self->last); } #if !defined i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self cx); STC_INLINE i_key _cx_memb(_value_clone)(i_key val) { return i_keyclone(val); } @@ -144,10 +145,10 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, i_key value) { return _cx_memb(_push_back)(self, value); } STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) { assert(!_cx_memb(_empty)(self)); _cx_memb(_erase_after_node)(self, self->last); } -STC_INLINE _cx_node* _cx_memb(_unlink_node_front)(_cx_self* self) - { return _cx_memb(_unlink_after_node)(self, self->last); } STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; } STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; } +STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } +STC_INLINE void _cx_memb(_value_drop)(_cx_value* pval) { i_keydrop(pval); } STC_INLINE intptr_t _cx_memb(_count)(const _cx_self* self) { diff --git a/include/stc/cmap.h b/include/stc/cmap.h index ec3238f6..4ba6156b 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -276,13 +276,6 @@ STC_INLINE intptr_t fastrange_1(uint64_t x, uint64_t n) STC_INLINE intptr_t fastrange_2(uint64_t x, uint64_t n) { return (intptr_t)(x & (n - 1)); } // n power of 2. -STC_INLINE uint64_t next_power_of_2(uint64_t n) { - n--; - n |= n >> 1, n |= n >> 2; - n |= n >> 4, n |= n >> 8; - n |= n >> 16, n |= n >> 32; - return n + 1; -} #endif // CMAP_H_INCLUDED STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) { @@ -422,7 +415,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) | 1; #if i_expandby == 2 - _newbucks = (intptr_t)next_power_of_2((uint64_t)_newbucks); + _newbucks = cnextpow2(_newbucks); #endif _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 254bc834..09a747e5 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -20,44 +20,198 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -// STC queue -/* -#include -#include - -#define i_key int -#include - -int main() { - int n = 10000000; - 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; i0; --i) { - int r = crand_unif(&rng, &dist); - if (r & 1) - ++n, cqueue_int_push(&Q, r); - else - --n, cqueue_int_pop(&Q); - } - printf("after: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q)); +#include "ccommon.h" + +#ifndef CQUEUE_H_INCLUDED +#include "forward.h" +#include +#include +#endif // CQUEUE_H_INCLUDED + +#ifndef _i_prefix +#define _i_prefix cqueue_ +#endif +#include "priv/template.h" + +#ifndef i_is_forward +_cx_deftypes(_c_cdeq_types, _cx_self, i_key); +#endif +typedef i_keyraw _cx_raw; + +STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n); +STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n); +STC_API void _cx_memb(_clear)(_cx_self* self); +STC_API void _cx_memb(_drop)(_cx_self* self); +STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); // push_back +STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); +STC_API _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n); + +#define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask) +#define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask) + +STC_INLINE _cx_self _cx_memb(_init)(void) + { _cx_self cx = {0}; return cx; } +STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); } + +#if !defined i_no_emplace +STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) + { return _cx_memb(_push)(self, i_keyfrom(raw)); } +#endif + +#if !defined i_no_clone +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +STC_INLINE i_key _cx_memb(_value_clone)(i_key val) + { return i_keyclone(val); } +#endif // !i_no_clone +STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) + { return _cdeq_toidx(self, self->end); } +STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) + { return self->capmask; } +STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) + { return self->start == self->end; } +STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) + { return i_keyto(pval); } + +STC_INLINE _cx_value* +_cx_memb(_front)(const _cx_self* self) + { return self->data + self->start; } + +STC_INLINE _cx_value* +_cx_memb(_back)(const _cx_self* self) + { return self->data + ((self->end - 1) & self->capmask); } + +STC_INLINE void +_cx_memb(_pop)(_cx_self* self) { // pop_front + c_ASSERT(!_cx_memb(_empty)(self)); + i_keydrop((self->data + self->start)); + self->start = (self->start + 1) & self->capmask; +} + +STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { + if (self->data == other->data) return; + _cx_memb(_drop)(self); + *self = _cx_memb(_clone)(*other); +} + +STC_INLINE _cx_iter +_cx_memb(_begin)(const _cx_self* self) { + return c_LITERAL(_cx_iter){ + _cx_memb(_empty)(self) ? NULL : self->data + self->start, + self->start, self + }; +} + +STC_INLINE _cx_iter +_cx_memb(_end)(const _cx_self* self) + { return c_LITERAL(_cx_iter){NULL, self->end, self}; } + +STC_INLINE void +_cx_memb(_next)(_cx_iter* it) { + if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; } + else { it->ref -= it->pos; it->pos = 0; } + if (it->pos == it->_s->end) it->ref = NULL; +} + +/* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined(i_implement) + +STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { + intptr_t len = _cx_memb(_size)(it._s); + intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos); + it.pos = (pos + n) & it._s->capmask; + it.ref += it.pos - pos; + if (!c_LTu(idx + n, len)) it.ref = NULL; + return it; +} + +STC_DEF void +_cx_memb(_clear)(_cx_self* self) { + c_foreach (i, _cx_self, *self) + { i_keydrop(i.ref); } + self->start = 0, self->end = 0; +} + +STC_DEF void +_cx_memb(_drop)(_cx_self* self) { + _cx_memb(_clear)(self); + i_free(self->data); +} + +STC_DEF _cx_self +_cx_memb(_with_capacity)(const intptr_t n) { + _cx_self cx = {0}; + _cx_memb(_reserve)(&cx, n); + return cx; +} + +STC_DEF bool +_cx_memb(_reserve)(_cx_self* self, const intptr_t n) { + if (n <= self->capmask) + return true; + intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1); + _cx_value* data = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data); + if (!data) + return false; + intptr_t head = oldcap - self->start; + if (self->start < self->end || self->start == 0) + ; + else if (head < self->end) { + self->start = newcap - head; + c_memmove(data + self->start, data + oldcap - head, head*c_sizeof *data); + } else { + c_memmove(data + oldcap, data, self->end*c_sizeof *data); + self->end += oldcap; } + self->capmask = newcap - 1; + self->data = data; + return true; } -*/ -#define _i_prefix cqueue_ -#define _i_queue -#define _pop_front _pop +STC_DEF _cx_value* +_cx_memb(_push)(_cx_self* self, i_key value) { // push_back + intptr_t end = (self->end + 1) & self->capmask; + if (end == self->start) { // full + _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand + end = (self->end + 1) & self->capmask; + } + _cx_value *v = self->data + self->end; + self->end = end; + *v = value; + return v; +} + +STC_DEF void +_cx_memb(_shrink_to_fit)(_cx_self *self) { + intptr_t sz = _cx_memb(_size)(self), j = 0; + if (sz > self->capmask/2) + return; + _cx_self out = _cx_memb(_with_capacity)(sz); + if (!out.data) + return; + c_foreach (i, _cx_self, *self) + out.data[j++] = *i.ref; + out.end = sz; + i_free(self->data); + *self = out; +} -#include "cdeq.h" +#if !defined i_no_clone +STC_DEF _cx_self +_cx_memb(_clone)(_cx_self cx) { + intptr_t sz = _cx_memb(_size)(&cx), j = 0; + _cx_self out = _cx_memb(_with_capacity)(sz); + if (out.data) + c_foreach (i, _cx_self, cx) + out.data[j++] = i_keyclone((*i.ref)); + out.end = sz; + return out; +} -#undef _pop_front -#undef _i_queue +#endif // i_no_clone +#endif // IMPLEMENTATION +#include "priv/template2.h" +#define CQUEUE_H_INCLUDED diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 3cbd90b7..a7eb1a05 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -81,10 +81,8 @@ STC_API void _cx_memb(_clear)(_cx_self* self); STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap); STC_API bool _cx_memb(_resize)(_cx_self* self, intptr_t size, i_key null); STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); -STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n); +STC_API _cx_iter _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n); +STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n); #if !defined i_no_cmp || defined _i_has_eq STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw); #endif @@ -95,26 +93,23 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); } #if !defined i_no_emplace -STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) { - return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); +STC_API _cx_iter +_cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw raw[], intptr_t n); + +STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { + return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter -_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); +STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { + return _cx_memb(_push)(self, i_keyfrom(raw)); +} +STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { + return _cx_memb(_emplace_n)(self, _it_ptr(it) - self->data, &raw, 1); } #endif // !i_no_emplace #if !defined i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_copy_n)(_cx_self* self, intptr_t idx, const _cx_value arr[], intptr_t n); STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) @@ -124,8 +119,7 @@ STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { if (self->data == other->data) return; _cx_memb(_clear)(self); - _cx_memb(_copy_range)(self, self->data, other->data, - other->data + other->_len); + _cx_memb(_copy_n)(self, 0, other->data, other->_len); } #endif // !i_no_clone @@ -161,31 +155,29 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, _cx_memb(_size)(self)); } - -STC_INLINE _cx_iter -_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) { - return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); -} STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { - return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); + _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); + if (it.ref) + c_memcpy(it.ref, arr, n*c_sizeof *arr); + return it; } STC_INLINE _cx_iter -_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); +_cx_memb(_insert)(_cx_self* self, const intptr_t idx, const i_key value) { + return _cx_memb(_insert_n)(self, idx, &value, 1); } - STC_INLINE _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { - return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); +_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const i_key value) { + return _cx_memb(_insert_n)(self, _it_ptr(it) - self->data, &value, 1); } + STC_INLINE _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); + return _cx_memb(_erase_n)(self, it.ref - self->data, 1); } STC_INLINE _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { - return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); + return _cx_memb(_erase_n)(self, i1.ref - self->data, _it2_ptr(i1, i2) - i1.ref); } STC_INLINE const _cx_value* @@ -329,73 +321,58 @@ _cx_memb(_push)(_cx_self* self, i_key value) { } STC_DEF _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) { - if (n) { - if (!pos) pos = self->data + self->_len; - const intptr_t idx = (pos - self->data); - if (self->_len + n > self->_cap) { - if (!_cx_memb(_reserve)(self, self->_len*3/2 + n)) - return _cx_memb(_end)(self); - pos = self->data + idx; - } - c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos); - self->_len += n; - } +_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { + if (self->_len + n > self->_cap) + if (!_cx_memb(_reserve)(self, self->_len*3/2 + n)) + return _cx_memb(_end)(self); + + _cx_value* pos = self->data + idx; + c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos); + self->_len += n; return c_LITERAL(_cx_iter){pos, self->data + self->_len}; } STC_DEF _cx_iter -_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); - if (it.ref) - c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1); - return it; -} - -STC_DEF _cx_iter -_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { - intptr_t len = (p2 - p1); - _cx_value* p = p1, *end = self->data + self->_len; - for (; p != p2; ++p) +_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t len) { + _cx_value* d = self->data + idx, *p = d, *end = self->data + self->_len; + for (intptr_t i = 0; i < len; ++i, ++p) { i_keydrop(p); } - c_memmove(p1, p2, (end - p2)*c_sizeof *p1); + c_memmove(d, p, (end - p)*c_sizeof *d); self->_len -= len; - return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len}; + return c_LITERAL(_cx_iter){p == end ? NULL : d, end - len}; } #if !defined i_no_clone STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { _cx_self out = _cx_memb(_init)(); - _cx_memb(_copy_range)(&out, out.data, cx.data, cx.data + cx._len); + _cx_memb(_copy_n)(&out, 0, cx.data, cx._len); return out; } STC_DEF _cx_iter -_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); +_cx_memb(_copy_n)(_cx_self* self, const intptr_t idx, + const _cx_value arr[], const intptr_t n) { + _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); if (it.ref) - for (_cx_value* p = it.ref; p1 != p2; ++p1) - *p++ = i_keyclone((*p1)); + for (_cx_value* p = it.ref, *q = p + n; p != q; ++arr) + *p++ = i_keyclone((*arr)); return it; } #endif // !i_no_clone #if !defined i_no_emplace STC_DEF _cx_iter -_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2) { - _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1)); +_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw raw[], intptr_t n) { + _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); if (it.ref) - for (_cx_value* p = it.ref; p1 != p2; ++p1) - *p++ = i_keyfrom((*p1)); + for (_cx_value* p = it.ref; n--; ++raw, ++p) + *p = i_keyfrom((*raw)); return it; } #endif // !i_no_emplace - #if !defined i_no_cmp || defined _i_has_eq + STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { const _cx_value* p2 = _it2_ptr(i1, i2); diff --git a/include/stc/forward.h b/include/stc/forward.h index b534e48b..9eafb857 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -81,12 +81,17 @@ typedef union { #define _c_cdeq_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ \ typedef struct SELF { \ - SELF##_value *_base, *data; \ - intptr_t _len, _cap; \ - } SELF + SELF##_value *data; \ + intptr_t start, end, capmask; \ + } SELF; \ +\ + typedef struct { \ + SELF##_value *ref; \ + intptr_t pos; \ + const SELF* _s; \ + } SELF##_iter #define _c_clist_types(SELF, VAL) \ typedef VAL SELF##_value; \ diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index 2605a434..f70281c7 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -20,9 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifdef _i_template - #error template.h already included -#endif +#ifndef _i_template #define _i_template #ifndef STC_TEMPLATE_H_INCLUDED @@ -107,6 +105,9 @@ #ifdef i_eq #define _i_has_eq #endif +#if defined i_cmp || defined i_less + #define _i_has_cmp +#endif #if defined i_key_str #define i_keyclass cstr @@ -288,3 +289,4 @@ #ifndef _i_has_from #define i_no_emplace #endif +#endif diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h index 2e8a6c8d..66ed7739 100644 --- a/include/stc/priv/template2.h +++ b/include/stc/priv/template2.h @@ -20,6 +20,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#ifdef i_more +#undef i_more +#else #undef i_type #undef i_tag #undef i_imp @@ -74,4 +77,6 @@ #undef _i_expandby #undef _i_has_from #undef _i_has_eq +#undef _i_has_cmp #undef _i_template +#endif \ No newline at end of file diff --git a/misc/benchmarks/various/csort_bench.c b/misc/benchmarks/various/csort_bench.c index d5d7fa7c..4d1149fc 100644 --- a/misc/benchmarks/various/csort_bench.c +++ b/misc/benchmarks/various/csort_bench.c @@ -5,8 +5,12 @@ #ifdef __cplusplus #include #endif +#define NDEBUG +#define i_type Ints #define i_val int -#include +#define i_more +#include +#include #define ROTL(d,bits) ((d<<(bits)) | (d>>(8*sizeof(d)-(bits)))) uint64_t romutrio(uint64_t s[3]) { @@ -21,14 +25,14 @@ static int cmp_int(const void* a, const void* b) { return c_default_cmp((const int*)a, (const int*)b); } -void testsort(int *a, int size, const char *desc) { +void testsort(Ints *a, int size, const char *desc) { clock_t t = clock(); #ifdef __cplusplus - printf("std::sort: "); std::sort(a, a + size); + printf("std::sort: "); std::sort(a->data, a->data + size); #elif defined QSORT - printf("qsort: "); qsort(a, size, sizeof *a, cmp_int); + printf("qsort: "); qsort(a->data, size, sizeof *a->data, cmp_int); #else - printf("stc_sort: "); csort_int(a, size); + printf("stc_qsort: "); Ints_sort_n(a, size); #endif t = clock() - t; @@ -41,27 +45,27 @@ int main(int argc, char *argv[]) { size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000; uint64_t s[3] = {123456789, 3456789123, 789123456}; - int32_t *a = (int32_t*)malloc(sizeof(*a) * size); - if (!a) return -1; + Ints a = Ints_with_capacity(size); for (i = 0; i < size; i++) - a[i] = romutrio(s) & (1U << 30) - 1; - testsort(a, size, "random"); + *Ints_push(&a, romutrio(s) & (1U << 30) - 1); + testsort(&a, size, "random"); for (i = 0; i < 20; i++) - printf(" %d", (int)a[i]); + printf(" %d", (int)*Ints_at(&a, i)); puts(""); for (i = 0; i < size; i++) - a[i] = i; - testsort(a, size, "sorted"); + *Ints_at_mut(&a, i) = i; + testsort(&a, size, "sorted"); for (i = 0; i < size; i++) - a[i] = size - i; - testsort(a, size, "reverse sorted"); + *Ints_at_mut(&a, i) = size - i; + testsort(&a, size, "reverse sorted"); for (i = 0; i < size; i++) - a[i] = 126735; - testsort(a, size, "constant"); + *Ints_at_mut(&a, i) = 126735; + testsort(&a, size, "constant"); for (i = 0; i < size; i++) - a[i] = i + 1; - a[size - 1] = 0; - testsort(a, size, "rotated"); - free(a); + *Ints_at_mut(&a, i) = i + 1; + *Ints_at_mut(&a, size - 1) = 0; + testsort(&a, size, "rotated"); + + Ints_drop(&a); } diff --git a/misc/benchmarks/various/cspan_bench.c b/misc/benchmarks/various/cspan_bench.c index 589df13a..02ae3237 100644 --- a/misc/benchmarks/various/cspan_bench.c +++ b/misc/benchmarks/various/cspan_bench.c @@ -1,4 +1,4 @@ -#define STC_NDEBUG +#define NDEBUG #include #include #include diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index 7459ac77..60a2d934 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -6,8 +6,6 @@ #include #define i_val int #include -#define i_val int -#include #define i_val_str #include #include @@ -40,9 +38,6 @@ int main() cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7}); printMe( (intspan)cspan_from(&stk) ); - cdeq_int deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8}); - printMe( (intspan)cspan_from(&deq) ); - csset_str set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"}); printf("%d:", (int)csset_str_size(&set)); c_foreach (e, csset_str, set) @@ -52,6 +47,5 @@ int main() // cleanup cvec_int_drop(&vec); cstack_int_drop(&stk); - cdeq_int_drop(&deq); csset_str_drop(&set); } diff --git a/src/cregex.c b/src/cregex.c index a1d43944..981a256a 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -1220,7 +1220,7 @@ _build_subst(const char* replace, int nmatch, const csview match[], if (g < (int)nmatch) { csview m = mfun && mfun(g, match[g], &mstr) ? cstr_sv(&mstr) : match[g]; if (len + m.size > cap) - dst = cstr_reserve(subst, cap = cap*3/2 + m.size); + dst = cstr_reserve(subst, cap += cap*3/2 + m.size); for (int i = 0; i < (int)m.size; ++i) dst[len++] = m.str[i]; } -- cgit v1.2.3 From 80df921622c97634aeea31821a61f46885324d9c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 29 May 2023 20:42:43 +0200 Subject: Update extern benchmark maps. Removed i_expandby in cmap. Always expand by 2 i.e 2^n buckets.. --- include/stc/cmap.h | 22 ++++------------------ misc/benchmarks/external/ankerl/unordered_dense.h | 6 +++--- misc/benchmarks/external/emhash/hash_table7.hpp | 2 +- misc/examples/scheduler.c | 6 +++--- 4 files changed, 11 insertions(+), 25 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 4ba6156b..837631f8 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -265,18 +265,7 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #ifndef i_max_load_factor #define i_max_load_factor 0.80f #endif -#ifndef i_expandby - #define i_expandby 2 -#endif - -#ifndef CMAP_H_INCLUDED -STC_INLINE intptr_t fastrange_1(uint64_t x, uint64_t n) - { return (intptr_t)((uint32_t)x*n >> 32); } // n < 2^32 - -STC_INLINE intptr_t fastrange_2(uint64_t x, uint64_t n) - { return (intptr_t)(x & (n - 1)); } // n power of 2. - -#endif // CMAP_H_INCLUDED +#define fastrange_2(x, n) (intptr_t)((x) & (size_t)((n) - 1)) // n power of 2. STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) { _cx_iter it = {self->data, self->data+self->bucket_count, self->slot}; @@ -356,7 +345,7 @@ STC_DEF chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); intptr_t _cap = self->bucket_count; - chash_bucket b = {c_PASTE(fastrange_,i_expandby)(_hash, (uint64_t)_cap), (uint8_t)(_hash | 0x80)}; + chash_bucket b = {fastrange_2(_hash, _cap), (uint8_t)(_hash | 0x80)}; const chash_slot* s = self->slot; while (s[b.idx].hashx) { if (s[b.idx].hashx == b.hashx) { @@ -413,10 +402,8 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { const intptr_t _oldbucks = self->bucket_count; if (_newcap != self->size && _newcap <= _oldbucks) return true; - intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) | 1; - #if i_expandby == 2 + intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; _newbucks = cnextpow2(_newbucks); - #endif _cx_self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), @@ -452,7 +439,7 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { if (! s[j].hashx) break; const _cx_keyraw _raw = i_keyto(_i_keyref(d + j)); - k = (intptr_t)c_PASTE(fastrange_,i_expandby)(i_hash((&_raw)), (uint64_t)_cap); + k = fastrange_2(i_hash((&_raw)), _cap); if ((j < i) ^ (k <= i) ^ (k > j)) { // is k outside (i, j]? d[i] = d[j]; s[i] = s[j]; @@ -464,7 +451,6 @@ _cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { } #endif // i_implement #undef i_max_load_factor -#undef i_expandby #undef _i_isset #undef _i_ismap #undef _i_keyref diff --git a/misc/benchmarks/external/ankerl/unordered_dense.h b/misc/benchmarks/external/ankerl/unordered_dense.h index dc4de8ab..b8cacea7 100644 --- a/misc/benchmarks/external/ankerl/unordered_dense.h +++ b/misc/benchmarks/external/ankerl/unordered_dense.h @@ -1,7 +1,7 @@ ///////////////////////// ankerl::unordered_dense::{map, set} ///////////////////////// // A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion. -// Version 4.0.0 +// Version 4.0.1 // https://github.com/martinus/unordered_dense // // Licensed under the MIT License . @@ -32,7 +32,7 @@ // see https://semver.org/spec/v2.0.0.html #define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 4 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes #define ANKERL_UNORDERED_DENSE_VERSION_MINOR 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible functionality -#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes +#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 1 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes // API versioning with inline namespace, see https://www.foonathan.net/2018/11/inline-namespaces/ @@ -1907,7 +1907,7 @@ auto erase_if(ankerl::unordered_dense::detail::table +#include static bool schedule(Scheduler* sched) { struct Task task = *Scheduler_front(sched); - Scheduler_pop_front(sched); + Scheduler_pop(sched); if (!cco_done(&task)) task.resume(&task); @@ -27,7 +27,7 @@ static bool schedule(Scheduler* sched) static bool push_task(const struct Task* task) { - Scheduler_push_back(task->sched, *task); + Scheduler_push(task->sched, *task); return false; } -- cgit v1.2.3 From 72b0f0e7839b487a5df7c79ffe84511480cad251 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 9 Jun 2023 19:31:59 +0200 Subject: Fixed issues with linking params i_implement, i_extern. --- docs/cregex_api.md | 6 +-- include/c11/fmt.h | 1 + include/stc/cbits.h | 6 +-- include/stc/ccommon.h | 2 +- include/stc/cdeq.h | 2 +- include/stc/clist.h | 2 +- include/stc/cmap.h | 2 +- include/stc/cpque.h | 2 +- include/stc/cqueue.h | 2 +- include/stc/crand.h | 2 +- include/stc/cregex.h | 10 ++-- include/stc/csmap.h | 2 +- include/stc/cspan.h | 2 +- include/stc/cstr.h | 102 ++++++++++++++++++++-------------------- include/stc/csview.h | 36 +++++++------- include/stc/cvec.h | 2 +- include/stc/forward.h | 1 + include/stc/utf8.h | 16 +++++-- misc/examples/arc_containers.c | 2 +- misc/examples/astar.c | 1 + misc/examples/books.c | 1 + misc/examples/box.c | 1 + misc/examples/complex.c | 3 +- misc/examples/convert.c | 2 +- misc/examples/coread.c | 2 +- misc/examples/csmap_erase.c | 1 + misc/examples/csmap_find.c | 1 + misc/examples/csmap_insert.c | 1 + misc/examples/cstr_match.c | 1 + misc/examples/demos.c | 1 + misc/examples/forfilter.c | 1 + misc/examples/gauss2.c | 3 +- misc/examples/hashmap.c | 1 + misc/examples/inits.c | 2 +- misc/examples/list_splice.c | 1 - misc/examples/make.sh | 2 +- misc/examples/mapmap.c | 2 +- misc/examples/mmap.c | 1 + misc/examples/multimap.c | 1 + misc/examples/music_arc.c | 1 + misc/examples/new_map.c | 1 + misc/examples/new_smap.c | 1 + misc/examples/new_sptr.c | 1 + misc/examples/person_arc.c | 1 + misc/examples/phonebook.c | 2 +- misc/examples/printspan.c | 1 + misc/examples/rawptr_elements.c | 2 +- misc/examples/read.c | 1 + misc/examples/regex_match.c | 1 + misc/examples/replace.c | 1 + misc/examples/splitstr.c | 1 + misc/examples/sso_map.c | 1 + misc/examples/sso_substr.c | 2 + misc/examples/sview_split.c | 2 + misc/examples/unordered_set.c | 1 + misc/examples/utf8replace_c.c | 1 + misc/examples/vikings.c | 1 + src/cregex.c | 19 +++++++- src/libstc.c | 12 +++++ src/utf8code.c | 5 +- 60 files changed, 180 insertions(+), 107 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/docs/cregex_api.md b/docs/cregex_api.md index e702c47c..fc86cc63 100644 --- a/docs/cregex_api.md +++ b/docs/cregex_api.md @@ -44,15 +44,15 @@ bool cregex_is_match(const cregex* re, const char* input); // Replace all matches in input cstr cregex_replace(const cregex* re, const char* input, const char* replace, int count = INT_MAX); - // Replace count matches in input string-view. Optionally transform replacement with mfun. + // Replace count matches in input string-view. Optionally transform replacement. cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count = INT_MAX); cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, int count, - bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags); + bool(*transform)(int group, csview match, cstr* result), int rflags); // All-in-one replacement (compile + find/replace + drop) cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count = INT_MAX); cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace, int count, - bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags); + bool(*transform)(int group, csview match, cstr* result), int rflags); // destroy void cregex_drop(cregex* self); ``` diff --git a/include/c11/fmt.h b/include/c11/fmt.h index 7e85e4dd..45044e33 100644 --- a/include/c11/fmt.h +++ b/include/c11/fmt.h @@ -69,6 +69,7 @@ int main() { */ #include #include +#include #include #define fmt_OVERLOAD(name, ...) \ diff --git a/include/stc/cbits.h b/include/stc/cbits.h index fe422202..8a6558bf 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -161,9 +161,9 @@ STC_INLINE void cbits_resize(cbits* self, const int64_t size, const bool value) if (new_n >= old_n) { c_memset(self->data64 + old_n, -(int)value, (new_n - old_n)*8); if (old_n > 0) { - uint64_t m = _cbits_bit(osize) - 1; /* mask */ - value ? (self->data64[old_n - 1] |= ~m) - : (self->data64[old_n - 1] &= m); + uint64_t mask = _cbits_bit(osize) - 1; + if (value) self->data64[old_n - 1] |= ~mask; + else self->data64[old_n - 1] &= mask; } } } diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 01ead57a..87522a6e 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -253,6 +253,6 @@ STC_INLINE intptr_t cnextpow2(intptr_t n) { #if defined(STC_EXTERN) #define i_extern #endif -#if defined(i_static) || defined(STC_IMPLEMENT) || defined(i_extern) +#if defined(STC_IMPLEMENT) || defined(i_extern) #define i_implement #endif diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index b3714bf8..8bb62602 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -113,7 +113,7 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw) #endif /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value) { diff --git a/include/stc/clist.h b/include/stc/clist.h index 128e848d..310db204 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -214,7 +214,7 @@ STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #endif // -------------------------- IMPLEMENTATION ------------------------- -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) #if !defined i_no_clone STC_DEF _cx_self diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 837631f8..f6c3eb07 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -261,7 +261,7 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { } /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) #ifndef i_max_load_factor #define i_max_load_factor 0.80f #endif diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 85002c67..31a53ece 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -108,7 +108,7 @@ STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) #endif // !i_no_emplace /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF void _cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) { diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 571c1fe9..28515877 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -121,7 +121,7 @@ STC_INLINE void _cx_memb(_adjust_end_)(_cx_self* self, intptr_t n) { self->end = (self->end + n) & self->capmask; } /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { intptr_t len = _cx_memb(_size)(it._s); diff --git a/include/stc/crand.h b/include/stc/crand.h index f566c1cf..b9687c01 100644 --- a/include/stc/crand.h +++ b/include/stc/crand.h @@ -92,7 +92,7 @@ STC_INLINE double crand_f64(crand_t* rng) { } /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) /* Global random() */ static crand_t crand_global = {{ diff --git a/include/stc/cregex.h b/include/stc/cregex.h index 919f5474..e6180a31 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -135,7 +135,7 @@ STC_INLINE bool cregex_is_match(const cregex* re, const char* input) #define cregex_replace_sv_4(pattern, input, replace, count) \ cregex_replace_sv_6(pattern, input, replace, count, NULL, CREG_DEFAULT) cstr cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, - bool (*mfun)(int i, csview match, cstr* mstr), int rflags); + bool (*transform)(int group, csview match, cstr* result), int rflags); /* replace input with replace using regular expression */ #define cregex_replace(...) c_MACRO_OVERLOAD(cregex_replace, __VA_ARGS__) @@ -153,20 +153,20 @@ STC_INLINE cstr cregex_replace_4(const cregex* re, const char* input, const char #define cregex_replace_pattern_4(pattern, input, replace, count) \ cregex_replace_pattern_6(pattern, input, replace, count, NULL, CREG_DEFAULT) cstr cregex_replace_pattern_6(const char* pattern, const char* input, const char* replace, int count, - bool (*mfun)(int i, csview match, cstr* mstr), int crflags); + bool (*transform)(int group, csview match, cstr* result), int crflags); /* destroy regex */ void cregex_drop(cregex* re); -#endif // CREGEX_H_INCLUDED -#if defined i_extern || defined i_implement +#if defined i_implement # include "../../src/cregex.c" #endif #if defined i_extern # include "../../src/utf8code.c" #endif +#endif // CREGEX_H_INCLUDED #undef i_opt #undef i_header #undef i_static -#undef i_implement #undef i_extern +#undef i_implement diff --git a/include/stc/csmap.h b/include/stc/csmap.h index e8138926..7638b8f2 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -249,7 +249,7 @@ _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF void _cx_memb(_next)(_cx_iter *it) { diff --git a/include/stc/cspan.h b/include/stc/cspan.h index b07e75a8..5b592098 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -212,7 +212,7 @@ STC_API intptr_t _cspan_slice(int32_t odim[], int32_t ostri[], int* orank, int rank, const int32_t a[][2]); /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF intptr_t _cspan_idxN(int rank, const int32_t shape[], const int32_t stri[], const int32_t a[]) { intptr_t off = a[0]; diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 03eefd2f..ae80dab4 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -24,16 +24,12 @@ /* A string type with short string optimization in C99 with good small-string * optimization (22 characters with 24 bytes string). */ +#define _i_no_undef +#include "utf8.h" + #ifndef CSTR_H_INCLUDED #define CSTR_H_INCLUDED -#define i_header -#if defined i_extern || defined STC_EXTERN -# define _i_extern -#endif -#include "ccommon.h" -#include "forward.h" -#include "utf8.h" #include /* malloc */ #include #include /* vsnprintf */ @@ -65,8 +61,8 @@ enum { cstr_s_cap = sizeof(cstr_buf) - 2 }; #define cstr_l_drop(s) c_free((s)->lon.data) #define cstr_is_long(s) ((s)->sml.size > 127) -STC_API char* _cstr_init(cstr* self, intptr_t len, intptr_t cap); -STC_API char* _cstr_internal_move(cstr* self, intptr_t pos1, intptr_t pos2); +extern char* _cstr_init(cstr* self, intptr_t len, intptr_t cap); +extern char* _cstr_internal_move(cstr* self, intptr_t pos1, intptr_t pos2); /**************************** PUBLIC API **********************************/ @@ -74,19 +70,21 @@ STC_API char* _cstr_internal_move(cstr* self, intptr_t pos1, intptr_t pos2); #define cstr_NULL (c_LITERAL(cstr){{{0}, 0}}) #define cstr_toraw(self) cstr_str(self) -STC_API char* cstr_reserve(cstr* self, intptr_t cap); -STC_API void cstr_shrink_to_fit(cstr* self); -STC_API char* cstr_resize(cstr* self, intptr_t size, char value); -STC_API intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); -STC_API char* cstr_assign_n(cstr* self, const char* str, intptr_t len); -STC_API char* cstr_append_n(cstr* self, const char* str, intptr_t len); -STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); -STC_API void cstr_erase(cstr* self, intptr_t pos, intptr_t len); -STC_API void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); -STC_API cstr cstr_from_fmt(const char* fmt, ...); -STC_API intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...); -STC_API intptr_t cstr_printf(cstr* self, const char* fmt, ...); -STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, int32_t count); +extern char* cstr_reserve(cstr* self, intptr_t cap); +extern void cstr_shrink_to_fit(cstr* self); +extern char* cstr_resize(cstr* self, intptr_t size, char value); +extern intptr_t cstr_find_at(const cstr* self, intptr_t pos, const char* search); +extern intptr_t cstr_find_sv(const cstr* self, csview search); +extern char* cstr_assign_n(cstr* self, const char* str, intptr_t len); +extern char* cstr_append_n(cstr* self, const char* str, intptr_t len); +extern bool cstr_getdelim(cstr *self, int delim, FILE *fp); +extern void cstr_erase(cstr* self, intptr_t pos, intptr_t len); +extern void cstr_u8_erase(cstr* self, intptr_t bytepos, intptr_t u8len); +extern cstr cstr_from_fmt(const char* fmt, ...); +extern intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...); +extern intptr_t cstr_printf(cstr* self, const char* fmt, ...); +extern cstr cstr_replace_sv(csview sv, csview search, csview repl, int32_t count); +extern uint64_t cstr_hash(const cstr *self); STC_INLINE cstr_buf cstr_buffer(cstr* s) { return cstr_is_long(s) @@ -284,8 +282,6 @@ STC_INLINE intptr_t cstr_find(const cstr* self, const char* search) { return res ? (res - str) : c_NPOS; } -STC_API intptr_t cstr_find_sv(const cstr* self, csview search); - STC_INLINE intptr_t cstr_find_s(const cstr* self, cstr search) { return cstr_find(self, cstr_str(&search)); } @@ -404,13 +400,15 @@ STC_INLINE void cstr_insert_s(cstr* self, intptr_t pos, cstr s) { cstr_replace_at_sv(self, pos, 0, sv); } - STC_INLINE bool cstr_getline(cstr *self, FILE *fp) { return cstr_getdelim(self, '\n', fp); } -STC_API uint64_t cstr_hash(const cstr *self); +#endif // CSTR_H_INCLUDED + +/* -------------------------- EXTERN ------------------------- */ +#if defined(i_extern) && !defined(CSTR_X_INCLUDED) +#define CSTR_X_INCLUDED -#ifdef _i_extern static struct { int (*conv_asc)(int); uint32_t (*conv_utf)(uint32_t); @@ -439,23 +437,25 @@ cstr cstr_tocase(csview sv, int k) { cstr_shrink_to_fit(&out); return out; } -#endif +#endif // i_extern /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#ifndef CSTR_C_INCLUDED +#if defined i_extern || (defined i_implement && !defined _i_no_undef) +#define CSTR_C_INCLUDED -STC_DEF uint64_t cstr_hash(const cstr *self) { +uint64_t cstr_hash(const cstr *self) { csview sv = cstr_sv(self); return cfasthash(sv.str, sv.size); } -STC_DEF intptr_t cstr_find_sv(const cstr* self, csview search) { +intptr_t cstr_find_sv(const cstr* self, csview search) { csview sv = cstr_sv(self); char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); return res ? (res - sv.str) : c_NPOS; } -STC_DEF char* _cstr_internal_move(cstr* self, const intptr_t pos1, const intptr_t pos2) { +char* _cstr_internal_move(cstr* self, const intptr_t pos1, const intptr_t pos2) { cstr_buf r = cstr_buffer(self); if (pos1 != pos2) { const intptr_t newlen = (r.size + pos2 - pos1); @@ -467,7 +467,7 @@ STC_DEF char* _cstr_internal_move(cstr* self, const intptr_t pos1, const intptr_ return r.data; } -STC_DEF char* _cstr_init(cstr* self, const intptr_t len, const intptr_t cap) { +char* _cstr_init(cstr* self, const intptr_t len, const intptr_t cap) { if (cap > cstr_s_cap) { self->lon.data = (char *)c_malloc(cap + 1); cstr_l_set_size(self, len); @@ -478,7 +478,7 @@ STC_DEF char* _cstr_init(cstr* self, const intptr_t len, const intptr_t cap) { return self->sml.data; } -STC_DEF void cstr_shrink_to_fit(cstr* self) { +void cstr_shrink_to_fit(cstr* self) { cstr_buf r = cstr_buffer(self); if (r.size == r.cap) return; @@ -492,7 +492,7 @@ STC_DEF void cstr_shrink_to_fit(cstr* self) { } } -STC_DEF char* cstr_reserve(cstr* self, const intptr_t cap) { +char* cstr_reserve(cstr* self, const intptr_t cap) { if (cstr_is_long(self)) { if (cap > cstr_l_cap(self)) { self->lon.data = (char *)c_realloc(self->lon.data, cap + 1); @@ -505,7 +505,7 @@ STC_DEF char* cstr_reserve(cstr* self, const intptr_t cap) { char* data = (char *)c_malloc(cap + 1); const intptr_t len = cstr_s_size(self); /* copy full short buffer to emulate realloc() */ - c_memcpy(data, self->sml.data, cstr_s_cap + 2); + c_memcpy(data, self->sml.data, sizeof self->sml); self->lon.data = data; self->lon.size = (size_t)len; cstr_l_set_cap(self, cap); @@ -514,7 +514,7 @@ STC_DEF char* cstr_reserve(cstr* self, const intptr_t cap) { return self->sml.data; } -STC_DEF char* cstr_resize(cstr* self, const intptr_t size, const char value) { +char* cstr_resize(cstr* self, const intptr_t size, const char value) { cstr_buf r = cstr_buffer(self); if (size > r.size) { if (size > r.cap && !(r.data = cstr_reserve(self, size))) @@ -525,20 +525,20 @@ STC_DEF char* cstr_resize(cstr* self, const intptr_t size, const char value) { return r.data; } -STC_DEF intptr_t cstr_find_at(const cstr* self, const intptr_t pos, const char* search) { +intptr_t cstr_find_at(const cstr* self, const intptr_t pos, const char* search) { csview sv = cstr_sv(self); if (pos > sv.size) return c_NPOS; const char* res = strstr((char*)sv.str + pos, search); return res ? (res - sv.str) : c_NPOS; } -STC_DEF char* cstr_assign_n(cstr* self, const char* str, const intptr_t len) { +char* cstr_assign_n(cstr* self, const char* str, const intptr_t len) { char* d = cstr_reserve(self, len); if (d) { c_memmove(d, str, len); _cstr_set_size(self, len); } return d; } -STC_DEF char* cstr_append_n(cstr* self, const char* str, const intptr_t len) { +char* cstr_append_n(cstr* self, const char* str, const intptr_t len) { cstr_buf r = cstr_buffer(self); if (r.size + len > r.cap) { const size_t off = (size_t)(str - r.data); @@ -551,7 +551,7 @@ STC_DEF char* cstr_append_n(cstr* self, const char* str, const intptr_t len) { return r.data; } -STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { +bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { int c = fgetc(fp); if (c == EOF) return false; @@ -571,7 +571,7 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { } } -STC_DEF cstr +cstr cstr_replace_sv(csview in, csview search, csview repl, int32_t count) { cstr out = cstr_NULL; intptr_t from = 0; char* res; @@ -587,14 +587,14 @@ cstr_replace_sv(csview in, csview search, csview repl, int32_t count) { return out; } -STC_DEF void cstr_erase(cstr* self, const intptr_t pos, intptr_t len) { +void cstr_erase(cstr* self, const intptr_t pos, intptr_t len) { cstr_buf r = cstr_buffer(self); if (len > r.size - pos) len = r.size - pos; c_memmove(&r.data[pos], &r.data[pos + len], r.size - (pos + len)); _cstr_set_size(self, r.size - len); } -STC_DEF void cstr_u8_erase(cstr* self, const intptr_t bytepos, const intptr_t u8len) { +void cstr_u8_erase(cstr* self, const intptr_t bytepos, const intptr_t u8len) { cstr_buf r = cstr_buffer(self); intptr_t len = utf8_pos(r.data + bytepos, u8len); c_memmove(&r.data[bytepos], &r.data[bytepos + len], r.size - (bytepos + len)); @@ -609,7 +609,7 @@ STC_DEF void cstr_u8_erase(cstr* self, const intptr_t bytepos, const intptr_t u8 # pragma warning(disable: 4996) #endif -STC_DEF intptr_t cstr_vfmt(cstr* self, intptr_t start, const char* fmt, va_list args) { +intptr_t cstr_vfmt(cstr* self, intptr_t start, const char* fmt, va_list args) { va_list args2; va_copy(args2, args); const int n = vsnprintf(NULL, 0ULL, fmt, args); @@ -624,7 +624,7 @@ STC_DEF intptr_t cstr_vfmt(cstr* self, intptr_t start, const char* fmt, va_list # pragma warning(pop) #endif -STC_DEF cstr cstr_from_fmt(const char* fmt, ...) { +cstr cstr_from_fmt(const char* fmt, ...) { cstr s = cstr_NULL; va_list args; va_start(args, fmt); @@ -633,7 +633,7 @@ STC_DEF cstr cstr_from_fmt(const char* fmt, ...) { return s; } -STC_DEF intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...) { +intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...) { va_list args; va_start(args, fmt); const intptr_t n = cstr_vfmt(self, cstr_size(self), fmt, args); @@ -642,21 +642,21 @@ STC_DEF intptr_t cstr_append_fmt(cstr* self, const char* fmt, ...) { } /* NB! self-data in args is UB */ -STC_DEF intptr_t cstr_printf(cstr* self, const char* fmt, ...) { +intptr_t cstr_printf(cstr* self, const char* fmt, ...) { va_list args; va_start(args, fmt); const intptr_t n = cstr_vfmt(self, 0, fmt, args); va_end(args); return n; } - #endif // i_implement +#endif // CSTR_C_INCLUDED + #if defined __GNUC__ && !defined __clang__ # pragma GCC diagnostic pop #endif -#endif // CSTR_H_INCLUDED #undef i_opt #undef i_header #undef i_static #undef i_implement -#undef _i_extern +#undef i_extern diff --git a/include/stc/csview.h b/include/stc/csview.h index e8a3ad9b..d38d5f59 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -20,12 +20,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#define _i_no_undef +#include "utf8.h" + #ifndef CSVIEW_H_INCLUDED #define CSVIEW_H_INCLUDED -#include "ccommon.h" -#include "utf8.h" - #define csview_NULL c_sv_1("") #define csview_init() csview_NULL #define csview_drop(p) c_default_drop(p) @@ -33,12 +33,12 @@ #define csview_lit(literal) c_sv_1(literal) #define csview_from_n(str, n) c_sv_2(str, n) -STC_API csview_iter csview_advance(csview_iter it, intptr_t pos); -STC_API intptr_t csview_find_sv(csview sv, csview search); -STC_API uint64_t csview_hash(const csview *self); -STC_API csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); -STC_API csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); -STC_API csview csview_token(csview sv, const char* sep, intptr_t* start); +extern csview_iter csview_advance(csview_iter it, intptr_t pos); +extern intptr_t csview_find_sv(csview sv, csview search); +extern uint64_t csview_hash(const csview *self); +extern csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2); +extern csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n); +extern csview csview_token(csview sv, const char* sep, intptr_t* start); STC_INLINE csview csview_from(const char* str) { return c_LITERAL(csview){str, c_strlen(str)}; } @@ -147,10 +147,14 @@ STC_INLINE int csview_icmp(const csview* x, const csview* y) STC_INLINE bool csview_eq(const csview* x, const csview* y) { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } +#endif // CSVIEW_H_INCLUDED + /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#ifndef CSVIEW_C_INCLUDED +#if defined i_extern || (defined i_implement && !defined _i_no_undef) +#define CSVIEW_C_INCLUDED -STC_DEF csview_iter csview_advance(csview_iter it, intptr_t pos) { +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; @@ -159,15 +163,15 @@ STC_DEF csview_iter csview_advance(csview_iter it, intptr_t pos) { return it; } -STC_DEF intptr_t csview_find_sv(csview sv, csview search) { +intptr_t csview_find_sv(csview sv, csview search) { char* res = cstrnstrn(sv.str, search.str, sv.size, search.size); return res ? (res - sv.str) : c_NPOS; } -STC_DEF uint64_t csview_hash(const csview *self) +uint64_t csview_hash(const csview *self) { return cfasthash(self->str, self->size); } -STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { +csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { if (pos < 0) { pos += sv.size; if (pos < 0) pos = 0; @@ -178,7 +182,7 @@ STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { return sv; } -STC_DEF csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { +csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { if (p1 < 0) { p1 += sv.size; if (p1 < 0) p1 = 0; @@ -189,7 +193,7 @@ STC_DEF csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { return sv; } -STC_DEF csview csview_token(csview sv, const char* sep, intptr_t* start) { +csview csview_token(csview sv, const char* sep, intptr_t* start) { intptr_t sep_size = c_strlen(sep); csview slice = {sv.str + *start, sv.size - *start}; const char* res = cstrnstrn(slice.str, sep, slice.size, sep_size); diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 512dbf67..747c654d 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -264,7 +264,7 @@ _cx_memb(_sort)(_cx_self* self) { } #endif // !c_no_cmp /* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) +#if defined(i_implement) || defined(i_static) STC_DEF _cx_self _cx_memb(_init)(void) { diff --git a/include/stc/forward.h b/include/stc/forward.h index 9eafb857..484a8b63 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -24,6 +24,7 @@ #define STC_FORWARD_H_INCLUDED #include +#include #define forward_carc(CX, VAL) _c_carc_types(CX, VAL) #define forward_cbox(CX, VAL) _c_cbox_types(CX, VAL) diff --git a/include/stc/utf8.h b/include/stc/utf8.h index a4cc3846..338f0db9 100644 --- a/include/stc/utf8.h +++ b/include/stc/utf8.h @@ -1,3 +1,4 @@ + #ifndef UTF8_H_INCLUDED #define UTF8_H_INCLUDED @@ -5,7 +6,6 @@ #include "forward.h" #include "ccommon.h" -// utf8 methods defined in src/utf8code.c: enum { U8G_Cc, U8G_Lt, U8G_Nd, U8G_Nl, U8G_Pc, U8G_Pd, U8G_Pf, U8G_Pi, @@ -16,6 +16,7 @@ enum { U8G_SIZE }; +// utf8 methods defined in src/utf8code.c: extern bool utf8_isgroup(int group, uint32_t c); extern bool utf8_isalpha(uint32_t c); extern uint32_t utf8_casefold(uint32_t c); @@ -112,9 +113,16 @@ STC_INLINE const char* utf8_at(const char *s, intptr_t index) { STC_INLINE intptr_t utf8_pos(const char* s, intptr_t index) { return (intptr_t)(utf8_at(s, index) - s); } - #endif // UTF8_H_INCLUDED -#if defined(i_extern) + +#if defined i_extern || (defined i_implement && !defined _i_no_undef) # include "../../src/utf8code.c" -# undef i_extern #endif +#ifndef _i_no_undef +#undef i_static +#undef i_header +#undef i_implement +#undef i_extern +#undef i_opt +#endif +#undef _i_no_undef diff --git a/misc/examples/arc_containers.c b/misc/examples/arc_containers.c index d6a0afa8..7038734e 100644 --- a/misc/examples/arc_containers.c +++ b/misc/examples/arc_containers.c @@ -1,6 +1,6 @@ // Create a stack and a list of shared pointers to maps, // and demonstrate sharing and cloning of maps. -#define i_static +#define i_implement #include #include #define i_type Map diff --git a/misc/examples/astar.c b/misc/examples/astar.c index dae6d609..db6bbd70 100644 --- a/misc/examples/astar.c +++ b/misc/examples/astar.c @@ -4,6 +4,7 @@ // This is a reimplementation of the CTL example to STC: // https://github.com/glouw/ctl/blob/master/examples/astar.c // https://www.redblobgames.com/pathfinding/a-star/introduction.html +#define i_implement #include #include #include diff --git a/misc/examples/books.c b/misc/examples/books.c index a62769b0..7f0660b8 100644 --- a/misc/examples/books.c +++ b/misc/examples/books.c @@ -1,4 +1,5 @@ // https://doc.rust-lang.org/std/collections/struct.HashMap.html +#define i_implement #include #define i_key_str #define i_val_str diff --git a/misc/examples/box.c b/misc/examples/box.c index 9954883c..e352aa2b 100644 --- a/misc/examples/box.c +++ b/misc/examples/box.c @@ -1,4 +1,5 @@ /* cbox: heap allocated boxed type */ +#define i_implement #include typedef struct { cstr name, last; } Person; diff --git a/misc/examples/complex.c b/misc/examples/complex.c index c730db33..2d8dbf62 100644 --- a/misc/examples/complex.c +++ b/misc/examples/complex.c @@ -5,10 +5,9 @@ // using StackList = std::stack; // using ListMap = std::unordered_map>; // using MapMap = std::unordered_map; - +#define i_implement #include - #define i_type FloatStack #define i_val float #include diff --git a/misc/examples/convert.c b/misc/examples/convert.c index c5649c55..318f09b8 100644 --- a/misc/examples/convert.c +++ b/misc/examples/convert.c @@ -1,3 +1,4 @@ +#define i_implement #include #include @@ -9,7 +10,6 @@ #include #define i_val_str -#define i_extern // define _clist_mergesort() once #include int main() diff --git a/misc/examples/coread.c b/misc/examples/coread.c index 2585fb81..63162ba3 100644 --- a/misc/examples/coread.c +++ b/misc/examples/coread.c @@ -1,4 +1,4 @@ -#define i_static +#define i_implement #include #include #include diff --git a/misc/examples/csmap_erase.c b/misc/examples/csmap_erase.c index 568dae29..9433d370 100644 --- a/misc/examples/csmap_erase.c +++ b/misc/examples/csmap_erase.c @@ -1,5 +1,6 @@ // map_erase.c // From C++ example: https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-16 +#define i_implement #include #include diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c index 92dd0031..a8928410 100644 --- a/misc/examples/csmap_find.c +++ b/misc/examples/csmap_find.c @@ -1,5 +1,6 @@ // This implements the c++ std::map::find example at: // https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-17 +#define i_implement #include #define i_key int diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c index 7708fdc9..f96cc08f 100644 --- a/misc/examples/csmap_insert.c +++ b/misc/examples/csmap_insert.c @@ -5,6 +5,7 @@ #define i_tag ii // Map of int => int #include +#define i_implement #include #define i_key int #define i_val_str diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c index 58cf8884..10a843cf 100644 --- a/misc/examples/cstr_match.c +++ b/misc/examples/cstr_match.c @@ -1,3 +1,4 @@ +#define i_implement #include #include #include diff --git a/misc/examples/demos.c b/misc/examples/demos.c index de92e378..8488dfb9 100644 --- a/misc/examples/demos.c +++ b/misc/examples/demos.c @@ -1,3 +1,4 @@ +#define i_implement #include void stringdemo1() diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 8ea3e6a1..f9505aa9 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -1,6 +1,7 @@ #include #define i_extern #include +#define i_implement #include #include #include diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c index e786824b..67586181 100644 --- a/misc/examples/gauss2.c +++ b/misc/examples/gauss2.c @@ -1,8 +1,9 @@ #include #include -#include +#define i_implement #include +#include // Declare int -> int sorted map. #define i_key int diff --git a/misc/examples/hashmap.c b/misc/examples/hashmap.c index 47a3bcff..cf11b7f7 100644 --- a/misc/examples/hashmap.c +++ b/misc/examples/hashmap.c @@ -1,4 +1,5 @@ // https://doc.rust-lang.org/rust-by-example/std/hash.html +#define i_implement #include #define i_key_str #define i_val_str diff --git a/misc/examples/inits.c b/misc/examples/inits.c index 1f01f88a..a3a6c4d2 100644 --- a/misc/examples/inits.c +++ b/misc/examples/inits.c @@ -1,3 +1,4 @@ +#define i_implement #include #define i_key int @@ -25,7 +26,6 @@ inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) { #define i_val ipair_t #define i_cmp ipair_cmp #define i_tag ip -#define i_extern // define _clist_mergesort() once #include #define i_val float diff --git a/misc/examples/list_splice.c b/misc/examples/list_splice.c index 73015454..e457694d 100644 --- a/misc/examples/list_splice.c +++ b/misc/examples/list_splice.c @@ -2,7 +2,6 @@ #define i_val int #define i_tag i -#define i_extern // define _clist_mergesort() once #include void print_ilist(const char* s, clist_i list) diff --git a/misc/examples/make.sh b/misc/examples/make.sh index d58ed0cb..61d9f879 100755 --- a/misc/examples/make.sh +++ b/misc/examples/make.sh @@ -6,7 +6,7 @@ if [ "$(uname)" = 'Linux' ]; then oflag='-o ' fi -cc=gcc; cflags="-DSTC_STATIC -std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-maybe-uninitialized -Wno-implicit-fallthrough -Wno-missing-field-initializers" +cc=gcc; cflags="-std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-maybe-uninitialized -Wno-implicit-fallthrough -Wno-missing-field-initializers" #cc=gcc; cflags="-DSTC_STATIC -std=c99 -g -Werror -Wfatal-errors -Wpedantic -Wall $sanitize" #cc=tcc; cflags="-DSTC_STATIC -std=c99 -Wall" #cc=clang; cflags="-DSTC_STATIC -std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -Wno-missing-field-initializers" diff --git a/misc/examples/mapmap.c b/misc/examples/mapmap.c index 668da5de..d3065659 100644 --- a/misc/examples/mapmap.c +++ b/misc/examples/mapmap.c @@ -1,5 +1,5 @@ // create a structure like: std::map>: - +#define i_implement #include // People: std::map diff --git a/misc/examples/mmap.c b/misc/examples/mmap.c index 0394a2df..63312e04 100644 --- a/misc/examples/mmap.c +++ b/misc/examples/mmap.c @@ -2,6 +2,7 @@ // https://en.cppreference.com/w/cpp/container/multimap/insert // Multimap entries +#define i_implement #include #define i_val_str #include diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c index d8981a81..dc4a1ee0 100644 --- a/misc/examples/multimap.c +++ b/misc/examples/multimap.c @@ -1,3 +1,4 @@ +#define i_implement #include // Olympics multimap example diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c index 87a57783..9c7173ef 100644 --- a/misc/examples/music_arc.c +++ b/misc/examples/music_arc.c @@ -1,5 +1,6 @@ // shared_ptr-examples.cpp // based on https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-160 +#define i_implement #include typedef struct diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c index 1f50db83..277bcbc2 100644 --- a/misc/examples/new_map.c +++ b/misc/examples/new_map.c @@ -1,3 +1,4 @@ +#define i_implement #include #include diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c index 2eaae836..77c4cdce 100644 --- a/misc/examples/new_smap.c +++ b/misc/examples/new_smap.c @@ -1,3 +1,4 @@ +#define i_implement #include #include diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c index 1b72e4f5..aa8dd175 100644 --- a/misc/examples/new_sptr.c +++ b/misc/examples/new_sptr.c @@ -1,3 +1,4 @@ +#define i_implement #include typedef struct { cstr name, last; } Person; diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c index c931089d..b4b926da 100644 --- a/misc/examples/person_arc.c +++ b/misc/examples/person_arc.c @@ -1,4 +1,5 @@ /* cbox: heap allocated boxed type */ +#define i_implement #include #include diff --git a/misc/examples/phonebook.c b/misc/examples/phonebook.c index 38a71089..faf7566e 100644 --- a/misc/examples/phonebook.c +++ b/misc/examples/phonebook.c @@ -20,7 +20,7 @@ // IN THE SOFTWARE. // Program to emulates the phone book. - +#define i_implement #include #define i_key_str diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index b9ec2476..b5099ed5 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -1,6 +1,7 @@ // printspan.c #include +#define i_implement #include #define i_val int #include diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c index 01bcdc44..8dd52aee 100644 --- a/misc/examples/rawptr_elements.c +++ b/misc/examples/rawptr_elements.c @@ -1,6 +1,6 @@ #include #include - +#define i_implement #include // Create cmap of cstr => long* diff --git a/misc/examples/read.c b/misc/examples/read.c index edc89f0e..545d706a 100644 --- a/misc/examples/read.c +++ b/misc/examples/read.c @@ -1,3 +1,4 @@ +#define i_implement #include #include #define i_val_str diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c index e49ebd0b..b4932015 100644 --- a/misc/examples/regex_match.c +++ b/misc/examples/regex_match.c @@ -1,5 +1,6 @@ #define i_extern #include +#define i_implement #include #define i_val float diff --git a/misc/examples/replace.c b/misc/examples/replace.c index cf5b45cb..9ac26c07 100644 --- a/misc/examples/replace.c +++ b/misc/examples/replace.c @@ -1,3 +1,4 @@ +#define i_implement #include int main () diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c index 2bc6fc07..658c46a1 100644 --- a/misc/examples/splitstr.c +++ b/misc/examples/splitstr.c @@ -1,6 +1,7 @@ #include #define i_extern // cstr + utf8 functions #include +#define i_implement #include int main() diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c index 70450e21..b78dcb2e 100644 --- a/misc/examples/sso_map.c +++ b/misc/examples/sso_map.c @@ -1,3 +1,4 @@ +#define i_implement #include #define i_key_str #define i_val_str diff --git a/misc/examples/sso_substr.c b/misc/examples/sso_substr.c index 4b2dbcc8..9b062eed 100644 --- a/misc/examples/sso_substr.c +++ b/misc/examples/sso_substr.c @@ -1,4 +1,6 @@ +#define i_implement #include +#define i_implement #include int main () diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c index 31a28e51..782e4096 100644 --- a/misc/examples/sview_split.c +++ b/misc/examples/sview_split.c @@ -1,4 +1,6 @@ +#define i_implement #include +#define i_implement #include int main() diff --git a/misc/examples/unordered_set.c b/misc/examples/unordered_set.c index 90c78521..006a1e80 100644 --- a/misc/examples/unordered_set.c +++ b/misc/examples/unordered_set.c @@ -1,5 +1,6 @@ // https://iq.opengenus.org/containers-cpp-stl/ // C program to demonstrate various function of stc cset +#define i_implement #include #include #define i_key_str diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c index 3cde8701..17352fee 100644 --- a/misc/examples/utf8replace_c.c +++ b/misc/examples/utf8replace_c.c @@ -1,3 +1,4 @@ +#define i_implement #include int main() diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c index abb909c3..cf087119 100644 --- a/misc/examples/vikings.c +++ b/misc/examples/vikings.c @@ -1,3 +1,4 @@ +#define i_implement #include typedef struct Viking { diff --git a/src/cregex.c b/src/cregex.c index 730d35a4..62a64b11 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -25,9 +25,24 @@ THE SOFTWARE. */ #ifndef CREGEX_C_INCLUDED #define CREGEX_C_INCLUDED -#include -#include // header only + #include +#ifdef i_extern +# define _i_extern +#endif +#ifndef CREGEX_H_INCLUDED +# include "../include/stc/cregex.h" +#endif +#ifdef _i_extern +# include "utf8code.c" +#endif +#ifdef _i_extern +# define i_implement +#else +# undef i_implement +#endif +#undef _i_extern +#include "../include/stc/cstr.h" typedef uint32_t _Rune; /* Utf8 code point */ typedef int32_t _Token; diff --git a/src/libstc.c b/src/libstc.c index bc61e37c..99611e05 100644 --- a/src/libstc.c +++ b/src/libstc.c @@ -1,4 +1,16 @@ +#include +#if 1 +#define i_extern +#include "../include/stc/utf8.h" +#define i_implement +#include "../include/stc/cstr.h" +#define i_implement +#include "../include/stc/cregex.h" +#define i_implement +#include "../include/stc/csview.h" +#else #define i_extern #include "../include/stc/cregex.h" #define i_implement #include "../include/stc/csview.h" +#endif diff --git a/src/utf8code.c b/src/utf8code.c index 496f5eef..6a133050 100644 --- a/src/utf8code.c +++ b/src/utf8code.c @@ -1,6 +1,9 @@ #ifndef UTF8_C_INCLUDED #define UTF8_C_INCLUDED -#include // header only + +#ifndef UTF8_H_INCLUDED +#include "../include/stc/utf8.h" /* header only */ +#endif #include "utf8tabs.inc" const uint8_t utf8_dtab[] = { -- cgit v1.2.3 From b564ef6bdfcd2437f1b4997f42054c45ccdedbb1 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 11 Jun 2023 14:03:16 +0200 Subject: Added priv/linkage.h and renamed priv/template2.h => priv/template_undef.h. Make all examples c++ compatible, except those using cspan.h Removed: crange_obj() Renamed: crange_make() => crange_init() Renamed: cspan_make() => cspan_init() Renamed: cstr_NULL => cstr_null Renamed: csview_NULL => csview_null --- docs/carc_api.md | 2 +- docs/cbox_api.md | 2 +- docs/ccommon_api.md | 14 +++++----- docs/cmap_api.md | 2 +- docs/cspan_api.md | 2 +- docs/cstr_api.md | 4 +-- docs/csview_api.md | 2 +- include/stc/algo/coroutine.h | 2 +- include/stc/algo/crange.h | 18 ++++++------- include/stc/algo/filter.h | 2 +- include/stc/algo/sort.h | 1 + include/stc/carc.h | 5 ++-- include/stc/cbox.h | 5 ++-- include/stc/ccommon.h | 51 +++++++++++++++---------------------- include/stc/clist.h | 3 ++- include/stc/cmap.h | 3 ++- include/stc/cpque.h | 3 ++- include/stc/cqueue.h | 3 ++- include/stc/crand.h | 3 ++- include/stc/cregex.h | 4 ++- include/stc/csmap.h | 3 ++- include/stc/cspan.h | 9 ++++--- include/stc/cstack.h | 3 ++- include/stc/cstr.h | 20 +++++++-------- include/stc/csview.h | 18 ++++++------- include/stc/cvec.h | 3 ++- include/stc/priv/linkage.h | 40 +++++++++++++++++++++++++++++ include/stc/utf8.h | 34 ++++++++++++++++++++----- misc/examples/astar.c | 2 +- misc/examples/box.c | 2 +- misc/examples/box2.c | 6 ++--- misc/examples/csmap_find.c | 12 ++++----- misc/examples/csmap_insert.c | 12 ++++----- misc/examples/dining_philosophers.c | 5 ++-- misc/examples/forfilter.c | 5 ++-- misc/examples/make.sh | 14 +++++----- misc/examples/music_arc.c | 2 +- misc/examples/new_list.c | 2 +- misc/examples/new_sptr.c | 3 ++- misc/examples/new_vec.c | 8 +++--- misc/examples/person_arc.c | 3 ++- misc/examples/prime.c | 4 ++- misc/examples/printspan.c | 8 +++--- misc/examples/read.c | 2 +- misc/examples/shape.c | 2 +- misc/examples/vikings.c | 10 ++++---- src/cregex.c | 32 +++++++++++------------ src/utf8code.c | 41 +++++++++++++++-------------- 48 files changed, 254 insertions(+), 182 deletions(-) create mode 100644 include/stc/priv/linkage.h (limited to 'include/stc/cmap.h') diff --git a/docs/carc_api.md b/docs/carc_api.md index 9f3d8cb9..22e6bac2 100644 --- a/docs/carc_api.md +++ b/docs/carc_api.md @@ -67,7 +67,7 @@ bool carc_X_value_eq(const i_val* x, const i_val* y); | Type name | Type definition | Used to represent... | |:------------------|:--------------------------------------------------|:-----------------------| -| `carc_NULL` | `{NULL, NULL}` | Init nullptr const | +| `carc_null` | `{0}` | Init nullptr const | | `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | | `carc_X_value` | `i_val` | The carc element type | | `carc_X_raw` | `i_valraw` | Convertion type | diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 5914a5ad..9151f56d 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -64,7 +64,7 @@ bool cbox_X_value_eq(const i_val* x, const i_val* y); | Type name | Type definition | Used to represent... | |:-------------------|:--------------------------------|:------------------------| -| `cbox_NULL` | `{NULL}` | Init nullptr const | +| `cbox_null` | `{0}` | Init nullptr const | | `cbox_X` | `struct { cbox_X_value* get; }` | The cbox type | | `cbox_X_value` | `i_val` | The cbox element type | diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index cd9be505..1f0847da 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -82,17 +82,16 @@ c_forrange (i, 30, 0, -5) printf(" %lld", i); ### crange A number sequence generator type, similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html). The **crange_value** type is `long long`. Below *start*, *stop*, and *step* are of type *crange_value*: ```c -crange& crange_obj(...) // create a compound literal crange object -crange crange_make(stop); // will generate 0, 1, ..., stop-1 -crange crange_make(start, stop); // will generate start, start+1, ... stop-1 -crange crange_make(start, stop, step); // will generate start, start+step, ... upto-not-including stop +crange crange_init(stop); // will generate 0, 1, ..., stop-1 +crange crange_init(start, stop); // will generate start, start+1, ... stop-1 +crange crange_init(start, stop, step); // will generate start, start+step, ... upto-not-including stop // note that step may be negative. crange_iter crange_begin(crange* self); crange_iter crange_end(crange* self); void crange_next(crange_iter* it); // 1. All primes less than 32: -crange r1 = crange_make(3, 32, 2); +crange r1 = crange_init(3, 32, 2); printf("2"); // first prime c_forfilter (i, crange, r1, isPrime(*i.ref)) printf(" %lld", *i.ref); @@ -100,7 +99,8 @@ c_forfilter (i, crange, r1, isPrime(*i.ref)) // 2. The first 11 primes: printf("2"); -c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2), +crange range = crange_init(3, INT64_MAX, 2); +c_forfilter (i, crange, range, isPrime(*i.ref) && c_flt_take(10) ){ @@ -140,7 +140,7 @@ bool isPrime(long long i) { int main() { // Get 10 prime numbers starting from 1000. Skip the first 15 primes, // then select every 25th prime (including the initial). - crange R = crange_make(1001, INT64_MAX, 2); // 1001, 1003, ... + crange R = crange_init(1001, INT64_MAX, 2); // 1001, 1003, ... c_forfilter (i, crange, R, isPrime(*i.ref) && diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 69e547a0..8ef322e6 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -277,7 +277,7 @@ typedef struct { cstr country; } Viking; -#define Viking_init() ((Viking){cstr_NULL, cstr_NULL}) +#define Viking_init() ((Viking){cstr_null, cstr_null}) static inline int Viking_cmp(const Viking* a, const Viking* b) { int c = cstr_cmp(&a->name, &b->name); diff --git a/docs/cspan_api.md b/docs/cspan_api.md index 3a811ebf..c78bb8a0 100644 --- a/docs/cspan_api.md +++ b/docs/cspan_api.md @@ -26,7 +26,7 @@ i.e., it may be expanded multiple times. However, all integer arguments are safe `cspan_at(&ms3, i++, j++, k++)` is allowed. If the number of arguments does not match the span rank, a compile error is issued. Runtime bounds checks are enabled by default (define `STC_NDEBUG` or `NDEBUG` to disable). ```c -SpanType cspan_make(T SpanType, {v1, v2, ...}); // make a 1-d cspan from values +SpanType cspan_init(T SpanType, {v1, v2, ...}); // make a 1-d cspan from values SpanType cspan_from(STCContainer* cnt); // make a 1-d cspan from compatible STC container SpanType cspan_from_array(ValueType array[]); // make a 1-d cspan from C array SpanTypeN cspan_md(ValueType* data, intptr_t xdim, ...); // make a multi-dimensional cspan diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 438dbf27..c7d19e0c 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -18,7 +18,7 @@ All cstr definitions and prototypes are available by including a single header f ## Methods ```c -cstr cstr_init(void); // constructor; same as cstr_NULL. +cstr cstr_init(void); // constructor; same as cstr_null. cstr cstr_lit(const char literal_only[]); // cstr from literal; no strlen() call. cstr cstr_from(const char* str); // constructor using strlen() cstr cstr_from_n(const char* str, intptr_t n); // constructor with n first bytes of str @@ -153,7 +153,7 @@ char* cstrnstrn(const char* str, const char* search, intptr_t slen, intpt | Name | Value | |:------------------|:------------------| | `c_NPOS` | `INTPTR_MAX` | -| `cstr_NULL` | cstr null value | +| `cstr_null` | empty cstr value | ## Example ```c diff --git a/docs/csview_api.md b/docs/csview_api.md index 879822d3..a02b007a 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -112,7 +112,7 @@ uint64_t csview_hash(const csview* x); | Name | Value | Usage | |:---------------|:---------------------|:---------------------------------------------| -| `csview_NULL` | same as `c_sv("")` | `sview = csview_NULL;` | +| `csview_null` | same as `c_sv("")` | `sview = csview_null;` | | `c_SV(sv)` | printf argument | `printf("sv: %.*s\n", c_SV(sv));` | ## Example diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index 67ea5a40..5cd6d68f 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -56,7 +56,7 @@ int main(void) { return 0; } */ -#include +#include "../ccommon.h" enum { cco_state_final = -1, diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index 56c317da..34ed541b 100644 --- a/include/stc/algo/crange.h +++ b/include/stc/algo/crange.h @@ -27,14 +27,15 @@ int main() { - crange r1 = crange_make(80, 90); + crange r1 = crange_init(80, 90); c_foreach (i, crange, r1) printf(" %lld", *i.ref); puts(""); // use a temporary crange object. int a = 100, b = INT32_MAX; - c_forfilter (i, crange, crange_obj(a, b, 8), + crange r2 = crange_init(a, b, 8); + c_forfilter (i, crange, r2, c_flt_skip(i, 10) && c_flt_take(i, 3)) printf(" %lld", *i.ref); @@ -44,20 +45,17 @@ int main() #ifndef STC_CRANGE_H_INCLUDED #define STC_CRANGE_H_INCLUDED -#include - -#define crange_obj(...) \ - (*(crange[]){crange_make(__VA_ARGS__)}) +#include "../ccommon.h" typedef long long crange_value; typedef struct { crange_value start, end, step, value; } crange; typedef struct { crange_value *ref, end, step; } crange_iter; -#define crange_make(...) c_MACRO_OVERLOAD(crange_make, __VA_ARGS__) -#define crange_make_1(stop) crange_make_3(0, stop, 1) -#define crange_make_2(start, stop) crange_make_3(start, stop, 1) +#define crange_init(...) c_MACRO_OVERLOAD(crange_init, __VA_ARGS__) +#define crange_init_1(stop) crange_init_3(0, stop, 1) +#define crange_init_2(start, stop) crange_init_3(start, stop, 1) -STC_INLINE crange crange_make_3(crange_value start, crange_value stop, crange_value step) +STC_INLINE crange crange_init_3(crange_value start, crange_value stop, crange_value step) { crange r = {start, stop - (step > 0), step}; return r; } STC_INLINE crange_iter crange_begin(crange* self) diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index 8dc1ad74..f5de1811 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -47,7 +47,7 @@ int main() #ifndef STC_FILTER_H_INCLUDED #define STC_FILTER_H_INCLUDED -#include +#include "../ccommon.h" // c_forfilter: diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h index bbd58427..2e73b0fb 100644 --- a/include/stc/algo/sort.h +++ b/include/stc/algo/sort.h @@ -42,6 +42,7 @@ int main() { } */ #include "../ccommon.h" + #ifndef i_type #define i_at(arr, idx) (&arr[idx]) #ifndef i_tag diff --git a/include/stc/carc.h b/include/stc/carc.h index 756b604f..749b1fc1 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -49,10 +49,11 @@ int main() { c_drop(ArcPers, &p, &q); } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CARC_H_INCLUDED #define CARC_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include @@ -72,7 +73,7 @@ int main() { #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) #endif -#define carc_NULL {NULL, NULL} +#define carc_null {0} #endif // CARC_H_INCLUDED #define _i_prefix carc_ diff --git a/include/stc/cbox.h b/include/stc/cbox.h index 699b32ac..d7f6246d 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -57,15 +57,16 @@ int main() { } } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CBOX_H_INCLUDED #define CBOX_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include -#define cbox_NULL {NULL} +#define cbox_null {0} #endif // CBOX_H_INCLUDED #define _i_prefix cbox_ diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index e491a567..5f280218 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -117,10 +117,6 @@ /* Function macros and others */ -#define c_init(C, ...) \ - C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw)) -#define c_make(C, ...) c_init(C, __VA_ARGS__) // [deprecated] - #define c_litstrlen(literal) (c_sizeof("" literal) - 1) #define c_arraylen(a) (intptr_t)(sizeof(a)/sizeof 0[a]) @@ -210,16 +206,23 @@ STC_INLINE intptr_t cnextpow2(intptr_t n) { ; (_inc > 0) ^ (i > _end); i += _inc) #ifndef __cplusplus + #define c_init(C, ...) \ + C##_from_n((C##_raw[])__VA_ARGS__, c_sizeof((C##_raw[])__VA_ARGS__)/c_sizeof(C##_raw)) #define c_forlist(it, T, ...) \ - for (struct {T* ref; int size, index;} \ - it = {.ref=(T[])__VA_ARGS__, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \ - ; it.index < it.size; ++it.ref, ++it.index) + for (struct {T* ref; int size, index;} \ + it = {.ref=(T[])__VA_ARGS__, .size=(int)(sizeof((T[])__VA_ARGS__)/sizeof(T))} \ + ; it.index < it.size; ++it.ref, ++it.index) #else - #include - #define c_forlist(it, T, ...) \ - for (struct {std::initializer_list _il; std::initializer_list::iterator ref; size_t size, index;} \ - it = {._il=__VA_ARGS__, .ref=it._il.begin(), .size=it._il.size()} \ - ; it.index < it.size; ++it.ref, ++it.index) + #include + template + inline C _from_n(C (*func)(const T[], intptr_t), std::initializer_list il) + { return func(&*il.begin(), il.size()); } + + #define c_init(C, ...) _from_n(C##_from_n, __VA_ARGS__) + #define c_forlist(it, T, ...) \ + for (struct {std::initializer_list _il; std::initializer_list::iterator ref; size_t size, index;} \ + it = {._il=__VA_ARGS__, .ref=it._il.begin(), .size=it._il.size()} \ + ; it.index < it.size; ++it.ref, ++it.index) #endif #define c_drop(C, ...) \ @@ -236,23 +239,9 @@ STC_INLINE intptr_t cnextpow2(intptr_t n) { #define c_umul128(a, b, lo, hi) \ asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b)) #endif -#endif // CCOMMON_H_INCLUDED -#undef STC_API -#undef STC_DEF - -#ifdef i_extern -# define i_import -#endif -#if !defined(i_static) && !defined(STC_STATIC) && (defined(i_header) || defined(STC_HEADER) || \ - defined(i_implement) || defined(STC_IMPLEMENT)) - #define STC_API extern - #define STC_DEF -#else - #define i_static - #define STC_API static inline - #define STC_DEF static inline -#endif -#if defined(STC_IMPLEMENT) || defined(i_import) - #define i_implement -#endif +// [deprecated]: +#define c_make(...) c_init(__VA_ARGS__) +#define cspan_make(...) cspan_init(__VA_ARGS__) +#define crange_make(...) crange_init(__VA_ARGS__) +#endif // CCOMMON_H_INCLUDED diff --git a/include/stc/clist.h b/include/stc/clist.h index 310db204..4d05a3d1 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -51,9 +51,10 @@ } } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CLIST_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include diff --git a/include/stc/cmap.h b/include/stc/cmap.h index f6c3eb07..2e234fb5 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -47,9 +47,10 @@ int main(void) { cmap_ichar_drop(&m); } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CMAP_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 31a53ece..b66c7735 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -20,9 +20,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CPQUE_H_INCLUDED +#include "ccommon.h" #include #include "forward.h" #endif diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 28515877..3adc1bcb 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -20,9 +20,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CQUEUE_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include diff --git a/include/stc/crand.h b/include/stc/crand.h index 95a65fb0..89b681cd 100644 --- a/include/stc/crand.h +++ b/include/stc/crand.h @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CRAND_H_INCLUDED #define CRAND_H_INCLUDED +#include "ccommon.h" /* // crand: Pseudo-random number generator #include "stc/crand.h" diff --git a/include/stc/cregex.h b/include/stc/cregex.h index 43a7fcbf..1d1d441f 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -22,6 +22,8 @@ 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 "priv/linkage.h" + #ifndef CREGEX_H_INCLUDED #define CREGEX_H_INCLUDED /* @@ -157,6 +159,7 @@ cstr cregex_replace_pattern_6(const char* pattern, const char* input, const char /* destroy regex */ void cregex_drop(cregex* re); +#endif // CREGEX_H_INCLUDED #if defined i_implement # include "../../src/cregex.c" @@ -164,7 +167,6 @@ void cregex_drop(cregex* re); #if defined i_import # include "../../src/utf8code.c" #endif -#endif // CREGEX_H_INCLUDED #undef i_opt #undef i_header #undef i_static diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 7638b8f2..28598f0a 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -49,9 +49,10 @@ int main(void) { csmap_sx_drop(&m); } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CSMAP_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include diff --git a/include/stc/cspan.h b/include/stc/cspan.h index dd6cb1c0..d7a72267 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -60,6 +60,7 @@ int demo2() { #ifndef STC_CSPAN_H_INCLUDED #define STC_CSPAN_H_INCLUDED +#include "priv/linkage.h" #include "ccommon.h" #define using_cspan(...) c_MACRO_OVERLOAD(using_cspan, __VA_ARGS__) @@ -80,7 +81,7 @@ int demo2() { return (Self){.data=raw, .shape={(int32_t)n}}; \ } \ STC_INLINE Self Self##_slice_(Self##_value* v, const int32_t shape[], const int32_t stri[], \ - const int rank, const int32_t a[][2]) { \ + const int rank, const int32_t a[][2]) { \ Self s = {.data=v}; int outrank; \ s.data += _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \ c_ASSERT(outrank == RANK); \ @@ -115,8 +116,8 @@ typedef struct { int32_t d[6]; } cspan_idx6; #define cspan_md(array, ...) \ {.data=array, .shape={__VA_ARGS__}, .stride={.d={__VA_ARGS__}}} -/* For static initialization, use cspan_make(). c_init() for non-static only. */ -#define cspan_make(SpanType, ...) \ +/* For static initialization, use cspan_init(). c_init() for non-static only. */ +#define cspan_init(SpanType, ...) \ {.data=(SpanType##_value[])__VA_ARGS__, .shape={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}} #define cspan_slice(OutSpan, parent, ...) \ @@ -210,6 +211,7 @@ STC_API intptr_t _cspan_next2(int rank, int32_t pos[], const int32_t shape[], co STC_API intptr_t _cspan_slice(int32_t odim[], int32_t ostri[], int* orank, const int32_t shape[], const int32_t stri[], int rank, const int32_t a[][2]); +#endif // STC_CSPAN_H_INCLUDED /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) @@ -260,7 +262,6 @@ STC_DEF intptr_t _cspan_slice(int32_t odim[], int32_t ostri[], int* orank, return off; } #endif -#endif #undef i_opt #undef i_header #undef i_implement diff --git a/include/stc/cstack.h b/include/stc/cstack.h index fa0fab2b..fb4eae4b 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -20,10 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CSTACK_H_INCLUDED #define CSTACK_H_INCLUDED +#include "ccommon.h" #include #include "forward.h" #endif // CSTACK_H_INCLUDED diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 0c5b67d8..bdfee39b 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -24,7 +24,7 @@ /* A string type with short string optimization in C99 with good small-string * optimization (22 characters with 24 bytes string). */ -#define _i_no_undef +#define _i_nested #include "utf8.h" #ifndef CSTR_H_INCLUDED @@ -67,7 +67,7 @@ extern char* _cstr_internal_move(cstr* self, intptr_t pos1, intptr_t pos2); /**************************** PUBLIC API **********************************/ #define cstr_lit(literal) cstr_from_n(literal, c_litstrlen(literal)) -#define cstr_NULL (c_LITERAL(cstr){{{0}, 0}}) +#define cstr_null (c_LITERAL(cstr){0}) #define cstr_toraw(self) cstr_str(self) extern char* cstr_reserve(cstr* self, intptr_t cap); @@ -97,7 +97,7 @@ STC_INLINE csview cstr_sv(const cstr* s) { } STC_INLINE cstr cstr_init(void) - { return cstr_NULL; } + { return cstr_null; } STC_INLINE cstr cstr_from_n(const char* str, const intptr_t len) { cstr s; @@ -132,7 +132,7 @@ STC_INLINE cstr* cstr_take(cstr* self, const cstr s) { STC_INLINE cstr cstr_move(cstr* self) { cstr tmp = *self; - *self = cstr_NULL; + *self = cstr_null; return tmp; } @@ -440,8 +440,8 @@ cstr cstr_tocase(csview sv, int k) { #endif // i_import /* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined i_import || (defined i_implement && !defined _i_nested) #ifndef CSTR_C_INCLUDED -#if defined i_import || (defined i_implement && !defined _i_no_undef) #define CSTR_C_INCLUDED uint64_t cstr_hash(const cstr *self) { @@ -573,7 +573,7 @@ bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { cstr cstr_replace_sv(csview in, csview search, csview repl, int32_t count) { - cstr out = cstr_NULL; + cstr out = cstr_null; intptr_t from = 0; char* res; if (!count) count = INT32_MAX; if (search.size) @@ -625,7 +625,7 @@ intptr_t cstr_vfmt(cstr* self, intptr_t start, const char* fmt, va_list args) { #endif cstr cstr_from_fmt(const char* fmt, ...) { - cstr s = cstr_NULL; + cstr s = cstr_null; va_list args; va_start(args, fmt); cstr_vfmt(&s, 0, fmt, args); @@ -649,17 +649,17 @@ intptr_t cstr_printf(cstr* self, const char* fmt, ...) { va_end(args); return n; } -#endif // i_implement #endif // CSTR_C_INCLUDED +#endif // i_implement #if defined __GNUC__ && !defined __clang__ # pragma GCC diagnostic pop #endif -#ifndef _i_no_undef +#ifndef _i_nested #undef i_opt #undef i_header #undef i_static #undef i_implement #undef i_import #endif -#undef _i_no_undef +#undef _i_nested diff --git a/include/stc/csview.h b/include/stc/csview.h index a1893063..c16f58bc 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -20,14 +20,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#define _i_no_undef +#define _i_nested #include "utf8.h" #ifndef CSVIEW_H_INCLUDED #define CSVIEW_H_INCLUDED -#define csview_NULL c_sv_1("") -#define csview_init() csview_NULL +#define csview_null c_sv_1("") +#define csview_init() csview_null #define csview_drop(p) c_default_drop(p) #define csview_clone(sv) c_default_clone(sv) #define csview_lit(literal) c_sv_1(literal) @@ -42,7 +42,7 @@ extern csview csview_token(csview sv, const char* sep, intptr_t* start); STC_INLINE csview csview_from(const char* str) { return c_LITERAL(csview){str, c_strlen(str)}; } -STC_INLINE void csview_clear(csview* self) { *self = csview_NULL; } +STC_INLINE void csview_clear(csview* self) { *self = csview_null; } STC_INLINE intptr_t csview_size(csview sv) { return sv.size; } STC_INLINE bool csview_empty(csview sv) { return sv.size == 0; } @@ -150,8 +150,8 @@ STC_INLINE csview cstr_u8_substr(const cstr* self , intptr_t bytepos, intptr_t u #endif /* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined i_import || (defined i_implement && !defined _i_nested) #ifndef CSVIEW_C_INCLUDED -#if defined i_import || (defined i_implement && !defined _i_no_undef) #define CSVIEW_C_INCLUDED csview_iter csview_advance(csview_iter it, intptr_t pos) { @@ -201,13 +201,13 @@ csview csview_token(csview sv, const char* sep, intptr_t* start) { *start += tok.size + sep_size; return tok; } -#endif -#endif -#ifndef _i_no_undef +#endif // CSVIEW_C_INCLUDED +#endif // i_implement +#ifndef _i_nested #undef i_static #undef i_header #undef i_implement #undef i_import #undef i_opt #endif -#undef _i_no_undef +#undef _i_nested diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 747c654d..874f4f47 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -58,9 +58,10 @@ int main() { cvec_str_drop(&svec); } */ -#include "ccommon.h" +#include "priv/linkage.h" #ifndef CVEC_H_INCLUDED +#include "ccommon.h" #include "forward.h" #include #include diff --git a/include/stc/priv/linkage.h b/include/stc/priv/linkage.h new file mode 100644 index 00000000..7f63f5f1 --- /dev/null +++ b/include/stc/priv/linkage.h @@ -0,0 +1,40 @@ +/* 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 STC_API +#undef STC_DEF + +#ifdef i_extern // [deprecated] +# define i_import +#endif +#if !defined(i_static) && !defined(STC_STATIC) && (defined(i_header) || defined(STC_HEADER) || \ + defined(i_implement) || defined(STC_IMPLEMENT)) + #define STC_API extern + #define STC_DEF +#else + #define i_static + #define STC_API static inline + #define STC_DEF static inline +#endif +#if defined(STC_IMPLEMENT) || defined(i_import) + #define i_implement +#endif diff --git a/include/stc/utf8.h b/include/stc/utf8.h index d6c759eb..190cc7f3 100644 --- a/include/stc/utf8.h +++ b/include/stc/utf8.h @@ -1,9 +1,31 @@ - -#include "ccommon.h" +/* 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 "priv/linkage.h" #ifndef UTF8_H_INCLUDED #define UTF8_H_INCLUDED +#include "ccommon.h" #include #include "forward.h" @@ -53,9 +75,9 @@ STC_INLINE bool utf8_isspace(uint32_t c) { /* decode next utf8 codepoint. https://bjoern.hoehrmann.de/utf-8/decoder/dfa */ typedef struct { uint32_t state, codep; } utf8_decode_t; +extern const uint8_t utf8_dtab[]; /* utf8code.c */ STC_INLINE uint32_t utf8_decode(utf8_decode_t* d, const uint32_t byte) { - extern const uint8_t utf8_dtab[]; /* utf8code.c */ const uint32_t type = utf8_dtab[byte]; d->codep = d->state ? (byte & 0x3fu) | (d->codep << 6) : (0xffU >> type) & byte; @@ -116,14 +138,14 @@ STC_INLINE intptr_t utf8_pos(const char* s, intptr_t index) { return (intptr_t)(utf8_at(s, index) - s); } #endif // UTF8_H_INCLUDED -#if defined i_import || (defined i_implement && !defined _i_no_undef) +#if defined i_import || (defined i_implement && !defined _i_nested) # include "../../src/utf8code.c" #endif -#ifndef _i_no_undef +#ifndef _i_nested #undef i_static #undef i_header #undef i_implement #undef i_import #undef i_opt #endif -#undef _i_no_undef +#undef _i_nested diff --git a/misc/examples/astar.c b/misc/examples/astar.c index db6bbd70..1b3876aa 100644 --- a/misc/examples/astar.c +++ b/misc/examples/astar.c @@ -21,7 +21,7 @@ point; point point_init(int x, int y, int width) { - return (point) { x, y, 0, width }; + return c_LITERAL(point){ x, y, 0, width }; } int diff --git a/misc/examples/box.c b/misc/examples/box.c index e352aa2b..a9131afa 100644 --- a/misc/examples/box.c +++ b/misc/examples/box.c @@ -5,7 +5,7 @@ typedef struct { cstr name, last; } Person; Person Person_make(const char* name, const char* last) { - return (Person){.name = cstr_from(name), .last = cstr_from(last)}; + return c_LITERAL(Person){.name = cstr_from(name), .last = cstr_from(last)}; } uint64_t Person_hash(const Person* a) { diff --git a/misc/examples/box2.c b/misc/examples/box2.c index 33212ef4..963a3815 100644 --- a/misc/examples/box2.c +++ b/misc/examples/box2.c @@ -29,12 +29,12 @@ typedef struct { #include // BoxBoxPoint Point origin(void) { - return (Point){ .x=1.0, .y=2.0 }; + return c_LITERAL(Point){ .x=1.0, .y=2.0 }; } cbox_Point boxed_origin(void) { // Allocate this point on the heap, and return a pointer to it - return cbox_Point_make((Point){ .x=1.0, .y=2.0 }); + return cbox_Point_make(c_LITERAL(Point){ .x=1.0, .y=2.0 }); } @@ -47,7 +47,7 @@ int main(void) { }; // Heap allocated rectangle - cbox_Rectangle boxed_rectangle = cbox_Rectangle_make((Rectangle){ + cbox_Rectangle boxed_rectangle = cbox_Rectangle_make(c_LITERAL(Rectangle){ .top_left = origin(), .bottom_right = { .x=3.0, .y=-4.0 } }); diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c index a8928410..c123e398 100644 --- a/misc/examples/csmap_find.c +++ b/misc/examples/csmap_find.c @@ -50,12 +50,12 @@ int main() print_collection_csmap_istr(&m1); typedef cvec_istr_value pair; - cvec_istr_push(&v, (pair){43, "Tc"}); - cvec_istr_push(&v, (pair){41, "Nb"}); - cvec_istr_push(&v, (pair){46, "Pd"}); - cvec_istr_push(&v, (pair){42, "Mo"}); - cvec_istr_push(&v, (pair){44, "Ru"}); - cvec_istr_push(&v, (pair){44, "Ru"}); // attempt a duplicate + cvec_istr_push(&v, c_LITERAL(pair){43, "Tc"}); + cvec_istr_push(&v, c_LITERAL(pair){41, "Nb"}); + cvec_istr_push(&v, c_LITERAL(pair){46, "Pd"}); + cvec_istr_push(&v, c_LITERAL(pair){42, "Mo"}); + cvec_istr_push(&v, c_LITERAL(pair){44, "Ru"}); + cvec_istr_push(&v, c_LITERAL(pair){44, "Ru"}); // attempt a duplicate puts("Inserting the following vector data into m1:"); print_collection_cvec_istr(&v); diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c index f96cc08f..18a88ec3 100644 --- a/misc/examples/csmap_insert.c +++ b/misc/examples/csmap_insert.c @@ -34,7 +34,7 @@ int main() // insert single values csmap_ii m1 = {0}; csmap_ii_insert(&m1, 1, 10); - csmap_ii_push(&m1, (csmap_ii_value){2, 20}); + csmap_ii_push(&m1, c_LITERAL(csmap_ii_value){2, 20}); puts("The original key and mapped values of m1 are:"); print_ii(m1); @@ -61,11 +61,11 @@ int main() csmap_ii m2 = {0}; cvec_ii v = {0}; typedef cvec_ii_value ipair; - cvec_ii_push(&v, (ipair){43, 294}); - cvec_ii_push(&v, (ipair){41, 262}); - cvec_ii_push(&v, (ipair){45, 330}); - cvec_ii_push(&v, (ipair){42, 277}); - cvec_ii_push(&v, (ipair){44, 311}); + cvec_ii_push(&v, c_LITERAL(ipair){43, 294}); + cvec_ii_push(&v, c_LITERAL(ipair){41, 262}); + cvec_ii_push(&v, c_LITERAL(ipair){45, 330}); + cvec_ii_push(&v, c_LITERAL(ipair){42, 277}); + cvec_ii_push(&v, c_LITERAL(ipair){44, 311}); puts("Inserting the following vector data into m2:"); c_foreach (e, cvec_ii, v) diff --git a/misc/examples/dining_philosophers.c b/misc/examples/dining_philosophers.c index f9c05e71..e13eb055 100644 --- a/misc/examples/dining_philosophers.c +++ b/misc/examples/dining_philosophers.c @@ -29,9 +29,10 @@ struct Dining { // Philosopher coroutine void philosopher(struct Philosopher* p) { + double duration; cco_routine(p) { while (1) { - double duration = 1.0 + crandf()*2.0; + duration = 1.0 + crandf()*2.0; printf("Philosopher %d is thinking for %.0f minutes...\n", p->id, duration*10); cco_timer_await(&p->tm, duration); @@ -46,7 +47,7 @@ void philosopher(struct Philosopher* p) cco_sem_release(p->left_fork); cco_sem_release(p->right_fork); } - + cco_final: printf("Philosopher %d finished\n", p->id); } diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 94a84065..d39693b5 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -55,7 +55,8 @@ fn main() { void demo2(void) { IVec vector = {0}; - c_forfilter (x, crange, crange_obj(INT64_MAX), + crange r = crange_init(INT64_MAX); + c_forfilter (x, crange, r, c_flt_skipwhile(x, *x.ref != 11) && (*x.ref % 2) != 0 && c_flt_take(x, 5) @@ -124,7 +125,7 @@ void demo5(void) { #define flt_even(i) ((*i.ref & 1) == 0) #define flt_mid_decade(i) ((*i.ref % 10) != 0) - crange R = crange_make(1963, INT32_MAX); + crange R = crange_init(1963, INT32_MAX); c_forfilter (i, crange, R, c_flt_skip(i,15) && diff --git a/misc/examples/make.sh b/misc/examples/make.sh index 61d9f879..cf224950 100755 --- a/misc/examples/make.sh +++ b/misc/examples/make.sh @@ -7,13 +7,13 @@ if [ "$(uname)" = 'Linux' ]; then fi cc=gcc; cflags="-std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-maybe-uninitialized -Wno-implicit-fallthrough -Wno-missing-field-initializers" -#cc=gcc; cflags="-DSTC_STATIC -std=c99 -g -Werror -Wfatal-errors -Wpedantic -Wall $sanitize" -#cc=tcc; cflags="-DSTC_STATIC -std=c99 -Wall" -#cc=clang; cflags="-DSTC_STATIC -std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -Wno-missing-field-initializers" -#cc=gcc; cflags="-DSTC_STATIC -x c++ -std=c++20 -O2 -s -Wall" -#cc=cl; cflags="-DSTC_STATIC -nologo -O2 -MD -W3 -wd4003" -#cc=cl; cflags="-DSTC_STATIC -nologo -TP -wd4003" -#cc=cl; cflags="-DSTC_STATIC -nologo -std:c11 -wd4003" +#cc=gcc; cflags="-std=c99 -g -Werror -Wfatal-errors -Wpedantic -Wall $sanitize" +#cc=tcc; cflags="-std=c99 -Wall" +#cc=clang; cflags="-std=c99 -s -O3 -Wall -Wextra -Wpedantic -Wconversion -Wwrite-strings -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -Wno-missing-field-initializers" +#cc=gcc; cflags="-x c++ -std=c++20 -O2 -s -Wall" +#cc=cl; cflags="-nologo -O2 -MD -W3 -wd4003" +#cc=cl; cflags="-nologo -TP -std:c++20 -wd4003" +#cc=cl; cflags="-nologo -std:c11 -wd4003" if [ "$cc" = "cl" ]; then oflag='/Fe:' diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c index 9c7173ef..18ea30c0 100644 --- a/misc/examples/music_arc.c +++ b/misc/examples/music_arc.c @@ -13,7 +13,7 @@ int Song_cmp(const Song* x, const Song* y) { return cstr_cmp(&x->title, &y->title); } Song Song_make(const char* artist, const char* title) - { return (Song){cstr_from(artist), cstr_from(title)}; } + { return c_LITERAL(Song){cstr_from(artist), cstr_from(title)}; } void Song_drop(Song* s) { printf("drop: %s\n", cstr_str(&s->title)); diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c index 993f1aac..382943bb 100644 --- a/misc/examples/new_list.c +++ b/misc/examples/new_list.c @@ -45,7 +45,7 @@ int main() { MyStruct my = {0}; clist_i32_push_back(&my.intlst, 123); - clist_pnt_push_back(&my.pntlst, (Point){123, 456}); + clist_pnt_push_back(&my.pntlst, c_LITERAL(Point){123, 456}); MyStruct_drop(&my); clist_pnt plst = c_init(clist_pnt, {{42, 14}, {32, 94}, {62, 81}}); diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c index aa8dd175..36a61f9c 100644 --- a/misc/examples/new_sptr.c +++ b/misc/examples/new_sptr.c @@ -30,7 +30,8 @@ uint64_t Person_hash(const Person* p); Person Person_make(const char* name, const char* last) { - return (Person){.name = cstr_from(name), .last = cstr_from(last)}; + Person p = {.name = cstr_from(name), .last = cstr_from(last)}; + return p; } int Person_cmp(const Person* a, const Person* b) { diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c index d4b66883..e10910d9 100644 --- a/misc/examples/new_vec.c +++ b/misc/examples/new_vec.c @@ -26,10 +26,10 @@ int main() { MyStruct my = {0}; - cvec_pnt_push(&my.pntvec, (Point){42, 14}); - cvec_pnt_push(&my.pntvec, (Point){32, 94}); - cvec_pnt_push(&my.pntvec, (Point){62, 81}); - cvec_pnt_push(&my.pntvec, (Point){32, 91}); + cvec_pnt_push(&my.pntvec, c_LITERAL(Point){42, 14}); + cvec_pnt_push(&my.pntvec, c_LITERAL(Point){32, 94}); + cvec_pnt_push(&my.pntvec, c_LITERAL(Point){62, 81}); + cvec_pnt_push(&my.pntvec, c_LITERAL(Point){32, 91}); cvec_pnt_sort(&my.pntvec); diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c index b4b926da..3614c02d 100644 --- a/misc/examples/person_arc.c +++ b/misc/examples/person_arc.c @@ -6,7 +6,8 @@ typedef struct { cstr name, last; } Person; Person Person_make(const char* name, const char* last) { - return (Person){.name = cstr_from(name), .last = cstr_from(last)}; + Person p = {.name = cstr_from(name), .last = cstr_from(last)}; + return p; } int Person_cmp(const Person* a, const Person* b) { diff --git a/misc/examples/prime.c b/misc/examples/prime.c index cb0f8926..34fa144c 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -41,7 +41,9 @@ int main(void) puts("\n"); puts("Show the last 50 primes using a temporary crange generator:"); - c_forfilter (i, crange, crange_obj(n - 1, 0, -2), + crange range = crange_init(n - 1, 0, -2); + + c_forfilter (i, crange, range, cbits_test(&primes, *i.ref/2) && c_flt_take(i, 50) ){ diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index b5099ed5..7564bd88 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -22,22 +22,22 @@ void printMe(intspan container) { int main() { - intspan sp1 = cspan_make(intspan, {1, 2}); + intspan sp1 = cspan_init(intspan, {1, 2}); printMe( sp1 ); printMe( c_init(intspan, {1, 2, 3}) ); int arr[] = {1, 2, 3, 4, 5, 6}; intspan sp2 = cspan_from_array(arr); - printMe( (intspan)cspan_subspan(&sp2, 1, 4) ); + printMe( c_LITERAL(intspan)cspan_subspan(&sp2, 1, 4) ); cvec_int vec = c_init(cvec_int, {1, 2, 3, 4, 5}); - printMe( (intspan)cspan_from(&vec) ); + printMe( c_LITERAL(intspan)cspan_from(&vec) ); printMe( sp2 ); cstack_int stk = c_init(cstack_int, {1, 2, 3, 4, 5, 6, 7}); - printMe( (intspan)cspan_from(&stk) ); + printMe( c_LITERAL(intspan)cspan_from(&stk) ); csset_str set = c_init(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"}); printf("%d:", (int)csset_str_size(&set)); diff --git a/misc/examples/read.c b/misc/examples/read.c index 545d706a..3c1cadf6 100644 --- a/misc/examples/read.c +++ b/misc/examples/read.c @@ -9,7 +9,7 @@ cvec_str read_file(const char* name) { cvec_str vec = cvec_str_init(); c_with (FILE* f = fopen(name, "r"), fclose(f)) - c_with (cstr line = cstr_NULL, cstr_drop(&line)) + c_with (cstr line = cstr_null, cstr_drop(&line)) while (cstr_getline(&line, f)) cvec_str_push(&vec, cstr_clone(line)); return vec; diff --git a/misc/examples/shape.c b/misc/examples/shape.c index 22e993db..1d9fe5c5 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -137,7 +137,7 @@ int main(void) { Shapes shapes = {0}; - Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); + Triangle* tri1 = c_new(Triangle, Triangle_from(c_LITERAL(Point){5, 7}, c_LITERAL(Point){12, 7}, c_LITERAL(Point){12, 20})); Polygon* pol1 = c_new(Polygon, Polygon_init()); Polygon* pol2 = c_new(Polygon, Polygon_init()); diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c index cf087119..d9024052 100644 --- a/misc/examples/vikings.c +++ b/misc/examples/vikings.c @@ -44,12 +44,12 @@ static inline RViking Viking_toraw(const Viking* vp) { int main() { Vikings vikings = {0}; - Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20); - Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24); - Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12); - Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10); + Vikings_emplace(&vikings, c_LITERAL(RViking){"Einar", "Norway"}, 20); + Vikings_emplace(&vikings, c_LITERAL(RViking){"Olaf", "Denmark"}, 24); + Vikings_emplace(&vikings, c_LITERAL(RViking){"Harald", "Iceland"}, 12); + Vikings_emplace(&vikings, c_LITERAL(RViking){"Björn", "Sweden"}, 10); - Vikings_value* v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"}); + Vikings_value* v = Vikings_get_mut(&vikings, c_LITERAL(RViking){"Einar", "Norway"}); v->second += 3; // add 3 hp points to Einar c_forpair (vk, hp, Vikings, vikings) { diff --git a/src/cregex.c b/src/cregex.c index 1af719b4..9b7179b6 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -28,20 +28,20 @@ THE SOFTWARE. #include #ifdef i_import -# define _i_extern +# define _i_import #endif #ifndef CREGEX_H_INCLUDED # include "../include/stc/cregex.h" #endif -#ifdef _i_extern +#ifdef _i_import # include "utf8code.c" #endif -#ifdef _i_extern +#ifdef _i_import # define i_implement #else # undef i_implement #endif -#undef _i_extern +#undef _i_import #include "../include/stc/cstr.h" typedef uint32_t _Rune; /* Utf8 code point */ @@ -944,14 +944,14 @@ _runematch(_Rune s, _Rune r) case ASC_LO: inv = 1; case ASC_lo: return inv ^ (islower((int)r) != 0); case ASC_UP: inv = 1; case ASC_up: return inv ^ (isupper((int)r) != 0); case ASC_XD: inv = 1; case ASC_xd: return inv ^ (isxdigit((int)r) != 0); - case UTF_AN: inv = 1; case UTF_an: return inv ^ utf8_isalnum(r); - case UTF_BL: inv = 1; case UTF_bl: return inv ^ utf8_isblank(r); - case UTF_SP: inv = 1; case UTF_sp: return inv ^ utf8_isspace(r); - case UTF_LL: inv = 1; case UTF_ll: return inv ^ utf8_islower(r); - case UTF_LU: inv = 1; case UTF_lu: return inv ^ utf8_isupper(r); - case UTF_LC: inv = 1; case UTF_lc: return inv ^ utf8_iscased(r); - case UTF_AL: inv = 1; case UTF_al: return inv ^ utf8_isalpha(r); - case UTF_WR: inv = 1; case UTF_wr: return inv ^ utf8_isword(r); + case UTF_AN: inv = 1; case UTF_an: return inv ^ (int)utf8_isalnum(r); + case UTF_BL: inv = 1; case UTF_bl: return inv ^ (int)utf8_isblank(r); + case UTF_SP: inv = 1; case UTF_sp: return inv ^ (int)utf8_isspace(r); + case UTF_LL: inv = 1; case UTF_ll: return inv ^ (int)utf8_islower(r); + case UTF_LU: inv = 1; case UTF_lu: return inv ^ (int)utf8_isupper(r); + case UTF_LC: inv = 1; case UTF_lc: return inv ^ (int)utf8_iscased(r); + case UTF_AL: inv = 1; case UTF_al: return inv ^ (int)utf8_isalpha(r); + case UTF_WR: inv = 1; case UTF_wr: return inv ^ (int)utf8_isword(r); case UTF_cc: case UTF_CC: case UTF_lt: case UTF_LT: case UTF_nd: case UTF_ND: @@ -972,7 +972,7 @@ _runematch(_Rune s, _Rune r) case UTF_latin: case UTF_LATIN: n = (int)s - UTF_GRP; inv = n & 1; - return inv ^ utf8_isgroup(n / 2, r); + return inv ^ (int)utf8_isgroup(n / 2, r); } return s == r; } @@ -1220,7 +1220,7 @@ _build_subst(const char* replace, int nmatch, const csview match[], cstr_buf buf = cstr_buffer(subst); intptr_t len = 0, cap = buf.cap; char* dst = buf.data; - cstr mstr = cstr_NULL; + cstr mstr = cstr_null; while (*replace != '\0') { if (*replace == '$') { @@ -1293,8 +1293,8 @@ cregex_find_pattern_4(const char* pattern, const char* input, cstr cregex_replace_sv_6(const cregex* re, csview input, const char* replace, int count, bool (*mfun)(int, csview, cstr*), int rflags) { - cstr out = cstr_NULL; - cstr subst = cstr_NULL; + cstr out = cstr_null; + cstr subst = cstr_null; csview match[CREG_MAX_CAPTURES]; int nmatch = cregex_captures(re) + 1; if (!count) count = INT32_MAX; diff --git a/src/utf8code.c b/src/utf8code.c index 6a133050..4abf10ea 100644 --- a/src/utf8code.c +++ b/src/utf8code.c @@ -461,28 +461,31 @@ static const URange16 Latin_range16[] = { #define UNI_ENTRY(Code) \ { Code##_range16, sizeof(Code##_range16)/sizeof(URange16) } -#ifndef __cplusplus +#ifdef __cplusplus +#define _e_arg(k, v) v +#else +#define _e_arg(k, v) [k] = v static #endif const UGroup _utf8_unicode_groups[U8G_SIZE] = { - [U8G_Cc] = UNI_ENTRY(Cc), - [U8G_Lt] = UNI_ENTRY(Lt), - [U8G_Nd] = UNI_ENTRY(Nd), - [U8G_Nl] = UNI_ENTRY(Nl), - [U8G_Pc] = UNI_ENTRY(Pc), - [U8G_Pd] = UNI_ENTRY(Pd), - [U8G_Pf] = UNI_ENTRY(Pf), - [U8G_Pi] = UNI_ENTRY(Pi), - [U8G_Sc] = UNI_ENTRY(Sc), - [U8G_Zl] = UNI_ENTRY(Zl), - [U8G_Zp] = UNI_ENTRY(Zp), - [U8G_Zs] = UNI_ENTRY(Zs), - [U8G_Arabic] = UNI_ENTRY(Arabic), - [U8G_Cyrillic] = UNI_ENTRY(Cyrillic), - [U8G_Devanagari] = UNI_ENTRY(Devanagari), - [U8G_Greek] = UNI_ENTRY(Greek), - [U8G_Han] = UNI_ENTRY(Han), - [U8G_Latin] = UNI_ENTRY(Latin), + _e_arg(U8G_Cc, UNI_ENTRY(Cc)), + _e_arg(U8G_Lt, UNI_ENTRY(Lt)), + _e_arg(U8G_Nd, UNI_ENTRY(Nd)), + _e_arg(U8G_Nl, UNI_ENTRY(Nl)), + _e_arg(U8G_Pc, UNI_ENTRY(Pc)), + _e_arg(U8G_Pd, UNI_ENTRY(Pd)), + _e_arg(U8G_Pf, UNI_ENTRY(Pf)), + _e_arg(U8G_Pi, UNI_ENTRY(Pi)), + _e_arg(U8G_Sc, UNI_ENTRY(Sc)), + _e_arg(U8G_Zl, UNI_ENTRY(Zl)), + _e_arg(U8G_Zp, UNI_ENTRY(Zp)), + _e_arg(U8G_Zs, UNI_ENTRY(Zs)), + _e_arg(U8G_Arabic, UNI_ENTRY(Arabic)), + _e_arg(U8G_Cyrillic, UNI_ENTRY(Cyrillic)), + _e_arg(U8G_Devanagari, UNI_ENTRY(Devanagari)), + _e_arg(U8G_Greek, UNI_ENTRY(Greek)), + _e_arg(U8G_Han, UNI_ENTRY(Han)), + _e_arg(U8G_Latin, UNI_ENTRY(Latin)), }; #endif -- cgit v1.2.3 From de4f8fa86f141dfeab15f5576029910474f56fa1 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 20 Jun 2023 15:28:02 +0200 Subject: Internal only: Renamed _cx_memb() macro to _cx_MEMB() Renamed _cx_self macro to _cx_Self --- include/stc/algo/sort.h | 14 +-- include/stc/carc.h | 76 ++++++------- include/stc/cbox.h | 74 ++++++------- include/stc/cdeq.h | 100 ++++++++--------- include/stc/clist.h | 212 +++++++++++++++++------------------ include/stc/cmap.h | 194 ++++++++++++++++---------------- include/stc/cpque.h | 84 +++++++------- include/stc/cqueue.h | 130 +++++++++++----------- include/stc/csmap.h | 264 ++++++++++++++++++++++---------------------- include/stc/cstack.h | 102 ++++++++--------- include/stc/cvec.h | 220 ++++++++++++++++++------------------ include/stc/extend.h | 2 +- include/stc/priv/template.h | 22 ++-- 13 files changed, 747 insertions(+), 747 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h index 2e73b0fb..291d90a6 100644 --- a/include/stc/algo/sort.h +++ b/include/stc/algo/sort.h @@ -52,12 +52,12 @@ int main() { typedef i_val i_type; #endif #ifndef i_at - #define i_at(arr, idx) _cx_memb(_at_mut)(arr, idx) + #define i_at(arr, idx) _cx_MEMB(_at_mut)(arr, idx) #endif #include "../priv/template.h" -static inline void _cx_memb(_insertsort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) { +static inline void _cx_MEMB(_insertsort_ij)(_cx_Self* arr, intptr_t lo, intptr_t hi) { for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) { i_val key = *i_at(arr, i); while (j >= 0 && (i_less((&key), i_at(arr, j)))) { @@ -68,7 +68,7 @@ static inline void _cx_memb(_insertsort_ij)(_cx_self* arr, intptr_t lo, intptr_t } } -static inline void _cx_memb(_sort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) { +static inline void _cx_MEMB(_sort_ij)(_cx_Self* arr, intptr_t lo, intptr_t hi) { intptr_t i = lo, j; while (lo < hi) { i_val pivot = *i_at(arr, lo + (hi - lo)*7/16); @@ -87,14 +87,14 @@ static inline void _cx_memb(_sort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) { c_swap(intptr_t, &hi, &j); } - if (j - lo > 64) _cx_memb(_sort_ij)(arr, lo, j); - else if (j > lo) _cx_memb(_insertsort_ij)(arr, lo, j); + if (j - lo > 64) _cx_MEMB(_sort_ij)(arr, lo, j); + else if (j > lo) _cx_MEMB(_insertsort_ij)(arr, lo, j); lo = i; } } -static inline void _cx_memb(_sort_n)(_cx_self* arr, intptr_t len) { - _cx_memb(_sort_ij)(arr, 0, len - 1); +static inline void _cx_MEMB(_sort_n)(_cx_Self* arr, intptr_t len) { + _cx_MEMB(_sort_ij)(arr, 0, len - 1); } #include "../priv/template2.h" diff --git a/include/stc/carc.h b/include/stc/carc.h index 749b1fc1..3b60fe78 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -91,119 +91,119 @@ typedef i_keyraw _cx_raw; #define _i_atomic_dec_and_test(v) !(--*(v)) #endif #ifndef i_is_forward -_cx_deftypes(_c_carc_types, _cx_self, i_key); +_cx_DEFTYPES(_c_carc_types, _cx_Self, i_key); #endif -struct _cx_memb(_rep_) { catomic_long counter; i_key value; }; +struct _cx_MEMB(_rep_) { catomic_long counter; i_key value; }; -STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_LITERAL(_cx_self){NULL, NULL}; } +STC_INLINE _cx_Self _cx_MEMB(_init)(void) + { return c_LITERAL(_cx_Self){NULL, NULL}; } -STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) +STC_INLINE long _cx_MEMB(_use_count)(const _cx_Self* self) { return self->use_count ? *self->use_count : 0; } -STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { - _cx_self ptr = {p}; +STC_INLINE _cx_Self _cx_MEMB(_from_ptr)(_cx_value* p) { + _cx_Self ptr = {p}; if (p) *(ptr.use_count = _i_alloc(catomic_long)) = 1; return ptr; } // c++: std::make_shared<_cx_value>(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { - _cx_self ptr; - struct _cx_memb(_rep_)* rep = _i_alloc(struct _cx_memb(_rep_)); +STC_INLINE _cx_Self _cx_MEMB(_make)(_cx_value val) { + _cx_Self ptr; + struct _cx_MEMB(_rep_)* rep = _i_alloc(struct _cx_MEMB(_rep_)); *(ptr.use_count = &rep->counter) = 1; *(ptr.get = &rep->value) = val; return ptr; } -STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) +STC_INLINE _cx_raw _cx_MEMB(_toraw)(const _cx_Self* self) { return i_keyto(self->get); } -STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { - _cx_self ptr = *self; +STC_INLINE _cx_Self _cx_MEMB(_move)(_cx_Self* self) { + _cx_Self ptr = *self; self->get = NULL, self->use_count = NULL; return ptr; } -STC_INLINE void _cx_memb(_drop)(_cx_self* self) { +STC_INLINE void _cx_MEMB(_drop)(_cx_Self* self) { if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { i_keydrop(self->get); - if ((char *)self->get != (char *)self->use_count + offsetof(struct _cx_memb(_rep_), value)) + if ((char *)self->get != (char *)self->use_count + offsetof(struct _cx_MEMB(_rep_), value)) i_free(self->get); i_free((long*)self->use_count); } } -STC_INLINE void _cx_memb(_reset)(_cx_self* self) { - _cx_memb(_drop)(self); +STC_INLINE void _cx_MEMB(_reset)(_cx_Self* self) { + _cx_MEMB(_drop)(self); self->use_count = NULL, self->get = NULL; } -STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { - _cx_memb(_drop)(self); - *self = _cx_memb(_from_ptr)(p); +STC_INLINE void _cx_MEMB(_reset_to)(_cx_Self* self, _cx_value* p) { + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_from_ptr)(p); } #ifndef i_no_emplace -STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } +STC_INLINE _cx_Self _cx_MEMB(_from)(_cx_raw raw) + { return _cx_MEMB(_make)(i_keyfrom(raw)); } #else -STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) - { return _cx_memb(_make)(val); } +STC_INLINE _cx_Self _cx_MEMB(_from)(_cx_value val) + { return _cx_MEMB(_make)(val); } #endif // does not use i_keyclone, so OK to always define. -STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) { +STC_INLINE _cx_Self _cx_MEMB(_clone)(_cx_Self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); return ptr; } // take ownership of unowned -STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) { - _cx_memb(_drop)(self); +STC_INLINE void _cx_MEMB(_take)(_cx_Self* self, _cx_Self unowned) { + _cx_MEMB(_drop)(self); *self = unowned; } // share ownership with ptr -STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) { +STC_INLINE void _cx_MEMB(_assign)(_cx_Self* self, _cx_Self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); - _cx_memb(_drop)(self); + _cx_MEMB(_drop)(self); *self = ptr; } #ifndef i_no_cmp -STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry) +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* self, const _cx_self* other) { +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 #ifdef _i_eq -STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) +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* self, const _cx_self* other) { +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) +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* self, const _cx_self* other) - { return _cx_memb(_cmp)(self, other) == 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) +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* self) +STC_INLINE uint64_t _cx_MEMB(_hash)(const _cx_Self* self) { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); } #endif diff --git a/include/stc/cbox.h b/include/stc/cbox.h index d7f6246d..86283ad7 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -77,119 +77,119 @@ int main() { typedef i_keyraw _cx_raw; #ifndef i_is_forward -_cx_deftypes(_c_cbox_types, _cx_self, i_key); +_cx_DEFTYPES(_c_cbox_types, _cx_Self, i_key); #endif // constructors (take ownership) -STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_LITERAL(_cx_self){NULL}; } +STC_INLINE _cx_Self _cx_MEMB(_init)(void) + { return c_LITERAL(_cx_Self){NULL}; } -STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) +STC_INLINE long _cx_MEMB(_use_count)(const _cx_Self* self) { return (long)(self->get != NULL); } -STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) - { return c_LITERAL(_cx_self){p}; } +STC_INLINE _cx_Self _cx_MEMB(_from_ptr)(_cx_value* p) + { return c_LITERAL(_cx_Self){p}; } // c++: std::make_unique(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { - _cx_self ptr = {_i_alloc(_cx_value)}; +STC_INLINE _cx_Self _cx_MEMB(_make)(_cx_value val) { + _cx_Self ptr = {_i_alloc(_cx_value)}; *ptr.get = val; return ptr; } -STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) +STC_INLINE _cx_raw _cx_MEMB(_toraw)(const _cx_Self* self) { return i_keyto(self->get); } // destructor -STC_INLINE void _cx_memb(_drop)(_cx_self* self) { +STC_INLINE void _cx_MEMB(_drop)(_cx_Self* self) { if (self->get) { i_keydrop(self->get); i_free(self->get); } } -STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { - _cx_self ptr = *self; +STC_INLINE _cx_Self _cx_MEMB(_move)(_cx_Self* self) { + _cx_Self ptr = *self; self->get = NULL; return ptr; } -STC_INLINE _cx_value* _cx_memb(_release)(_cx_self* self) - { return _cx_memb(_move)(self).get; } +STC_INLINE _cx_value* _cx_MEMB(_release)(_cx_Self* self) + { return _cx_MEMB(_move)(self).get; } -STC_INLINE void _cx_memb(_reset)(_cx_self* self) { - _cx_memb(_drop)(self); +STC_INLINE void _cx_MEMB(_reset)(_cx_Self* self) { + _cx_MEMB(_drop)(self); self->get = NULL; } // take ownership of p -STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { - _cx_memb(_drop)(self); +STC_INLINE void _cx_MEMB(_reset_to)(_cx_Self* self, _cx_value* p) { + _cx_MEMB(_drop)(self); self->get = p; } #ifndef i_no_emplace -STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } +STC_INLINE _cx_Self _cx_MEMB(_from)(_cx_raw raw) + { return _cx_MEMB(_make)(i_keyfrom(raw)); } #else -STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) - { return _cx_memb(_make)(val); } +STC_INLINE _cx_Self _cx_MEMB(_from)(_cx_value val) + { return _cx_MEMB(_make)(val); } #endif #if !defined i_no_clone - STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { + STC_INLINE _cx_Self _cx_MEMB(_clone)(_cx_Self other) { if (!other.get) return other; - _cx_self out = {_i_alloc(i_key)}; + _cx_Self out = {_i_alloc(i_key)}; *out.get = i_keyclone((*other.get)); return out; } #endif // !i_no_clone // take ownership of unowned -STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) { - _cx_memb(_drop)(self); +STC_INLINE void _cx_MEMB(_take)(_cx_Self* self, _cx_Self unowned) { + _cx_MEMB(_drop)(self); *self = unowned; } // transfer ownership from moved; set moved to NULL -STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* moved) { +STC_INLINE void _cx_MEMB(_assign)(_cx_Self* self, _cx_Self* moved) { if (moved->get == self->get) return; - _cx_memb(_drop)(self); + _cx_MEMB(_drop)(self); *self = *moved; moved->get = NULL; } #ifndef i_no_cmp -STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry) +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* self, const _cx_self* other) { +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 #ifdef _i_eq -STC_INLINE bool _cx_memb(_raw_eq)(const _cx_raw* rx, const _cx_raw* ry) +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* self, const _cx_self* other) { +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) +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* self, const _cx_self* other) - { return _cx_memb(_cmp)(self, other) == 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) +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* self) +STC_INLINE uint64_t _cx_MEMB(_hash)(const _cx_Self* self) { _cx_raw rx = i_keyto(self->get); return i_hash((&rx)); } #endif diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index a406c2b0..0eac5a1d 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -32,101 +32,101 @@ #endif #undef _pop -STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); -STC_API _cx_iter _cx_memb(_insert_n)(_cx_self* self, intptr_t idx, const _cx_value* arr, intptr_t n); -STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n); -STC_API void _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n); +STC_API _cx_value* _cx_MEMB(_push_front)(_cx_Self* self, i_key value); +STC_API _cx_iter _cx_MEMB(_insert_n)(_cx_Self* self, intptr_t idx, const _cx_value* arr, intptr_t n); +STC_API _cx_iter _cx_MEMB(_insert_uninit)(_cx_Self* self, intptr_t idx, intptr_t n); +STC_API void _cx_MEMB(_erase_n)(_cx_Self* self, intptr_t idx, intptr_t n); STC_INLINE const _cx_value* -_cx_memb(_at)(const _cx_self* self, intptr_t idx) +_cx_MEMB(_at)(const _cx_Self* self, intptr_t idx) { return self->data + _cdeq_topos(self, idx); } STC_INLINE _cx_value* -_cx_memb(_at_mut)(_cx_self* self, intptr_t idx) +_cx_MEMB(_at_mut)(_cx_Self* self, intptr_t idx) { return self->data + _cdeq_topos(self, idx); } STC_INLINE _cx_value* -_cx_memb(_push_back)(_cx_self* self, _cx_value val) - { return _cx_memb(_push)(self, val); } +_cx_MEMB(_push_back)(_cx_Self* self, _cx_value val) + { return _cx_MEMB(_push)(self, val); } STC_INLINE void -_cx_memb(_pop_back)(_cx_self* self) { - assert(!_cx_memb(_empty)(self)); +_cx_MEMB(_pop_back)(_cx_Self* self) { + assert(!_cx_MEMB(_empty)(self)); self->end = (self->end - 1) & self->capmask; i_keydrop((self->data + self->end)); } -STC_INLINE _cx_value _cx_memb(_pull_back)(_cx_self* self) { // move back out of deq - assert(!_cx_memb(_empty)(self)); +STC_INLINE _cx_value _cx_MEMB(_pull_back)(_cx_Self* self) { // move back out of deq + assert(!_cx_MEMB(_empty)(self)); self->end = (self->end - 1) & self->capmask; return self->data[self->end]; } STC_INLINE _cx_iter -_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const _cx_value val) { +_cx_MEMB(_insert_at)(_cx_Self* self, _cx_iter it, const _cx_value val) { intptr_t idx = _cdeq_toidx(self, it.pos); - return _cx_memb(_insert_n)(self, idx, &val, 1); + return _cx_MEMB(_insert_n)(self, idx, &val, 1); } STC_INLINE _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - _cx_memb(_erase_n)(self, _cdeq_toidx(self, it.pos), 1); +_cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it) { + _cx_MEMB(_erase_n)(self, _cdeq_toidx(self, it.pos), 1); if (it.pos == self->end) it.ref = NULL; return it; } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { +_cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2) { intptr_t idx1 = _cdeq_toidx(self, it1.pos); intptr_t idx2 = _cdeq_toidx(self, it2.pos); - _cx_memb(_erase_n)(self, idx1, idx2 - idx1); + _cx_MEMB(_erase_n)(self, idx1, idx2 - idx1); if (it1.pos == self->end) it1.ref = NULL; return it1; } #if !defined i_no_emplace STC_API _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw* raw, intptr_t n); +_cx_MEMB(_emplace_n)(_cx_Self* self, intptr_t idx, const _cx_raw* raw, intptr_t n); STC_INLINE _cx_value* -_cx_memb(_emplace_front)(_cx_self* self, const _cx_raw raw) - { return _cx_memb(_push_front)(self, i_keyfrom(raw)); } +_cx_MEMB(_emplace_front)(_cx_Self* self, const _cx_raw raw) + { return _cx_MEMB(_push_front)(self, i_keyfrom(raw)); } STC_INLINE _cx_value* -_cx_memb(_emplace_back)(_cx_self* self, const _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } +_cx_MEMB(_emplace_back)(_cx_Self* self, const _cx_raw raw) + { return _cx_MEMB(_push)(self, i_keyfrom(raw)); } STC_INLINE _cx_iter -_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, const _cx_raw raw) - { return _cx_memb(_insert_at)(self, it, i_keyfrom(raw)); } +_cx_MEMB(_emplace_at)(_cx_Self* self, _cx_iter it, const _cx_raw raw) + { return _cx_MEMB(_insert_at)(self, it, i_keyfrom(raw)); } #endif #if defined _i_has_cmp || defined _i_has_eq -STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); +STC_API _cx_iter _cx_MEMB(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); STC_INLINE _cx_iter -_cx_memb(_find)(const _cx_self* self, _cx_raw raw) { - return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw); +_cx_MEMB(_find)(const _cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_find_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), raw); } STC_INLINE const _cx_value* -_cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw).ref; +_cx_MEMB(_get)(const _cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_find_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), raw).ref; } STC_INLINE _cx_value* -_cx_memb(_get_mut)(_cx_self* self, _cx_raw raw) - { return (_cx_value *) _cx_memb(_get)(self, raw); } +_cx_MEMB(_get_mut)(_cx_Self* self, _cx_raw raw) + { return (_cx_value *) _cx_MEMB(_get)(self, raw); } #endif /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) STC_DEF _cx_value* -_cx_memb(_push_front)(_cx_self* self, i_key value) { +_cx_MEMB(_push_front)(_cx_Self* self, i_key value) { intptr_t start = (self->start - 1) & self->capmask; if (start == self->end) { // full - _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand + _cx_MEMB(_reserve)(self, self->capmask + 3); // => 2x expand start = (self->start - 1) & self->capmask; } _cx_value *v = self->data + start; @@ -136,24 +136,24 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { } STC_DEF void -_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) { - const intptr_t len = _cx_memb(_size)(self); +_cx_MEMB(_erase_n)(_cx_Self* self, const intptr_t idx, const intptr_t n) { + const intptr_t len = _cx_MEMB(_size)(self); for (intptr_t i = idx + n - 1; i >= idx; --i) - i_keydrop(_cx_memb(_at_mut)(self, i)); + i_keydrop(_cx_MEMB(_at_mut)(self, i)); for (intptr_t i = idx, j = i + n; j < len; ++i, ++j) - *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j); + *_cx_MEMB(_at_mut)(self, i) = *_cx_MEMB(_at)(self, j); self->end = (self->end - n) & self->capmask; } STC_DEF _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { - const intptr_t len = _cx_memb(_size)(self); +_cx_MEMB(_insert_uninit)(_cx_Self* self, const intptr_t idx, const intptr_t n) { + const intptr_t len = _cx_MEMB(_size)(self); _cx_iter it = {._s=self}; if (len + n > self->capmask) - if (!_cx_memb(_reserve)(self, len + n)) + if (!_cx_MEMB(_reserve)(self, len + n)) return it; for (intptr_t i = len - 1, j = i + n; i >= idx; --i, --j) - *_cx_memb(_at_mut)(self, j) = *_cx_memb(_at)(self, i); + *_cx_MEMB(_at_mut)(self, j) = *_cx_MEMB(_at)(self, i); self->end = (self->end + n) & self->capmask; it.pos = _cdeq_topos(self, idx); @@ -162,27 +162,27 @@ _cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { } STC_DEF _cx_iter -_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value* arr, const intptr_t n) { - _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); +_cx_MEMB(_insert_n)(_cx_Self* self, const intptr_t idx, const _cx_value* arr, const intptr_t n) { + _cx_iter it = _cx_MEMB(_insert_uninit)(self, idx, n); for (intptr_t i = idx, j = 0; j < n; ++i, ++j) - *_cx_memb(_at_mut)(self, i) = arr[j]; + *_cx_MEMB(_at_mut)(self, i) = arr[j]; return it; } #if !defined i_no_emplace STC_DEF _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw* raw, const intptr_t n) { - _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); +_cx_MEMB(_emplace_n)(_cx_Self* self, const intptr_t idx, const _cx_raw* raw, const intptr_t n) { + _cx_iter it = _cx_MEMB(_insert_uninit)(self, idx, n); for (intptr_t i = idx, j = 0; j < n; ++i, ++j) - *_cx_memb(_at_mut)(self, i) = i_keyfrom(raw[j]); + *_cx_MEMB(_at_mut)(self, i) = i_keyfrom(raw[j]); return it; } #endif #if defined _i_has_cmp || defined _i_has_eq STC_DEF _cx_iter -_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - for (; i1.pos != i2.pos; _cx_memb(_next)(&i1)) { +_cx_MEMB(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { + for (; i1.pos != i2.pos; _cx_MEMB(_next)(&i1)) { const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) break; diff --git a/include/stc/clist.h b/include/stc/clist.h index 4d05a3d1..0785a6af 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -82,77 +82,77 @@ #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_clist_types, _cx_self, i_key); + _cx_DEFTYPES(_c_clist_types, _cx_Self, i_key); #endif -_cx_deftypes(_c_clist_complete_types, _cx_self, dummy); +_cx_DEFTYPES(_c_clist_complete_types, _cx_Self, dummy); typedef i_keyraw _cx_raw; -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value); -STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); -STC_API _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value); -STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); -STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); +STC_API void _cx_MEMB(_drop)(_cx_Self* self); +STC_API _cx_value* _cx_MEMB(_push_back)(_cx_Self* self, i_key value); +STC_API _cx_value* _cx_MEMB(_push_front)(_cx_Self* self, i_key value); +STC_API _cx_iter _cx_MEMB(_insert_at)(_cx_Self* self, _cx_iter it, i_key value); +STC_API _cx_iter _cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it); +STC_API _cx_iter _cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2); #if !defined i_no_cmp || defined _i_has_eq -STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val); -STC_API intptr_t _cx_memb(_remove)(_cx_self* self, _cx_raw val); +STC_API _cx_iter _cx_MEMB(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val); +STC_API intptr_t _cx_MEMB(_remove)(_cx_Self* self, _cx_raw val); #endif #ifndef i_no_cmp -STC_API bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, const _cx_value*)); -STC_API int _cx_memb(_sort_cmp_)(const _cx_value*, const _cx_value*); -STC_INLINE bool _cx_memb(_sort)(_cx_self* self) - { return _cx_memb(_sort_with)(self, _cx_memb(_sort_cmp_)); } +STC_API bool _cx_MEMB(_sort_with)(_cx_Self* self, int(*cmp)(const _cx_value*, const _cx_value*)); +STC_API int _cx_MEMB(_sort_cmp_)(const _cx_value*, const _cx_value*); +STC_INLINE bool _cx_MEMB(_sort)(_cx_Self* self) + { return _cx_MEMB(_sort_with)(self, _cx_MEMB(_sort_cmp_)); } #endif -STC_API void _cx_memb(_reverse)(_cx_self* self); -STC_API _cx_iter _cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other); -STC_API _cx_self _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2); -STC_API _cx_value* _cx_memb(_push_back_node)(_cx_self* self, _cx_node* node); -STC_API _cx_value* _cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node); -STC_API _cx_node* _cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref); -STC_API void _cx_memb(_erase_after_node)(_cx_self* self, _cx_node* ref); -STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* pval) { return _clist_tonode(pval); } -STC_INLINE _cx_node* _cx_memb(_unlink_front_node)(_cx_self* self) - { return _cx_memb(_unlink_after_node)(self, self->last); } +STC_API void _cx_MEMB(_reverse)(_cx_Self* self); +STC_API _cx_iter _cx_MEMB(_splice)(_cx_Self* self, _cx_iter it, _cx_Self* other); +STC_API _cx_Self _cx_MEMB(_split_off)(_cx_Self* self, _cx_iter it1, _cx_iter it2); +STC_API _cx_value* _cx_MEMB(_push_back_node)(_cx_Self* self, _cx_node* node); +STC_API _cx_value* _cx_MEMB(_insert_after_node)(_cx_Self* self, _cx_node* ref, _cx_node* node); +STC_API _cx_node* _cx_MEMB(_unlink_after_node)(_cx_Self* self, _cx_node* ref); +STC_API void _cx_MEMB(_erase_after_node)(_cx_Self* self, _cx_node* ref); +STC_INLINE _cx_node* _cx_MEMB(_get_node)(_cx_value* pval) { return _clist_tonode(pval); } +STC_INLINE _cx_node* _cx_MEMB(_unlink_front_node)(_cx_Self* self) + { return _cx_MEMB(_unlink_after_node)(self, self->last); } #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_INLINE i_key _cx_memb(_value_clone)(i_key val) { return i_keyclone(val); } +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self cx); +STC_INLINE i_key _cx_MEMB(_value_clone)(i_key val) { return i_keyclone(val); } STC_INLINE void -_cx_memb(_copy)(_cx_self *self, const _cx_self* other) { +_cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { if (self->last == other->last) return; - _cx_memb(_drop)(self); *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); *self = _cx_MEMB(_clone)(*other); } #endif // !i_no_clone #if !defined i_no_emplace -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push_back)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push_front)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) - { return _cx_memb(_insert_at)(self, it, i_keyfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push_back)(self, i_keyfrom(raw)); } +STC_INLINE _cx_value* _cx_MEMB(_emplace_back)(_cx_Self* self, _cx_raw raw) + { return _cx_MEMB(_push_back)(self, i_keyfrom(raw)); } +STC_INLINE _cx_value* _cx_MEMB(_emplace_front)(_cx_Self* self, _cx_raw raw) + { return _cx_MEMB(_push_front)(self, i_keyfrom(raw)); } +STC_INLINE _cx_iter _cx_MEMB(_emplace_at)(_cx_Self* self, _cx_iter it, _cx_raw raw) + { return _cx_MEMB(_insert_at)(self, it, i_keyfrom(raw)); } +STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) + { return _cx_MEMB(_push_back)(self, i_keyfrom(raw)); } #endif // !i_no_emplace -STC_INLINE _cx_self _cx_memb(_init)(void) { return c_LITERAL(_cx_self){NULL}; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push_back)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) { (void)(self + n); return true; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return self->last == NULL; } -STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); } -STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, i_key value) - { return _cx_memb(_push_back)(self, value); } -STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) - { assert(!_cx_memb(_empty)(self)); _cx_memb(_erase_after_node)(self, self->last); } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; } -STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } -STC_INLINE void _cx_memb(_value_drop)(_cx_value* pval) { i_keydrop(pval); } +STC_INLINE _cx_Self _cx_MEMB(_init)(void) { return c_LITERAL(_cx_Self){NULL}; } +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_MEMB(_push_back)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } +STC_INLINE bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t n) { (void)(self + n); return true; } +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self) { return self->last == NULL; } +STC_INLINE void _cx_MEMB(_clear)(_cx_Self* self) { _cx_MEMB(_drop)(self); } +STC_INLINE _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value) + { return _cx_MEMB(_push_back)(self, value); } +STC_INLINE void _cx_MEMB(_pop_front)(_cx_Self* self) + { assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_after_node)(self, self->last); } +STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return &self->last->next->value; } +STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return &self->last->value; } +STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } +STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* pval) { i_keydrop(pval); } STC_INLINE intptr_t -_cx_memb(_count)(const _cx_self* self) { +_cx_MEMB(_count)(const _cx_Self* self) { intptr_t n = 1; const _cx_node *node = self->last; if (!node) return 0; while ((node = node->next) != self->last) ++n; @@ -160,53 +160,53 @@ _cx_memb(_count)(const _cx_self* self) { } STC_INLINE _cx_iter -_cx_memb(_begin)(const _cx_self* self) { +_cx_MEMB(_begin)(const _cx_Self* self) { _cx_value* head = self->last ? &self->last->next->value : NULL; return c_LITERAL(_cx_iter){head, &self->last, self->last}; } STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) +_cx_MEMB(_end)(const _cx_Self* self) { return c_LITERAL(_cx_iter){NULL}; } STC_INLINE void -_cx_memb(_next)(_cx_iter* it) { +_cx_MEMB(_next)(_cx_iter* it) { _cx_node* node = it->prev = _clist_tonode(it->ref); it->ref = (node == *it->_last ? NULL : &node->next->value); } STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { - while (n-- && it.ref) _cx_memb(_next)(&it); +_cx_MEMB(_advance)(_cx_iter it, size_t n) { + while (n-- && it.ref) _cx_MEMB(_next)(&it); return it; } STC_INLINE _cx_iter -_cx_memb(_splice_range)(_cx_self* self, _cx_iter it, - _cx_self* other, _cx_iter it1, _cx_iter it2) { - _cx_self tmp = _cx_memb(_split_off)(other, it1, it2); - return _cx_memb(_splice)(self, it, &tmp); +_cx_MEMB(_splice_range)(_cx_Self* self, _cx_iter it, + _cx_Self* other, _cx_iter it1, _cx_iter it2) { + _cx_Self tmp = _cx_MEMB(_split_off)(other, it1, it2); + return _cx_MEMB(_splice)(self, it, &tmp); } #if !defined i_no_cmp || defined _i_has_eq STC_INLINE _cx_iter -_cx_memb(_find)(const _cx_self* self, _cx_raw val) { - return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val); +_cx_MEMB(_find)(const _cx_Self* self, _cx_raw val) { + return _cx_MEMB(_find_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), val); } STC_INLINE const _cx_value* -_cx_memb(_get)(const _cx_self* self, _cx_raw val) { - return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), val).ref; +_cx_MEMB(_get)(const _cx_Self* self, _cx_raw val) { + return _cx_MEMB(_find_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), val).ref; } STC_INLINE _cx_value* -_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; +_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* 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)) { +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; } @@ -218,29 +218,29 @@ STC_INLINE bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #if defined(i_implement) || defined(i_static) #if !defined i_no_clone -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - _cx_self out = _cx_memb(_init)(); - c_foreach (it, _cx_self, cx) - _cx_memb(_push_back)(&out, i_keyclone((*it.ref))); +STC_DEF _cx_Self +_cx_MEMB(_clone)(_cx_Self cx) { + _cx_Self out = _cx_MEMB(_init)(); + c_foreach (it, _cx_Self, cx) + _cx_MEMB(_push_back)(&out, i_keyclone((*it.ref))); return out; } #endif STC_DEF void -_cx_memb(_drop)(_cx_self* self) { - while (self->last) _cx_memb(_erase_after_node)(self, self->last); +_cx_MEMB(_drop)(_cx_Self* self) { + while (self->last) _cx_MEMB(_erase_after_node)(self, self->last); } STC_DEF _cx_value* -_cx_memb(_push_back)(_cx_self* self, i_key value) { +_cx_MEMB(_push_back)(_cx_Self* self, i_key value) { _c_clist_insert_entry_after(self->last, value); self->last = entry; return &entry->value; } STC_DEF _cx_value* -_cx_memb(_push_front)(_cx_self* self, i_key value) { +_cx_MEMB(_push_front)(_cx_Self* self, i_key value) { _c_clist_insert_entry_after(self->last, value); if (!self->last) self->last = entry; @@ -248,14 +248,14 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { } STC_DEF _cx_value* -_cx_memb(_push_back_node)(_cx_self* self, _cx_node* node) { +_cx_MEMB(_push_back_node)(_cx_Self* self, _cx_node* node) { _c_clist_insert_after_node(self->last, node); self->last = node; return &node->value; } STC_DEF _cx_value* -_cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node) { +_cx_MEMB(_insert_after_node)(_cx_Self* self, _cx_node* ref, _cx_node* node) { _c_clist_insert_after_node(ref, node); if (!self->last) self->last = node; @@ -263,7 +263,7 @@ _cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node) { } STC_DEF _cx_iter -_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { +_cx_MEMB(_insert_at)(_cx_Self* self, _cx_iter it, i_key value) { _cx_node* node = it.ref ? it.prev : self->last; _c_clist_insert_entry_after(node, value); if (!self->last || !it.ref) { @@ -275,32 +275,32 @@ _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { } STC_DEF _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { +_cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it) { _cx_node *node = _clist_tonode(it.ref); it.ref = (node == self->last) ? NULL : &node->next->value; - _cx_memb(_erase_after_node)(self, it.prev); + _cx_MEMB(_erase_after_node)(self, it.prev); return it; } STC_DEF _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { +_cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2) { _cx_node *end = it2.ref ? _clist_tonode(it2.ref) : self->last->next; if (it1.ref != it2.ref) do { - _cx_memb(_erase_after_node)(self, it1.prev); + _cx_MEMB(_erase_after_node)(self, it1.prev); if (!self->last) break; } while (it1.prev->next != end); return it2; } STC_DEF void -_cx_memb(_erase_after_node)(_cx_self* self, _cx_node* ref) { - _cx_node* node = _cx_memb(_unlink_after_node)(self, ref); +_cx_MEMB(_erase_after_node)(_cx_Self* self, _cx_node* ref) { + _cx_node* node = _cx_MEMB(_unlink_after_node)(self, ref); i_keydrop((&node->value)); i_free(node); } STC_DEF _cx_node* -_cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref) { +_cx_MEMB(_unlink_after_node)(_cx_Self* self, _cx_node* ref) { _cx_node* node = ref->next, *next = node->next; ref->next = next; if (node == next) @@ -311,17 +311,17 @@ _cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref) { } STC_DEF void -_cx_memb(_reverse)(_cx_self* self) { - _cx_self rev = {NULL}; +_cx_MEMB(_reverse)(_cx_Self* self) { + _cx_Self rev = {NULL}; while (self->last) { - _cx_node* node = _cx_memb(_unlink_after_node)(self, self->last); - _cx_memb(_insert_after_node)(&rev, rev.last, node); + _cx_node* node = _cx_MEMB(_unlink_after_node)(self, self->last); + _cx_MEMB(_insert_after_node)(&rev, rev.last, node); } *self = rev; } STC_DEF _cx_iter -_cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other) { +_cx_MEMB(_splice)(_cx_Self* self, _cx_iter it, _cx_Self* other) { if (!self->last) self->last = other->last; else if (other->last) { @@ -335,9 +335,9 @@ _cx_memb(_splice)(_cx_self* self, _cx_iter it, _cx_self* other) { return it; } -STC_DEF _cx_self -_cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - _cx_self lst = {NULL}; +STC_DEF _cx_Self +_cx_MEMB(_split_off)(_cx_Self* self, _cx_iter it1, _cx_iter it2) { + _cx_Self lst = {NULL}; if (it1.ref == it2.ref) return lst; _cx_node *p1 = it1.prev, @@ -353,8 +353,8 @@ _cx_memb(_split_off)(_cx_self* self, _cx_iter it1, _cx_iter it2) { #if !defined i_no_cmp || defined _i_has_eq STC_DEF _cx_iter -_cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val) { - c_foreach (it, _cx_self, it1, it2) { +_cx_MEMB(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val) { + c_foreach (it, _cx_Self, it1, it2) { _cx_raw r = i_keyto(it.ref); if (i_eq((&r), (&val))) return it; @@ -363,14 +363,14 @@ _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw val) { } STC_DEF intptr_t -_cx_memb(_remove)(_cx_self* self, _cx_raw val) { +_cx_MEMB(_remove)(_cx_Self* self, _cx_raw val) { intptr_t n = 0; _cx_node *prev = self->last, *node; if (prev) do { node = prev->next; _cx_raw r = i_keyto((&node->value)); if (i_eq((&r), (&val))) { - _cx_memb(_erase_after_node)(self, prev), ++n; + _cx_MEMB(_erase_after_node)(self, prev), ++n; if (!self->last) break; } else prev = node; @@ -380,16 +380,16 @@ _cx_memb(_remove)(_cx_self* self, _cx_raw val) { #endif #ifndef i_no_cmp -STC_DEF int _cx_memb(_sort_cmp_)(const _cx_value* x, const _cx_value* y) { +STC_DEF int _cx_MEMB(_sort_cmp_)(const _cx_value* x, const _cx_value* y) { const _cx_raw a = i_keyto(x), b = i_keyto(y); return i_cmp((&a), (&b)); } -STC_DEF bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, const _cx_value*)) { +STC_DEF bool _cx_MEMB(_sort_with)(_cx_Self* self, int(*cmp)(const _cx_value*, const _cx_value*)) { size_t len = 0, cap = 0; _cx_value *a = NULL, *p = NULL; _cx_iter i; - for (i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i)) { + for (i = _cx_MEMB(_begin)(self); i.ref; _cx_MEMB(_next)(&i)) { if (len == cap) { if ((p = (_cx_value *)i_realloc(a, (cap += cap/2 + 4)*sizeof *a))) a = p; else { i_free(a); return false; } @@ -397,7 +397,7 @@ STC_DEF bool _cx_memb(_sort_with)(_cx_self* self, int(*cmp)(const _cx_value*, co a[len++] = *i.ref; } qsort(a, len, sizeof *a, (int(*)(const void*, const void*))cmp); - for (i = _cx_memb(_begin)(self); i.ref; _cx_memb(_next)(&i), ++p) + for (i = _cx_MEMB(_begin)(self); i.ref; _cx_MEMB(_next)(&i), ++p) *i.ref = *p; i_free(a); return true; } diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 2e234fb5..21e7b933 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -72,7 +72,7 @@ typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_chash_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); + _cx_DEFTYPES(_c_chash_types, _cx_Self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); #endif _i_MAP_ONLY( struct _cx_value { @@ -81,60 +81,60 @@ _i_MAP_ONLY( struct _cx_value { }; ) typedef i_keyraw _cx_keyraw; -typedef i_valraw _cx_memb(_rmapped); +typedef i_valraw _cx_MEMB(_rmapped); typedef _i_SET_ONLY( i_keyraw ) _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) _cx_raw; -STC_API _cx_self _cx_memb(_with_capacity)(intptr_t cap); +STC_API _cx_Self _cx_MEMB(_with_capacity)(intptr_t cap); #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self map); +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self map); #endif -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t capacity); -STC_API chash_bucket _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr); -STC_API _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); -STC_API void _cx_memb(_erase_entry)(_cx_self* self, _cx_value* val); -STC_API float _cx_memb(_max_load_factor)(const _cx_self* self); -STC_API intptr_t _cx_memb(_capacity)(const _cx_self* map); - -STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self map = {0}; return map; } -STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, (intptr_t)self->size); } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* map) { return !map->size; } -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* map) { return (intptr_t)map->size; } -STC_INLINE intptr_t _cx_memb(_bucket_count)(_cx_self* map) { return map->bucket_count; } -STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) - { return self->size && _cx_memb(_bucket_)(self, &rkey).found; } +STC_API void _cx_MEMB(_drop)(_cx_Self* self); +STC_API void _cx_MEMB(_clear)(_cx_Self* self); +STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t capacity); +STC_API chash_bucket _cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr); +STC_API _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey); +STC_API void _cx_MEMB(_erase_entry)(_cx_Self* self, _cx_value* val); +STC_API float _cx_MEMB(_max_load_factor)(const _cx_Self* self); +STC_API intptr_t _cx_MEMB(_capacity)(const _cx_Self* map); + +STC_INLINE _cx_Self _cx_MEMB(_init)(void) { _cx_Self map = {0}; return map; } +STC_INLINE void _cx_MEMB(_shrink_to_fit)(_cx_Self* self) { _cx_MEMB(_reserve)(self, (intptr_t)self->size); } +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* map) { return !map->size; } +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* map) { return (intptr_t)map->size; } +STC_INLINE intptr_t _cx_MEMB(_bucket_count)(_cx_Self* map) { return map->bucket_count; } +STC_INLINE bool _cx_MEMB(_contains)(const _cx_Self* self, _cx_keyraw rkey) + { return self->size && _cx_MEMB(_bucket_)(self, &rkey).found; } #ifndef _i_isset - STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); + STC_API _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key key, i_val mapped); #if !defined i_no_emplace - STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped); + STC_API _cx_result _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped); #endif STC_INLINE const _cx_mapped* - _cx_memb(_at)(const _cx_self* self, _cx_keyraw rkey) { - chash_bucket b = _cx_memb(_bucket_)(self, &rkey); + _cx_MEMB(_at)(const _cx_Self* self, _cx_keyraw rkey) { + chash_bucket b = _cx_MEMB(_bucket_)(self, &rkey); assert(b.found); return &self->data[b.idx].second; } STC_INLINE _cx_mapped* - _cx_memb(_at_mut)(_cx_self* self, _cx_keyraw rkey) - { return (_cx_mapped*)_cx_memb(_at)(self, rkey); } + _cx_MEMB(_at_mut)(_cx_Self* self, _cx_keyraw rkey) + { return (_cx_mapped*)_cx_MEMB(_at)(self, rkey); } #endif // !_i_isset #if !defined i_no_clone -STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { +STC_INLINE void _cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_clone)(*other); } STC_INLINE _cx_value -_cx_memb(_value_clone)(_cx_value _val) { +_cx_MEMB(_value_clone)(_cx_value _val) { *_i_keyref(&_val) = i_keyclone((*_i_keyref(&_val))); _i_MAP_ONLY( _val.second = i_valclone(_val.second); ) return _val; @@ -143,8 +143,8 @@ _cx_memb(_value_clone)(_cx_value _val) { #if !defined i_no_emplace STC_INLINE _cx_result -_cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { - _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); +_cx_MEMB(_emplace)(_cx_Self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, rkey); if (_res.inserted) { *_i_keyref(_res.ref) = i_keyfrom(rkey); _i_MAP_ONLY( _res.ref->second = i_valfrom(rmapped); ) @@ -153,19 +153,19 @@ _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmappe } #endif // !i_no_emplace -STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { +STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* val) { return _i_SET_ONLY( i_keyto(val) ) _i_MAP_ONLY( c_LITERAL(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); } -STC_INLINE void _cx_memb(_value_drop)(_cx_value* _val) { +STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* _val) { i_keydrop(_i_keyref(_val)); _i_MAP_ONLY( i_valdrop((&_val->second)); ) } STC_INLINE _cx_result -_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); +_cx_MEMB(_insert)(_cx_Self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); if (_res.inserted) { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} else @@ -173,90 +173,90 @@ _cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { return _res; } -STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value _val) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); +STC_INLINE _cx_value* _cx_MEMB(_push)(_cx_Self* self, _cx_value _val) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); if (_res.inserted) *_res.ref = _val; else - _cx_memb(_value_drop)(&_val); + _cx_MEMB(_value_drop)(&_val); return _res.ref; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) { while (n--) #if defined _i_isset && defined i_no_emplace - _cx_memb(_insert)(self, *raw++); + _cx_MEMB(_insert)(self, *raw++); #elif defined _i_isset - _cx_memb(_emplace)(self, *raw++); + _cx_MEMB(_emplace)(self, *raw++); #elif defined i_no_emplace - _cx_memb(_insert_or_assign)(self, raw->first, raw->second), ++raw; + _cx_MEMB(_insert_or_assign)(self, raw->first, raw->second), ++raw; #else - _cx_memb(_emplace_or_assign)(self, raw->first, raw->second), ++raw; + _cx_MEMB(_emplace_or_assign)(self, raw->first, raw->second), ++raw; #endif } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } -STC_API _cx_iter _cx_memb(_begin)(const _cx_self* self); +STC_API _cx_iter _cx_MEMB(_begin)(const _cx_Self* self); -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) +STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self) { return c_LITERAL(_cx_iter){NULL}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { +STC_INLINE void _cx_MEMB(_next)(_cx_iter* it) { while ((++it->ref, (++it->sref)->hashx == 0)) ; if (it->ref == it->_end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) { - while (n-- && it.ref) _cx_memb(_next)(&it); +STC_INLINE _cx_iter _cx_MEMB(_advance)(_cx_iter it, size_t n) { + while (n-- && it.ref) _cx_MEMB(_next)(&it); return it; } STC_INLINE _cx_iter -_cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_find)(const _cx_Self* self, _cx_keyraw rkey) { chash_bucket b; - if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) + if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) return c_LITERAL(_cx_iter){self->data + b.idx, self->data + self->bucket_count, self->slot + b.idx}; - return _cx_memb(_end)(self); + return _cx_MEMB(_end)(self); } STC_INLINE const _cx_value* -_cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_get)(const _cx_Self* self, _cx_keyraw rkey) { chash_bucket b; - if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) + if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) return self->data + b.idx; return NULL; } STC_INLINE _cx_value* -_cx_memb(_get_mut)(_cx_self* self, _cx_keyraw rkey) - { return (_cx_value*)_cx_memb(_get)(self, rkey); } +_cx_MEMB(_get_mut)(_cx_Self* self, _cx_keyraw rkey) + { return (_cx_value*)_cx_MEMB(_get)(self, rkey); } STC_INLINE int -_cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_erase)(_cx_Self* self, _cx_keyraw rkey) { chash_bucket b = {0}; - if (self->size && (b = _cx_memb(_bucket_)(self, &rkey)).found) - _cx_memb(_erase_entry)(self, self->data + b.idx); + if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) + _cx_MEMB(_erase_entry)(self, self->data + b.idx); return b.found; } STC_INLINE _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - _cx_memb(_erase_entry)(self, it.ref); +_cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it) { + _cx_MEMB(_erase_entry)(self, it.ref); if (it.sref->hashx == 0) - _cx_memb(_next)(&it); + _cx_MEMB(_next)(&it); return it; } STC_INLINE bool -_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)) { +_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_keyraw _raw = i_keyto(_i_keyref(i.ref)); - if (!_cx_memb(_contains)(other, _raw)) return false; + if (!_cx_MEMB(_contains)(other, _raw)) return false; } return true; } @@ -268,7 +268,7 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #endif #define fastrange_2(x, n) (intptr_t)((x) & (size_t)((n) - 1)) // n power of 2. -STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) { +STC_DEF _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) { _cx_iter it = {self->data, self->data+self->bucket_count, self->slot}; if (it.sref) while (it.sref->hashx == 0) @@ -277,46 +277,46 @@ STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) { return it; } -STC_DEF float _cx_memb(_max_load_factor)(const _cx_self* self) { +STC_DEF float _cx_MEMB(_max_load_factor)(const _cx_Self* self) { return (float)(i_max_load_factor); } -STC_DEF intptr_t _cx_memb(_capacity)(const _cx_self* map) { +STC_DEF intptr_t _cx_MEMB(_capacity)(const _cx_Self* map) { return (intptr_t)((float)map->bucket_count * (i_max_load_factor)); } -STC_DEF _cx_self _cx_memb(_with_capacity)(const intptr_t cap) { - _cx_self map = {0}; - _cx_memb(_reserve)(&map, cap); +STC_DEF _cx_Self _cx_MEMB(_with_capacity)(const intptr_t cap) { + _cx_Self map = {0}; + _cx_MEMB(_reserve)(&map, cap); return map; } -STC_INLINE void _cx_memb(_wipe_)(_cx_self* self) { +STC_INLINE void _cx_MEMB(_wipe_)(_cx_Self* self) { if (self->size == 0) return; _cx_value* d = self->data, *_end = d + self->bucket_count; chash_slot* s = self->slot; for (; d != _end; ++d) if ((s++)->hashx) - _cx_memb(_value_drop)(d); + _cx_MEMB(_value_drop)(d); } -STC_DEF void _cx_memb(_drop)(_cx_self* self) { - _cx_memb(_wipe_)(self); +STC_DEF void _cx_MEMB(_drop)(_cx_Self* self) { + _cx_MEMB(_wipe_)(self); i_free(self->slot); i_free(self->data); } -STC_DEF void _cx_memb(_clear)(_cx_self* self) { - _cx_memb(_wipe_)(self); +STC_DEF void _cx_MEMB(_clear)(_cx_Self* self) { + _cx_MEMB(_wipe_)(self); self->size = 0; c_memset(self->slot, 0, c_sizeof(chash_slot)*self->bucket_count); } #ifndef _i_isset STC_DEF _cx_result - _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); + _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key _key, i_val _mapped) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); _cx_mapped* _mp = _res.ref ? &_res.ref->second : &_mapped; if (_res.inserted) _res.ref->first = _key; @@ -328,8 +328,8 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { #if !defined i_no_emplace STC_DEF _cx_result - _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped) { - _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); + _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, rkey); if (_res.inserted) _res.ref->first = i_keyfrom(rkey); else { @@ -343,7 +343,7 @@ STC_DEF void _cx_memb(_clear)(_cx_self* self) { #endif // !_i_isset STC_DEF chash_bucket -_cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { +_cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); intptr_t _cap = self->bucket_count; chash_bucket b = {fastrange_2(_hash, _cap), (uint8_t)(_hash | 0x80)}; @@ -362,13 +362,13 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_keyraw* rkeyptr) { } STC_DEF _cx_result -_cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; if (self->size >= (intptr_t)((float)self->bucket_count * (i_max_load_factor))) - if (!_cx_memb(_reserve)(self, (intptr_t)(self->size*3/2 + 2))) + if (!_cx_MEMB(_reserve)(self, (intptr_t)(self->size*3/2 + 2))) return res; - chash_bucket b = _cx_memb(_bucket_)(self, &rkey); + chash_bucket b = _cx_MEMB(_bucket_)(self, &rkey); res.ref = &self->data[b.idx]; if (!b.found) { self->slot[b.idx].hashx = b.hashx; @@ -379,8 +379,8 @@ _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { } #if !defined i_no_clone -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self m) { +STC_DEF _cx_Self +_cx_MEMB(_clone)(_cx_Self m) { if (m.data) { _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket_count), *_dst = d, *_end = m.data + m.bucket_count; @@ -391,7 +391,7 @@ _cx_memb(_clone)(_cx_self m) { else for (; m.data != _end; ++m.data, ++m.slot, ++_dst) if (m.slot->hashx) - *_dst = _cx_memb(_value_clone)(*m.data); + *_dst = _cx_MEMB(_value_clone)(*m.data); m.data = d, m.slot = s; } return m; @@ -399,13 +399,13 @@ _cx_memb(_clone)(_cx_self m) { #endif STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { +_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { const intptr_t _oldbucks = self->bucket_count; if (_newcap != self->size && _newcap <= _oldbucks) return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; _newbucks = cnextpow2(_newbucks); - _cx_self m = { + _cx_Self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), self->size, _newbucks @@ -417,11 +417,11 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { const chash_slot* s = self->slot; for (intptr_t i = 0; i < _oldbucks; ++i, ++d) if ((s++)->hashx) { _cx_keyraw r = i_keyto(_i_keyref(d)); - chash_bucket b = _cx_memb(_bucket_)(&m, &r); + chash_bucket b = _cx_MEMB(_bucket_)(&m, &r); m.slot[b.idx].hashx = b.hashx; m.data[b.idx] = *d; // move } - c_swap(_cx_self, self, &m); + c_swap(_cx_Self, self, &m); } i_free(m.slot); i_free(m.data); @@ -429,12 +429,12 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) { } STC_DEF void -_cx_memb(_erase_entry)(_cx_self* self, _cx_value* _val) { +_cx_MEMB(_erase_entry)(_cx_Self* self, _cx_value* _val) { _cx_value* d = self->data; chash_slot* s = self->slot; intptr_t i = _val - d, j = i, k; const intptr_t _cap = self->bucket_count; - _cx_memb(_value_drop)(_val); + _cx_MEMB(_value_drop)(_val); for (;;) { // delete without leaving tombstone if (++j == _cap) j = 0; if (! s[j].hashx) diff --git a/include/stc/cpque.h b/include/stc/cpque.h index b66c7735..cfe027cc 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -31,88 +31,88 @@ #define _i_prefix cpque_ #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_cpque_types, _cx_self, i_key); + _cx_DEFTYPES(_c_cpque_types, _cx_Self, i_key); #endif typedef i_keyraw _cx_raw; -STC_API void _cx_memb(_make_heap)(_cx_self* self); -STC_API void _cx_memb(_erase_at)(_cx_self* self, intptr_t idx); -STC_API _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value value); +STC_API void _cx_MEMB(_make_heap)(_cx_Self* self); +STC_API void _cx_MEMB(_erase_at)(_cx_Self* self, intptr_t idx); +STC_API _cx_value* _cx_MEMB(_push)(_cx_Self* self, _cx_value value); -STC_INLINE _cx_self _cx_memb(_init)(void) - { return c_LITERAL(_cx_self){NULL}; } +STC_INLINE _cx_Self _cx_MEMB(_init)(void) + { return c_LITERAL(_cx_Self){NULL}; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { +STC_INLINE bool _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t cap) { if (cap != self->_len && cap <= self->_cap) return true; _cx_value *d = (_cx_value *)i_realloc(self->data, cap*c_sizeof *d); return d ? (self->data = d, self->_cap = cap, true) : false; } -STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) - { _cx_memb(_reserve)(self, self->_len); } +STC_INLINE void _cx_MEMB(_shrink_to_fit)(_cx_Self* self) + { _cx_MEMB(_reserve)(self, self->_len); } -STC_INLINE _cx_self _cx_memb(_with_capacity)(const intptr_t cap) { - _cx_self out = {NULL}; _cx_memb(_reserve)(&out, cap); +STC_INLINE _cx_Self _cx_MEMB(_with_capacity)(const intptr_t cap) { + _cx_Self out = {NULL}; _cx_MEMB(_reserve)(&out, cap); return out; } -STC_INLINE _cx_self _cx_memb(_with_size)(const intptr_t size, i_key null) { - _cx_self out = {NULL}; _cx_memb(_reserve)(&out, size); +STC_INLINE _cx_Self _cx_MEMB(_with_size)(const intptr_t size, i_key null) { + _cx_Self out = {NULL}; _cx_MEMB(_reserve)(&out, size); while (out._len < size) out.data[out._len++] = null; return out; } -STC_INLINE void _cx_memb(_clear)(_cx_self* self) { +STC_INLINE void _cx_MEMB(_clear)(_cx_Self* self) { intptr_t i = self->_len; self->_len = 0; while (i--) { i_keydrop((self->data + i)); } } -STC_INLINE void _cx_memb(_drop)(_cx_self* self) - { _cx_memb(_clear)(self); i_free(self->data); } +STC_INLINE void _cx_MEMB(_drop)(_cx_Self* self) + { _cx_MEMB(_clear)(self); i_free(self->data); } -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* q) +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* q) { return q->_len; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* q) +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* q) { return !q->_len; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* q) +STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* q) { return q->_cap; } -STC_INLINE const _cx_value* _cx_memb(_top)(const _cx_self* self) +STC_INLINE const _cx_value* _cx_MEMB(_top)(const _cx_Self* self) { return &self->data[0]; } -STC_INLINE void _cx_memb(_pop)(_cx_self* self) - { assert(!_cx_memb(_empty)(self)); _cx_memb(_erase_at)(self, 0); } +STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) + { assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_at)(self, 0); } #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self q); +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self q); -STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { +STC_INLINE void _cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_clone)(*other); } -STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) +STC_INLINE i_key _cx_MEMB(_value_clone)(_cx_value val) { return i_keyclone(val); } #endif // !i_no_clone #if !defined i_no_emplace -STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { _cx_memb(_push)(self, i_keyfrom(raw)); } +STC_INLINE void _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) + { _cx_MEMB(_push)(self, i_keyfrom(raw)); } #endif // !i_no_emplace /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) STC_DEF void -_cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) { +_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((&arr[c]), (&arr[c + (c < n)])); @@ -122,15 +122,15 @@ _cx_memb(_sift_down_)(_cx_self* self, const intptr_t idx, const intptr_t n) { } STC_DEF void -_cx_memb(_make_heap)(_cx_self* self) { +_cx_MEMB(_make_heap)(_cx_Self* self) { intptr_t n = self->_len; for (intptr_t k = n/2; k != 0; --k) - _cx_memb(_sift_down_)(self, k, n); + _cx_MEMB(_sift_down_)(self, k, n); } #if !defined i_no_clone -STC_DEF _cx_self _cx_memb(_clone)(_cx_self q) { - _cx_self out = _cx_memb(_with_capacity)(q._len); +STC_DEF _cx_Self _cx_MEMB(_clone)(_cx_Self q) { + _cx_Self out = _cx_MEMB(_with_capacity)(q._len); for (; out._len < out._cap; ++q.data) out.data[out._len++] = i_keyclone((*q.data)); return out; @@ -138,17 +138,17 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self q) { #endif STC_DEF void -_cx_memb(_erase_at)(_cx_self* self, const intptr_t idx) { +_cx_MEMB(_erase_at)(_cx_Self* self, const intptr_t idx) { i_keydrop((self->data + idx)); const intptr_t n = --self->_len; self->data[idx] = self->data[n]; - _cx_memb(_sift_down_)(self, idx + 1, n); + _cx_MEMB(_sift_down_)(self, idx + 1, n); } STC_DEF _cx_value* -_cx_memb(_push)(_cx_self* self, _cx_value value) { +_cx_MEMB(_push)(_cx_Self* self, _cx_value value) { if (self->_len == self->_cap) - _cx_memb(_reserve)(self, self->_len*3/2 + 4); + _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((&arr[c/2]), (&value))); c /= 2) diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index 2f709172..6eee712b 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -35,104 +35,104 @@ #include "priv/template.h" #ifndef i_is_forward -_cx_deftypes(_c_cdeq_types, _cx_self, i_key); +_cx_DEFTYPES(_c_cdeq_types, _cx_Self, i_key); #endif typedef i_keyraw _cx_raw; -STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n); -STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n); -STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); // push_back -STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); -STC_API _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n); +STC_API _cx_Self _cx_MEMB(_with_capacity)(const intptr_t n); +STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n); +STC_API void _cx_MEMB(_clear)(_cx_Self* self); +STC_API void _cx_MEMB(_drop)(_cx_Self* self); +STC_API _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value); // push_back +STC_API void _cx_MEMB(_shrink_to_fit)(_cx_Self *self); +STC_API _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n); #define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask) #define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask) -STC_INLINE _cx_self _cx_memb(_init)(void) - { _cx_self cx = {0}; return cx; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } -STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); } +STC_INLINE _cx_Self _cx_MEMB(_init)(void) + { _cx_Self cx = {0}; return cx; } +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } +STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(val); } #if !defined i_no_emplace -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } +STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) + { return _cx_MEMB(_push)(self, i_keyfrom(raw)); } #endif #if defined _i_has_cmp || defined _i_has_eq -STC_API bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other); +STC_API bool _cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other); #endif #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_INLINE i_key _cx_memb(_value_clone)(i_key val) +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self cx); +STC_INLINE i_key _cx_MEMB(_value_clone)(i_key val) { return i_keyclone(val); } #endif // !i_no_clone -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* self) { return _cdeq_toidx(self, self->end); } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) +STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* self) { return self->capmask; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self) { return self->start == self->end; } -STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) +STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) +STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return self->data + self->start; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) +STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return self->data + ((self->end - 1) & self->capmask); } -STC_INLINE void _cx_memb(_pop)(_cx_self* self) { // pop_front - assert(!_cx_memb(_empty)(self)); +STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { // pop_front + assert(!_cx_MEMB(_empty)(self)); i_keydrop((self->data + self->start)); self->start = (self->start + 1) & self->capmask; } -STC_INLINE _cx_value _cx_memb(_pull)(_cx_self* self) { // move front out of queue - assert(!_cx_memb(_empty)(self)); +STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { // move front out of queue + assert(!_cx_MEMB(_empty)(self)); intptr_t s = self->start; self->start = (s + 1) & self->capmask; return self->data[s]; } -STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { +STC_INLINE void _cx_MEMB(_copy)(_cx_Self* self, const _cx_Self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_clone)(*other); } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { +STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) { return c_LITERAL(_cx_iter){ - _cx_memb(_empty)(self) ? NULL : self->data + self->start, + _cx_MEMB(_empty)(self) ? NULL : self->data + self->start, self->start, self }; } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) +STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self) { return c_LITERAL(_cx_iter){.pos=self->end, ._s=self}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { +STC_INLINE void _cx_MEMB(_next)(_cx_iter* it) { if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; } else { it->ref -= it->pos; it->pos = 0; } if (it->pos == it->_s->end) it->ref = NULL; } -STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) +STC_INLINE intptr_t _cx_MEMB(_index)(const _cx_Self* self, _cx_iter it) { return _cdeq_toidx(self, it.pos); } -STC_INLINE void _cx_memb(_adjust_end_)(_cx_self* self, intptr_t n) +STC_INLINE void _cx_MEMB(_adjust_end_)(_cx_Self* self, intptr_t n) { self->end = (self->end + n) & self->capmask; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) -STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { - intptr_t len = _cx_memb(_size)(it._s); +STC_DEF _cx_iter _cx_MEMB(_advance)(_cx_iter it, intptr_t n) { + intptr_t len = _cx_MEMB(_size)(it._s); intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos); it.pos = (pos + n) & it._s->capmask; it.ref += it.pos - pos; @@ -141,27 +141,27 @@ STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) { } STC_DEF void -_cx_memb(_clear)(_cx_self* self) { - c_foreach (i, _cx_self, *self) +_cx_MEMB(_clear)(_cx_Self* self) { + c_foreach (i, _cx_Self, *self) { i_keydrop(i.ref); } self->start = 0, self->end = 0; } STC_DEF void -_cx_memb(_drop)(_cx_self* self) { - _cx_memb(_clear)(self); +_cx_MEMB(_drop)(_cx_Self* self) { + _cx_MEMB(_clear)(self); i_free(self->data); } -STC_DEF _cx_self -_cx_memb(_with_capacity)(const intptr_t n) { - _cx_self cx = {0}; - _cx_memb(_reserve)(&cx, n); +STC_DEF _cx_Self +_cx_MEMB(_with_capacity)(const intptr_t n) { + _cx_Self cx = {0}; + _cx_MEMB(_reserve)(&cx, n); return cx; } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t n) { +_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n) { if (n <= self->capmask) return true; intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1); @@ -184,10 +184,10 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t n) { } STC_DEF _cx_value* -_cx_memb(_push)(_cx_self* self, i_key value) { // push_back +_cx_MEMB(_push)(_cx_Self* self, i_key value) { // push_back intptr_t end = (self->end + 1) & self->capmask; if (end == self->start) { // full - _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand + _cx_MEMB(_reserve)(self, self->capmask + 3); // => 2x expand end = (self->end + 1) & self->capmask; } _cx_value *v = self->data + self->end; @@ -197,14 +197,14 @@ _cx_memb(_push)(_cx_self* self, i_key value) { // push_back } STC_DEF void -_cx_memb(_shrink_to_fit)(_cx_self *self) { - intptr_t sz = _cx_memb(_size)(self), j = 0; +_cx_MEMB(_shrink_to_fit)(_cx_Self *self) { + intptr_t sz = _cx_MEMB(_size)(self), j = 0; if (sz > self->capmask/2) return; - _cx_self out = _cx_memb(_with_capacity)(sz); + _cx_Self out = _cx_MEMB(_with_capacity)(sz); if (!out.data) return; - c_foreach (i, _cx_self, *self) + c_foreach (i, _cx_Self, *self) out.data[j++] = *i.ref; out.end = sz; i_free(self->data); @@ -212,12 +212,12 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { } #if !defined i_no_clone -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - intptr_t sz = _cx_memb(_size)(&cx), j = 0; - _cx_self out = _cx_memb(_with_capacity)(sz); +STC_DEF _cx_Self +_cx_MEMB(_clone)(_cx_Self cx) { + intptr_t sz = _cx_MEMB(_size)(&cx), j = 0; + _cx_Self out = _cx_MEMB(_with_capacity)(sz); if (out.data) - c_foreach (i, _cx_self, cx) + c_foreach (i, _cx_Self, cx) out.data[j++] = i_keyclone((*i.ref)); out.end = sz; return out; @@ -226,10 +226,10 @@ _cx_memb(_clone)(_cx_self cx) { #if defined _i_has_cmp || defined _i_has_eq STC_DEF bool -_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), j = _cx_memb(_begin)(other); - i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j)) +_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), j = _cx_MEMB(_begin)(other); + i.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; diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 28598f0a..f4d33a4d 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -73,7 +73,7 @@ int main(void) { #endif #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); + _cx_DEFTYPES(_c_aatree_types, _cx_Self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); #endif _i_MAP_ONLY( struct _cx_value { @@ -87,133 +87,133 @@ struct _cx_node { }; typedef i_keyraw _cx_keyraw; -typedef i_valraw _cx_memb(_rmapped); +typedef i_valraw _cx_MEMB(_rmapped); typedef _i_SET_ONLY( i_keyraw ) _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } ) _cx_raw; #if !defined i_no_emplace -STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)); +STC_API _cx_result _cx_MEMB(_emplace)(_cx_Self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)); #endif // !i_no_emplace #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self tree); +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self tree); #endif // !i_no_clone -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap); -STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out); -STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, _cx_keyraw rkey); -STC_API _cx_value* _cx_memb(_front)(const _cx_self* self); -STC_API _cx_value* _cx_memb(_back)(const _cx_self* self); -STC_API int _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey); -STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it); -STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2); -STC_API _cx_iter _cx_memb(_begin)(const _cx_self* self); -STC_API void _cx_memb(_next)(_cx_iter* it); - -STC_INLINE _cx_self _cx_memb(_init)(void) { _cx_self tree = {0}; return tree; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* cx) { return cx->size == 0; } -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* cx) { return cx->size; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* cx) { return cx->cap; } -STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_keyraw rkey) - { _cx_iter it; _cx_memb(_find_it)(self, rkey, &it); return it; } -STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, _cx_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it) != NULL; } -STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } -STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, _cx_keyraw rkey) - { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } - -STC_INLINE _cx_self -_cx_memb(_with_capacity)(const intptr_t cap) { - _cx_self tree = _cx_memb(_init)(); - _cx_memb(_reserve)(&tree, cap); +STC_API void _cx_MEMB(_drop)(_cx_Self* self); +STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t cap); +STC_API _cx_value* _cx_MEMB(_find_it)(const _cx_Self* self, _cx_keyraw rkey, _cx_iter* out); +STC_API _cx_iter _cx_MEMB(_lower_bound)(const _cx_Self* self, _cx_keyraw rkey); +STC_API _cx_value* _cx_MEMB(_front)(const _cx_Self* self); +STC_API _cx_value* _cx_MEMB(_back)(const _cx_Self* self); +STC_API int _cx_MEMB(_erase)(_cx_Self* self, _cx_keyraw rkey); +STC_API _cx_iter _cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it); +STC_API _cx_iter _cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2); +STC_API _cx_iter _cx_MEMB(_begin)(const _cx_Self* self); +STC_API void _cx_MEMB(_next)(_cx_iter* it); + +STC_INLINE _cx_Self _cx_MEMB(_init)(void) { _cx_Self tree = {0}; return tree; } +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* cx) { return cx->size == 0; } +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* cx) { return cx->size; } +STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* cx) { return cx->cap; } +STC_INLINE _cx_iter _cx_MEMB(_find)(const _cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; _cx_MEMB(_find_it)(self, rkey, &it); return it; } +STC_INLINE bool _cx_MEMB(_contains)(const _cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; return _cx_MEMB(_find_it)(self, rkey, &it) != NULL; } +STC_INLINE const _cx_value* _cx_MEMB(_get)(const _cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; return _cx_MEMB(_find_it)(self, rkey, &it); } +STC_INLINE _cx_value* _cx_MEMB(_get_mut)(_cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; return _cx_MEMB(_find_it)(self, rkey, &it); } + +STC_INLINE _cx_Self +_cx_MEMB(_with_capacity)(const intptr_t cap) { + _cx_Self tree = _cx_MEMB(_init)(); + _cx_MEMB(_reserve)(&tree, cap); return tree; } STC_INLINE void -_cx_memb(_clear)(_cx_self* self) - { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); } +_cx_MEMB(_clear)(_cx_Self* self) + { _cx_MEMB(_drop)(self); *self = _cx_MEMB(_init)(); } STC_INLINE _cx_raw -_cx_memb(_value_toraw)(const _cx_value* val) { +_cx_MEMB(_value_toraw)(const _cx_value* val) { return _i_SET_ONLY( i_keyto(val) ) _i_MAP_ONLY( c_LITERAL(_cx_raw){i_keyto((&val->first)), i_valto((&val->second))} ); } STC_INLINE void -_cx_memb(_value_drop)(_cx_value* val) { +_cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(_i_keyref(val)); _i_MAP_ONLY( i_valdrop((&val->second)); ) } #if !defined i_no_clone STC_INLINE _cx_value -_cx_memb(_value_clone)(_cx_value _val) { +_cx_MEMB(_value_clone)(_cx_value _val) { *_i_keyref(&_val) = i_keyclone((*_i_keyref(&_val))); _i_MAP_ONLY( _val.second = i_valclone(_val.second); ) return _val; } STC_INLINE void -_cx_memb(_copy)(_cx_self *self, const _cx_self* other) { +_cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { if (self->nodes == other->nodes) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_clone)(*other); } STC_INLINE void -_cx_memb(_shrink_to_fit)(_cx_self *self) { - _cx_self tmp = _cx_memb(_clone)(*self); - _cx_memb(_drop)(self); *self = tmp; +_cx_MEMB(_shrink_to_fit)(_cx_Self *self) { + _cx_Self tmp = _cx_MEMB(_clone)(*self); + _cx_MEMB(_drop)(self); *self = tmp; } #endif // !i_no_clone #ifndef _i_isset - STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped); + STC_API _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key key, i_val mapped); #if !defined i_no_emplace - STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped); + STC_API _cx_result _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped); #endif STC_INLINE const _cx_mapped* - _cx_memb(_at)(const _cx_self* self, _cx_keyraw rkey) - { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } + _cx_MEMB(_at)(const _cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; return &_cx_MEMB(_find_it)(self, rkey, &it)->second; } STC_INLINE _cx_mapped* - _cx_memb(_at_mut)(_cx_self* self, _cx_keyraw rkey) - { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; } + _cx_MEMB(_at_mut)(_cx_Self* self, _cx_keyraw rkey) + { _cx_iter it; return &_cx_MEMB(_find_it)(self, rkey, &it)->second; } #endif // !_i_isset STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) { +_cx_MEMB(_end)(const _cx_Self* self) { (void)self; _cx_iter it; it.ref = NULL, it._top = 0, it._tn = 0; return it; } STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { +_cx_MEMB(_advance)(_cx_iter it, size_t n) { while (n-- && it.ref) - _cx_memb(_next)(&it); + _cx_MEMB(_next)(&it); return it; } STC_INLINE bool -_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)) { +_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_keyraw _rx = i_keyto(_i_keyref(i.ref)), _ry = i_keyto(_i_keyref(j.ref)); if (!(i_eq((&_rx), (&_ry)))) return false; } return true; } -static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey); +static _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey); STC_INLINE _cx_result -_cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); +_cx_MEMB(_insert)(_cx_Self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); if (_res.inserted) { *_i_keyref(_res.ref) = _key; _i_MAP_ONLY( _res.ref->second = _mapped; )} else @@ -222,38 +222,38 @@ _cx_memb(_insert)(_cx_self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { } STC_INLINE _cx_value* -_cx_memb(_push)(_cx_self* self, _cx_value _val) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); +_cx_MEMB(_push)(_cx_Self* self, _cx_value _val) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto(_i_keyref(&_val))); if (_res.inserted) *_res.ref = _val; else - _cx_memb(_value_drop)(&_val); + _cx_MEMB(_value_drop)(&_val); return _res.ref; } STC_INLINE void -_cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) { +_cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) { while (n--) #if defined _i_isset && defined i_no_emplace - _cx_memb(_insert)(self, *raw++); + _cx_MEMB(_insert)(self, *raw++); #elif defined _i_isset - _cx_memb(_emplace)(self, *raw++); + _cx_MEMB(_emplace)(self, *raw++); #elif defined i_no_emplace - _cx_memb(_insert_or_assign)(self, raw->first, raw->second), ++raw; + _cx_MEMB(_insert_or_assign)(self, raw->first, raw->second), ++raw; #else - _cx_memb(_emplace_or_assign)(self, raw->first, raw->second), ++raw; + _cx_MEMB(_emplace_or_assign)(self, raw->first, raw->second), ++raw; #endif } -STC_INLINE _cx_self -_cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE _cx_Self +_cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) STC_DEF void -_cx_memb(_next)(_cx_iter *it) { +_cx_MEMB(_next)(_cx_iter *it) { int32_t tn = it->_tn; if (it->_top || tn) { while (tn) { @@ -268,18 +268,18 @@ _cx_memb(_next)(_cx_iter *it) { } STC_DEF _cx_iter -_cx_memb(_begin)(const _cx_self* self) { +_cx_MEMB(_begin)(const _cx_Self* self) { _cx_iter it; it.ref = NULL; it._d = self->nodes, it._top = 0; it._tn = self->root; if (it._tn) - _cx_memb(_next)(&it); + _cx_MEMB(_next)(&it); return it; } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { +_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t cap) { if (cap <= self->cap) return false; _cx_node* nodes = (_cx_node*)i_realloc(self->nodes, (cap + 1)*c_sizeof(_cx_node)); @@ -292,7 +292,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { } STC_DEF _cx_value* -_cx_memb(_front)(const _cx_self* self) { +_cx_MEMB(_front)(const _cx_Self* self) { _cx_node *d = self->nodes; int32_t tn = self->root; while (d[tn].link[0]) @@ -301,7 +301,7 @@ _cx_memb(_front)(const _cx_self* self) { } STC_DEF _cx_value* -_cx_memb(_back)(const _cx_self* self) { +_cx_MEMB(_back)(const _cx_Self* self) { _cx_node *d = self->nodes; int32_t tn = self->root; while (d[tn].link[1]) @@ -310,14 +310,14 @@ _cx_memb(_back)(const _cx_self* self) { } static int32_t -_cx_memb(_new_node_)(_cx_self* self, int level) { +_cx_MEMB(_new_node_)(_cx_Self* self, int level) { int32_t tn; if (self->disp) { tn = self->disp; self->disp = self->nodes[tn].link[1]; } else { if (self->head == self->cap) - if (!_cx_memb(_reserve)(self, self->head*3/2 + 4)) + if (!_cx_MEMB(_reserve)(self, self->head*3/2 + 4)) return 0; tn = ++self->head; /* start with 1, 0 is nullnode. */ } @@ -328,8 +328,8 @@ _cx_memb(_new_node_)(_cx_self* self, int level) { #ifndef _i_isset STC_DEF _cx_result - _cx_memb(_insert_or_assign)(_cx_self* self, i_key _key, i_val _mapped) { - _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto((&_key))); + _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key _key, i_val _mapped) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); _cx_mapped* _mp = _res.ref ? &_res.ref->second : &_mapped; if (_res.inserted) _res.ref->first = _key; @@ -341,8 +341,8 @@ _cx_memb(_new_node_)(_cx_self* self, int level) { #if !defined i_no_emplace STC_DEF _cx_result - _cx_memb(_emplace_or_assign)(_cx_self* self, _cx_keyraw rkey, i_valraw rmapped) { - _cx_result _res = _cx_memb(_insert_entry_)(self, rkey); + _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, rkey); if (_res.inserted) _res.ref->first = i_keyfrom(rkey); else { @@ -356,7 +356,7 @@ _cx_memb(_new_node_)(_cx_self* self, int level) { #endif // !_i_isset STC_DEF _cx_value* -_cx_memb(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out) { +_cx_MEMB(_find_it)(const _cx_Self* self, _cx_keyraw rkey, _cx_iter* out) { int32_t tn = self->root; _cx_node *d = out->_d = self->nodes; out->_top = 0; @@ -373,9 +373,9 @@ _cx_memb(_find_it)(const _cx_self* self, _cx_keyraw rkey, _cx_iter* out) { } STC_DEF _cx_iter -_cx_memb(_lower_bound)(const _cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_lower_bound)(const _cx_Self* self, _cx_keyraw rkey) { _cx_iter it; - _cx_memb(_find_it)(self, rkey, &it); + _cx_MEMB(_find_it)(self, rkey, &it); if (!it.ref && it._top) { int32_t tn = it._st[--it._top]; it._tn = it._d[tn].link[1]; @@ -385,7 +385,7 @@ _cx_memb(_lower_bound)(const _cx_self* self, _cx_keyraw rkey) { } STC_DEF int32_t -_cx_memb(_skew_)(_cx_node *d, int32_t tn) { +_cx_MEMB(_skew_)(_cx_node *d, int32_t tn) { if (tn && d[d[tn].link[0]].level == d[tn].level) { int32_t tmp = d[tn].link[0]; d[tn].link[0] = d[tmp].link[1]; @@ -396,7 +396,7 @@ _cx_memb(_skew_)(_cx_node *d, int32_t tn) { } STC_DEF int32_t -_cx_memb(_split_)(_cx_node *d, int32_t tn) { +_cx_MEMB(_split_)(_cx_node *d, int32_t tn) { if (d[d[d[tn].link[1]].link[1]].level == d[tn].level) { int32_t tmp = d[tn].link[1]; d[tn].link[1] = d[tmp].link[0]; @@ -408,7 +408,7 @@ _cx_memb(_split_)(_cx_node *d, int32_t tn) { } static int32_t -_cx_memb(_insert_entry_i_)(_cx_self* self, int32_t tn, const _cx_keyraw* rkey, _cx_result* _res) { +_cx_MEMB(_insert_entry_i_)(_cx_Self* self, int32_t tn, const _cx_keyraw* rkey, _cx_result* _res) { int32_t up[64], tx = tn; _cx_node* d = self->nodes; int c, top = 0, dir = 0; @@ -420,7 +420,7 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, int32_t tn, const _cx_keyraw* rkey, _ dir = (c < 0); tx = d[tx].link[dir]; } - if ((tx = _cx_memb(_new_node_)(self, 1)) == 0) + if ((tx = _cx_MEMB(_new_node_)(self, 1)) == 0) return 0; d = self->nodes; _res->ref = &d[tx].value; @@ -431,8 +431,8 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, int32_t tn, const _cx_keyraw* rkey, _ while (top--) { if (top) dir = (d[up[top - 1]].link[1] == up[top]); - up[top] = _cx_memb(_skew_)(d, up[top]); - up[top] = _cx_memb(_split_)(d, up[top]); + up[top] = _cx_MEMB(_skew_)(d, up[top]); + up[top] = _cx_MEMB(_split_)(d, up[top]); if (top) d[up[top - 1]].link[dir] = up[top]; } @@ -440,33 +440,33 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, int32_t tn, const _cx_keyraw* rkey, _ } static _cx_result -_cx_memb(_insert_entry_)(_cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; - int32_t tn = _cx_memb(_insert_entry_i_)(self, self->root, &rkey, &res); + int32_t tn = _cx_MEMB(_insert_entry_i_)(self, self->root, &rkey, &res); self->root = tn; self->size += res.inserted; return res; } static int32_t -_cx_memb(_erase_r_)(_cx_self *self, int32_t tn, const _cx_keyraw* rkey, int *erased) { +_cx_MEMB(_erase_r_)(_cx_Self *self, int32_t tn, const _cx_keyraw* rkey, int *erased) { _cx_node *d = self->nodes; if (tn == 0) return 0; _cx_keyraw raw = i_keyto(_i_keyref(&d[tn].value)); int32_t 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); + d[tn].link[c < 0] = _cx_MEMB(_erase_r_)(self, d[tn].link[c < 0], rkey, erased); else { if (!(*erased)++) - _cx_memb(_value_drop)(&d[tn].value); + _cx_MEMB(_value_drop)(&d[tn].value); if (d[tn].link[0] && d[tn].link[1]) { tx = d[tn].link[0]; while (d[tx].link[1]) tx = d[tx].link[1]; d[tn].value = d[tx].value; /* move */ raw = i_keyto(_i_keyref(&d[tn].value)); - d[tn].link[0] = _cx_memb(_erase_r_)(self, d[tn].link[0], &raw, erased); + d[tn].link[0] = _cx_MEMB(_erase_r_)(self, d[tn].link[0], &raw, erased); } else { /* unlink node */ tx = tn; tn = d[tn].link[ d[tn].link[0] == 0 ]; @@ -479,19 +479,19 @@ _cx_memb(_erase_r_)(_cx_self *self, int32_t tn, const _cx_keyraw* rkey, int *era if (d[d[tn].link[0]].level < d[tn].level - 1 || d[tx].level < d[tn].level - 1) { if (d[tx].level > --d[tn].level) d[tx].level = d[tn].level; - tn = _cx_memb(_skew_)(d, tn); - tx = d[tn].link[1] = _cx_memb(_skew_)(d, d[tn].link[1]); - d[tx].link[1] = _cx_memb(_skew_)(d, d[tx].link[1]); - tn = _cx_memb(_split_)(d, tn); - d[tn].link[1] = _cx_memb(_split_)(d, d[tn].link[1]); + tn = _cx_MEMB(_skew_)(d, tn); + tx = d[tn].link[1] = _cx_MEMB(_skew_)(d, d[tn].link[1]); + d[tx].link[1] = _cx_MEMB(_skew_)(d, d[tx].link[1]); + tn = _cx_MEMB(_split_)(d, tn); + d[tn].link[1] = _cx_MEMB(_split_)(d, d[tn].link[1]); } return tn; } STC_DEF int -_cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { +_cx_MEMB(_erase)(_cx_Self* self, _cx_keyraw rkey) { int erased = 0; - int32_t root = _cx_memb(_erase_r_)(self, self->root, &rkey, &erased); + int32_t root = _cx_MEMB(_erase_r_)(self, self->root, &rkey, &erased); if (!erased) return 0; self->root = root; @@ -500,23 +500,23 @@ _cx_memb(_erase)(_cx_self* self, _cx_keyraw rkey) { } STC_DEF _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { +_cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it) { _cx_keyraw raw = i_keyto(_i_keyref(it.ref)); - _cx_memb(_next)(&it); + _cx_MEMB(_next)(&it); if (it.ref) { _cx_keyraw nxt = i_keyto(_i_keyref(it.ref)); - _cx_memb(_erase)(self, raw); - _cx_memb(_find_it)(self, nxt, &it); + _cx_MEMB(_erase)(self, raw); + _cx_MEMB(_find_it)(self, nxt, &it); } else - _cx_memb(_erase)(self, raw); + _cx_MEMB(_erase)(self, raw); return it; } STC_DEF _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { +_cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2) { if (!it2.ref) { while (it1.ref) - it1 = _cx_memb(_erase_at)(self, it1); + it1 = _cx_MEMB(_erase_at)(self, it1); return it1; } _cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref); @@ -524,30 +524,30 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { for (;;) { if (memcmp(&k1, &k2, sizeof k1) == 0) return it1; - _cx_memb(_next)(&it1); + _cx_MEMB(_next)(&it1); k1 = *_i_keyref(it1.ref); - _cx_memb(_erase)(self, r1); + _cx_MEMB(_erase)(self, r1); r1 = i_keyto((&k1)); - _cx_memb(_find_it)(self, r1, &it1); + _cx_MEMB(_find_it)(self, r1, &it1); } } #if !defined i_no_clone static int32_t -_cx_memb(_clone_r_)(_cx_self* self, _cx_node* src, int32_t sn) { +_cx_MEMB(_clone_r_)(_cx_Self* self, _cx_node* src, int32_t sn) { if (sn == 0) return 0; - int32_t tx, tn = _cx_memb(_new_node_)(self, src[sn].level); - self->nodes[tn].value = _cx_memb(_value_clone)(src[sn].value); - tx = _cx_memb(_clone_r_)(self, src, src[sn].link[0]); self->nodes[tn].link[0] = tx; - tx = _cx_memb(_clone_r_)(self, src, src[sn].link[1]); self->nodes[tn].link[1] = tx; + int32_t tx, tn = _cx_MEMB(_new_node_)(self, src[sn].level); + self->nodes[tn].value = _cx_MEMB(_value_clone)(src[sn].value); + tx = _cx_MEMB(_clone_r_)(self, src, src[sn].link[0]); self->nodes[tn].link[0] = tx; + tx = _cx_MEMB(_clone_r_)(self, src, src[sn].link[1]); self->nodes[tn].link[1] = tx; return tn; } -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self tree) { - _cx_self clone = _cx_memb(_with_capacity)(tree.size); - int32_t root = _cx_memb(_clone_r_)(&clone, tree.nodes, tree.root); +STC_DEF _cx_Self +_cx_MEMB(_clone)(_cx_Self tree) { + _cx_Self clone = _cx_MEMB(_with_capacity)(tree.size); + int32_t root = _cx_MEMB(_clone_r_)(&clone, tree.nodes, tree.root); clone.root = root; clone.size = tree.size; return clone; @@ -556,8 +556,8 @@ _cx_memb(_clone)(_cx_self tree) { #if !defined i_no_emplace STC_DEF _cx_result -_cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { - _cx_result res = _cx_memb(_insert_entry_)(self, rkey); +_cx_MEMB(_emplace)(_cx_Self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) { + _cx_result res = _cx_MEMB(_insert_entry_)(self, rkey); if (res.inserted) { *_i_keyref(res.ref) = i_keyfrom(rkey); _i_MAP_ONLY(res.ref->second = i_valfrom(rmapped);) @@ -567,18 +567,18 @@ _cx_memb(_emplace)(_cx_self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmappe #endif // i_no_emplace static void -_cx_memb(_drop_r_)(_cx_node* d, int32_t tn) { +_cx_MEMB(_drop_r_)(_cx_node* d, int32_t tn) { if (tn) { - _cx_memb(_drop_r_)(d, d[tn].link[0]); - _cx_memb(_drop_r_)(d, d[tn].link[1]); - _cx_memb(_value_drop)(&d[tn].value); + _cx_MEMB(_drop_r_)(d, d[tn].link[0]); + _cx_MEMB(_drop_r_)(d, d[tn].link[1]); + _cx_MEMB(_value_drop)(&d[tn].value); } } STC_DEF void -_cx_memb(_drop)(_cx_self* self) { +_cx_MEMB(_drop)(_cx_Self* self) { if (self->cap) { - _cx_memb(_drop_r_)(self->nodes, self->root); + _cx_MEMB(_drop_r_)(self->nodes, self->root); i_free(self->nodes); } } diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 5f0ffe2b..24ec2d5f 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -35,64 +35,64 @@ #ifndef i_is_forward #ifdef i_capacity #define i_no_clone - _cx_deftypes(_c_cstack_fixed, _cx_self, i_key, i_capacity); + _cx_DEFTYPES(_c_cstack_fixed, _cx_Self, i_key, i_capacity); #else - _cx_deftypes(_c_cstack_types, _cx_self, i_key); + _cx_DEFTYPES(_c_cstack_types, _cx_Self, i_key); #endif #endif typedef i_keyraw _cx_raw; #ifdef i_capacity -STC_INLINE void _cx_memb(_init)(_cx_self* self) +STC_INLINE void _cx_MEMB(_init)(_cx_Self* self) { self->_len = 0; } #else -STC_INLINE _cx_self _cx_memb(_init)(void) { - _cx_self out = {0}; +STC_INLINE _cx_Self _cx_MEMB(_init)(void) { + _cx_Self out = {0}; return out; } -STC_INLINE _cx_self _cx_memb(_with_capacity)(intptr_t cap) { - _cx_self out = {(_cx_value *) i_malloc(cap*c_sizeof(i_key)), 0, cap}; +STC_INLINE _cx_Self _cx_MEMB(_with_capacity)(intptr_t cap) { + _cx_Self out = {(_cx_value *) i_malloc(cap*c_sizeof(i_key)), 0, cap}; return out; } -STC_INLINE _cx_self _cx_memb(_with_size)(intptr_t size, i_key null) { - _cx_self out = {(_cx_value *) i_malloc(size*c_sizeof null), size, size}; +STC_INLINE _cx_Self _cx_MEMB(_with_size)(intptr_t size, i_key null) { + _cx_Self out = {(_cx_value *) i_malloc(size*c_sizeof null), size, size}; while (size) out.data[--size] = null; return out; } #endif // i_capacity -STC_INLINE void _cx_memb(_clear)(_cx_self* self) { +STC_INLINE void _cx_MEMB(_clear)(_cx_Self* self) { _cx_value *p = self->data + self->_len; while (p-- != self->data) { i_keydrop(p); } self->_len = 0; } -STC_INLINE void _cx_memb(_drop)(_cx_self* self) { - _cx_memb(_clear)(self); +STC_INLINE void _cx_MEMB(_drop)(_cx_Self* self) { + _cx_MEMB(_clear)(self); #ifndef i_capacity i_free(self->data); #endif } -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* self) { return self->_len; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self) { return !self->_len; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { +STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* self) { #ifndef i_capacity return self->_cap; #else return i_capacity; #endif } -STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) +STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(val); } -STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) { +STC_INLINE bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t n) { if (n < self->_len) return true; #ifndef i_capacity _cx_value *t = (_cx_value *)i_realloc(self->data, n*c_sizeof *t); @@ -101,100 +101,100 @@ STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) { return false; } -STC_INLINE _cx_value* _cx_memb(_append_uninit)(_cx_self *self, intptr_t n) { +STC_INLINE _cx_value* _cx_MEMB(_append_uninit)(_cx_Self *self, intptr_t n) { intptr_t len = self->_len; - if (!_cx_memb(_reserve)(self, len + n)) return NULL; + if (!_cx_MEMB(_reserve)(self, len + n)) return NULL; self->_len += n; return self->data + len; } -STC_INLINE void _cx_memb(_shrink_to_fit)(_cx_self* self) - { _cx_memb(_reserve)(self, self->_len); } +STC_INLINE void _cx_MEMB(_shrink_to_fit)(_cx_Self* self) + { _cx_MEMB(_reserve)(self, self->_len); } -STC_INLINE const _cx_value* _cx_memb(_top)(const _cx_self* self) +STC_INLINE const _cx_value* _cx_MEMB(_top)(const _cx_Self* self) { return &self->data[self->_len - 1]; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) +STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return (_cx_value*) &self->data[self->_len - 1]; } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) +STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return (_cx_value*) &self->data[0]; } -STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { - if (self->_len == _cx_memb(_capacity)(self)) - if (!_cx_memb(_reserve)(self, self->_len*3/2 + 4)) +STC_INLINE _cx_value* _cx_MEMB(_push)(_cx_Self* self, _cx_value val) { + if (self->_len == _cx_MEMB(_capacity)(self)) + if (!_cx_MEMB(_reserve)(self, self->_len*3/2 + 4)) return NULL; _cx_value* vp = self->data + self->_len++; *vp = val; return vp; } -STC_INLINE void _cx_memb(_pop)(_cx_self* self) +STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } -STC_INLINE _cx_value _cx_memb(_pull)(_cx_self* self) +STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { assert(self->_len); return self->data[--self->_len]; } -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } -STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, intptr_t idx) +STC_INLINE const _cx_value* _cx_MEMB(_at)(const _cx_Self* self, intptr_t idx) { assert(idx < self->_len); return self->data + idx; } -STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, intptr_t idx) +STC_INLINE _cx_value* _cx_MEMB(_at_mut)(_cx_Self* self, intptr_t idx) { assert(idx < self->_len); return self->data + idx; } #if !defined i_no_emplace -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) - { return _cx_memb(_push)(self, i_keyfrom(raw)); } +STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) + { return _cx_MEMB(_push)(self, i_keyfrom(raw)); } #endif // !i_no_emplace #if !defined i_no_clone -STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { - _cx_self out = {(_cx_value *)i_malloc(v._len*c_sizeof(_cx_value)), v._len, v._len}; +STC_INLINE _cx_Self _cx_MEMB(_clone)(_cx_Self v) { + _cx_Self out = {(_cx_value *)i_malloc(v._len*c_sizeof(_cx_value)), v._len, v._len}; if (!out.data) out._cap = 0; else for (intptr_t i = 0; i < v._len; ++v.data) out.data[i++] = i_keyclone((*v.data)); return out; } -STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { +STC_INLINE void _cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_MEMB(_drop)(self); + *self = _cx_MEMB(_clone)(*other); } -STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) +STC_INLINE i_key _cx_MEMB(_value_clone)(_cx_value val) { return i_keyclone(val); } -STC_INLINE i_keyraw _cx_memb(_value_toraw)(const _cx_value* val) +STC_INLINE i_keyraw _cx_MEMB(_value_toraw)(const _cx_value* val) { return i_keyto(val); } #endif // !i_no_clone -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { +STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) { return c_LITERAL(_cx_iter){self->_len ? (_cx_value*)self->data : NULL, (_cx_value*)self->data + self->_len}; } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) +STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self) { return c_LITERAL(_cx_iter){NULL, (_cx_value*)self->data + self->_len}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) +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, size_t n) +STC_INLINE _cx_iter _cx_MEMB(_advance)(_cx_iter it, size_t n) { if ((it.ref += n) >= it.end) it.ref = NULL ; return it; } -STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) +STC_INLINE intptr_t _cx_MEMB(_index)(const _cx_Self* self, _cx_iter it) { return (it.ref - self->data); } -STC_INLINE void _cx_memb(_adjust_end_)(_cx_self* self, intptr_t n) +STC_INLINE void _cx_MEMB(_adjust_end_)(_cx_Self* self, intptr_t n) { self->_len += n; } #if defined _i_has_eq || defined _i_has_cmp STC_INLINE bool -_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { +_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); diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 71787733..3213dd1c 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -74,164 +74,164 @@ int main() { #include "priv/template.h" #ifndef i_is_forward - _cx_deftypes(_c_cvec_types, _cx_self, i_key); + _cx_DEFTYPES(_c_cvec_types, _cx_Self, i_key); #endif typedef i_keyraw _cx_raw; -STC_API _cx_self _cx_memb(_init)(void); -STC_API void _cx_memb(_drop)(_cx_self* self); -STC_API void _cx_memb(_clear)(_cx_self* self); -STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap); -STC_API bool _cx_memb(_resize)(_cx_self* self, intptr_t size, i_key null); -STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); -STC_API _cx_iter _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n); -STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n); +STC_API _cx_Self _cx_MEMB(_init)(void); +STC_API void _cx_MEMB(_drop)(_cx_Self* self); +STC_API void _cx_MEMB(_clear)(_cx_Self* self); +STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t cap); +STC_API bool _cx_MEMB(_resize)(_cx_Self* self, intptr_t size, i_key null); +STC_API _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value); +STC_API _cx_iter _cx_MEMB(_erase_n)(_cx_Self* self, intptr_t idx, intptr_t n); +STC_API _cx_iter _cx_MEMB(_insert_uninit)(_cx_Self* self, intptr_t idx, intptr_t n); #if !defined i_no_cmp || defined _i_has_eq -STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw); +STC_API _cx_iter _cx_MEMB(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw); #endif #ifndef i_no_cmp -STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); -STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw, _cx_iter* lower_bound); +STC_API int _cx_MEMB(_value_cmp)(const _cx_value* x, const _cx_value* y); +STC_API _cx_iter _cx_MEMB(_binary_search_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw, _cx_iter* lower_bound); #endif -STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); } +STC_INLINE void _cx_MEMB(_value_drop)(_cx_value* val) { i_keydrop(val); } #if !defined i_no_emplace STC_API _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw raw[], intptr_t n); +_cx_MEMB(_emplace_n)(_cx_Self* self, intptr_t idx, const _cx_raw raw[], intptr_t n); -STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { - return _cx_memb(_push)(self, i_keyfrom(raw)); +STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { - return _cx_memb(_push)(self, i_keyfrom(raw)); +STC_INLINE _cx_value* _cx_MEMB(_emplace_back)(_cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_n)(self, _it_ptr(it) - self->data, &raw, 1); +STC_INLINE _cx_iter _cx_MEMB(_emplace_at)(_cx_Self* self, _cx_iter it, _cx_raw raw) { + return _cx_MEMB(_emplace_n)(self, _it_ptr(it) - self->data, &raw, 1); } #endif // !i_no_emplace #if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_API _cx_iter _cx_memb(_copy_n)(_cx_self* self, intptr_t idx, const _cx_value arr[], intptr_t n); -STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n) - { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); } -STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n) - { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; } -STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) +STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self cx); +STC_API _cx_iter _cx_MEMB(_copy_n)(_cx_Self* self, intptr_t idx, const _cx_value arr[], intptr_t n); +STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) + { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); } +STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) + { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } +STC_INLINE i_key _cx_MEMB(_value_clone)(_cx_value val) { return i_keyclone(val); } -STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { +STC_INLINE void _cx_MEMB(_copy)(_cx_Self* self, const _cx_Self* other) { if (self->data == other->data) return; - _cx_memb(_clear)(self); - _cx_memb(_copy_n)(self, 0, other->data, other->_len); + _cx_MEMB(_clear)(self); + _cx_MEMB(_copy_n)(self, 0, other->data, other->_len); } #endif // !i_no_clone -STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; } -STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; } -STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; } -STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* val) { return i_keyto(val); } -STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; } -STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) +STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* self) { return self->_len; } +STC_INLINE intptr_t _cx_MEMB(_capacity)(const _cx_Self* self) { return self->_cap; } +STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* self) { return !self->_len; } +STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* val) { return i_keyto(val); } +STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return self->data; } +STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return self->data + self->_len - 1; } -STC_INLINE void _cx_memb(_pop)(_cx_self* self) +STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } -STC_INLINE _cx_value _cx_memb(_pull)(_cx_self* self) +STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { assert(self->_len); return self->data[--self->_len]; } -STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) - { return _cx_memb(_push)(self, value); } -STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_memb(_pop)(self); } - -STC_INLINE _cx_self -_cx_memb(_with_size)(const intptr_t size, i_key null) { - _cx_self cx = _cx_memb(_init)(); - _cx_memb(_resize)(&cx, size, null); +STC_INLINE _cx_value* _cx_MEMB(_push_back)(_cx_Self* self, i_key value) + { return _cx_MEMB(_push)(self, value); } +STC_INLINE void _cx_MEMB(_pop_back)(_cx_Self* self) { _cx_MEMB(_pop)(self); } + +STC_INLINE _cx_Self +_cx_MEMB(_with_size)(const intptr_t size, i_key null) { + _cx_Self cx = _cx_MEMB(_init)(); + _cx_MEMB(_resize)(&cx, size, null); return cx; } -STC_INLINE _cx_self -_cx_memb(_with_capacity)(const intptr_t cap) { - _cx_self cx = _cx_memb(_init)(); - _cx_memb(_reserve)(&cx, cap); +STC_INLINE _cx_Self +_cx_MEMB(_with_capacity)(const intptr_t cap) { + _cx_Self cx = _cx_MEMB(_init)(); + _cx_MEMB(_reserve)(&cx, cap); return cx; } STC_INLINE void -_cx_memb(_shrink_to_fit)(_cx_self* self) { - _cx_memb(_reserve)(self, _cx_memb(_size)(self)); +_cx_MEMB(_shrink_to_fit)(_cx_Self* self) { + _cx_MEMB(_reserve)(self, _cx_MEMB(_size)(self)); } STC_INLINE _cx_iter -_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { - _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); +_cx_MEMB(_insert_n)(_cx_Self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { + _cx_iter it = _cx_MEMB(_insert_uninit)(self, idx, n); if (it.ref) c_memcpy(it.ref, arr, n*c_sizeof *arr); return it; } STC_INLINE _cx_iter -_cx_memb(_insert)(_cx_self* self, const intptr_t idx, const i_key value) { - return _cx_memb(_insert_n)(self, idx, &value, 1); +_cx_MEMB(_insert)(_cx_Self* self, const intptr_t idx, const i_key value) { + return _cx_MEMB(_insert_n)(self, idx, &value, 1); } STC_INLINE _cx_iter -_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const i_key value) { - return _cx_memb(_insert_n)(self, _it_ptr(it) - self->data, &value, 1); +_cx_MEMB(_insert_at)(_cx_Self* self, _cx_iter it, const i_key value) { + return _cx_MEMB(_insert_n)(self, _it_ptr(it) - self->data, &value, 1); } STC_INLINE _cx_iter -_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { - return _cx_memb(_erase_n)(self, it.ref - self->data, 1); +_cx_MEMB(_erase_at)(_cx_Self* self, _cx_iter it) { + return _cx_MEMB(_erase_n)(self, it.ref - self->data, 1); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { - return _cx_memb(_erase_n)(self, i1.ref - self->data, _it2_ptr(i1, i2) - i1.ref); +_cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter i1, _cx_iter i2) { + return _cx_MEMB(_erase_n)(self, i1.ref - self->data, _it2_ptr(i1, i2) - i1.ref); } STC_INLINE const _cx_value* -_cx_memb(_at)(const _cx_self* self, const intptr_t idx) { +_cx_MEMB(_at)(const _cx_Self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } STC_INLINE _cx_value* -_cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) { +_cx_MEMB(_at_mut)(_cx_Self* self, const intptr_t idx) { assert(idx < self->_len); return self->data + idx; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { +STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) { intptr_t n = self->_len; return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n}; } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) +STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self) { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) +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, size_t n) +STC_INLINE _cx_iter _cx_MEMB(_advance)(_cx_iter it, size_t n) { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } -STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it) +STC_INLINE intptr_t _cx_MEMB(_index)(const _cx_Self* self, _cx_iter it) { return (it.ref - self->data); } -STC_INLINE void _cx_memb(_adjust_end_)(_cx_self* self, intptr_t n) +STC_INLINE void _cx_MEMB(_adjust_end_)(_cx_Self* self, intptr_t n) { self->_len += n; } #if !defined i_no_cmp || defined _i_has_eq STC_INLINE _cx_iter -_cx_memb(_find)(const _cx_self* self, _cx_raw raw) { - return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw); +_cx_MEMB(_find)(const _cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_find_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), raw); } STC_INLINE const _cx_value* -_cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - return _cx_memb(_find)(self, raw).ref; +_cx_MEMB(_get)(const _cx_Self* self, _cx_raw raw) { + return _cx_MEMB(_find)(self, raw).ref; } STC_INLINE _cx_value* -_cx_memb(_get_mut)(const _cx_self* self, _cx_raw raw) - { return (_cx_value*) _cx_memb(_get)(self, raw); } +_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* self, const _cx_self* other) { +_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); @@ -243,39 +243,39 @@ _cx_memb(_eq)(const _cx_self* self, const _cx_self* other) { #ifndef i_no_cmp STC_INLINE _cx_iter -_cx_memb(_binary_search)(const _cx_self* self, _cx_raw raw) { +_cx_MEMB(_binary_search)(const _cx_Self* self, _cx_raw raw) { _cx_iter lower; - return _cx_memb(_binary_search_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw, &lower); + return _cx_MEMB(_binary_search_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), raw, &lower); } STC_INLINE _cx_iter -_cx_memb(_lower_bound)(const _cx_self* self, _cx_raw raw) { +_cx_MEMB(_lower_bound)(const _cx_Self* self, _cx_raw raw) { _cx_iter lower; - _cx_memb(_binary_search_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw, &lower); + _cx_MEMB(_binary_search_in)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), raw, &lower); return lower; } STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { +_cx_MEMB(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { qsort(i1.ref, (size_t)(_it2_ptr(i1, i2) - i1.ref), sizeof(_cx_value), (int(*)(const void*, const void*)) cmp); } STC_INLINE void -_cx_memb(_sort)(_cx_self* self) { - _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); +_cx_MEMB(_sort)(_cx_Self* self) { + _cx_MEMB(_sort_range)(_cx_MEMB(_begin)(self), _cx_MEMB(_end)(self), _cx_MEMB(_value_cmp)); } #endif // !c_no_cmp /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) || defined(i_static) -STC_DEF _cx_self -_cx_memb(_init)(void) { - return c_LITERAL(_cx_self){NULL}; +STC_DEF _cx_Self +_cx_MEMB(_init)(void) { + return c_LITERAL(_cx_Self){NULL}; } STC_DEF void -_cx_memb(_clear)(_cx_self* self) { +_cx_MEMB(_clear)(_cx_Self* self) { if (self->_cap) { for (_cx_value *p = self->data, *q = p + self->_len; p != q; ) { --q; i_keydrop(q); @@ -285,15 +285,15 @@ _cx_memb(_clear)(_cx_self* self) { } STC_DEF void -_cx_memb(_drop)(_cx_self* self) { +_cx_MEMB(_drop)(_cx_Self* self) { if (self->_cap == 0) return; - _cx_memb(_clear)(self); + _cx_MEMB(_clear)(self); i_free(self->data); } STC_DEF bool -_cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { +_cx_MEMB(_reserve)(_cx_Self* self, const intptr_t cap) { if (cap > self->_cap || (cap && cap == self->_len)) { _cx_value* d = (_cx_value*)i_realloc(self->data, cap*c_sizeof(i_key)); if (!d) @@ -305,8 +305,8 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t cap) { } STC_DEF bool -_cx_memb(_resize)(_cx_self* self, const intptr_t len, i_key null) { - if (!_cx_memb(_reserve)(self, len)) +_cx_MEMB(_resize)(_cx_Self* self, const intptr_t len, i_key null) { + if (!_cx_MEMB(_reserve)(self, len)) return false; const intptr_t n = self->_len; for (intptr_t i = len; i < n; ++i) @@ -318,9 +318,9 @@ _cx_memb(_resize)(_cx_self* self, const intptr_t len, i_key null) { } STC_DEF _cx_value* -_cx_memb(_push)(_cx_self* self, i_key value) { +_cx_MEMB(_push)(_cx_Self* self, i_key value) { if (self->_len == self->_cap) - if (!_cx_memb(_reserve)(self, self->_len*3/2 + 4)) + if (!_cx_MEMB(_reserve)(self, self->_len*3/2 + 4)) return NULL; _cx_value *v = self->data + self->_len++; *v = value; @@ -328,10 +328,10 @@ _cx_memb(_push)(_cx_self* self, i_key value) { } STC_DEF _cx_iter -_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { +_cx_MEMB(_insert_uninit)(_cx_Self* self, const intptr_t idx, const intptr_t n) { if (self->_len + n > self->_cap) - if (!_cx_memb(_reserve)(self, self->_len*3/2 + n)) - return _cx_memb(_end)(self); + if (!_cx_MEMB(_reserve)(self, self->_len*3/2 + n)) + return _cx_MEMB(_end)(self); _cx_value* pos = self->data + idx; c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos); @@ -340,7 +340,7 @@ _cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) { } STC_DEF _cx_iter -_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t len) { +_cx_MEMB(_erase_n)(_cx_Self* self, const intptr_t idx, const intptr_t len) { _cx_value* d = self->data + idx, *p = d, *end = self->data + self->_len; for (intptr_t i = 0; i < len; ++i, ++p) { i_keydrop(p); } @@ -350,17 +350,17 @@ _cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t len) { } #if !defined i_no_clone -STC_DEF _cx_self -_cx_memb(_clone)(_cx_self cx) { - _cx_self out = _cx_memb(_init)(); - _cx_memb(_copy_n)(&out, 0, cx.data, cx._len); +STC_DEF _cx_Self +_cx_MEMB(_clone)(_cx_Self cx) { + _cx_Self out = _cx_MEMB(_init)(); + _cx_MEMB(_copy_n)(&out, 0, cx.data, cx._len); return out; } STC_DEF _cx_iter -_cx_memb(_copy_n)(_cx_self* self, const intptr_t idx, +_cx_MEMB(_copy_n)(_cx_Self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) { - _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); + _cx_iter it = _cx_MEMB(_insert_uninit)(self, idx, n); if (it.ref) for (_cx_value* p = it.ref, *q = p + n; p != q; ++arr) *p++ = i_keyclone((*arr)); @@ -370,8 +370,8 @@ _cx_memb(_copy_n)(_cx_self* self, const intptr_t idx, #if !defined i_no_emplace STC_DEF _cx_iter -_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw raw[], intptr_t n) { - _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n); +_cx_MEMB(_emplace_n)(_cx_Self* self, const intptr_t idx, const _cx_raw raw[], intptr_t n) { + _cx_iter it = _cx_MEMB(_insert_uninit)(self, idx, n); if (it.ref) for (_cx_value* p = it.ref; n--; ++raw, ++p) *p = i_keyfrom((*raw)); @@ -381,7 +381,7 @@ _cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw raw[], in #if !defined i_no_cmp || defined _i_has_eq STC_DEF _cx_iter -_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { +_cx_MEMB(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { const _cx_value* p2 = _it2_ptr(i1, i2); for (; i1.ref != p2; ++i1.ref) { const _cx_raw r = i_keyto(i1.ref); @@ -395,7 +395,7 @@ _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { #ifndef i_no_cmp STC_DEF _cx_iter -_cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, +_cx_MEMB(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, _cx_iter* lower_bound) { _cx_value* w[2] = {i1.ref, _it2_ptr(i1, i2)}; _cx_iter mid = i1; @@ -412,7 +412,7 @@ _cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, i1.ref = NULL; return i1; } -STC_DEF int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { +STC_DEF int _cx_MEMB(_value_cmp)(const _cx_value* x, const _cx_value* y) { const _cx_raw rx = i_keyto(x); const _cx_raw ry = i_keyto(y); return i_cmp((&rx), (&ry)); diff --git a/include/stc/extend.h b/include/stc/extend.h index f697d2b3..f9ac92bf 100644 --- a/include/stc/extend.h +++ b/include/stc/extend.h @@ -54,7 +54,7 @@ typedef struct { i_type get; } c_PASTE(i_type, _ext); -#define c_extend(self) c_container_of(self, _cx_memb(_ext), get) +#define c_extend(self) c_container_of(self, _cx_MEMB(_ext), get) #define i_is_forward #define _i_inc diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index b3f3eabe..c1b7c1e7 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -25,17 +25,17 @@ #ifndef STC_TEMPLATE_H_INCLUDED #define STC_TEMPLATE_H_INCLUDED - #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) - #define _cx_key _cx_memb(_key) - #define _cx_mapped _cx_memb(_mapped) - #define _cx_raw _cx_memb(_raw) - #define _cx_keyraw _cx_memb(_keyraw) - #define _cx_iter _cx_memb(_iter) - #define _cx_result _cx_memb(_result) - #define _cx_node _cx_memb(_node) + #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) + #define _cx_key _cx_MEMB(_key) + #define _cx_mapped _cx_MEMB(_mapped) + #define _cx_raw _cx_MEMB(_raw) + #define _cx_keyraw _cx_MEMB(_keyraw) + #define _cx_iter _cx_MEMB(_iter) + #define _cx_result _cx_MEMB(_result) + #define _cx_node _cx_MEMB(_node) #endif #ifndef i_type -- cgit v1.2.3 From ebe5abc29d51c643520301e42124365477f44957 Mon Sep 17 00:00:00 2001 From: tylov Date: Wed, 12 Jul 2023 19:39:59 +0200 Subject: Changed docs and examples to use i_key* template parameters instead of i_val* for all non-maps. Renamed c_ASSERT() to c_assert() and added optional message parameter to c_static_assert(). --- README.md | 36 ++++++++++---------- docs/carc_api.md | 38 ++++++++++----------- docs/cbox_api.md | 52 ++++++++++++++-------------- docs/ccommon_api.md | 10 +++--- docs/cdeq_api.md | 54 ++++++++++++++--------------- docs/clist_api.md | 56 +++++++++++++++--------------- docs/cpque_api.md | 32 +++++++++--------- docs/cqueue_api.md | 28 +++++++-------- docs/cset_api.md | 2 +- docs/cspan_api.md | 7 ++-- docs/csset_api.md | 2 +- docs/cstack_api.md | 38 ++++++++++----------- docs/csview_api.md | 2 +- docs/cvec_api.md | 64 +++++++++++++++++------------------ include/stc/algo/sort.h | 21 +++++++----- include/stc/cbits.h | 8 ++--- include/stc/ccommon.h | 14 ++++---- include/stc/cdeq.h | 4 +-- include/stc/clist.h | 2 +- include/stc/cmap.h | 2 +- include/stc/cpque.h | 2 +- include/stc/cqueue.h | 4 +-- include/stc/cspan.h | 28 +++++++-------- include/stc/cstack.h | 8 ++--- include/stc/cvec.h | 8 ++--- include/stc/extend.h | 4 ++- misc/benchmarks/various/csort_bench.c | 2 +- misc/examples/arc_containers.c | 8 ++--- misc/examples/arc_demo.c | 8 ++--- misc/examples/arcvec_erase.c | 6 ++-- misc/examples/astar.c | 4 +-- misc/examples/box.c | 4 +-- misc/examples/box2.c | 6 ++-- misc/examples/cointerleave.c | 2 +- misc/examples/complex.c | 4 +-- misc/examples/convert.c | 4 +-- misc/examples/csmap_find.c | 2 +- misc/examples/csmap_insert.c | 2 +- misc/examples/demos.c | 6 ++-- misc/examples/forfilter.c | 4 +-- misc/examples/forloops.c | 2 +- misc/examples/functor.c | 2 +- misc/examples/inits.c | 6 ++-- misc/examples/intrusive.c | 2 +- misc/examples/list.c | 2 +- misc/examples/list_erase.c | 2 +- misc/examples/list_splice.c | 2 +- misc/examples/lower_bound.c | 4 +-- misc/examples/mmap.c | 2 +- misc/examples/multimap.c | 2 +- misc/examples/music_arc.c | 4 +-- misc/examples/new_list.c | 10 +++--- misc/examples/new_pque.c | 2 +- misc/examples/new_queue.c | 4 +-- misc/examples/new_sptr.c | 10 +++--- misc/examples/new_vec.c | 4 +-- misc/examples/person_arc.c | 4 +-- misc/examples/printspan.c | 8 ++--- misc/examples/priority.c | 2 +- misc/examples/queue.c | 2 +- misc/examples/rawptr_elements.c | 2 +- misc/examples/read.c | 2 +- misc/examples/regex_match.c | 2 +- misc/examples/scheduler.c | 2 +- misc/examples/shape.c | 6 ++-- misc/examples/stack.c | 4 +-- misc/tests/cspan_test.c | 4 +-- 67 files changed, 348 insertions(+), 338 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/README.md b/README.md index ab350488..67c4d7fd 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ List of contents 1. ***Centralized analysis of template parameters***. The analyser assigns values to all non-specified template parameters (based on the specified ones) using meta-programming, so that you don't have to! You may specify a set of "standard" template parameters for each -container, but as a minimum *only one is required*: `i_val` (+ `i_key` for maps). In this +container, but as a minimum *only one is required*: `i_key` (+ `i_val` for maps). In this case, STC assumes that the elements are of basic types. For non-trivial types, additional template parameters must be given. 2. ***Alternative insert/lookup type***. You may specify an alternative type to use for @@ -118,7 +118,7 @@ Benchmark notes: - Container names are prefixed by `c`, e.g. `cvec`, `cstr`. - Public STC macros are prefixed by `c_`, e.g. `c_foreach`, `c_init`. -- Template parameter macros are prefixed by `i_`, e.g. `i_val`, `i_type`. +- Template parameter macros are prefixed by `i_`, e.g. `i_key`, `i_type`. - All containers can be initialized with `{0}`, i.e. no heap allocation used by default init. - Common types for a container type Con: - Con @@ -150,7 +150,7 @@ templated types in C++. However, to specify template parameters with STC, you de including the container: ```c #define i_type Floats // Container type name; unless defined name would be cvec_float -#define i_val float // Container element type +#define i_key float // Container element type #include // "instantiate" the desired container type #include @@ -177,7 +177,7 @@ You may switch to a different container type, e.g. a sorted set (csset): [ [Run this code](https://godbolt.org/z/qznfa65e1) ] ```c #define i_type Floats -#define i_val float +#define i_key float #include // Use a sorted set instead #include @@ -196,7 +196,7 @@ int main() } ``` For user-defined struct elements, `i_cmp` compare function should be defined as the default `<` and `==` -only works for integral types. *Alternatively, `#define i_opt c_no_cmp` to disable sorting and searching*. Similarily, if an element destructor `i_valdrop` is defined, `i_valclone` function is required. +only works for integral types. *Alternatively, `#define i_opt c_no_cmp` to disable sorting and searching*. Similarily, if an element destructor `i_keydrop` is defined, `i_keyclone` function is required. *Alternatively `#define i_opt c_no_clone` to disable container cloning.* Let's make a vector of vectors, which can be cloned. All of its element vectors will be destroyed when destroying the Vec2D. @@ -206,11 +206,11 @@ Let's make a vector of vectors, which can be cloned. All of its element vectors #include #define i_type Vec -#define i_val float +#define i_key float #include #define i_type Vec2D -#define i_valclass Vec // Use i_valclass when element type has "members" _clone(), _drop() and _cmp(). +#define i_keyclass Vec // Use i_keyclass when element type has "members" _clone(), _drop() and _cmp(). #define i_opt c_no_cmp // Disable cmp (search/sort) for Vec2D because Vec_cmp() is not defined. #include @@ -246,12 +246,12 @@ This example uses four different container types: struct Point { float x, y; }; // Define cvec_pnt with a less-comparison function for Point. -#define i_val struct Point +#define i_key struct Point #define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y) #define i_tag pnt #include // cvec_pnt: vector of struct Point -#define i_val int +#define i_key int #include // clist_int: singly linked list #define i_key int @@ -369,10 +369,10 @@ or define your own, e.g.: #define i_tag ix #include // cset_ix -#define i_val int +#define i_key int #include // cvec_int -#define i_val Point +#define i_key Point #define i_tag pnt #include // clist_pnt ``` @@ -383,8 +383,8 @@ Each templated type requires one `#include`, even if it's the same container bas The template parameters are given by a `#define i_xxxx` statement, where *xxxx* is the parameter name. The list of template parameters: -- `i_key` *Type* - Element key type for map/set only. **[required]**. -- `i_val` *Type* - Element value type. **[required for]** cmap/csmap, it is the mapped value type. +- `i_key` *Type* - Element key type. **[required]**. Note: `i_val` *may* be used instead for non-maps (not recommended). +- `i_val` *Type* - Element value type. **[required for]** cmap/csmap as the mapped value type. - `i_cmp` *Func* - Three-way comparison of two *i_keyraw*\* or *i_valraw*\* - **[required for]** non-integral *i_keyraw* elements unless *i_opt* is defined with *c_no_cmp*. - `i_hash` *Func* - Hash function taking *i_keyraw*\* - defaults to *c_default_hash*. **[required for]** ***cmap/cset*** with non-POD *i_keyraw* elements. - `i_eq` *Func* - Equality comparison of two *i_keyraw*\* - defaults to *!i_cmp*. Companion with *i_hash*. @@ -458,7 +458,7 @@ and non-emplace methods: #define i_implement // define in ONE file to implement longer functions in cstr #include -#define i_val_str // special macro to enable container of cstr +#define i_key_str // special macro to enable container of cstr #include // vector of string (cstr) ... cvec_str vec = {0}; @@ -518,7 +518,7 @@ last example on the **cmap** page demonstrates how to specify a map with non-tri Define `i_type` instead of `i_tag`: ```c #define i_type MyVec -#define i_val int +#define i_key int #include myvec vec = MyVec_init(); @@ -543,7 +543,7 @@ typedef struct Dataset { // Implementation #define i_is_forward // flag that the container was forward declared. -#define i_val struct Point +#define i_key struct Point #define i_tag pnt #include ``` @@ -617,8 +617,8 @@ STC is generally very memory efficient. Memory usage for the different container - coroutines: much improved with some new API and added features. - cspan: Support for column-major (fortran order) multidim spans and transposed views. - Removed default comparison for clist, cvec and cdeq (as with cstack and cqueue). - - Using i_val_str, i_valclass, i_valboxed still expects comparisons defined. - - Define i_native_cmp to enable built-in i_val types comparisons (<, ==). + - Using i_key_str, i_keyclass, i_keyboxed still expects comparisons defined. + - Define i_native_cmp to enable built-in i_key types comparisons (<, ==). - cstr and csview are now shared linked by default. Static linking by defining i_static. - New cdeq and cqueue implementation(s), using circular buffer. - Renamed i_extern => i_import. diff --git a/docs/carc_api.md b/docs/carc_api.md index 22e6bac2..254f868a 100644 --- a/docs/carc_api.md +++ b/docs/carc_api.md @@ -6,14 +6,14 @@ deallocated when the last remaining **carc** owning the object is destroyed with The object is destroyed using *carc_X_drop()*. A **carc** may also own no objects, in which case it is called empty. The *carc_X_cmp()*, *carc_X_drop()* methods are defined based on -the `i_cmp` and `i_valdrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of +the `i_cmp` and `i_keydrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of the pointed-to object. All **carc** functions can be called by multiple threads on different instances of **carc** without additional synchronization even if these instances are copies and share ownership of the same object. **carc** uses thread-safe atomic reference counting, through the *carc_X_clone()* and *carc_X_drop()* methods. -When declaring a container with shared pointers, define `i_valboxed` with the carc type, see example. +When declaring a container with shared pointers, define `i_keyboxed` with the carc type, see example. See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference, or Rust [std::sync::Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) / [std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html). @@ -21,14 +21,14 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ```c #define i_type // full typename of the carc -#define i_val // value: REQUIRED +#define i_key // element type: REQUIRED -#define i_valraw // convertion "raw" type - defaults to i_val -#define i_valto // convertion func i_val* => i_valraw: REQUIRED IF i_valraw defined. -#define i_valfrom // convertion func i_valraw => i_val +#define i_keyraw // convertion "raw" type - defaults to i_key +#define i_keyto // convertion func i_key* => i_keyraw: REQUIRED IF i_keyraw defined. +#define i_keyfrom // convertion func i_keyraw => i_key #define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc. -#define i_tag // alternative typename: carc_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: carc_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -36,9 +36,9 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory ## Methods ```c carc_X carc_X_init(); // empty shared pointer -carc_X carc_X_from(i_valraw raw); // create an carc from raw type (available if i_valraw defined by user). -carc_X carc_X_from_ptr(i_val* p); // create an carc from raw pointer. Takes ownership of p. -carc_X carc_X_make(i_val val); // create an carc from constructed val object. Faster than from_ptr(). +carc_X carc_X_from(i_keyraw raw); // create an carc from raw type (available if i_keyraw defined by user). +carc_X carc_X_from_ptr(i_key* p); // create an carc from raw pointer. Takes ownership of p. +carc_X carc_X_make(i_key key); // create an carc from constructed key object. Faster than from_ptr(). carc_X carc_X_clone(carc_X other); // return other with increased use count carc_X carc_X_move(carc_X* self); // transfer ownership to receiver; self becomes NULL @@ -49,7 +49,7 @@ void carc_X_drop(carc_X* self); // destruct (decr long carc_X_use_count(const carc_X* self); void carc_X_reset(carc_X* self); -void carc_X_reset_to(carc_X* self, i_val* p); // assign new carc from ptr. Takes ownership of p. +void carc_X_reset_to(carc_X* self, i_key* p); // assign new carc from ptr. Takes ownership of p. uint64_t carc_X_hash(const carc_X* x); // hash value int carc_X_cmp(const carc_X* x, const carc_X* y); // compares pointer addresses if no `i_cmp` is specified. @@ -58,9 +58,9 @@ bool carc_X_eq(const carc_X* x, const carc_X* y); // carc_X_cmp() = // functions on pointed to objects. -uint64_t carc_X_value_hash(const i_val* x); -int carc_X_value_cmp(const i_val* x, const i_val* y); -bool carc_X_value_eq(const i_val* x, const i_val* y); +uint64_t carc_X_value_hash(const i_key* x); +int carc_X_value_cmp(const i_key* x, const i_key* y); +bool carc_X_value_eq(const i_key* x, const i_key* y); ``` ## Types and constants @@ -69,8 +69,8 @@ bool carc_X_value_eq(const i_val* x, const i_val* y); |:------------------|:--------------------------------------------------|:-----------------------| | `carc_null` | `{0}` | Init nullptr const | | `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | -| `carc_X_value` | `i_val` | The carc element type | -| `carc_X_raw` | `i_valraw` | Convertion type | +| `carc_X_value` | `i_key` | The carc element type | +| `carc_X_raw` | `i_keyraw` | Convertion type | ## Example @@ -89,12 +89,12 @@ bool carc_X_value_eq(const i_val* x, const i_val* y); #include #define i_type Arc // (atomic) ref. counted pointer -#define i_val Map -#define i_valdrop(p) (printf("drop Arc:\n"), Map_drop(p)) +#define i_key Map +#define i_keydrop(p) (printf("drop Arc:\n"), Map_drop(p)) #include #define i_type Stack -#define i_valboxed Arc // Note: use i_valboxed for carc or cbox value types +#define i_keyboxed Arc // Note: use i_keyboxed for carc or cbox value types #include int main() diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 9151f56d..83d59521 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -2,11 +2,11 @@ **cbox** is a smart pointer to a heap allocated value of type X. A **cbox** can be empty. The *cbox_X_cmp()*, *cbox_X_drop()* methods are defined based on the `i_cmp` -and `i_valdrop` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the -`i_valclone` macro if defined. +and `i_keydrop` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the +`i_keyclone` macro if defined. -When declaring a container of **cbox** values, define `i_valboxed` with the -cbox type instead of defining `i_val`. This will auto-set `i_valdrop`, `i_valclone`, and `i_cmp` using +When declaring a container of **cbox** values, define `i_keyboxed` with the +cbox type instead of defining `i_key`. This will auto-set `i_keydrop`, `i_keyclone`, and `i_cmp` using functions defined by the specified **cbox**. See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) for a functional reference, or Rust [std::boxed::Box](https://doc.rust-lang.org/std/boxed/struct.Box.html) @@ -15,29 +15,29 @@ See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory ```c #define i_type // full typename of the cbox -#define i_val // value: REQUIRED -#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED if i_valdrop is defined, unless 'i_opt c_no_clone' is defined. +#define i_key // element type: REQUIRED +#define i_cmp // three-way compare two i_key* : REQUIRED IF i_key is a non-integral type +#define i_keydrop // destroy element func - defaults to empty destruct +#define i_keyclone // REQUIRED if i_keydrop is defined, unless 'i_opt c_no_clone' is defined. -#define i_valraw // convertion type (lookup): default to {i_val} -#define i_valto // convertion func i_val* => i_valraw: REQUIRED IF i_valraw defined. -#define i_valfrom // from-raw func. +#define i_keyraw // convertion type (lookup): default to {i_key} +#define i_keyto // convertion func i_key* => i_keyraw: REQUIRED IF i_keyraw defined. +#define i_keyfrom // from-raw func. -#define i_valclass // alt. to i_val: REQUIRES that {i_val}_clone, {i_val}_drop, {i_valraw}_cmp exist. -#define i_tag // alternative typename: cbox_{i_tag}. i_tag defaults to i_val +#define i_keyclass // alt. to i_key: REQUIRES that {i_key}_clone, {i_key}_drop, {i_keyraw}_cmp exist. +#define i_tag // alternative typename: cbox_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. -Define `i_opt` with `c_no_cmp` if comparison between i_val's is not needed/available. Will then +Define `i_opt` with `c_no_cmp` if comparison between i_key's is not needed/available. Will then compare the pointer addresses when used. Additionally, `c_no_clone` or `i_is_fwd` may be defined. ## Methods ```c cbox_X cbox_X_init(); // return an empty cbox -cbox_X cbox_X_from(i_valraw raw); // create a cbox from raw type. Avail if i_valraw user defined. -cbox_X cbox_X_from_ptr(i_val* ptr); // create a cbox from a pointer. Takes ownership of ptr. -cbox_X cbox_X_make(i_val val); // create a cbox from unowned val object. +cbox_X cbox_X_from(i_keyraw raw); // create a cbox from raw type. Avail if i_keyraw user defined. +cbox_X cbox_X_from_ptr(i_key* ptr); // create a cbox from a pointer. Takes ownership of ptr. +cbox_X cbox_X_make(i_key val); // create a cbox from unowned val object. cbox_X cbox_X_clone(cbox_X other); // return deep copied clone cbox_X cbox_X_move(cbox_X* self); // transfer ownership to receiving cbox returned. self becomes NULL. @@ -46,7 +46,7 @@ void cbox_X_assign(cbox_X* self, cbox_X* moved); // transfer owners void cbox_X_drop(cbox_X* self); // destruct the contained object and free its heap memory. void cbox_X_reset(cbox_X* self); -void cbox_X_reset_to(cbox_X* self, i_val* p); // assign new cbox from ptr. Takes ownership of p. +void cbox_X_reset_to(cbox_X* self, i_key* p); // assign new cbox from ptr. Takes ownership of p. uint64_t cbox_X_hash(const cbox_X* x); // hash value int cbox_X_cmp(const cbox_X* x, const cbox_X* y); // compares pointer addresses if no `i_cmp` is specified. @@ -55,9 +55,9 @@ bool cbox_X_eq(const cbox_X* x, const cbox_X* y); // cbox_X_cmp() == // functions on pointed to objects. -uint64_t cbox_X_value_hash(const i_val* x); -int cbox_X_value_cmp(const i_val* x, const i_val* y); -bool cbox_X_value_eq(const i_val* x, const i_val* y); +uint64_t cbox_X_value_hash(const i_key* x); +int cbox_X_value_cmp(const i_key* x, const i_key* y); +bool cbox_X_value_eq(const i_key* x, const i_key* y); ``` ## Types and constants @@ -66,7 +66,7 @@ bool cbox_X_value_eq(const i_val* x, const i_val* y); |:-------------------|:--------------------------------|:------------------------| | `cbox_null` | `{0}` | Init nullptr const | | `cbox_X` | `struct { cbox_X_value* get; }` | The cbox type | -| `cbox_X_value` | `i_val` | The cbox element type | +| `cbox_X_value` | `i_key` | The cbox element type | ## Example @@ -77,9 +77,9 @@ void int_drop(int* x) { } #define i_type IBox -#define i_val int -#define i_valdrop int_drop // optional func, just to display elements destroyed -#define i_valclone(x) x // must specified when i_valdrop is defined. +#define i_key int +#define i_keydrop int_drop // optional func, just to display elements destroyed +#define i_keyclone(x) x // must specified when i_keydrop is defined. #include #define i_type ISet @@ -87,7 +87,7 @@ void int_drop(int* x) { #include // ISet : std::set> #define i_type IVec -#define i_valboxed IBox // NB: use i_valboxed instead of i_val +#define i_keyboxed IBox // NB: use i_keyboxed instead of i_key #include // IVec : std::vector> int main() diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 7569bb5b..52ad88e4 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -162,7 +162,7 @@ Note that `c_flt_take()` and `c_flt_takewhile()` breaks the loop on false. Make any container from an initializer list: ```c -#define i_val_str // owned cstr string value type +#define i_key_str // owned cstr string value type #include #define i_key int @@ -210,7 +210,7 @@ You may customize `i_tag` and the comparison function `i_cmp` or `i_less`. There is a [benchmark/test file here](../misc/benchmarks/various/csort_bench.c). ```c -#define i_val int +#define i_key int #include #include @@ -224,7 +224,7 @@ Containers with random access may also be sorted. Even sorting cdeq/cqueue (with possible and very fast. Note that `i_more` must be defined to retain specified template parameters for use by sort: ```c #define i_type MyDeq -#define i_val int +#define i_key int #define i_more #include // deque #include @@ -273,7 +273,7 @@ int* ip = c_const_cast(int*, cs); // issues a warning! ### Predefined template parameter functions -**crawstr** - Non-owned `const char*` "class" element type: `#define i_valclass crawstr` +**crawstr** - Non-owned `const char*` "class" element type: `#define i_keyclass crawstr` ```c typedef const char* crawstr; int crawstr_cmp(const crawstr* x, const crawstr* y); @@ -485,7 +485,7 @@ return ok; #define i_implement #include -#define i_val_str +#define i_key_str #include // receiver should check errno variable diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 5a00d69a..292b0933 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -11,16 +11,16 @@ See the c++ class [std::deque](https://en.cppreference.com/w/cpp/container/deque ```c #define i_type // full typename of the container -#define i_val // value: REQUIRED -#define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined +#define i_key // value: REQUIRED +#define i_cmp // three-way compare two i_keyraw* : REQUIRED IF i_keyraw is a non-integral type +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined -#define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val -#define i_valto // convertion func i_val* => i_valraw +#define i_keyraw // convertion "raw" type - defaults to i_key +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_keyto // convertion func i_key* => i_keyraw -#define i_tag // alternative typename: cdeq_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cdeq_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -44,30 +44,30 @@ intptr_t cdeq_X_capacity(const cdeq_X* self); const cdeq_X_value* cdeq_X_at(const cdeq_X* self, intptr_t idx); cdeq_X_value* cdeq_X_at_mut(cdeq_X* self, intptr_t idx); -const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_valraw raw); // return NULL if not found -cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_valraw raw); // mutable get -cdeq_X_iter cdeq_X_find(const cdeq_X* self, i_valraw raw); -cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_valraw raw); // return cvec_X_end() if not found +const cdeq_X_value* cdeq_X_get(const cdeq_X* self, i_keyraw raw); // return NULL if not found +cdeq_X_value* cdeq_X_get_mut(cdeq_X* self, i_keyraw raw); // mutable get +cdeq_X_iter cdeq_X_find(const cdeq_X* self, i_keyraw raw); +cdeq_X_iter cdeq_X_find_in(cdeq_X_iter i1, cdeq_X_iter i2, i_keyraw raw); // return cvec_X_end() if not found cdeq_X_value* cdeq_X_front(const cdeq_X* self); cdeq_X_value* cdeq_X_back(const cdeq_X* self); -cdeq_X_value* cdeq_X_push_front(cdeq_X* self, i_val value); -cdeq_X_value* cdeq_X_emplace_front(cdeq_X* self, i_valraw raw); +cdeq_X_value* cdeq_X_push_front(cdeq_X* self, i_key value); +cdeq_X_value* cdeq_X_emplace_front(cdeq_X* self, i_keyraw raw); void cdeq_X_pop_front(cdeq_X* self); -cdeq_X_value* cdeq_X_push_back(cdeq_X* self, i_val value); -cdeq_X_value* cdeq_X_push(cdeq_X* self, i_val value); // alias for push_back() -cdeq_X_value* cdeq_X_emplace_back(cdeq_X* self, i_valraw raw); -cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_valraw raw); // alias for emplace_back() +cdeq_X_value* cdeq_X_push_back(cdeq_X* self, i_key value); +cdeq_X_value* cdeq_X_push(cdeq_X* self, i_key value); // alias for push_back() +cdeq_X_value* cdeq_X_emplace_back(cdeq_X* self, i_keyraw raw); +cdeq_X_value* cdeq_X_emplace(cdeq_X* self, i_keyraw raw); // alias for emplace_back() void cdeq_X_pop_back(cdeq_X* self); -cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_val[] arr, intptr_t n); // move values -cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value +cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, intptr_t idx, const i_key[] arr, intptr_t n); // move values +cdeq_X_iter cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_key value); // move value cdeq_X_iter cdeq_X_insert_uninit(cdeq_X* self, intptr_t idx, intptr_t n); // uninitialized data // copy values: -cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_valraw[] arr, intptr_t n); -cdeq_X_iter cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw); +cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, intptr_t idx, const i_keyraw[] arr, intptr_t n); +cdeq_X_iter cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_keyraw raw); void cdeq_X_erase_n(cdeq_X* self, intptr_t idx, intptr_t n); cdeq_X_iter cdeq_X_erase_at(cdeq_X* self, cdeq_X_iter it); @@ -88,14 +88,14 @@ void cdeq_X_value_drop(cdeq_X_value* pval); | Type name | Type definition | Used to represent... | |:-------------------|:------------------------------------|:-----------------------| -| `cdeq_X` | `struct { cdeq_X_value* data; }` | The cdeq type | -| `cdeq_X_value` | `i_val` | The cdeq value type | -| `cdeq_X_raw` | `i_valraw` | The raw value type | -| `cdeq_X_iter` | `struct { cdeq_X_value* ref; }` | The iterator type | +| `cdeq_X` | `struct { cdeq_X_value* data; }` | The cdeq type | +| `cdeq_X_value` | `i_key` | The cdeq value type | +| `cdeq_X_raw` | `i_keyraw` | The raw value type | +| `cdeq_X_iter` | `struct { cdeq_X_value* ref; }` | The iterator type | ## Examples ```c -#define i_val int +#define i_key int #define i_tag i #include diff --git a/docs/clist_api.md b/docs/clist_api.md index 51b7af6a..023cca41 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -22,16 +22,16 @@ See the c++ class [std::list](https://en.cppreference.com/w/cpp/container/list) ## Header file and declaration ```c -#define i_type // container type name (default: clist_{i_val}) -#define i_val // value: REQUIRED -#define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined - -#define i_valraw // convertion "raw" type (default: {i_val}) -#define i_valto // convertion func i_val* => i_valraw -#define i_valfrom // convertion func i_valraw => i_val -#define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_val +#define i_type // container type name (default: clist_{i_key}) +#define i_key // value: REQUIRED +#define i_cmp // three-way compare two i_keyraw* : REQUIRED IF i_keyraw is a non-integral type +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined + +#define i_keyraw // convertion "raw" type (default: {i_key}) +#define i_keyto // convertion func i_key* => i_keyraw +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_key #include ``` @@ -53,31 +53,31 @@ intptr_t clist_X_count(const clist_X* list); clist_X_value* clist_X_back(const clist_X* self); clist_X_value* clist_X_front(const clist_X* self); -void clist_X_push_back(clist_X* self, i_val value); // note: no pop_back() -void clist_X_push_front(clist_X* self, i_val value); -void clist_X_push(clist_X* self, i_val value); // alias for push_back() +void clist_X_push_back(clist_X* self, i_key value); // note: no pop_back() +void clist_X_push_front(clist_X* self, i_key value); +void clist_X_push(clist_X* self, i_key value); // alias for push_back() -void clist_X_emplace_back(clist_X* self, i_valraw raw); -void clist_X_emplace_front(clist_X* self, i_valraw raw); -void clist_X_emplace(clist_X* self, i_valraw raw); // alias for emplace_back() +void clist_X_emplace_back(clist_X* self, i_keyraw raw); +void clist_X_emplace_front(clist_X* self, i_keyraw raw); +void clist_X_emplace(clist_X* self, i_keyraw raw); // alias for emplace_back() -clist_X_iter clist_X_insert_at(clist_X* self, clist_X_iter it, i_val value); // return iter to new elem -clist_X_iter clist_X_emplace_at(clist_X* self, clist_X_iter it, i_valraw raw); +clist_X_iter clist_X_insert_at(clist_X* self, clist_X_iter it, i_key value); // return iter to new elem +clist_X_iter clist_X_emplace_at(clist_X* self, clist_X_iter it, i_keyraw raw); void clist_X_pop_front(clist_X* self); clist_X_iter clist_X_erase_at(clist_X* self, clist_X_iter it); // return iter after it clist_X_iter clist_X_erase_range(clist_X* self, clist_X_iter it1, clist_X_iter it2); -intptr_t clist_X_remove(clist_X* self, i_valraw raw); // removes all matches +intptr_t clist_X_remove(clist_X* self, i_keyraw raw); // removes all matches clist_X clist_X_split_off(clist_X* self, clist_X_iter i1, clist_X_iter i2); // split off [i1, i2) clist_X_iter clist_X_splice(clist_X* self, clist_X_iter it, clist_X* other); // return updated valid it clist_X_iter clist_X_splice_range(clist_X* self, clist_X_iter it, // return updated valid it clist_X* other, clist_X_iter it1, clist_X_iter it2); -clist_X_iter clist_X_find(const clist_X* self, i_valraw raw); -clist_X_iter clist_X_find_in(clist_X_iter it1, clist_X_iter it2, i_valraw raw); -const i_val* clist_X_get(const clist_X* self, i_valraw raw); -i_val* clist_X_get_mut(clist_X* self, i_valraw raw); +clist_X_iter clist_X_find(const clist_X* self, i_keyraw raw); +clist_X_iter clist_X_find_in(clist_X_iter it1, clist_X_iter it2, i_keyraw raw); +const i_key* clist_X_get(const clist_X* self, i_keyraw raw); +i_key* clist_X_get_mut(clist_X* self, i_keyraw raw); void clist_X_reverse(clist_X* self); void clist_X_sort(clist_X* self); @@ -108,8 +108,8 @@ void clist_X_value_drop(clist_X_value* pval); |:--------------------|:------------------------------------|:-----------------------------------------| | `clist_X` | `struct { clist_X_node* last; }` | The clist type | | `clist_X_node` | `struct { clist_X_node* next; clist_X_value value; }` | The clist node type | -| `clist_X_value` | `i_val` | The clist element type | -| `clist_X_raw` | `i_valraw` | clist raw value type | +| `clist_X_value` | `i_key` | The clist element type | +| `clist_X_raw` | `i_keyraw` | clist raw value type | | `clist_X_iter` | `struct { clist_value *ref; ... }` | clist iterator | ## Example @@ -117,7 +117,7 @@ void clist_X_value_drop(clist_X_value* pval); Interleave *push_front()* / *push_back()* then *sort()*: ```c #define i_type DList -#define i_val double +#define i_key double #include #include @@ -154,7 +154,7 @@ Use of *erase_at()* and *erase_range()*: ```c // erasing from clist #define i_tag i -#define i_val int +#define i_key int #include #include @@ -189,7 +189,7 @@ mylist contains: 10 30 Splice `[30, 40]` from *L2* into *L1* before `3`: ```c #define i_tag i -#define i_val int +#define i_key int #include #include diff --git a/docs/cpque_api.md b/docs/cpque_api.md index 962ee162..ca94e367 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -8,17 +8,17 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai ## Header file and declaration ```c -#define i_type // define type name of the container (default cpque_{i_val}) -#define i_val // value: REQUIRED -#define i_less // compare two i_val* : REQUIRED IF i_val/i_valraw is a non-integral type -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined +#define i_type // define type name of the container (default cpque_{i_key}) +#define i_key // value: REQUIRED +#define i_less // compare two i_key* : REQUIRED IF i_key/i_keyraw is a non-integral type +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined -#define i_valraw // convertion type -#define i_valfrom // convertion func i_valraw => i_val -#define i_valto // convertion func i_val* => i_valraw. +#define i_keyraw // convertion type +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_keyto // convertion func i_key* => i_keyraw. -#define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -28,7 +28,7 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai ```c cpque_X cpque_X_init(void); // create empty pri-queue. cpque_X cpque_X_with_capacity(intptr_t cap); -cpque_X cpque_X_with_size(intptr_t size, i_val null); +cpque_X cpque_X_with_size(intptr_t size, i_key null); cpque_X cpque_X_clone(cpque_X pq); void cpque_X_clear(cpque_X* self); @@ -39,16 +39,16 @@ void cpque_X_drop(cpque_X* self); // destructor intptr_t cpque_X_size(const cpque_X* self); bool cpque_X_empty(const cpque_X* self); -i_val* cpque_X_top(const cpque_X* self); +i_key* cpque_X_top(const cpque_X* self); void cpque_X_make_heap(cpque_X* self); // heapify the vector. -void cpque_X_push(cpque_X* self, i_val value); -void cpque_X_emplace(cpque_X* self, i_valraw raw); // converts from raw +void cpque_X_push(cpque_X* self, i_key value); +void cpque_X_emplace(cpque_X* self, i_keyraw raw); // converts from raw void cpque_X_pop(cpque_X* self); void cpque_X_erase_at(cpque_X* self, intptr_t idx); -i_val cpque_X_value_clone(i_val value); +i_key cpque_X_value_clone(i_key value); ``` ## Types @@ -56,14 +56,14 @@ i_val cpque_X_value_clone(i_val value); | Type name | Type definition | Used to represent... | |:-------------------|:--------------------------------------|:------------------------| | `cpque_X` | `struct {cpque_X_value* data; ...}` | The cpque type | -| `cpque_X_value` | `i_val` | The cpque element type | +| `cpque_X_value` | `i_key` | The cpque element type | ## Example ```c #include #include -#define i_val int64_t +#define i_key int64_t #define i_cmp -c_default_cmp // min-heap #define i_tag i #include diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index f5df86d6..bce62833 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -7,16 +7,16 @@ See the c++ class [std::queue](https://en.cppreference.com/w/cpp/container/queue ## Header file and declaration ```c -#define i_type // container type name (default: cset_{i_key}) -#define i_val // value: REQUIRED -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined +#define i_type // container type name (default: cqueue_{i_key}) +#define i_key // value: REQUIRED +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined -#define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val -#define i_valto // convertion func i_val* => i_valraw +#define i_keyraw // convertion "raw" type - defaults to i_key +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_keyto // convertion func i_key* => i_keyraw -#define i_tag // alternative typename: cqueue_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cqueue_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -42,8 +42,8 @@ bool cqueue_X_empty(const cqueue_X* self); cqueue_X_value* cqueue_X_front(const cqueue_X* self); cqueue_X_value* cqueue_X_back(const cqueue_X* self); -cqueue_X_value* cqueue_X_push(cqueue_X* self, i_val value); -cqueue_X_value* cqueue_X_emplace(cqueue_X* self, i_valraw raw); +cqueue_X_value* cqueue_X_push(cqueue_X* self, i_key value); +cqueue_X_value* cqueue_X_emplace(cqueue_X* self, i_keyraw raw); void cqueue_X_pop(cqueue_X* self); cqueue_X_iter cqueue_X_begin(const cqueue_X* self); @@ -52,7 +52,7 @@ void cqueue_X_next(cqueue_X_iter* it); cqueue_X_iter cqueue_X_advance(cqueue_X_iter it, intptr_t n); bool cqueue_X_eq(const cqueue_X* c1, const cqueue_X* c2); // require i_eq/i_cmp/i_less. -i_val cqueue_X_value_clone(i_val value); +i_key cqueue_X_value_clone(i_key value); cqueue_X_raw cqueue_X_value_toraw(const cqueue_X_value* pval); void cqueue_X_value_drop(cqueue_X_value* pval); ``` @@ -62,13 +62,13 @@ void cqueue_X_value_drop(cqueue_X_value* pval); | Type name | Type definition | Used to represent... | |:--------------------|:---------------------|:-------------------------| | `cqueue_X` | `cdeq_X` | The cqueue type | -| `cqueue_X_value` | `i_val` | The cqueue element type | -| `cqueue_X_raw` | `i_valraw` | cqueue raw value type | +| `cqueue_X_value` | `i_key` | The cqueue element type | +| `cqueue_X_raw` | `i_keyraw` | cqueue raw value type | | `cqueue_X_iter` | `cdeq_X_iter` | cqueue iterator | ## Examples ```c -#define i_val int +#define i_key int #define i_tag i #include diff --git a/docs/cset_api.md b/docs/cset_api.md index ecf87e5b..7bce3136 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -18,7 +18,7 @@ A **cset** is an associative container that contains a set of unique objects of #define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_key #define i_expandby // default 1. If 2, table expand 2x (else 1.5x) #include ``` diff --git a/docs/cspan_api.md b/docs/cspan_api.md index 4262b1ef..1aeeb4f7 100644 --- a/docs/cspan_api.md +++ b/docs/cspan_api.md @@ -47,8 +47,11 @@ SpanTypeN_iter SpanType_begin(const SpanTypeN* self); SpanTypeN_iter SpanType_end(const SpanTypeN* self); void SpanType_next(SpanTypeN_iter* it); -SpanTypeN cspan_md(char order, ValueType* data, d1, d2, ...); // make a multi-dim cspan. order: 'C' or 'F' (Fortran) - // transpose the md span (inverse axes). no changes to the underlying array. +SpanTypeN cspan_md(ValueType* data, d1, d2, ...); // make a multi-dim cspan, row-major order. +SpanTypeN cspan_md_left(ValueType* data, d1, d2, ...); // column-major ordered cspan (layout left). +SpanTypeN cspan_md_ordered(char order, ValueType* data, d1, d2, ...); // order='C': row-major, 'F' (Fortran): column-major. + + // transpose a md span (inverse axes). no changes to the underlying array. void cspan_transpose(const SpanTypeN* self); // create a sub md span of lower rank. Like e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL}); diff --git a/docs/csset_api.md b/docs/csset_api.md index 5695ecf6..d086b660 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -18,7 +18,7 @@ See the c++ class [std::set](https://en.cppreference.com/w/cpp/container/set) fo #define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_tag // alternative typename: csset_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: csset_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. diff --git a/docs/cstack_api.md b/docs/cstack_api.md index 9cb7b42b..51889d7f 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -9,15 +9,15 @@ See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack ```c #define i_type // full typename of the container -#define i_val // value: REQUIRED -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined +#define i_key // value: REQUIRED +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined -#define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val -#define i_valto // convertion func i_val* => i_valraw +#define i_keyraw // convertion "raw" type - defaults to i_key +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_keyto // convertion func i_key* => i_keyraw -#define i_tag // alternative typename: cstack_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cstack_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -27,13 +27,13 @@ See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack ```c cstack_X cstack_X_init(void); cstack_X cstack_X_with_capacity(intptr_t cap); -cstack_X cstack_X_with_size(intptr_t size, i_val fill); +cstack_X cstack_X_with_size(intptr_t size, i_key fill); cstack_X cstack_X_clone(cstack_X st); void cstack_X_clear(cstack_X* self); bool cstack_X_reserve(cstack_X* self, intptr_t n); void cstack_X_shrink_to_fit(cstack_X* self); -i_val* cstack_X_append_uninit(cstack_X* self, intptr_t n); +i_key* cstack_X_append_uninit(cstack_X* self, intptr_t n); void cstack_X_copy(cstack_X* self, const cstack_X* other); void cstack_X_drop(cstack_X* self); // destructor @@ -41,12 +41,12 @@ intptr_t cstack_X_size(const cstack_X* self); intptr_t cstack_X_capacity(const cstack_X* self); bool cstack_X_empty(const cstack_X* self); -i_val* cstack_X_top(const cstack_X* self); -const i_val* cstack_X_at(const cstack_X* self, intptr_t idx); -i_val* cstack_X_at_mut(cstack_X* self, intptr_t idx); +i_key* cstack_X_top(const cstack_X* self); +const i_key* cstack_X_at(const cstack_X* self, intptr_t idx); +i_key* cstack_X_at_mut(cstack_X* self, intptr_t idx); -i_val* cstack_X_push(cstack_X* self, i_val value); -i_val* cstack_X_emplace(cstack_X* self, i_valraw raw); +i_key* cstack_X_push(cstack_X* self, i_key value); +i_key* cstack_X_emplace(cstack_X* self, i_keyraw raw); void cstack_X_pop(cstack_X* self); @@ -55,8 +55,8 @@ cstack_X_iter cstack_X_end(const cstack_X* self); void cstack_X_next(cstack_X_iter* it); bool cstack_X_eq(const cstack_X* c1, const cstack_X* c2); // require i_eq/i_cmp/i_less. -i_val cstack_X_value_clone(i_val value); -i_valraw cstack_X_value_toraw(const cvec_X_value* pval); +i_key cstack_X_value_clone(i_key value); +i_keyraw cstack_X_value_toraw(const cvec_X_value* pval); void cstack_X_value_drop(cvec_X_value* pval); ``` @@ -65,14 +65,14 @@ void cstack_X_value_drop(cvec_X_value* pval); | Type name | Type definition | Used to represent... | |:--------------------|:-------------------------------------|:----------------------------| | `cstack_X` | `struct { cstack_value *data; ... }` | The cstack type | -| `cstack_X_value` | `i_val` | The cstack element type | -| `cstack_X_raw` | `i_valraw` | cstack raw value type | +| `cstack_X_value` | `i_key` | The cstack element type | +| `cstack_X_raw` | `i_keyraw` | cstack raw value type | | `cstack_X_iter` | `struct { cstack_value *ref; }` | cstack iterator | ## Example ```c #define i_type IStack -#define i_val int +#define i_key int #include #include diff --git a/docs/csview_api.md b/docs/csview_api.md index a02b007a..33df6a64 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -185,7 +185,7 @@ void print_split(csview input, const char* sep) } #define i_implement #include -#define i_val_str +#define i_key_str #include cstack_str string_split(csview input, const char* sep) diff --git a/docs/cvec_api.md b/docs/cvec_api.md index d19f4bae..ce85e446 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -13,16 +13,16 @@ See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vect ```c #define i_type // full typename of the container -#define i_val // value: REQUIRED -#define i_cmp // three-way compare two i_valraw* : REQUIRED IF i_valraw is a non-integral type -#define i_valdrop // destroy value func - defaults to empty destruct -#define i_valclone // REQUIRED IF i_valdrop defined +#define i_key // value: REQUIRED +#define i_cmp // three-way compare two i_keyraw* : REQUIRED IF i_keyraw is a non-integral type +#define i_keydrop // destroy value func - defaults to empty destruct +#define i_keyclone // REQUIRED IF i_keydrop defined -#define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val -#define i_valto // convertion func i_val* => i_valraw +#define i_keyraw // convertion "raw" type - defaults to i_key +#define i_keyfrom // convertion func i_keyraw => i_key +#define i_keyto // convertion func i_key* => i_keyraw -#define i_tag // alternative typename: cvec_{i_tag}. i_tag defaults to i_val +#define i_tag // alternative typename: cvec_{i_tag}. i_tag defaults to i_key #include ``` `X` should be replaced by the value of `i_tag` in all of the following documentation. @@ -31,15 +31,15 @@ See the c++ class [std::vector](https://en.cppreference.com/w/cpp/container/vect ```c cvec_X cvec_X_init(void); -cvec_X cvec_X_with_size(intptr_t size, i_val null); +cvec_X cvec_X_with_size(intptr_t size, i_key null); cvec_X cvec_X_with_capacity(intptr_t size); cvec_X cvec_X_clone(cvec_X vec); void cvec_X_clear(cvec_X* self); void cvec_X_copy(cvec_X* self, const cvec_X* other); -cvec_X_iter cvec_X_copy_n(cvec_X* self, intptr_t idx, const i_val* arr, intptr_t n); +cvec_X_iter cvec_X_copy_n(cvec_X* self, intptr_t idx, const i_key* arr, intptr_t n); bool cvec_X_reserve(cvec_X* self, intptr_t cap); -bool cvec_X_resize(cvec_X* self, intptr_t size, i_val null); +bool cvec_X_resize(cvec_X* self, intptr_t size, i_key null); void cvec_X_shrink_to_fit(cvec_X* self); void cvec_X_drop(cvec_X* self); // destructor @@ -48,34 +48,34 @@ intptr_t cvec_X_size(const cvec_X* self); intptr_t cvec_X_capacity(const cvec_X* self); const cvec_X_value* cvec_X_at(const cvec_X* self, intptr_t idx); -const cvec_X_value* cvec_X_get(const cvec_X* self, i_valraw raw); // return NULL if not found +const cvec_X_value* cvec_X_get(const cvec_X* self, i_keyraw raw); // return NULL if not found cvec_X_value* cvec_X_at_mut(cvec_X* self, intptr_t idx); // return mutable at idx -cvec_X_value* cvec_X_get_mut(cvec_X* self, i_valraw raw); // find mutable value -cvec_X_iter cvec_X_find(const cvec_X* self, i_valraw raw); -cvec_X_iter cvec_X_find_in(cvec_X_iter i1, cvec_X_iter i2, i_valraw raw); // return cvec_X_end() if not found +cvec_X_value* cvec_X_get_mut(cvec_X* self, i_keyraw raw); // find mutable value +cvec_X_iter cvec_X_find(const cvec_X* self, i_keyraw raw); +cvec_X_iter cvec_X_find_in(cvec_X_iter i1, cvec_X_iter i2, i_keyraw raw); // return cvec_X_end() if not found // On sorted vectors: -cvec_X_iter cvec_X_binary_search(const cvec_X* self, i_valraw raw); // at elem == raw, else end -cvec_X_iter cvec_X_lower_bound(const cvec_X* self, i_valraw raw); // at first elem >= raw, else end +cvec_X_iter cvec_X_binary_search(const cvec_X* self, i_keyraw raw); // at elem == raw, else end +cvec_X_iter cvec_X_lower_bound(const cvec_X* self, i_keyraw raw); // at first elem >= raw, else end cvec_X_iter cvec_X_binary_search_in(cvec_X_iter i1, cvec_X_iter i2, - i_valraw raw, cvec_X_iter* lower_bound); + i_keyraw raw, cvec_X_iter* lower_bound); cvec_X_value* cvec_X_front(const cvec_X* self); cvec_X_value* cvec_X_back(const cvec_X* self); -cvec_X_value* cvec_X_push(cvec_X* self, i_val value); -cvec_X_value* cvec_X_emplace(cvec_X* self, i_valraw raw); -cvec_X_value* cvec_X_push_back(cvec_X* self, i_val value); // alias for push -cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); // alias for emplace +cvec_X_value* cvec_X_push(cvec_X* self, i_key value); +cvec_X_value* cvec_X_emplace(cvec_X* self, i_keyraw raw); +cvec_X_value* cvec_X_push_back(cvec_X* self, i_key value); // alias for push +cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_keyraw raw); // alias for emplace void cvec_X_pop(cvec_X* self); void cvec_X_pop_back(cvec_X* self); // alias for pop -cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_val arr[], intptr_t n); // move values -cvec_X_iter cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value +cvec_X_iter cvec_X_insert_n(cvec_X* self, intptr_t idx, const i_key arr[], intptr_t n); // move values +cvec_X_iter cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_key value); // move value cvec_X_iter cvec_X_insert_uninit(cvec_X* self, intptr_t idx, intptr_t n); // return iter at idx -cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_valraw raw[], intptr_t n); -cvec_X_iter cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw); +cvec_X_iter cvec_X_emplace_n(cvec_X* self, intptr_t idx, const i_keyraw raw[], intptr_t n); +cvec_X_iter cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_keyraw raw); cvec_X_iter cvec_X_erase_n(cvec_X* self, intptr_t idx, intptr_t n); cvec_X_iter cvec_X_erase_at(cvec_X* self, cvec_X_iter it); @@ -83,7 +83,7 @@ cvec_X_iter cvec_X_erase_range(cvec_X* self, cvec_X_iter it1, cvec_X_ite void cvec_X_sort(cvec_X* self); void cvec_X_sort_range(cvec_X_iter i1, cvec_X_iter i2, - int(*cmp)(const i_val*, const i_val*)); + int(*cmp)(const i_key*, const i_key*)); cvec_X_iter cvec_X_begin(const cvec_X* self); cvec_X_iter cvec_X_end(const cvec_X* self); @@ -101,13 +101,13 @@ cvec_X_raw cvec_X_value_drop(cvec_X_value* pval); | Type name | Type definition | Used to represent... | |:-------------------|:----------------------------------|:-----------------------| | `cvec_X` | `struct { cvec_X_value* data; }` | The cvec type | -| `cvec_X_value` | `i_val` | The cvec value type | -| `cvec_X_raw` | `i_valraw` | The raw value type | +| `cvec_X_value` | `i_key` | The cvec value type | +| `cvec_X_raw` | `i_keyraw` | The raw value type | | `cvec_X_iter` | `struct { cvec_X_value* ref; }` | The iterator type | ## Examples ```c -#define i_val int +#define i_key int #include #include @@ -150,7 +150,7 @@ sorted: 5 7 8 13 16 25 #define i_implement #include -#define i_val_str +#define i_key_str #include int main() { @@ -206,7 +206,7 @@ User User_clone(User user) { // Declare a managed, clonable vector of users. #define i_type UVec -#define i_valclass User // User is a "class" as it has _cmp, _clone and _drop functions. +#define i_keyclass User // User is a "class" as it has _cmp, _clone and _drop functions. #include int main(void) { diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h index 8365ccc5..01e7d521 100644 --- a/include/stc/algo/sort.h +++ b/include/stc/algo/sort.h @@ -22,13 +22,13 @@ */ /* Generic Quicksort in C, performs as fast as c++ std::sort(). template params: -#define i_val - value type [required] +#define i_key - value type [required] #define i_less - less function. default: *x < *y -#define i_type name - define {{name}}_sort_n(), else {{i_val}}array_sort_n(). +#define i_type name - define {{name}}_sort_n(), else {{i_key}}array_sort_n(). // ex1: #include -#define i_val int +#define i_key int #include int main() { @@ -42,7 +42,7 @@ int main() { } // ex2: -#define i_val int +#define i_key int #define i_type IDeq #define i_more // retain input template params to be reused by sort.h #include @@ -62,13 +62,16 @@ int main() { */ #include "../ccommon.h" +#if !defined i_key && defined i_val + #define i_key i_val +#endif #ifndef i_type #define i_at(arr, idx) (&arr[idx]) #ifndef i_tag - #define i_tag i_val + #define i_tag i_key #endif #define i_type c_PASTE(i_tag, array) - typedef i_val i_type; + typedef i_key i_type; #endif #ifndef i_at #define i_at(arr, idx) _cx_MEMB(_at_mut)(arr, idx) @@ -78,7 +81,7 @@ int main() { static inline void _cx_MEMB(_insertsort_ij)(_cx_Self* arr, intptr_t lo, intptr_t hi) { for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) { - i_val key = *i_at(arr, i); + i_key key = *i_at(arr, i); while (j >= 0 && (i_less((&key), i_at(arr, j)))) { *i_at(arr, j + 1) = *i_at(arr, j); --j; @@ -90,14 +93,14 @@ static inline void _cx_MEMB(_insertsort_ij)(_cx_Self* arr, intptr_t lo, intptr_t static inline void _cx_MEMB(_sort_ij)(_cx_Self* arr, intptr_t lo, intptr_t hi) { intptr_t i = lo, j; while (lo < hi) { - i_val pivot = *i_at(arr, lo + (hi - lo)*7/16); + i_key pivot = *i_at(arr, lo + (hi - lo)*7/16); j = hi; while (i <= j) { while (i_less(i_at(arr, i), (&pivot))) ++i; while (i_less((&pivot), i_at(arr, j))) --j; if (i <= j) { - c_swap(i_val, i_at(arr, i), i_at(arr, j)); + c_swap(i_key, i_at(arr, i), i_at(arr, j)); ++i; --j; } } diff --git a/include/stc/cbits.h b/include/stc/cbits.h index 9463c82c..66bc6354 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -90,7 +90,7 @@ STC_INLINE _llong _cbits_count(const uint64_t* set, const _llong sz) { STC_INLINE char* _cbits_to_str(const uint64_t* set, const _llong sz, char* out, _llong start, _llong stop) { if (stop > sz) stop = sz; - assert(start <= stop); + c_assert(start <= stop); c_memset(out, '0', stop - start); for (_llong i = start; i < stop; ++i) @@ -122,7 +122,7 @@ STC_INLINE bool _cbits_disjoint(const uint64_t* set, const uint64_t* other, cons #if !defined i_capacity // DYNAMIC SIZE BITARRAY -#define _i_assert(x) assert(x) +#define _i_assert(x) c_assert(x) #define i_type cbits typedef struct { uint64_t *data64; _llong _size; } i_type; @@ -216,13 +216,13 @@ STC_INLINE void _i_memb(_set_all)(i_type *self, const bool value); STC_INLINE void _i_memb(_set_pattern)(i_type *self, const uint64_t pattern); STC_INLINE i_type _i_memb(_with_size)(const _llong size, const bool value) { - assert(size <= i_capacity); + c_assert(size <= i_capacity); i_type set; _i_memb(_set_all)(&set, value); return set; } STC_INLINE i_type _i_memb(_with_pattern)(const _llong size, const uint64_t pattern) { - assert(size <= i_capacity); + c_assert(size <= i_capacity); i_type set; _i_memb(_set_pattern)(&set, pattern); return set; } diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index d6da8734..efbebdc3 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -34,11 +34,6 @@ typedef long long _llong; #define c_NPOS INTPTR_MAX #define c_ZI PRIiPTR #define c_ZU PRIuPTR -#if defined STC_NDEBUG || defined NDEBUG - #define c_ASSERT(expr) (void)(0) -#else - #define c_ASSERT(expr) assert(expr) -#endif #if defined(_MSC_VER) #pragma warning(disable: 4116 4996) // unnamed type definition in parentheses @@ -80,7 +75,14 @@ typedef long long _llong; #define c_free(p) free(p) #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_static_assert(...) c_MACRO_OVERLOAD(c_static_assert, __VA_ARGS__) +#define c_static_assert_1(b) ((int)(0*sizeof(int[(b) ? 1 : -1]))) +#define c_static_assert_2(b, m) c_static_assert_1(b) +#if defined STC_NDEBUG || defined NDEBUG + #define c_assert(expr) ((void)0) +#else + #define c_assert(expr) assert(expr) +#endif #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, \ diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index bac40f90..056ef005 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -51,13 +51,13 @@ _cx_MEMB(_push_back)(_cx_Self* self, _cx_value val) STC_INLINE void _cx_MEMB(_pop_back)(_cx_Self* self) { - assert(!_cx_MEMB(_empty)(self)); + c_assert(!_cx_MEMB(_empty)(self)); self->end = (self->end - 1) & self->capmask; i_keydrop((self->data + self->end)); } STC_INLINE _cx_value _cx_MEMB(_pull_back)(_cx_Self* self) { // move back out of deq - assert(!_cx_MEMB(_empty)(self)); + c_assert(!_cx_MEMB(_empty)(self)); self->end = (self->end - 1) & self->capmask; return self->data[self->end]; } diff --git a/include/stc/clist.h b/include/stc/clist.h index 38358d73..9cc1bb39 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -145,7 +145,7 @@ STC_INLINE void _cx_MEMB(_clear)(_cx_Self* self) { _cx_MEMB(_drop)(self) STC_INLINE _cx_value* _cx_MEMB(_push)(_cx_Self* self, i_key value) { return _cx_MEMB(_push_back)(self, value); } STC_INLINE void _cx_MEMB(_pop_front)(_cx_Self* self) - { assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_after_node)(self, self->last); } + { c_assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_after_node)(self, self->last); } STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return &self->last->next->value; } STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return &self->last->value; } STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); } diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 21e7b933..513a8b93 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -117,7 +117,7 @@ STC_INLINE bool _cx_MEMB(_contains)(const _cx_Self* self, _cx_keyraw rke STC_INLINE const _cx_mapped* _cx_MEMB(_at)(const _cx_Self* self, _cx_keyraw rkey) { chash_bucket b = _cx_MEMB(_bucket_)(self, &rkey); - assert(b.found); + c_assert(b.found); return &self->data[b.idx].second; } STC_INLINE _cx_mapped* diff --git a/include/stc/cpque.h b/include/stc/cpque.h index cfe027cc..ca51eeff 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -89,7 +89,7 @@ STC_INLINE const _cx_value* _cx_MEMB(_top)(const _cx_Self* self) { return &self->data[0]; } STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) - { assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_at)(self, 0); } + { c_assert(!_cx_MEMB(_empty)(self)); _cx_MEMB(_erase_at)(self, 0); } #if !defined i_no_clone STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self q); diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index e9f1b877..5d38ca89 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -88,13 +88,13 @@ STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return self->data + ((self->end - 1) & self->capmask); } STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) { // pop_front - assert(!_cx_MEMB(_empty)(self)); + c_assert(!_cx_MEMB(_empty)(self)); i_keydrop((self->data + self->start)); self->start = (self->start + 1) & self->capmask; } STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) { // move front out of queue - assert(!_cx_MEMB(_empty)(self)); + c_assert(!_cx_MEMB(_empty)(self)); intptr_t s = self->start; self->start = (s + 1) & self->capmask; return self->data[s]; diff --git a/include/stc/cspan.h b/include/stc/cspan.h index 89986d6f..4d091395 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -84,7 +84,7 @@ int demo2() { const int rank, const int32_t a[][2]) { \ Self s = {.data=v}; int outrank; \ s.data += _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \ - c_ASSERT(outrank == RANK); \ + c_assert(outrank == RANK); \ return s; \ } \ STC_INLINE Self##_iter Self##_begin(const Self* self) { \ @@ -145,7 +145,6 @@ using_cspan_tuple(7); using_cspan_tuple(8); #define cspan_subspan3(self, offset, count) \ {.data=cspan_at(self, offset, 0, 0), .shape={count, (self)->shape[1], (self)->shape[2]}, .stride=(self)->stride} - // cspan_submd(): Reduce rank (N <= 4) Optimized, same as e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL}); #define cspan_submd2(OutSpan, self, ...) _cspan_submdN(OutSpan, 2, self, __VA_ARGS__) #define cspan_submd3(OutSpan, self, ...) _cspan_submdN(OutSpan, 3, self, __VA_ARGS__) @@ -172,23 +171,22 @@ using_cspan_tuple(7); using_cspan_tuple(8); #define _cspan_submd4_5(ok, self, x, y, z) \ {.data=cspan_at(self, x, y, z, 0) + ok, .shape={(self)->shape[3]}, .stride={.d={(self)->stride.d[3]}}} -#define cspan_md(array, ...) cspan_md_order('C', array, __VA_ARGS__) -#define cspan_md_left(array, ...) cspan_md_order('F', array, __VA_ARGS__) -#define cspan_md_order(order, array, ...) \ +#define cspan_md(array, ...) cspan_md_ordered('C', array, __VA_ARGS__) +#define cspan_md_left(array, ...) cspan_md_ordered('F', array, __VA_ARGS__) +#define cspan_md_ordered(order, array, ...) \ {.data=array, .shape={__VA_ARGS__}, \ .stride=*(c_PASTE(cspan_tuple, c_NUMARGS(__VA_ARGS__))*)_cspan_shape2stride(order, ((int32_t[]){__VA_ARGS__}), c_NUMARGS(__VA_ARGS__))} #define cspan_transpose(self) \ _cspan_transpose((self)->shape, (self)->stride.d, cspan_rank(self)) - // General slicing function; #define cspan_slice(OutSpan, parent, ...) \ OutSpan##_slice_((parent)->data, (parent)->shape, (parent)->stride.d, cspan_rank(parent) + \ c_static_assert(cspan_rank(parent) == sizeof((int32_t[][2]){__VA_ARGS__})/sizeof(int32_t[2])), \ (const int32_t[][2]){__VA_ARGS__}) -// ----------- private definitions ------------ +/* ------------------- PRIVAT DEFINITIONS ------------------- */ // cspan_index() helpers: #define cspan_idx_1 cspan_idx_3 @@ -215,19 +213,19 @@ STC_INLINE void _cspan_transpose(int32_t shape[], int32_t stride[], int rank) { } STC_INLINE intptr_t _cspan_idx1(const int32_t shape[1], const cspan_tuple1 stri, int32_t x) - { c_ASSERT(c_LTu(x, shape[0])); return x; } + { c_assert(c_LTu(x, shape[0])); return (intptr_t)stri.d[0]*x; } STC_INLINE intptr_t _cspan_idx2(const int32_t shape[2], const cspan_tuple2 stri, int32_t x, int32_t y) - { c_ASSERT(c_LTu(x, shape[0]) && c_LTu(y, shape[1])); return (intptr_t)stri.d[0]*x + stri.d[1]*y; } + { c_assert(c_LTu(x, shape[0]) && c_LTu(y, shape[1])); return (intptr_t)stri.d[0]*x + stri.d[1]*y; } STC_INLINE intptr_t _cspan_idx3(const int32_t shape[3], const cspan_tuple3 stri, int32_t x, int32_t y, int32_t z) { - c_ASSERT(c_LTu(x, shape[0]) && c_LTu(y, shape[1]) && c_LTu(z, shape[2])); + c_assert(c_LTu(x, shape[0]) && c_LTu(y, shape[1]) && c_LTu(z, shape[2])); return (intptr_t)stri.d[0]*x + stri.d[1]*y + stri.d[2]*z; } STC_INLINE intptr_t _cspan_idxN(int rank, const int32_t shape[], const int32_t stride[], const int32_t a[]) { intptr_t off = 0; while (rank--) { - c_ASSERT(c_LTu(a[rank], shape[rank])); + c_assert(c_LTu(a[rank], shape[rank])); off += stride[rank]*a[rank]; } return off; @@ -239,6 +237,8 @@ STC_API intptr_t _cspan_next2(int32_t pos[], const int32_t shape[], const int32_ #define _cspan_next4 _cspan_next2 #define _cspan_next5 _cspan_next2 #define _cspan_next6 _cspan_next2 +#define _cspan_next7 _cspan_next2 +#define _cspan_next8 _cspan_next2 STC_API intptr_t _cspan_slice(int32_t oshape[], int32_t ostride[], int* orank, const int32_t shape[], const int32_t stride[], @@ -247,7 +247,7 @@ STC_API intptr_t _cspan_slice(int32_t oshape[], int32_t ostride[], int* orank, STC_API int32_t* _cspan_shape2stride(char order, int32_t shape[], int rank); #endif // STC_CSPAN_H_INCLUDED -/* -------------------------- IMPLEMENTATION ------------------------- */ +/* --------------------- IMPLEMENTATION --------------------- */ #if defined(i_implement) || defined(i_static) STC_DEF int32_t* _cspan_shape2stride(char order, int32_t shape[], int rank) { @@ -283,13 +283,13 @@ STC_DEF intptr_t _cspan_slice(int32_t oshape[], int32_t ostride[], int* orank, for (; i < rank; ++i) { off += stride[i]*a[i][0]; switch (a[i][1]) { - case 0: c_ASSERT(c_LTu(a[i][0], shape[i])); continue; + case 0: c_assert(c_LTu(a[i][0], shape[i])); continue; case -1: end = shape[i]; break; default: end = a[i][1]; } oshape[oi] = end - a[i][0]; ostride[oi] = stride[i]; - c_ASSERT(c_LTu(0, oshape[oi]) & !c_LTu(shape[i], end)); + c_assert(c_LTu(0, oshape[oi]) & !c_LTu(shape[i], end)); ++oi; } *orank = oi; diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 24ec2d5f..f8640ed1 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -129,10 +129,10 @@ STC_INLINE _cx_value* _cx_MEMB(_push)(_cx_Self* self, _cx_value val) { } STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) - { assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } + { c_assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) - { assert(self->_len); return self->data[--self->_len]; } + { c_assert(self->_len); return self->data[--self->_len]; } STC_INLINE void _cx_MEMB(_put_n)(_cx_Self* self, const _cx_raw* raw, intptr_t n) { while (n--) _cx_MEMB(_push)(self, i_keyfrom(*raw++)); } @@ -141,9 +141,9 @@ STC_INLINE _cx_Self _cx_MEMB(_from_n)(const _cx_raw* raw, intptr_t n) { _cx_Self cx = {0}; _cx_MEMB(_put_n)(&cx, raw, n); return cx; } STC_INLINE const _cx_value* _cx_MEMB(_at)(const _cx_Self* self, intptr_t idx) - { assert(idx < self->_len); return self->data + idx; } + { c_assert(idx < self->_len); return self->data + idx; } STC_INLINE _cx_value* _cx_MEMB(_at_mut)(_cx_Self* self, intptr_t idx) - { assert(idx < self->_len); return self->data + idx; } + { c_assert(idx < self->_len); return self->data + idx; } #if !defined i_no_emplace STC_INLINE _cx_value* _cx_MEMB(_emplace)(_cx_Self* self, _cx_raw raw) diff --git a/include/stc/cvec.h b/include/stc/cvec.h index e1d34365..9b95306e 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -133,9 +133,9 @@ STC_INLINE _cx_value* _cx_MEMB(_front)(const _cx_Self* self) { return self->da STC_INLINE _cx_value* _cx_MEMB(_back)(const _cx_Self* self) { return self->data + self->_len - 1; } STC_INLINE void _cx_MEMB(_pop)(_cx_Self* self) - { assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } + { c_assert(self->_len); _cx_value* p = &self->data[--self->_len]; i_keydrop(p); } STC_INLINE _cx_value _cx_MEMB(_pull)(_cx_Self* self) - { assert(self->_len); return self->data[--self->_len]; } + { c_assert(self->_len); return self->data[--self->_len]; } STC_INLINE _cx_value* _cx_MEMB(_push_back)(_cx_Self* self, i_key value) { return _cx_MEMB(_push)(self, value); } STC_INLINE void _cx_MEMB(_pop_back)(_cx_Self* self) { _cx_MEMB(_pop)(self); } @@ -182,11 +182,11 @@ _cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter i1, _cx_iter i2) { STC_INLINE const _cx_value* _cx_MEMB(_at)(const _cx_Self* self, const intptr_t idx) { - assert(idx < self->_len); return self->data + idx; + c_assert(idx < self->_len); return self->data + idx; } STC_INLINE _cx_value* _cx_MEMB(_at_mut)(_cx_Self* self, const intptr_t idx) { - assert(idx < self->_len); return self->data + idx; + c_assert(idx < self->_len); return self->data + idx; } diff --git a/include/stc/extend.h b/include/stc/extend.h index c0a00ff8..52d59414 100644 --- a/include/stc/extend.h +++ b/include/stc/extend.h @@ -43,8 +43,10 @@ #define _i_val i_val #endif -#ifdef _i_key +#if defined _i_key && defined _i_val c_PASTE(forward_, i_base)(i_type, _i_key, _i_val); +#elif defined _i_key + c_PASTE(forward_, i_base)(i_type, _i_key); #else c_PASTE(forward_, i_base)(i_type, _i_val); #endif diff --git a/misc/benchmarks/various/csort_bench.c b/misc/benchmarks/various/csort_bench.c index d434693f..f6b7f1db 100644 --- a/misc/benchmarks/various/csort_bench.c +++ b/misc/benchmarks/various/csort_bench.c @@ -7,7 +7,7 @@ #endif #define NDEBUG #define i_type Ints -#define i_val int +#define i_key int #define i_more #include #include diff --git a/misc/examples/arc_containers.c b/misc/examples/arc_containers.c index b05bbea6..524758e7 100644 --- a/misc/examples/arc_containers.c +++ b/misc/examples/arc_containers.c @@ -10,18 +10,18 @@ #include #define i_type Arc // (atomic) ref. counted type -#define i_val Map -#define i_valdrop(p) (printf("drop Arc:\n"), Map_drop(p)) +#define i_key Map +#define i_keydrop(p) (printf("drop Arc:\n"), Map_drop(p)) // no need for atomic ref. count in single thread: #define i_opt c_no_atomic #include #define i_type Stack -#define i_valboxed Arc // define i_valboxed for carc/cbox value (not i_val) +#define i_keyboxed Arc // define i_keyboxed for carc/cbox value (not i_key) #include #define i_type List -#define i_valboxed Arc // as above +#define i_keyboxed Arc // as above #include int main() diff --git a/misc/examples/arc_demo.c b/misc/examples/arc_demo.c index 4cda1c8b..547e1737 100644 --- a/misc/examples/arc_demo.c +++ b/misc/examples/arc_demo.c @@ -6,18 +6,18 @@ void int_drop(int* x) { } // carc implements its own clone method using reference counting, -// so 'i_valclone' is not required to be defined (ignored). +// so 'i_keyclone' is not required to be defined (ignored). #define i_type Arc // set type name to be defined (instead of 'carc_int') -#define i_val int -#define i_valdrop int_drop // optional, just to display the elements destroyed +#define i_key int +#define i_keydrop int_drop // optional, just to display the elements destroyed #define i_native_cmp // use int comparison (x < y, x == y). #include // Arc #define i_keyboxed Arc // note: use i_keyboxed instead of i_key for carc/cbox elements #include // csset_Arc (like: std::set>) -#define i_valboxed Arc // note: as above. +#define i_keyboxed Arc // note: as above. #include // cvec_Arc (like: std::vector>) int main() diff --git a/misc/examples/arcvec_erase.c b/misc/examples/arcvec_erase.c index 0b9252d9..f409258b 100644 --- a/misc/examples/arcvec_erase.c +++ b/misc/examples/arcvec_erase.c @@ -3,13 +3,13 @@ void show_drop(int* x) { printf("drop: %d\n", *x); } #define i_type Arc -#define i_val int -#define i_valdrop show_drop +#define i_key int +#define i_keydrop show_drop #define i_native_cmp // enable sort/search for int type #include // Shared pointer to int #define i_type Vec -#define i_valboxed Arc +#define i_keyboxed Arc #include // Vec: cvec diff --git a/misc/examples/astar.c b/misc/examples/astar.c index 1b3876aa..44cdefee 100644 --- a/misc/examples/astar.c +++ b/misc/examples/astar.c @@ -57,11 +57,11 @@ point_key_cmp(const point* a, const point* b) return (i == j) ? 0 : (i < j) ? -1 : 1; } -#define i_val point +#define i_key point #define i_cmp point_cmp_priority #include -#define i_val point +#define i_key point #define i_opt c_no_cmp #include diff --git a/misc/examples/box.c b/misc/examples/box.c index a9131afa..3f55e15d 100644 --- a/misc/examples/box.c +++ b/misc/examples/box.c @@ -29,11 +29,11 @@ void Person_drop(Person* p) { } #define i_type PBox -#define i_valclass Person // "class" binds _cmp, _clone, _drop functions. +#define i_keyclass Person // "class" binds _cmp, _clone, _drop functions. #include #define i_type Persons -#define i_valboxed PBox // "arcbox" informs that PBox is a smart pointer. +#define i_keyboxed PBox // "arcbox" informs that PBox is a smart pointer. #include int main() diff --git a/misc/examples/box2.c b/misc/examples/box2.c index d3762462..5ac706d4 100644 --- a/misc/examples/box2.c +++ b/misc/examples/box2.c @@ -14,15 +14,15 @@ typedef struct { Point bottom_right; } Rectangle; -#define i_val Point +#define i_key Point #include // cbox_Point -#define i_val Rectangle +#define i_key Rectangle #include // cbox_Rectangle // Box in box: #define i_type BoxBoxPoint -#define i_valboxed cbox_Point // NB: use i_valboxed when value is a cbox or carc! +#define i_keyboxed cbox_Point // NB: use i_keyboxed when value is a cbox or carc! #define i_no_cmp #include // BoxBoxPoint diff --git a/misc/examples/cointerleave.c b/misc/examples/cointerleave.c index 61562a5f..c3c5926a 100644 --- a/misc/examples/cointerleave.c +++ b/misc/examples/cointerleave.c @@ -2,7 +2,7 @@ #include #include #define i_type IVec -#define i_val int +#define i_key int #include struct GenValue { diff --git a/misc/examples/complex.c b/misc/examples/complex.c index b5ea847a..405afef3 100644 --- a/misc/examples/complex.c +++ b/misc/examples/complex.c @@ -9,11 +9,11 @@ #include #define i_type FloatStack -#define i_val float +#define i_key float #include #define i_type StackList -#define i_valclass FloatStack // "class" picks up _clone, _drop, _cmp +#define i_keyclass FloatStack // "class" picks up _clone, _drop, _cmp #define i_opt c_no_cmp // exclude FloatStack_cmp(): not defined #include diff --git a/misc/examples/convert.c b/misc/examples/convert.c index 318f09b8..3b9dc3ec 100644 --- a/misc/examples/convert.c +++ b/misc/examples/convert.c @@ -6,10 +6,10 @@ #define i_val_str #include -#define i_val_str +#define i_key_str #include -#define i_val_str +#define i_key_str #include int main() diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c index 645828a3..b535e9ad 100644 --- a/misc/examples/csmap_find.c +++ b/misc/examples/csmap_find.c @@ -8,7 +8,7 @@ #define i_tag istr #include -#define i_val csmap_istr_raw +#define i_key csmap_istr_raw #define i_tag istr #include diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c index 18a88ec3..df638c22 100644 --- a/misc/examples/csmap_insert.c +++ b/misc/examples/csmap_insert.c @@ -12,7 +12,7 @@ #define i_tag istr // Map of int => cstr #include -#define i_val csmap_ii_raw +#define i_key csmap_ii_raw #define i_opt c_no_cmp #define i_tag ii #include diff --git a/misc/examples/demos.c b/misc/examples/demos.c index b2f50ebf..2e91b20c 100644 --- a/misc/examples/demos.c +++ b/misc/examples/demos.c @@ -28,7 +28,7 @@ void stringdemo1() cstr_drop(&cs); } -#define i_val int64_t +#define i_key int64_t #define i_tag ix #include @@ -52,7 +52,7 @@ void vectordemo1() cvec_ix_drop(&bignums); } -#define i_val_str +#define i_key_str #include void vectordemo2() @@ -72,7 +72,7 @@ void vectordemo2() cvec_str_drop(&names); } -#define i_val int +#define i_key int #define i_tag ix #define i_native_cmp #include diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 7e3c4c9c..f3c008b3 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -7,7 +7,7 @@ #include #define i_type IVec -#define i_val int +#define i_key int #include // filters and transforms: @@ -83,7 +83,7 @@ fn main() { } */ #define i_type SVec -#define i_valclass csview +#define i_keyclass csview #include void demo3(void) diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 337cfaa1..99b12871 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -2,7 +2,7 @@ #include #define i_type IVec -#define i_val int +#define i_key int #include #define i_type IMap diff --git a/misc/examples/functor.c b/misc/examples/functor.c index a233a874..ea409a56 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -6,7 +6,7 @@ #define i_type IPQue #define i_base cpque -#define i_val int +#define i_key int #define i_extend bool(*less)(const int*, const int*); #define i_less(x, y) c_extend()->less(x, y) // Note: i_less: c_extend() accessible for cpque types diff --git a/misc/examples/inits.c b/misc/examples/inits.c index a3a6c4d2..53a49f1f 100644 --- a/misc/examples/inits.c +++ b/misc/examples/inits.c @@ -18,17 +18,17 @@ inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) { } -#define i_val ipair_t +#define i_key ipair_t #define i_cmp ipair_cmp #define i_tag ip #include -#define i_val ipair_t +#define i_key ipair_t #define i_cmp ipair_cmp #define i_tag ip #include -#define i_val float +#define i_key float #define i_tag f #include diff --git a/misc/examples/intrusive.c b/misc/examples/intrusive.c index e3939f4e..1e3f7b83 100644 --- a/misc/examples/intrusive.c +++ b/misc/examples/intrusive.c @@ -3,7 +3,7 @@ #include #define i_type List -#define i_val int +#define i_key int #define i_native_cmp #include diff --git a/misc/examples/list.c b/misc/examples/list.c index 08fe837f..a0045db9 100644 --- a/misc/examples/list.c +++ b/misc/examples/list.c @@ -4,7 +4,7 @@ #include #define i_type DList -#define i_val double +#define i_key double #define i_native_cmp #include diff --git a/misc/examples/list_erase.c b/misc/examples/list_erase.c index 17adf11f..357dd75b 100644 --- a/misc/examples/list_erase.c +++ b/misc/examples/list_erase.c @@ -2,7 +2,7 @@ #include #define i_type IList -#define i_val int +#define i_key int #include int main () diff --git a/misc/examples/list_splice.c b/misc/examples/list_splice.c index e457694d..25c2a42d 100644 --- a/misc/examples/list_splice.c +++ b/misc/examples/list_splice.c @@ -1,6 +1,6 @@ #include -#define i_val int +#define i_key int #define i_tag i #include diff --git a/misc/examples/lower_bound.c b/misc/examples/lower_bound.c index 5b395e45..ee32f49b 100644 --- a/misc/examples/lower_bound.c +++ b/misc/examples/lower_bound.c @@ -1,10 +1,10 @@ #include -#define i_val int +#define i_key int #define i_native_cmp #include -#define i_val int +#define i_key int #include int main() diff --git a/misc/examples/mmap.c b/misc/examples/mmap.c index 63312e04..fd00499c 100644 --- a/misc/examples/mmap.c +++ b/misc/examples/mmap.c @@ -4,7 +4,7 @@ // Multimap entries #define i_implement #include -#define i_val_str +#define i_key_str #include // Map of int => clist_str. diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c index dc4a1ee0..a89b251b 100644 --- a/misc/examples/multimap.c +++ b/misc/examples/multimap.c @@ -40,7 +40,7 @@ OlympicLoc OlympicLoc_clone(OlympicLoc loc); void OlympicLoc_drop(OlympicLoc* self); // Create a clist, can be sorted by year. -#define i_valclass OlympicLoc // binds _cmp, _clone and _drop. +#define i_keyclass OlympicLoc // binds _cmp, _clone and _drop. #define i_tag OL #include diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c index 4efc35c8..49008523 100644 --- a/misc/examples/music_arc.c +++ b/misc/examples/music_arc.c @@ -22,13 +22,13 @@ void Song_drop(Song* s) { // Define the shared pointer: #define i_type SongArc -#define i_valclass Song +#define i_keyclass Song #define i_no_hash // no hash fn for Song, fallback hash pointer to Song. #include // ... and a vector of them #define i_type SongVec -#define i_valboxed SongArc // use i_valboxed on carc / cbox (instead of i_val) +#define i_keyboxed SongArc // use i_keyboxed on carc / cbox (instead of i_key) #include void example3() diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c index 5ffdaca2..ee250b2b 100644 --- a/misc/examples/new_list.c +++ b/misc/examples/new_list.c @@ -9,7 +9,7 @@ typedef struct { clist_pnt pntlist; } MyStruct; -#define i_val int +#define i_key int #define i_tag i32 #define i_is_forward #include @@ -20,20 +20,20 @@ int point_cmp(const Point* a, const Point* b) { return c ? c : a->y - b->y; } -#define i_val Point +#define i_key Point #define i_cmp point_cmp #define i_is_forward #define i_tag pnt #include -#define i_val float +#define i_key float #define i_native_cmp // use < and == operators for comparison #include void MyStruct_drop(MyStruct* s); #define i_type MyList -#define i_val MyStruct -#define i_valdrop MyStruct_drop // define drop function +#define i_key MyStruct +#define i_keydrop MyStruct_drop // define drop function #define i_no_clone // must explicitely exclude or define cloning support because of drop. #include diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c index dc2ecf12..3df39e0e 100644 --- a/misc/examples/new_pque.c +++ b/misc/examples/new_pque.c @@ -3,7 +3,7 @@ typedef struct Point { int x, y; } Point; #define i_type PointQ -#define i_val Point +#define i_key Point #define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y) #include diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c index b784bc18..104871bf 100644 --- a/misc/examples/new_queue.c +++ b/misc/examples/new_queue.c @@ -10,14 +10,14 @@ int point_cmp(const Point* a, const Point* b) { int c = c_default_cmp(&a->x, &b->x); return c ? c : c_default_cmp(&a->y, &b->y); } -#define i_val Point +#define i_key Point #define i_cmp point_cmp #define i_is_forward #define i_tag pnt #include #define i_type IQ -#define i_val int +#define i_key int #include int main() { diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c index 2eff41a5..7fef5d1f 100644 --- a/misc/examples/new_sptr.c +++ b/misc/examples/new_sptr.c @@ -9,21 +9,21 @@ int Person_cmp(const Person* a, const Person* b); uint64_t Person_hash(const Person* p); #define i_type PersonArc -#define i_valclass Person // "class" assume _clone, _drop, _cmp, _hash is defined. +#define i_keyclass Person // "class" assume _clone, _drop, _cmp, _hash is defined. #include #define i_type IPtr -#define i_val int -#define i_valdrop(x) printf("drop: %d\n", *x) +#define i_key int +#define i_keydrop(x) printf("drop: %d\n", *x) #define i_native_cmp #include #define i_type IPStack -#define i_valboxed IPtr +#define i_keyboxed IPtr #include #define i_type PASet -#define i_valboxed PersonArc +#define i_keyboxed PersonArc #include diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c index 6329b185..6d928cfc 100644 --- a/misc/examples/new_vec.c +++ b/misc/examples/new_vec.c @@ -9,14 +9,14 @@ typedef struct MyStruct { cvec_pnt pntvec; } MyStruct; -#define i_val int +#define i_key int #define i_tag i32 #define i_is_forward #include typedef struct Point { int x, y; } Point; -#define i_val Point +#define i_key Point #define i_tag pnt #define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y) #define i_eq(a, b) a->x == b->x && a->y == b->y diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c index 3614c02d..c78b541c 100644 --- a/misc/examples/person_arc.c +++ b/misc/examples/person_arc.c @@ -31,12 +31,12 @@ void Person_drop(Person* p) { } #define i_type PSPtr -#define i_valclass Person // ensure Person_drop +#define i_keyclass Person // ensure Person_drop #define i_cmp Person_cmp // specify object cmp, instead of ptr cmp for arc. #include #define i_type Persons -#define i_valboxed PSPtr // binds PSPtr_cmp, PSPtr_drop... +#define i_keyboxed PSPtr // binds PSPtr_cmp, PSPtr_drop... #include diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c index 7564bd88..5084536a 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -3,14 +3,14 @@ #include #define i_implement #include -#define i_val int +#define i_key int #include -#define i_val int +#define i_key int #include -#define i_val_str +#define i_key_str #include -#include +#include using_cspan(intspan, int, 1); void printMe(intspan container) { diff --git a/misc/examples/priority.c b/misc/examples/priority.c index 95dd3183..148e8fc5 100644 --- a/misc/examples/priority.c +++ b/misc/examples/priority.c @@ -3,7 +3,7 @@ #include #include -#define i_val int64_t +#define i_key int64_t #define i_cmp -c_default_cmp // min-heap (increasing values) #define i_tag i #include diff --git a/misc/examples/queue.c b/misc/examples/queue.c index 83c18d09..3154f115 100644 --- a/misc/examples/queue.c +++ b/misc/examples/queue.c @@ -1,7 +1,7 @@ #include #include -#define i_val int +#define i_key int #define i_tag i #include diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c index 8dd52aee..9c394d8e 100644 --- a/misc/examples/rawptr_elements.c +++ b/misc/examples/rawptr_elements.c @@ -16,7 +16,7 @@ // Alternatively, using cbox: #define i_type IBox -#define i_val long +#define i_key long #include // unique_ptr alike. // cmap of cstr => IBox diff --git a/misc/examples/read.c b/misc/examples/read.c index 3c1cadf6..c25cd740 100644 --- a/misc/examples/read.c +++ b/misc/examples/read.c @@ -1,7 +1,7 @@ #define i_implement #include #include -#define i_val_str +#define i_key_str #include #include diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c index 310e0797..88d3747b 100644 --- a/misc/examples/regex_match.c +++ b/misc/examples/regex_match.c @@ -3,7 +3,7 @@ #define i_implement #include -#define i_val float +#define i_key float #include int main() diff --git a/misc/examples/scheduler.c b/misc/examples/scheduler.c index c1168850..d812ff42 100644 --- a/misc/examples/scheduler.c +++ b/misc/examples/scheduler.c @@ -9,7 +9,7 @@ struct Task { }; #define i_type Scheduler -#define i_val struct Task +#define i_key struct Task #include static bool schedule(Scheduler* sched) diff --git a/misc/examples/shape.c b/misc/examples/shape.c index 1d9fe5c5..bd4bdd5a 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -76,7 +76,7 @@ struct ShapeAPI Triangle_api = { // ============================================================ #define i_type PointVec -#define i_val Point +#define i_key Point #include typedef struct { @@ -122,8 +122,8 @@ struct ShapeAPI Polygon_api = { // ============================================================ #define i_type Shapes -#define i_val Shape* -#define i_valdrop(x) Shape_delete(*x) +#define i_key Shape* +#define i_keydrop(x) Shape_delete(*x) #define i_no_clone #include diff --git a/misc/examples/stack.c b/misc/examples/stack.c index c817e1ae..96bab24b 100644 --- a/misc/examples/stack.c +++ b/misc/examples/stack.c @@ -3,11 +3,11 @@ #define i_tag i #define i_capacity 100 -#define i_val int +#define i_key int #include #define i_tag c -#define i_val char +#define i_key char #include int main() { diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c index 6834dce1..aa055ea6 100644 --- a/misc/tests/cspan_test.c +++ b/misc/tests/cspan_test.c @@ -44,7 +44,7 @@ CTEST(cspan, slice) { ASSERT_EQ(45, sum2); } -#define i_val int +#define i_key int #include CTEST(cspan, slice2) { @@ -75,7 +75,7 @@ CTEST(cspan, slice2) { #define i_type Tiles -#define i_val intspan3 +#define i_key intspan3 #include CTEST_FIXTURE(cspan_cube) { -- cgit v1.2.3 From d7fba27af452de2d709767e615fa2e90d6b3a391 Mon Sep 17 00:00:00 2001 From: tylov Date: Wed, 26 Jul 2023 21:23:15 +0200 Subject: Added cmap_emplace_key() / csmap_emplace_key() More docs. --- README.md | 29 +++++----- docs/algorithm_api.md | 4 +- docs/cmap_api.md | 8 ++- docs/csmap_api.md | 1 + include/stc/algo/filter.h | 2 +- include/stc/cmap.h | 87 +++++++++++++++------------- include/stc/csmap.h | 30 ++++++---- include/stc/forward.h | 1 + misc/examples/smartpointers/arc_containers.c | 1 - misc/tests/cspan_test.c | 4 +- 10 files changed, 95 insertions(+), 72 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/README.md b/README.md index 9b6698e5..d66a7f1c 100644 --- a/README.md +++ b/README.md @@ -619,23 +619,24 @@ STC is generally very memory efficient. Memory usage for the different container # Version History ## Version 4.3 -- Some breaking changes. -- **coroutines**: much improved with some new API and added features. -- **cspan**: Rewritten to add support for **column-major** order (fortran) multidim spans and transposed views. -- Removed default comparison for **clist**, **cvec** and **cdeq** (like cstack and cqueue). - - Define `i_cmp_native` to enable built-in i_key types comparisons (<, ==). - - Use of `i_keyclass` still expects comparison functions defined. - - Use of `i_keyboxed` compares hosted pointers instead of pointed to values if comparisons not defined. -- **cstr** and **csview** now uses *shared linking* by default. Implement by either defining `i_implement` or `i_static` before including. +- Some breaking changes: + - **cstr** and **csview** now uses *shared linking* by default. Implement by either defining `i_implement` or `i_static` before including. + - Changes in `coroutine.h`: much improved with some new API and added features. + - Renamed stc/calgo.h => `` + - Removed deprecated stc/crandom.h. Use `` with the new API. + - Removed default comparison for **clist**, **cvec** and **cdeq**: + - Define `i_cmp_native` to enable comparison for built-in i_key types (<, ==). + - Use of `i_keyclass` still expects comparison functions to be defined. + - Use of `i_keyboxed` compares hosted pointers instead of pointed to values if comparisons not defined. + - Renamed input enum flags for ***cregex***-functions. +- **cspan**: Changed representation of strides to add **column-major** order (fortran) multidimensional spans and transposed views. - All new faster and smaller **cqueue** and **cdeq** implementations, using a circular buffer. -- Renamed i_extern => `i_import`. - - Define `i_import` before `#include ` will also define utf8 case conversions. +- Renamed i_extern => `i_import` (i_extern deprecated). + - Define `i_import` before `#include ` will also define full utf8 case conversions. - Define `i_import` before `#include ` will also define cstr + utf8 tables. -- Renamed c_make() => ***c_init()*** macro for initializing containers with element lists. -- Renamed input enum flags for ***cregex***-functions. -- Removed deprecated . Use `` with the new API. +- Renamed c_make() => ***c_init()*** macro for initializing containers with element lists. c_make deprecated. - Removed deprecated uppercase flow-control macro names. -- Improved default string hash function. +- Other smaller additions, bug fixes and improved documentation. ## Version 4.2 - New home! And online single headers for https://godbolt.org diff --git a/docs/algorithm_api.md b/docs/algorithm_api.md index 490771b5..40ff32d6 100644 --- a/docs/algorithm_api.md +++ b/docs/algorithm_api.md @@ -130,7 +130,7 @@ Iterate a container or a crange with chained `&&` filtering. [ [Run this example](https://godbolt.org/z/n9aYrYPv8) ] ```c -#include +#include #include bool isPrime(long long i) { @@ -309,8 +309,6 @@ The **checkauto** utility described below, ensures that the `c_auto*` macros are | `continue` | Exit a defer-block without resource leak | ```c -#include // or -... // `c_defer` executes the expression(s) when leaving scope. // Note: does not require inclusion of "raii.h". cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world"); diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 17f27662..4e6da57d 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -71,7 +71,8 @@ cmap_X_result cmap_X_insert_or_assign(cmap_X* self, i_key key, i_val map cmap_X_result cmap_X_push(cmap_X* self, cmap_X_value entry); // similar to insert cmap_X_result cmap_X_emplace(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map -cmap_X_result cmap_X_emplace_or_assign(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update +cmap_X_result cmap_X_emplace_or_assign(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update mapped +cmap_X_result cmap_X_emplace_key(cmap_X* self, i_keyraw rkey); // see example 1. int cmap_X_erase(cmap_X* self, i_keyraw rkey); // return 0 or 1 cmap_X_iter cmap_X_erase_at(cmap_X* self, cmap_X_iter it); // return iter after it @@ -138,6 +139,11 @@ int main(void) cmap_str_emplace(&umap, "BLACK", "#000000"); cmap_str_emplace(&umap, "WHITE", "#FFFFFF"); + // Insert only if "CYAN" is not in the map: create mapped value when needed only. + cmap_str_result res = cmap_str_emplace_key(&umap, "CYAN"); + if (res.inserted) + res.ref->second = cstr_from("#00FFFF"); // must assign second if key was inserted. + // Output values by key printf("The HEX of color RED is:[%s]\n", cstr_str(cmap_str_at(&umap, "RED"))); printf("The HEX of color BLACK is:[%s]\n", cstr_str(cmap_str_at(&umap, "BLACK"))); diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 164b0f8a..d739283b 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -72,6 +72,7 @@ csmap_X_result csmap_X_push(csmap_X* self, csmap_X_value entry); csmap_X_result csmap_X_emplace(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map csmap_X_result csmap_X_emplace_or_assign(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update rmapped +csmap_X_result csmap_X_emplace_key(csmap_X* self, i_keyraw rkey); // if key not in map, mapped is left unassigned int csmap_X_erase(csmap_X* self, i_keyraw rkey); csmap_X_iter csmap_X_erase_at(csmap_X* self, csmap_X_iter it); // returns iter after it diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h index 1a62c3e1..320cd50d 100644 --- a/include/stc/algo/filter.h +++ b/include/stc/algo/filter.h @@ -24,7 +24,7 @@ #include #define i_val int #include -#include +#include int main(void) { diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 513a8b93..2dd8cbe6 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -55,7 +55,6 @@ int main(void) { #include #include struct chash_slot { uint8_t hashx; }; -typedef struct { intptr_t idx; uint8_t hashx, found; } chash_bucket; #endif // CMAP_H_INCLUDED #ifndef _i_prefix @@ -94,7 +93,7 @@ STC_API _cx_Self _cx_MEMB(_clone)(_cx_Self map); STC_API void _cx_MEMB(_drop)(_cx_Self* self); STC_API void _cx_MEMB(_clear)(_cx_Self* self); STC_API bool _cx_MEMB(_reserve)(_cx_Self* self, intptr_t capacity); -STC_API chash_bucket _cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr); +STC_API _cx_result _cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr); STC_API _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey); STC_API void _cx_MEMB(_erase_entry)(_cx_Self* self, _cx_value* val); STC_API float _cx_MEMB(_max_load_factor)(const _cx_Self* self); @@ -106,9 +105,9 @@ STC_INLINE bool _cx_MEMB(_empty)(const _cx_Self* map) { return !map->siz STC_INLINE intptr_t _cx_MEMB(_size)(const _cx_Self* map) { return (intptr_t)map->size; } STC_INLINE intptr_t _cx_MEMB(_bucket_count)(_cx_Self* map) { return map->bucket_count; } STC_INLINE bool _cx_MEMB(_contains)(const _cx_Self* self, _cx_keyraw rkey) - { return self->size && _cx_MEMB(_bucket_)(self, &rkey).found; } + { return self->size && !_cx_MEMB(_bucket_)(self, &rkey).inserted; } -#ifndef _i_isset +#ifdef _i_ismap STC_API _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key key, i_val mapped); #if !defined i_no_emplace STC_API _cx_result _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped); @@ -116,14 +115,15 @@ STC_INLINE bool _cx_MEMB(_contains)(const _cx_Self* self, _cx_keyraw rke STC_INLINE const _cx_mapped* _cx_MEMB(_at)(const _cx_Self* self, _cx_keyraw rkey) { - chash_bucket b = _cx_MEMB(_bucket_)(self, &rkey); - c_assert(b.found); - return &self->data[b.idx].second; + _cx_result b = _cx_MEMB(_bucket_)(self, &rkey); + c_assert(!b.inserted); + return &b.ref->second; } + STC_INLINE _cx_mapped* _cx_MEMB(_at_mut)(_cx_Self* self, _cx_keyraw rkey) { return (_cx_mapped*)_cx_MEMB(_at)(self, rkey); } -#endif // !_i_isset +#endif // _i_ismap #if !defined i_no_clone STC_INLINE void _cx_MEMB(_copy)(_cx_Self *self, const _cx_Self* other) { @@ -151,6 +151,16 @@ _cx_MEMB(_emplace)(_cx_Self* self, _cx_keyraw rkey _i_MAP_ONLY(, i_valraw rmappe } return _res; } + +#ifdef _i_ismap + STC_INLINE _cx_result + _cx_MEMB(_emplace_key)(_cx_Self* self, _cx_keyraw rkey) { + _cx_result _res = _cx_MEMB(_insert_entry_)(self, rkey); + if (_res.inserted) + _res.ref->first = i_keyfrom(rkey); + return _res; + } +#endif // _i_ismap #endif // !i_no_emplace STC_INLINE _cx_raw _cx_MEMB(_value_toraw)(const _cx_value* val) { @@ -215,19 +225,19 @@ STC_INLINE _cx_iter _cx_MEMB(_advance)(_cx_iter it, size_t n) { STC_INLINE _cx_iter _cx_MEMB(_find)(const _cx_Self* self, _cx_keyraw rkey) { - chash_bucket b; - if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) - return c_LITERAL(_cx_iter){self->data + b.idx, + _cx_result b; + if (self->size && !(b = _cx_MEMB(_bucket_)(self, &rkey)).inserted) + return c_LITERAL(_cx_iter){b.ref, self->data + self->bucket_count, - self->slot + b.idx}; + self->slot + (b.ref - self->data)}; return _cx_MEMB(_end)(self); } STC_INLINE const _cx_value* _cx_MEMB(_get)(const _cx_Self* self, _cx_keyraw rkey) { - chash_bucket b; - if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) - return self->data + b.idx; + _cx_result b; + if (self->size && !(b = _cx_MEMB(_bucket_)(self, &rkey)).inserted) + return b.ref; return NULL; } @@ -237,10 +247,10 @@ _cx_MEMB(_get_mut)(_cx_Self* self, _cx_keyraw rkey) STC_INLINE int _cx_MEMB(_erase)(_cx_Self* self, _cx_keyraw rkey) { - chash_bucket b = {0}; - if (self->size && (b = _cx_MEMB(_bucket_)(self, &rkey)).found) - _cx_MEMB(_erase_entry)(self, self->data + b.idx); - return b.found; + _cx_result b; + if (self->size && !(b = _cx_MEMB(_bucket_)(self, &rkey)).inserted) + { _cx_MEMB(_erase_entry)(self, b.ref); return 1; } + return 0; } STC_INLINE _cx_iter @@ -313,7 +323,7 @@ STC_DEF void _cx_MEMB(_clear)(_cx_Self* self) { c_memset(self->slot, 0, c_sizeof(chash_slot)*self->bucket_count); } -#ifndef _i_isset +#ifdef _i_ismap STC_DEF _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key _key, i_val _mapped) { _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); @@ -340,42 +350,41 @@ STC_DEF void _cx_MEMB(_clear)(_cx_Self* self) { return _res; } #endif // !i_no_emplace -#endif // !_i_isset +#endif // _i_ismap -STC_DEF chash_bucket +STC_DEF _cx_result _cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr) { const uint64_t _hash = i_hash(rkeyptr); intptr_t _cap = self->bucket_count; - chash_bucket b = {fastrange_2(_hash, _cap), (uint8_t)(_hash | 0x80)}; + intptr_t _idx = fastrange_2(_hash, _cap); + _cx_result b = {NULL, true, (uint8_t)(_hash | 0x80)}; const chash_slot* s = self->slot; - while (s[b.idx].hashx) { - if (s[b.idx].hashx == b.hashx) { - const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + b.idx)); + while (s[_idx].hashx) { + if (s[_idx].hashx == b.hashx) { + const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + _idx)); if (i_eq((&_raw), rkeyptr)) { - b.found = true; + b.inserted = false; break; } } - if (++b.idx == _cap) b.idx = 0; + if (++_idx == _cap) _idx = 0; } + b.ref = self->data + _idx; return b; } STC_DEF _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey) { - _cx_result res = {NULL}; if (self->size >= (intptr_t)((float)self->bucket_count * (i_max_load_factor))) if (!_cx_MEMB(_reserve)(self, (intptr_t)(self->size*3/2 + 2))) - return res; + return c_LITERAL(_cx_result){NULL}; - chash_bucket b = _cx_MEMB(_bucket_)(self, &rkey); - res.ref = &self->data[b.idx]; - if (!b.found) { - self->slot[b.idx].hashx = b.hashx; - res.inserted = true; + _cx_result b = _cx_MEMB(_bucket_)(self, &rkey); + if (b.inserted) { + self->slot[b.ref - self->data].hashx = b.hashx; ++self->size; } - return res; + return b; } #if !defined i_no_clone @@ -417,9 +426,9 @@ _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { const chash_slot* s = self->slot; for (intptr_t i = 0; i < _oldbucks; ++i, ++d) if ((s++)->hashx) { _cx_keyraw r = i_keyto(_i_keyref(d)); - chash_bucket b = _cx_MEMB(_bucket_)(&m, &r); - m.slot[b.idx].hashx = b.hashx; - m.data[b.idx] = *d; // move + _cx_result b = _cx_MEMB(_bucket_)(&m, &r); + m.slot[b.ref - m.data].hashx = b.hashx; + *b.ref = *d; // move } c_swap(_cx_Self, self, &m); } diff --git a/include/stc/csmap.h b/include/stc/csmap.h index f4d33a4d..d2e1d1fc 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -170,19 +170,29 @@ _cx_MEMB(_shrink_to_fit)(_cx_Self *self) { } #endif // !i_no_clone -#ifndef _i_isset +STC_API _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey); + +#ifdef _i_ismap STC_API _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key key, i_val mapped); #if !defined i_no_emplace STC_API _cx_result _cx_MEMB(_emplace_or_assign)(_cx_Self* self, _cx_keyraw rkey, i_valraw rmapped); - #endif + STC_INLINE _cx_result + _cx_MEMB(_emplace_key)(_cx_Self* self, _cx_keyraw rkey) { + _cx_result res = _cx_MEMB(_insert_entry_)(self, rkey); + if (res.inserted) + res.ref->first = i_keyfrom(rkey); + return res; + } + #endif STC_INLINE const _cx_mapped* _cx_MEMB(_at)(const _cx_Self* self, _cx_keyraw rkey) { _cx_iter it; return &_cx_MEMB(_find_it)(self, rkey, &it)->second; } + STC_INLINE _cx_mapped* _cx_MEMB(_at_mut)(_cx_Self* self, _cx_keyraw rkey) { _cx_iter it; return &_cx_MEMB(_find_it)(self, rkey, &it)->second; } -#endif // !_i_isset +#endif // _i_ismap STC_INLINE _cx_iter _cx_MEMB(_end)(const _cx_Self* self) { @@ -209,8 +219,6 @@ _cx_MEMB(_eq)(const _cx_Self* self, const _cx_Self* other) { return true; } -static _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey); - STC_INLINE _cx_result _cx_MEMB(_insert)(_cx_Self* self, i_key _key _i_MAP_ONLY(, i_val _mapped)) { _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); @@ -326,7 +334,7 @@ _cx_MEMB(_new_node_)(_cx_Self* self, int level) { return tn; } -#ifndef _i_isset +#ifdef _i_ismap STC_DEF _cx_result _cx_MEMB(_insert_or_assign)(_cx_Self* self, i_key _key, i_val _mapped) { _cx_result _res = _cx_MEMB(_insert_entry_)(self, i_keyto((&_key))); @@ -353,7 +361,7 @@ _cx_MEMB(_new_node_)(_cx_Self* self, int level) { return _res; } #endif // !i_no_emplace -#endif // !_i_isset +#endif // !_i_ismap STC_DEF _cx_value* _cx_MEMB(_find_it)(const _cx_Self* self, _cx_keyraw rkey, _cx_iter* out) { @@ -407,7 +415,7 @@ _cx_MEMB(_split_)(_cx_node *d, int32_t tn) { return tn; } -static int32_t +STC_DEF int32_t _cx_MEMB(_insert_entry_i_)(_cx_Self* self, int32_t tn, const _cx_keyraw* rkey, _cx_result* _res) { int32_t up[64], tx = tn; _cx_node* d = self->nodes; @@ -439,7 +447,7 @@ _cx_MEMB(_insert_entry_i_)(_cx_Self* self, int32_t tn, const _cx_keyraw* rkey, _ return up[0]; } -static _cx_result +STC_DEF _cx_result _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey) { _cx_result res = {NULL}; int32_t tn = _cx_MEMB(_insert_entry_i_)(self, self->root, &rkey, &res); @@ -448,7 +456,7 @@ _cx_MEMB(_insert_entry_)(_cx_Self* self, _cx_keyraw rkey) { return res; } -static int32_t +STC_DEF int32_t _cx_MEMB(_erase_r_)(_cx_Self *self, int32_t tn, const _cx_keyraw* rkey, int *erased) { _cx_node *d = self->nodes; if (tn == 0) @@ -533,7 +541,7 @@ _cx_MEMB(_erase_range)(_cx_Self* self, _cx_iter it1, _cx_iter it2) { } #if !defined i_no_clone -static int32_t +STC_DEF int32_t _cx_MEMB(_clone_r_)(_cx_Self* self, _cx_node* src, int32_t sn) { if (sn == 0) return 0; diff --git a/include/stc/forward.h b/include/stc/forward.h index 484a8b63..085205cf 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -120,6 +120,7 @@ typedef struct chash_slot chash_slot; typedef struct { \ SELF##_value *ref; \ bool inserted; \ + uint8_t hashx; \ } SELF##_result; \ \ typedef struct { \ diff --git a/misc/examples/smartpointers/arc_containers.c b/misc/examples/smartpointers/arc_containers.c index 2fb04c56..6209005d 100644 --- a/misc/examples/smartpointers/arc_containers.c +++ b/misc/examples/smartpointers/arc_containers.c @@ -2,7 +2,6 @@ // and demonstrate sharing and cloning of maps. #define i_implement #include -#include #define i_type Map #define i_key_str // strings #define i_val int diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c index d7ca9b64..ce267b14 100644 --- a/misc/tests/cspan_test.c +++ b/misc/tests/cspan_test.c @@ -1,6 +1,5 @@ #include #include -#include #include "ctest.h" using_cspan3(intspan, int); @@ -48,7 +47,8 @@ CTEST(cspan, slice) { #include CTEST(cspan, slice2) { - c_auto (cstack_int, stack) + cstack_int stack = {0}; + c_defer (cstack_int_drop(&stack)) { c_forrange (i, 10*20*30) cstack_int_push(&stack, i); -- cgit v1.2.3 From da14db1a3b3570d52f22c7ae4027d1a53b6ac862 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 1 Aug 2023 20:50:29 +0200 Subject: Added some checks that a proper i_cmp/(i_hash) is defined when i_keyraw conversion type is specified for maps. Advanced usage. --- include/stc/cmap.h | 2 ++ include/stc/cpque.h | 2 ++ include/stc/priv/template.h | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 2dd8cbe6..cd7430ba 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -69,6 +69,7 @@ struct chash_slot { uint8_t hashx; }; #define _i_SET_ONLY c_true #define _i_keyref(vp) (vp) #endif +#define _i_ishash #include "priv/template.h" #ifndef i_is_forward _cx_DEFTYPES(_c_chash_types, _cx_Self, i_key, i_val, _i_MAP_ONLY, _i_SET_ONLY); @@ -463,6 +464,7 @@ _cx_MEMB(_erase_entry)(_cx_Self* self, _cx_value* _val) { #undef i_max_load_factor #undef _i_isset #undef _i_ismap +#undef _i_ishash #undef _i_keyref #undef _i_MAP_ONLY #undef _i_SET_ONLY diff --git a/include/stc/cpque.h b/include/stc/cpque.h index ca51eeff..520514ef 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -29,6 +29,7 @@ #endif #define _i_prefix cpque_ +#define _i_ispque #include "priv/template.h" #ifndef i_is_forward _cx_DEFTYPES(_c_cpque_types, _cx_Self, i_key); @@ -160,3 +161,4 @@ _cx_MEMB(_push)(_cx_Self* self, _cx_value value) { #endif #define CPQUE_H_INCLUDED #include "priv/template2.h" +#undef _i_ispque \ No newline at end of file diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h index ccdce718..0f4ac893 100644 --- a/include/stc/priv/template.h +++ b/include/stc/priv/template.h @@ -171,6 +171,15 @@ #endif #endif +#ifndef i_no_cmp + #if defined i_cmp || defined i_less || defined i_cmp_native + #define _i_has_cmp + #endif + #if defined i_eq || defined i_cmp_native + #define _i_has_eq + #endif +#endif + #if !defined i_key #error "No i_key or i_val defined" #elif defined i_keyraw ^ defined i_keyto @@ -179,6 +188,10 @@ #error "Both i_keyclone/i_valclone and i_keydrop/i_valdrop must be defined, if any" #elif defined i_from || defined i_drop #error "i_from / i_drop not supported. Define i_keyfrom/i_valfrom and/or i_keydrop/i_valdrop instead" +#elif defined i_keyraw && defined _i_ishash && !(defined i_hash && (defined _i_has_cmp || defined i_eq)) + #error "For cmap/cset, both i_hash and i_eq (or i_less or i_cmp) must be defined when i_keyraw is defined." +#elif defined i_keyraw && (defined _i_ismap || defined _i_isset || defined _i_ispque) && !defined _i_has_cmp + #error "For csmap/csset/cpque, i_cmp or i_less must be defined when i_keyraw is defined." #endif #ifndef i_tag @@ -203,13 +216,6 @@ #endif #ifndef i_no_cmp - #if defined i_cmp || defined i_less || defined i_cmp_native - #define _i_has_cmp - #endif - #if defined i_eq || defined i_cmp_native - #define _i_has_eq - #endif - // i_eq, i_less, i_cmp #if !defined i_eq && (defined i_cmp || defined i_less) #define i_eq(x, y) !(i_cmp(x, y)) -- cgit v1.2.3 From c27c266b6c4ae0e5e535b18c3790ee97416412b9 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 8 Aug 2023 12:28:15 +0200 Subject: Reverted cco_cleanup => cco_final. (cco_cleanup deprecated). Updated generator.c example. Misc internal refactoring. --- docs/coroutine_api.md | 12 +++++------ include/stc/cmap.h | 16 +++++++-------- include/stc/coroutine.h | 5 +++-- include/stc/forward.h | 6 ++---- include/stc/priv/cqueue_hdr.h | 4 ++-- misc/examples/coroutines/coread.c | 2 +- misc/examples/coroutines/coroutines.c | 6 +++--- misc/examples/coroutines/cotasks1.c | 4 ++-- misc/examples/coroutines/cotasks2.c | 4 ++-- misc/examples/coroutines/dining_philosophers.c | 4 ++-- misc/examples/coroutines/filetask.c | 4 ++-- misc/examples/coroutines/generator.c | 28 ++++++++++++++++++-------- misc/examples/coroutines/triples.c | 2 +- 13 files changed, 54 insertions(+), 43 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/docs/coroutine_api.md b/docs/coroutine_api.md index b356dcf0..6bd558f2 100644 --- a/docs/coroutine_api.md +++ b/docs/coroutine_api.md @@ -16,7 +16,7 @@ NB! ***cco_yield\*()*** / ***cco_await\*()*** may not be called from within a `s | | Function / operator | Description | |:----------|:-------------------------------------|:----------------------------------------| |`cco_result` | `CCO_DONE`, `CCO_AWAIT`, `CCO_YIELD` | Default set of return values from coroutines | -| | `cco_cleanup:` | Label for cleanup position in coroutine | +| | `cco_final:` | Label for cleanup position in coroutine | | `bool` | `cco_done(co)` | Is coroutine done? | | | `cco_routine(co) {}` | The coroutine scope | | | `cco_yield();` | Yield/suspend execution (return CCO_YIELD)| @@ -101,13 +101,13 @@ int triples(struct triples* i) { (int64_t)i->c * i->c) { if (i->c > i->max_c) - cco_return; // "jump" to cco_cleanup if defined, else exit scope. + cco_return; // "jump" to cco_final if defined, else exit scope. cco_yield(); } } } } - cco_cleanup: + cco_final: puts("done"); } return 0; // CCO_DONE @@ -160,7 +160,7 @@ int gcd1_triples(struct gcd1_triples* i) else cco_yield(); } - cco_cleanup: + cco_final: cco_stop(&i->tri); // to cleanup state if still active triples(&i->tri); // do cleanup (or no-op if done) } @@ -248,7 +248,7 @@ int produce_items(struct produce_items* p, cco_runtime* rt) printf("produced %s\n", cstr_str(&p->str)); cco_yield(); } - cco_cleanup: + cco_final: cstr_drop(&p->str); puts("done produce"); } @@ -273,7 +273,7 @@ int consume_items(struct consume_items* c, cco_runtime* rt) print_time(); printf("consumed %s\n", cstr_str(&c->produce.str)); } - cco_cleanup: + cco_final: cco_stop(&c->produce); cco_resume_task(&c->produce, rt); puts("done consume"); diff --git a/include/stc/cmap.h b/include/stc/cmap.h index cd7430ba..e0134964 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -306,7 +306,7 @@ STC_INLINE void _cx_MEMB(_wipe_)(_cx_Self* self) { if (self->size == 0) return; _cx_value* d = self->data, *_end = d + self->bucket_count; - chash_slot* s = self->slot; + struct chash_slot* s = self->slot; for (; d != _end; ++d) if ((s++)->hashx) _cx_MEMB(_value_drop)(d); @@ -321,7 +321,7 @@ STC_DEF void _cx_MEMB(_drop)(_cx_Self* self) { STC_DEF void _cx_MEMB(_clear)(_cx_Self* self) { _cx_MEMB(_wipe_)(self); self->size = 0; - c_memset(self->slot, 0, c_sizeof(chash_slot)*self->bucket_count); + c_memset(self->slot, 0, c_sizeof(struct chash_slot)*self->bucket_count); } #ifdef _i_ismap @@ -359,7 +359,7 @@ _cx_MEMB(_bucket_)(const _cx_Self* self, const _cx_keyraw* rkeyptr) { intptr_t _cap = self->bucket_count; intptr_t _idx = fastrange_2(_hash, _cap); _cx_result b = {NULL, true, (uint8_t)(_hash | 0x80)}; - const chash_slot* s = self->slot; + const struct chash_slot* s = self->slot; while (s[_idx].hashx) { if (s[_idx].hashx == b.hashx) { const _cx_keyraw _raw = i_keyto(_i_keyref(self->data + _idx)); @@ -394,8 +394,8 @@ _cx_MEMB(_clone)(_cx_Self m) { if (m.data) { _cx_value *d = (_cx_value *)i_malloc(c_sizeof(_cx_value)*m.bucket_count), *_dst = d, *_end = m.data + m.bucket_count; - const intptr_t _mem = c_sizeof(chash_slot)*(m.bucket_count + 1); - chash_slot *s = (chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); + const intptr_t _mem = c_sizeof(struct chash_slot)*(m.bucket_count + 1); + struct chash_slot *s = (struct chash_slot *)c_memcpy(i_malloc(_mem), m.slot, _mem); if (!(d && s)) { i_free(d), i_free(s), d = 0, s = 0, m.bucket_count = 0; } else @@ -417,14 +417,14 @@ _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { _newbucks = cnextpow2(_newbucks); _cx_Self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), - (chash_slot *)i_calloc(_newbucks + 1, sizeof(chash_slot)), + (struct chash_slot *)i_calloc(_newbucks + 1, sizeof(struct chash_slot)), self->size, _newbucks }; bool ok = m.data && m.slot; if (ok) { // Rehash: m.slot[_newbucks].hashx = 0xff; const _cx_value* d = self->data; - const chash_slot* s = self->slot; + const struct chash_slot* s = self->slot; for (intptr_t i = 0; i < _oldbucks; ++i, ++d) if ((s++)->hashx) { _cx_keyraw r = i_keyto(_i_keyref(d)); _cx_result b = _cx_MEMB(_bucket_)(&m, &r); @@ -441,7 +441,7 @@ _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { STC_DEF void _cx_MEMB(_erase_entry)(_cx_Self* self, _cx_value* _val) { _cx_value* d = self->data; - chash_slot* s = self->slot; + struct chash_slot* s = self->slot; intptr_t i = _val - d, j = i, k; const intptr_t _cap = self->bucket_count; _cx_MEMB(_value_drop)(_val); diff --git a/include/stc/coroutine.h b/include/stc/coroutine.h index 0e592bae..cecd4002 100644 --- a/include/stc/coroutine.h +++ b/include/stc/coroutine.h @@ -38,7 +38,7 @@ int iterpair(struct iterpair* I) { for (I->y = 0; I->y < I->max_y; I->y++) cco_yield(); - cco_cleanup: // required if there is cleanup code + cco_final: // required if there is cleanup code puts("final"); } return 0; // CCO_DONE @@ -103,7 +103,8 @@ typedef enum { /* cco_blocking_call(): assumes coroutine returns a cco_result value (int) */ #define cco_blocking_call(corocall) while ((corocall) != CCO_DONE) -#define cco_cleanup \ +#define cco_cleanup cco_final // [deprecated] +#define cco_final \ *_state = CCO_STATE_CLEANUP; case CCO_STATE_CLEANUP #define cco_return \ diff --git a/include/stc/forward.h b/include/stc/forward.h index 085205cf..572a319f 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -107,8 +107,6 @@ typedef union { SELF##_node *last; \ } SELF -typedef struct chash_slot chash_slot; - #define _c_chash_types(SELF, KEY, VAL, MAP_ONLY, SET_ONLY) \ typedef KEY SELF##_key; \ typedef VAL SELF##_mapped; \ @@ -125,12 +123,12 @@ typedef struct chash_slot chash_slot; \ typedef struct { \ SELF##_value *ref, *_end; \ - chash_slot* sref; \ + struct chash_slot* sref; \ } SELF##_iter; \ \ typedef struct SELF { \ SELF##_value* data; \ - chash_slot* slot; \ + struct chash_slot* slot; \ intptr_t size, bucket_count; \ } SELF diff --git a/include/stc/priv/cqueue_hdr.h b/include/stc/priv/cqueue_hdr.h index 90539f36..1cad8684 100644 --- a/include/stc/priv/cqueue_hdr.h +++ b/include/stc/priv/cqueue_hdr.h @@ -96,8 +96,8 @@ STC_INLINE void _cx_MEMB(_copy)(_cx_Self* self, const _cx_Self* other) { STC_INLINE _cx_iter _cx_MEMB(_begin)(const _cx_Self* self) { return c_LITERAL(_cx_iter){ - _cx_MEMB(_empty)(self) ? NULL : self->data + self->start, - self->start, self + .ref=_cx_MEMB(_empty)(self) ? NULL : self->data + self->start, + .pos=self->start, ._s=self }; } diff --git a/misc/examples/coroutines/coread.c b/misc/examples/coroutines/coread.c index 359ca85d..6d3acdd7 100644 --- a/misc/examples/coroutines/coread.c +++ b/misc/examples/coroutines/coread.c @@ -21,7 +21,7 @@ int file_read(struct file_read* g) cco_await(!cstr_getline(&g->line, g->fp)); - cco_cleanup: + cco_final: printf("finish\n"); cstr_drop(&g->line); if (g->fp) fclose(g->fp); diff --git a/misc/examples/coroutines/coroutines.c b/misc/examples/coroutines/coroutines.c index faeb71f6..802a976a 100644 --- a/misc/examples/coroutines/coroutines.c +++ b/misc/examples/coroutines/coroutines.c @@ -34,7 +34,7 @@ int prime(struct prime* g) { cco_yield(); } } - cco_cleanup: + cco_final: printf("final prm\n"); } return 0; @@ -68,7 +68,7 @@ int fibonacci(struct fibonacci* g) { } cco_yield(); } - cco_cleanup: + cco_final: printf("final fib\n"); } return 0; @@ -92,7 +92,7 @@ int combined(struct combined* g) { cco_reset(&g->prm); cco_await_call(prime(&g->prm)); - cco_cleanup: + cco_final: puts("final combined"); } return 0; diff --git a/misc/examples/coroutines/cotasks1.c b/misc/examples/coroutines/cotasks1.c index 230bd62b..7df4eb34 100644 --- a/misc/examples/coroutines/cotasks1.c +++ b/misc/examples/coroutines/cotasks1.c @@ -52,7 +52,7 @@ int produce_items(struct produce_items* p) printf("produced %s\n", cstr_str(&p->str)); cco_yield(); } - cco_cleanup: + cco_final: cstr_drop(&p->str); puts("done produce"); } @@ -76,7 +76,7 @@ int consume_items(struct consume_items* c, struct produce_items* p) print_time(); printf("consumed %s\n", cstr_str(&p->str)); } - cco_cleanup: + cco_final: puts("done consume"); } return 0; diff --git a/misc/examples/coroutines/cotasks2.c b/misc/examples/coroutines/cotasks2.c index d77a28bc..f6257a7e 100644 --- a/misc/examples/coroutines/cotasks2.c +++ b/misc/examples/coroutines/cotasks2.c @@ -53,7 +53,7 @@ int produce_items(struct produce_items* p, cco_runtime* rt) cco_yield(); } - cco_cleanup: + cco_final: cstr_drop(&p->str); puts("done produce"); } @@ -80,7 +80,7 @@ int consume_items(struct consume_items* c, cco_runtime* rt) printf("consumed %s\n", cstr_str(&c->produce.str)); } - cco_cleanup: + cco_final: cco_stop(&c->produce); cco_resume_task(&c->produce, rt); puts("done consume"); diff --git a/misc/examples/coroutines/dining_philosophers.c b/misc/examples/coroutines/dining_philosophers.c index e917c303..d353b3b9 100644 --- a/misc/examples/coroutines/dining_philosophers.c +++ b/misc/examples/coroutines/dining_philosophers.c @@ -48,7 +48,7 @@ int philosopher(struct Philosopher* p) cco_sem_release(p->right_fork); } - cco_cleanup: + cco_final: printf("Philosopher %d finished\n", p->id); } return 0; @@ -76,7 +76,7 @@ int dining(struct Dining* d) cco_yield(); // suspend, return control back to main } - cco_cleanup: + cco_final: for (int i = 0; i < num_philosophers; ++i) { cco_stop(&d->ph[i]); philosopher(&d->ph[i]); diff --git a/misc/examples/coroutines/filetask.c b/misc/examples/coroutines/filetask.c index 0607442d..74388359 100644 --- a/misc/examples/coroutines/filetask.c +++ b/misc/examples/coroutines/filetask.c @@ -28,7 +28,7 @@ int file_read(struct file_read* co, cco_runtime* rt) cco_yield(); } - cco_cleanup: + cco_final: fclose(co->fp); cstr_drop(&co->line); puts("done file_read"); @@ -56,7 +56,7 @@ int count_line(struct count_line* co, cco_runtime* rt) cco_yield(); } - cco_cleanup: + cco_final: cstr_drop(&co->path); puts("done count_line"); } diff --git a/misc/examples/coroutines/generator.c b/misc/examples/coroutines/generator.c index 3f51ce9c..96498498 100644 --- a/misc/examples/coroutines/generator.c +++ b/misc/examples/coroutines/generator.c @@ -2,12 +2,15 @@ #include #include +#include typedef struct { - int size; + int max_triples; int a, b, c; } Triple; +// Create an iterable generator over Triple with count items. +// Requires coroutine Triple_next() and function Triple_begin() to be defined. cco_iter_struct(Triple, int count; ); @@ -20,16 +23,15 @@ int Triple_next(Triple_iter* it) { for (g->a = 1; g->a < g->c; ++g->a) { for (g->b = g->a; g->b < g->c; ++g->b) { if (g->a*g->a + g->b*g->b == g->c*g->c) { - if (it->count++ == g->size) + if (it->count++ == g->max_triples) cco_return; cco_yield(); } } } } - cco_cleanup: - it->ref = NULL; - puts("done"); + cco_final: + it->ref = NULL; // stop the iterator } return 0; } @@ -43,12 +45,22 @@ Triple_iter Triple_begin(Triple* g) { int main(void) { - puts("Pythagorean triples; stops at 100 triples or c >= 100:"); - Triple triple = {.size=100}; + puts("Pythagorean triples.\nGet max 200 triples with c < 50:"); + Triple triple = {.max_triples=200}; + c_foreach (i, Triple, triple) { - if (i.ref->c < 100) + if (i.ref->c < 50) printf("%u: (%d, %d, %d)\n", i.count, i.ref->a, i.ref->b, i.ref->c); else cco_stop(&i); } + + puts("\nGet the 10 first triples with odd a's and a <= 20:"); + c_forfilter (i, Triple, triple, + i.ref->a <= 20 && + (i.ref->a & 1) && + c_flt_take(i, 10) + ){ + printf("%d: (%d, %d, %d)\n", c_flt_getcount(i), i.ref->a, i.ref->b, i.ref->c); + } } diff --git a/misc/examples/coroutines/triples.c b/misc/examples/coroutines/triples.c index 22914c2b..d6ce2791 100644 --- a/misc/examples/coroutines/triples.c +++ b/misc/examples/coroutines/triples.c @@ -40,7 +40,7 @@ int triples_coro(struct triples* t) { } } } - cco_cleanup: + cco_final: puts("done"); } return 0; -- cgit v1.2.3 From 5be09e526bc4ee4d1f586aa906e1f9a9c8e3e165 Mon Sep 17 00:00:00 2001 From: tylov Date: Tue, 15 Aug 2023 10:34:05 +0200 Subject: Fixed c_i2u() didn't trigger -Wsign-conversion warning. --- include/stc/ccommon.h | 6 +++--- include/stc/clist.h | 6 +++--- include/stc/cmap.h | 2 +- include/stc/cstr.h | 2 +- src/cregex.c | 14 +++++++------- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 42631f85..e33e657a 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -88,16 +88,16 @@ typedef long long _llong; #define c_const_cast(T, p) ((T)(1 ? (p) : (T)0)) #define c_swap(T, xp, yp) do { T *_xp = xp, *_yp = yp, \ _tv = *_xp; *_xp = *_yp; *_yp = _tv; } while (0) +// use with gcc -Wsign-conversion #define c_sizeof (intptr_t)sizeof #define c_strlen(s) (intptr_t)strlen(s) - #define c_strncmp(a, b, ilen) strncmp(a, b, c_i2u(ilen)) #define c_memcpy(d, s, ilen) memcpy(d, s, c_i2u(ilen)) #define c_memmove(d, s, ilen) memmove(d, s, c_i2u(ilen)) #define c_memset(d, val, ilen) memset(d, val, c_i2u(ilen)) #define c_memcmp(a, b, ilen) memcmp(a, b, c_i2u(ilen)) -#define c_u2i(u) ((intptr_t)(1 ? (u) : (size_t)1)) -#define c_i2u(i) ((size_t)(1 ? (i) : (intptr_t)1)) +#define c_u2i(u) (intptr_t)(1 ? (u) : (size_t)1) +#define c_i2u(i) (size_t)(1 ? (i) : -1) #define c_LTu(a, b) ((size_t)(a) < (size_t)(b)) // x and y are i_keyraw* type, defaults to i_key*: diff --git a/include/stc/clist.h b/include/stc/clist.h index d7cf30b9..6a205c2b 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -385,17 +385,17 @@ STC_DEF int _cx_MEMB(_sort_cmp_)(const _cx_value* x, const _cx_value* y) { } STC_DEF bool _cx_MEMB(_sort_with)(_cx_Self* self, int(*cmp)(const _cx_value*, const _cx_value*)) { - size_t len = 0, cap = 0; + intptr_t len = 0, cap = 0; _cx_value *a = NULL, *p = NULL; _cx_iter i; for (i = _cx_MEMB(_begin)(self); i.ref; _cx_MEMB(_next)(&i)) { if (len == cap) { - if ((p = (_cx_value *)i_realloc(a, (cap += cap/2 + 4)*sizeof *a))) a = p; + if ((p = (_cx_value *)i_realloc(a, (cap += cap/2 + 4)*c_sizeof *a))) a = p; else { i_free(a); return false; } } a[len++] = *i.ref; } - qsort(a, len, sizeof *a, (int(*)(const void*, const void*))cmp); + qsort(a, (size_t)len, sizeof *a, (int(*)(const void*, const void*))cmp); for (i = _cx_MEMB(_begin)(self); i.ref; _cx_MEMB(_next)(&i), ++p) *i.ref = *p; i_free(a); return true; diff --git a/include/stc/cmap.h b/include/stc/cmap.h index e0134964..deee1f59 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -417,7 +417,7 @@ _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { _newbucks = cnextpow2(_newbucks); _cx_Self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), - (struct chash_slot *)i_calloc(_newbucks + 1, sizeof(struct chash_slot)), + (struct chash_slot *)i_calloc(_newbucks + 1, c_sizeof(struct chash_slot)), self->size, _newbucks }; bool ok = m.data && m.slot; diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 3822020f..bc147469 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -509,7 +509,7 @@ STC_DEF char* cstr_reserve(cstr* self, const intptr_t cap) { char* data = (char *)c_malloc(cap + 1); const intptr_t len = cstr_s_size(self); /* copy full short buffer to emulate realloc() */ - c_memcpy(data, self->sml.data, sizeof self->sml); + c_memcpy(data, self->sml.data, c_sizeof self->sml); self->lon.data = data; self->lon.size = (size_t)len; cstr_l_set_cap(self, cap); diff --git a/src/cregex.c b/src/cregex.c index e6da66b2..551cb6f6 100644 --- a/src/cregex.c +++ b/src/cregex.c @@ -362,7 +362,7 @@ typedef struct _Parser bool lastwasand; /* Last token was _operand */ short nbra; short nclass; - size_t instcap; + intptr_t instcap; _Rune yyrune; /* last lex'd rune */ _Reclass *yyclassp; /* last lex'd class */ _Reclass* classp; @@ -562,11 +562,11 @@ _optimize(_Parser *par, _Reprog *pp) * necessary. Reallocate to the actual space used * and then relocate the code. */ - if ((par->freep - pp->firstinst)*2 > (ptrdiff_t)par->instcap) + if ((par->freep - pp->firstinst)*2 > par->instcap) return pp; - intptr_t ipp = (intptr_t)pp; - size_t size = sizeof(_Reprog) + (size_t)(par->freep - pp->firstinst)*sizeof(_Reinst); + intptr_t ipp = (intptr_t)pp; // convert pointer to intptr_t! + intptr_t size = c_sizeof(_Reprog) + (par->freep - pp->firstinst)*c_sizeof(_Reinst); _Reprog *npp = (_Reprog *)c_realloc(pp, size); ptrdiff_t diff = (intptr_t)npp - ipp; @@ -862,9 +862,9 @@ _regcomp1(_Reprog *pp, _Parser *par, const char *s, int cflags) _Token token; /* get memory for the program. estimated max usage */ - par->instcap = 5U + 6*strlen(s); + par->instcap = 5 + 6*c_strlen(s); _Reprog* old_pp = pp; - pp = (_Reprog *)c_realloc(pp, sizeof(_Reprog) + par->instcap*sizeof(_Reinst)); + pp = (_Reprog *)c_realloc(pp, c_sizeof(_Reprog) + par->instcap*c_sizeof(_Reinst)); if (! pp) { c_free(old_pp); par->error = CREG_OUTOFMEMORY; @@ -1152,7 +1152,7 @@ _regexec2(const _Reprog *progp, /* program to run */ _Relist *relists; /* mark space */ - relists = (_Relist *)c_malloc(2 * _BIGLISTSIZE*sizeof(_Relist)); + relists = (_Relist *)c_malloc(2 * _BIGLISTSIZE*c_sizeof(_Relist)); if (relists == NULL) return -1; -- cgit v1.2.3 From 493c34e9c2de0587f38681340db8f2735e72d7dd Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 5 Sep 2023 18:10:14 +0200 Subject: Renamed (half)internal functions: cfasthash() => stc_hash() cstrhash() => stc_strhash() cnextpow2() => stc_nextpow2() --- docs/cmap_api.md | 15 ++++++++------- docs/cstr_api.md | 5 +++-- include/stc/ccommon.h | 16 ++++++++-------- include/stc/cmap.h | 2 +- include/stc/crawstr.h | 4 ++-- include/stc/cstr.h | 6 +++--- include/stc/csview.h | 6 +++--- include/stc/priv/cqueue_imp.h | 2 +- misc/examples/hashmaps/vikings.c | 2 +- 9 files changed, 30 insertions(+), 28 deletions(-) (limited to 'include/stc/cmap.h') diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 0fbd9b7a..8e29efe1 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -72,7 +72,7 @@ cmap_X_result cmap_X_push(cmap_X* self, cmap_X_value entry); cmap_X_result cmap_X_emplace(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map cmap_X_result cmap_X_emplace_or_assign(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update mapped -cmap_X_result cmap_X_emplace_key(cmap_X* self, i_keyraw rkey); // see example 1. +cmap_X_result cmap_X_emplace_key(cmap_X* self, i_keyraw rkey); // see example 1. int cmap_X_erase(cmap_X* self, i_keyraw rkey); // return 0 or 1 cmap_X_iter cmap_X_erase_at(cmap_X* self, cmap_X_iter it); // return iter after it @@ -86,13 +86,14 @@ cmap_X_iter cmap_X_advance(cmap_X_iter it, cmap_X_ssize n); cmap_X_value cmap_X_value_clone(cmap_X_value val); cmap_X_raw cmap_X_value_toraw(cmap_X_value* pval); ``` -Helpers: +Free helper functions: ```c -uint64_t cbytehash(const void *data, intptr_t len); // base hash function -uint64_t cstrhash(const char *str); // string hash funcion, uses strlen() -uint64_t c_default_hash(const X *obj); // macro, calls cbytehash(obj, sizeof *obj) +uint64_t stc_hash(const void *data, intptr_t len); // base hash function +uint64_t stc_strhash(const char *str); // string hash funcion, uses strlen() +uint64_t stc_nextpow2(intptr_t i); // get next power of 2 >= i -// equalto template parameter functions: +// hash/equal template default functions: +uint64_t c_default_hash(const X *obj); // macro, calls stc_hash(obj, sizeof *obj) bool c_default_eq(const i_keyraw* a, const i_keyraw* b); // *a == *b bool c_memcmp_eq(const i_keyraw* a, const i_keyraw* b); // !memcmp(a, b, sizeof *a) ``` @@ -381,7 +382,7 @@ static inline RViking Viking_toraw(const Viking* vp) { #define i_keyraw RViking #define i_keyfrom Viking_from #define i_opt c_no_clone // disable map cloning -#define i_hash(rp) (cstrhash(rp->name) ^ cstrhash(rp->country)) +#define i_hash(rp) (stc_strhash(rp->name) ^ stc_strhash(rp->country)) #define i_val int #include diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 397634ec..69512a9e 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -142,8 +142,9 @@ Note that all methods with arguments `(..., const char* str, intptr_t n)`, `n` m ```c int cstr_cmp(const cstr* s1, const cstr* s2); bool cstr_eq(const cstr* s1, const cstr* s2); -bool cstr_hash(const cstr* self); -char* cstrnstrn(const char* str, const char* search, intptr_t slen, intptr_t nlen); +uint64_t cstr_hash(const cstr* self); + +char* stc_strnstrn(const char* str, const char* search, intptr_t slen, intptr_t nlen); ``` ## Types diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 8363fbe5..d074701f 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -103,7 +103,7 @@ typedef long long _llong; #define c_default_less(x, y) (*(x) < *(y)) #define c_default_eq(x, y) (*(x) == *(y)) #define c_memcmp_eq(x, y) (memcmp(x, y, sizeof *(x)) == 0) -#define c_default_hash(x) cbytehash(x, c_sizeof(*(x))) +#define c_default_hash(x) stc_hash(x, c_sizeof(*(x))) #define c_default_clone(v) (v) #define c_default_toraw(vp) (*(vp)) @@ -124,7 +124,7 @@ typedef long long _llong; // Non-owning c-string "class" typedef const char* ccharptr; #define ccharptr_cmp(xp, yp) strcmp(*(xp), *(yp)) -#define ccharptr_hash(p) cstrhash(*(p)) +#define ccharptr_hash(p) stc_strhash(*(p)) #define ccharptr_clone(s) (s) #define ccharptr_drop(p) ((void)p) @@ -138,7 +138,7 @@ typedef const char* ccharptr; #define c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) -STC_INLINE uint64_t cbytehash(const void* key, intptr_t len) { +STC_INLINE uint64_t stc_hash(const void* key, intptr_t len) { uint32_t u4; uint64_t u8; switch (len) { case 8: memcpy(&u8, key, 8); return u8*0xc6a4a7935bd1e99d; @@ -156,11 +156,11 @@ STC_INLINE uint64_t cbytehash(const void* key, intptr_t len) { return h ^ c_ROTL(h, 26); } -STC_INLINE uint64_t cstrhash(const char *str) - { return cbytehash(str, c_strlen(str)); } +STC_INLINE uint64_t stc_strhash(const char *str) + { return stc_hash(str, c_strlen(str)); } -STC_INLINE char* cstrnstrn(const char *str, const char *needle, - intptr_t slen, const intptr_t nlen) { +STC_INLINE char* stc_strnstrn(const char *str, const char *needle, + intptr_t slen, const intptr_t nlen) { if (!nlen) return (char *)str; if (nlen > slen) return NULL; slen -= nlen; @@ -172,7 +172,7 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle, return NULL; } -STC_INLINE intptr_t cnextpow2(intptr_t n) { +STC_INLINE intptr_t stc_nextpow2(intptr_t n) { n--; n |= n >> 1, n |= n >> 2; n |= n >> 4, n |= n >> 8; diff --git a/include/stc/cmap.h b/include/stc/cmap.h index deee1f59..c069fbd8 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -414,7 +414,7 @@ _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t _newcap) { if (_newcap != self->size && _newcap <= _oldbucks) return true; intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) + 4; - _newbucks = cnextpow2(_newbucks); + _newbucks = stc_nextpow2(_newbucks); _cx_Self m = { (_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)), (struct chash_slot *)i_calloc(_newbucks + 1, c_sizeof(struct chash_slot)), diff --git a/include/stc/crawstr.h b/include/stc/crawstr.h index a244397d..9dbdb6f7 100644 --- a/include/stc/crawstr.h +++ b/include/stc/crawstr.h @@ -45,7 +45,7 @@ STC_INLINE bool crawstr_equals(crawstr rs, const char* str) { } STC_INLINE intptr_t crawstr_find(crawstr rs, const char* search) { - char* res = cstrnstrn(rs.str, search, rs.size, c_strlen(search)); + char* res = strstr(rs.str, search); return res ? (res - rs.str) : c_NPOS; } @@ -98,7 +98,7 @@ STC_INLINE bool crawstr_eq(const crawstr* x, const crawstr* y) { return x->size == y->size && !c_memcmp(x->str, y->str, x->size); } STC_INLINE uint64_t crawstr_hash(const crawstr *self) - { return cbytehash(self->str, self->size); } + { return stc_hash(self->str, self->size); } #endif // CRAWSTR_H_INCLUDED #undef i_static diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 51519d82..d2faeb62 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -450,12 +450,12 @@ bool cstr_valid_utf8(const cstr* self) STC_DEF uint64_t cstr_hash(const cstr *self) { csview sv = cstr_sv(self); - return cbytehash(sv.buf, sv.size); + return stc_hash(sv.buf, sv.size); } STC_DEF intptr_t cstr_find_sv(const cstr* self, csview search) { csview sv = cstr_sv(self); - char* res = cstrnstrn(sv.buf, search.buf, sv.size, search.size); + char* res = stc_strnstrn(sv.buf, search.buf, sv.size, search.size); return res ? (res - sv.buf) : c_NPOS; } @@ -588,7 +588,7 @@ STC_DEF cstr cstr_replace_sv(csview in, csview search, csview repl, int32_t coun intptr_t from = 0; char* res; if (!count) count = INT32_MAX; if (search.size) - while (count-- && (res = cstrnstrn(in.buf + from, search.buf, in.size - from, search.size))) { + while (count-- && (res = stc_strnstrn(in.buf + from, search.buf, in.size - from, search.size))) { const intptr_t pos = (res - in.buf); cstr_append_n(&out, in.buf + from, pos - from); cstr_append_n(&out, repl.buf, repl.size); diff --git a/include/stc/csview.h b/include/stc/csview.h index 005f27de..f41acf4f 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -165,12 +165,12 @@ STC_DEF csview_iter csview_advance(csview_iter it, intptr_t pos) { } STC_DEF intptr_t csview_find_sv(csview sv, csview search) { - char* res = cstrnstrn(sv.buf, search.buf, sv.size, search.size); + char* res = stc_strnstrn(sv.buf, search.buf, sv.size, search.size); return res ? (res - sv.buf) : c_NPOS; } STC_DEF uint64_t csview_hash(const csview *self) - { return cbytehash(self->buf, self->size); } + { return stc_hash(self->buf, self->size); } STC_DEF csview csview_substr_ex(csview sv, intptr_t pos, intptr_t n) { if (pos < 0) { @@ -197,7 +197,7 @@ STC_DEF csview csview_slice_ex(csview sv, intptr_t p1, intptr_t p2) { STC_DEF csview csview_token(csview sv, const char* sep, intptr_t* start) { intptr_t sep_size = c_strlen(sep); csview slice = {sv.buf + *start, sv.size - *start}; - const char* res = cstrnstrn(slice.buf, sep, slice.size, sep_size); + const char* res = stc_strnstrn(slice.buf, sep, slice.size, sep_size); csview tok = {slice.buf, res ? (res - slice.buf) : slice.size}; *start += tok.size + sep_size; return tok; diff --git a/include/stc/priv/cqueue_imp.h b/include/stc/priv/cqueue_imp.h index 2ad9c811..18c1bb15 100644 --- a/include/stc/priv/cqueue_imp.h +++ b/include/stc/priv/cqueue_imp.h @@ -54,7 +54,7 @@ STC_DEF bool _cx_MEMB(_reserve)(_cx_Self* self, const intptr_t n) { if (n <= self->capmask) return true; - intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1); + intptr_t oldcap = self->capmask + 1, newcap = stc_nextpow2(n + 1); _cx_value* d = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data); if (!d) return false; diff --git a/misc/examples/hashmaps/vikings.c b/misc/examples/hashmaps/vikings.c index d6125854..cef17a04 100644 --- a/misc/examples/hashmaps/vikings.c +++ b/misc/examples/hashmaps/vikings.c @@ -37,7 +37,7 @@ static inline RViking Viking_toraw(const Viking* vp) { #define i_rawclass RViking // lookup type #define i_keyfrom Viking_from #define i_opt c_no_clone -#define i_hash(rp) cstrhash(rp->name) ^ cstrhash(rp->country) +#define i_hash(rp) stc_strhash(rp->name) ^ stc_strhash(rp->country) #define i_val int // mapped type #include -- cgit v1.2.3