From 8970472ccac02ffdbab3b2c5caf677da4ffb2cc2 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 4 May 2021 13:37:30 +0200 Subject: Added get() method to cvec, cdeq, clist, cmap, csmap. Restructured emplace/insert api on cvec, will be done on cdeq as well. General internal coding improvements. --- docs/cdeq_api.md | 2 + docs/cvec_api.md | 15 +++--- stc/ccommon.h | 9 +++- stc/cdeq.h | 12 ++++- stc/clist.h | 5 ++ stc/cmap.h | 128 ++++++++++++++++++++++---------------------- stc/cvec.h | 159 +++++++++++++++++++++++++++++-------------------------- 7 files changed, 182 insertions(+), 148 deletions(-) diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index cea4f571..bd394f5c 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -72,6 +72,8 @@ cdeq_X_iter_t cdeq_X_erase_n(cdeq_X* self, size_t idx, size_t n); cdeq_X_iter_t cdeq_X_find(const cdeq_X* self, RawValue raw); cdeq_X_iter_t cdeq_X_find_in(cdeq_X_iter_t i1, cdeq_X_iter_t i2, RawValue raw); +cdeq_X_value_t* cdeq_X_get(const cdeq_X* self, RawValue raw); // returns NULL if not found + void cdeq_X_sort(cdeq_X* self); void cdeq_X_sort_range(cdeq_X_iter_t i1, cdeq_X_iter_t i2, int(*cmp)(const cdeq_X_value_t*, const cdeq_X_value_t*)); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 0171f3e7..60808cf1 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -57,13 +57,14 @@ void cvec_X_push_back(cvec_X* self, Value value); void cvec_X_emplace_back(cvec_X* self, RawValue raw); void cvec_X_pop_back(cvec_X* self); -cvec_X_iter_t cvec_X_insert(cvec_X* self, cvec_X_iter_t it, Value value); // expects new/cloned value -cvec_X_iter_t cvec_X_insert_range(cvec_X* self, cvec_X_iter_t it, - cvec_X_iter_t i1, cvec_X_iter_t i2); // clones input values -cvec_X_iter_t cvec_X_insert_at(cvec_X* self, size_t idx, const Value[] arr, size_t n); // clones input values +cvec_X_iter_t cvec_X_insert(cvec_X* self, cvec_X_iter_t it, Value value); // move value +cvec_X_iter_t cvec_X_insert_at(cvec_X* self, size_t idx, const Value[] arr, size_t n); // move arr values cvec_X_iter_t cvec_X_emplace(cvec_X* self, cvec_X_iter_t it, RawValue raw); -void cvec_X_emplace_n(cvec_X *self, const RawValue arr[], size_t n); // emplace_back only +cvec_X_iter_t cvec_X_emplace_range(cvec_X* self, cvec_X_iter_t it, + cvec_X_iter_t i1, cvec_X_iter_t i2); // note: does clone +cvec_X_iter_t cvec_X_emplace_at(cvec_X* self, size_t idx, const RawValue[] arr, size_t n); +void cvec_X_emplace_n(cvec_X *self, const RawValue arr[], size_t n); // emplace_at back cvec_X_iter_t cvec_X_erase_at(cvec_X* self, cvec_X_iter_t it); cvec_X_iter_t cvec_X_erase_range(cvec_X* self, cvec_X_iter_t i1, cvec_X_iter_t i2); @@ -71,6 +72,7 @@ cvec_X_iter_t cvec_X_erase_n(cvec_X* self, size_t idx, size_t n); cvec_X_iter_t cvec_X_find(const cvec_X* self, RawValue raw); cvec_X_iter_t cvec_X_find_in(cvec_X_iter_t i1, cvec_X_iter_t i2, RawValue raw); +cvec_X_value_t* cvec_X_get(const cvec_X* self, RawValue raw); // return NULL if not found cvec_X_iter_t cvec_X_bsearch(const cvec_X* self, RawValue raw); cvec_X_iter_t cvec_X_bsearch_in(cvec_X_iter_t i1, cvec_X_iter_t i2, RawValue raw); @@ -81,7 +83,8 @@ void cvec_X_sort_range(cvec_X_iter_t i1, cvec_X_iter_t i2, cvec_X_iter_t cvec_X_begin(const cvec_X* self); cvec_X_iter_t cvec_X_end(const cvec_X* self); void cvec_X_next(cvec_X_iter_t* iter); -size_t cvec_X_index(const cvec_X vec, cvec_X_iter_t it); +cvec_X_iter_t cvec_X_it(cvec_X* self, size_t pos); +cvec_X_iter_t cvec_X_adv(cvec_X_iter_t it, ptrdiff_t d); cvec_X_value_t cvec_X_value_clone(cvec_X_value_t val); ``` diff --git a/stc/ccommon.h b/stc/ccommon.h index f0265703..c44b9384 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -66,8 +66,13 @@ ((type *)((char *)(ptr) - offsetof(type, member))) #define c_struct(S) typedef struct S S; struct S -#define c_new(T) ((T *) c_malloc(sizeof(T))) -#define c_new_n(T, n) ((T *) c_malloc(sizeof(T)*(n))) +#if __cplusplus +#define c_new(T) static_cast(c_malloc(sizeof(T)) +#define c_new_n(T, n) static_cast(c_malloc(sizeof(T[n])) +#else +#define c_new(T) c_malloc(sizeof(T)) +#define c_new_n(T, n) c_malloc(sizeof(T[n])) +#endif #ifndef c_malloc #define c_malloc(sz) malloc(sz) #define c_calloc(n, sz) calloc(n, sz) diff --git a/stc/cdeq.h b/stc/cdeq.h index f4ed7159..b99d87d8 100644 --- a/stc/cdeq.h +++ b/stc/cdeq.h @@ -163,11 +163,18 @@ struct cdeq_rep { size_t size, cap; void* base[]; }; CX##_find(const CX* self, RawValue raw) { \ return CX##_find_in(CX##_begin(self), CX##_end(self), raw); \ } \ +\ + STC_INLINE CX##_value_t* \ + CX##_get(const CX* self, RawValue raw) { \ + CX##_iter_t end = CX##_end(self); \ + CX##_value_t* val = CX##_find_in(CX##_begin(self), end, raw).ref; \ + return val == end.ref ? NULL : val; \ + } \ \ STC_INLINE void \ CX##_sort_range(CX##_iter_t i1, CX##_iter_t i2, \ - int(*cmp)(const CX##_value_t*, const CX##_value_t*)) { \ - qsort(i1.ref, i2.ref - i1.ref, sizeof *i1.ref, (int(*)(const void*, const void*)) cmp); \ + int(*_cmp_)(const CX##_value_t*, const CX##_value_t*)) { \ + qsort(i1.ref, i2.ref - i1.ref, sizeof *i1.ref, (int(*)(const void*, const void*)) _cmp_); \ } \ \ STC_INLINE void \ @@ -287,6 +294,7 @@ static struct cdeq_rep _cdeq_inits = {0, 0}; CX##_iter_t it = {pos}; \ if (n) cdeq_rep_(self)->size += n; \ if (clone) while (p1 != p2) *pos++ = valueFromRaw(valueToRaw(p1++)); \ + else memcpy(pos, p1, n*sizeof *p1); \ return it; \ } \ \ diff --git a/stc/clist.h b/stc/clist.h index d44636a8..7474d870 100644 --- a/stc/clist.h +++ b/stc/clist.h @@ -174,6 +174,11 @@ STC_API size_t _clist_count(const clist_VOID* self); CX##_find(const CX* self, RawValue val) { \ return CX##_find_in(CX##_begin(self), CX##_end(self), val); \ } \ +\ + STC_INLINE CX##_value_t* \ + CX##_get(const CX* self, RawValue val) { \ + return CX##_find_in(CX##_begin(self), CX##_end(self), val).ref; \ + } \ \ _c_implement_clist(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ struct stc_trailing_semicolon diff --git a/stc/cmap.h b/stc/cmap.h index daefb9e9..cca673ce 100644 --- a/stc/cmap.h +++ b/stc/cmap.h @@ -205,25 +205,25 @@ STC_INLINE uint64_t c_default_hash64(const void* data, size_t ignored) {return CX##_find(self, rkey).ref;} \ \ STC_INLINE void \ - CX##_value_clone(CX##_value_t* dst, CX##_value_t* val) { \ - *(CX##_key_t*) KEY_REF_##C(dst) = keyFromRaw(keyToRaw(KEY_REF_##C(val))); \ - MAP_ONLY_##C( dst->second = mappedFromRaw(mappedToRaw(&val->second)); ) \ + CX##_value_clone(CX##_value_t* _dst, CX##_value_t* _val) { \ + *(CX##_key_t*) KEY_REF_##C(_dst) = keyFromRaw(keyToRaw(KEY_REF_##C(_val))); \ + MAP_ONLY_##C( _dst->second = mappedFromRaw(mappedToRaw(&_val->second)); ) \ } \ \ STC_INLINE void \ - CX##_value_del(CX##_value_t* val) { \ - keyDel((CX##_key_t*) KEY_REF_##C(val)); \ - MAP_ONLY_##C( mappedDel(&val->second); ) \ + CX##_value_del(CX##_value_t* _val) { \ + keyDel((CX##_key_t*) KEY_REF_##C(_val)); \ + MAP_ONLY_##C( mappedDel(&_val->second); ) \ } \ \ STC_INLINE CX##_result_t \ CX##_emplace(CX* self, RawKey rkey MAP_ONLY_##C(, RawMapped rmapped)) { \ - CX##_result_t res = CX##_insert_entry_(self, rkey); \ - if (res.inserted) { \ - *(CX##_key_t*) KEY_REF_##C(res.ref) = keyFromRaw(rkey); \ - MAP_ONLY_##C(res.ref->second = mappedFromRaw(rmapped);) \ + CX##_result_t _res = CX##_insert_entry_(self, rkey); \ + if (_res.inserted) { \ + *(CX##_key_t*) KEY_REF_##C(_res.ref) = keyFromRaw(rkey); \ + MAP_ONLY_##C(_res.ref->second = mappedFromRaw(rmapped);) \ } \ - return res; \ + return _res; \ } \ \ STC_INLINE void \ @@ -233,20 +233,20 @@ STC_INLINE uint64_t c_default_hash64(const void* data, size_t ignored) } \ \ STC_INLINE CX##_result_t \ - CX##_insert(CX* self, Key key MAP_ONLY_##C(, Mapped mapped)) { \ - CX##_result_t res = CX##_insert_entry_(self, keyToRaw(&key)); \ - if (res.inserted) {*(CX##_key_t*) KEY_REF_##C(res.ref) = key; MAP_ONLY_##C( res.ref->second = mapped; )} \ - else {keyDel(&key); MAP_ONLY_##C( mappedDel(&mapped); )} \ - return res; \ + CX##_insert(CX* self, Key _key MAP_ONLY_##C(, Mapped _mapped)) { \ + CX##_result_t _res = CX##_insert_entry_(self, keyToRaw(&_key)); \ + if (_res.inserted) {*(CX##_key_t*) KEY_REF_##C(_res.ref) = _key; MAP_ONLY_##C( _res.ref->second = _mapped; )} \ + else {keyDel(&_key); MAP_ONLY_##C( mappedDel(&_mapped); )} \ + return _res; \ } \ \ MAP_ONLY_##C( \ STC_INLINE CX##_result_t \ - CX##_insert_or_assign(CX* self, Key key, Mapped mapped) { \ - CX##_result_t res = CX##_insert_entry_(self, keyToRaw(&key)); \ - if (res.inserted) *(CX##_key_t*) &res.ref->first = key; \ - else {keyDel(&key); mappedDel(&res.ref->second);} \ - res.ref->second = mapped; return res; \ + CX##_insert_or_assign(CX* self, Key _key, Mapped _mapped) { \ + CX##_result_t _res = CX##_insert_entry_(self, keyToRaw(&_key)); \ + if (_res.inserted) *(CX##_key_t*) &_res.ref->first = _key; \ + else {keyDel(&_key); mappedDel(&_res.ref->second);} \ + _res.ref->second = _mapped; return _res; \ } \ \ STC_INLINE CX##_result_t \ @@ -256,10 +256,10 @@ STC_INLINE uint64_t c_default_hash64(const void* data, size_t ignored) \ STC_INLINE CX##_result_t \ CX##_emplace_or_assign(CX* self, RawKey rkey, RawMapped rmapped) { \ - CX##_result_t res = CX##_insert_entry_(self, rkey); \ - if (res.inserted) *(CX##_key_t*) &res.ref->first = keyFromRaw(rkey); \ - else mappedDel(&res.ref->second); \ - res.ref->second = mappedFromRaw(rmapped); return res; \ + CX##_result_t _res = CX##_insert_entry_(self, rkey); \ + if (_res.inserted) *(CX##_key_t*) &_res.ref->first = keyFromRaw(rkey); \ + else mappedDel(&_res.ref->second); \ + _res.ref->second = mappedFromRaw(rmapped); return _res; \ } \ \ STC_INLINE CX##_mapped_t* \ @@ -347,16 +347,16 @@ STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n) \ \ STC_DEF chash_bucket_t \ CX##_bucket_(const CX* self, const CX##_rawkey_t* rkeyptr) { \ - const uint64_t hash = keyHashRaw(rkeyptr, sizeof *rkeyptr); \ - uint_fast8_t sx; size_t cap = self->bucket_count; \ - chash_bucket_t b = {_c_SELECT(fastrange,CMAP_SIZE_T)(hash, cap), (uint_fast8_t)(hash | 0x80)}; \ - const uint8_t* hashx = self->_hashx; \ - while ((sx = hashx[b.idx])) { \ - if (sx == b.hx) { \ - CX##_rawkey_t raw = keyToRaw(KEY_REF_##C(self->table + b.idx)); \ - if (keyEqualsRaw(&raw, rkeyptr)) break; \ + const uint64_t _hash = keyHashRaw(rkeyptr, sizeof *rkeyptr); \ + uint_fast8_t _hx; size_t _cap = self->bucket_count; \ + chash_bucket_t b = {_c_SELECT(fastrange,CMAP_SIZE_T)(_hash, _cap), (uint_fast8_t)(_hash | 0x80)}; \ + const uint8_t* _hashx = self->_hashx; \ + while ((_hx = _hashx[b.idx])) { \ + if (_hx == b.hx) { \ + CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(self->table + b.idx)); \ + if (keyEqualsRaw(&_raw, rkeyptr)) break; \ } \ - if (++b.idx == cap) b.idx = 0; \ + if (++b.idx == _cap) b.idx = 0; \ } \ return b; \ } \ @@ -398,47 +398,47 @@ STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n) \ } \ \ STC_DEF void \ - CX##_reserve(CX* self, size_t newcap) { \ - if (newcap < self->size) return; \ - size_t oldcap = self->bucket_count; \ - newcap = (size_t) (2 + newcap / self->max_load_factor) | 1; \ - CX tmp = { \ - c_new_n(CX##_value_t, newcap), \ - (uint8_t *) c_calloc(newcap + 1, sizeof(uint8_t)), \ - self->size, (CX##_size_t) newcap, \ + CX##_reserve(CX* self, size_t _newcap) { \ + if (_newcap < self->size) return; \ + size_t _oldcap = self->bucket_count; \ + _newcap = (size_t) (2 + _newcap / self->max_load_factor) | 1; \ + CX _tmp = { \ + c_new_n(CX##_value_t, _newcap), \ + (uint8_t *) c_calloc(_newcap + 1, sizeof(uint8_t)), \ + self->size, (CX##_size_t) _newcap, \ self->max_load_factor \ }; \ /* Rehash: */ \ - tmp._hashx[newcap] = 0xff; c_swap(CX, *self, tmp); \ - CX##_value_t* e = tmp.table, *slot = self->table; \ - uint8_t* hashx = self->_hashx; \ - for (size_t i = 0; i < oldcap; ++i, ++e) \ - if (tmp._hashx[i]) { \ - CX##_rawkey_t raw = keyToRaw(KEY_REF_##C(e)); \ - chash_bucket_t b = CX##_bucket_(self, &raw); \ - memcpy((void *) &slot[b.idx], e, sizeof *e); \ - hashx[b.idx] = (uint8_t) b.hx; \ + _tmp._hashx[_newcap] = 0xff; c_swap(CX, *self, _tmp); \ + CX##_value_t* e = _tmp.table, *_slot = self->table; \ + uint8_t* _hashx = self->_hashx; \ + for (size_t i = 0; i < _oldcap; ++i, ++e) \ + if (_tmp._hashx[i]) { \ + CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(e)); \ + chash_bucket_t b = CX##_bucket_(self, &_raw); \ + memcpy((void *) &_slot[b.idx], e, sizeof *e); \ + _hashx[b.idx] = (uint8_t) b.hx; \ } \ - c_free(tmp._hashx); \ - c_free((void *) tmp.table); \ + c_free(_tmp._hashx); \ + c_free((void *) _tmp.table); \ } \ \ STC_DEF void \ - CX##_erase_entry(CX* self, CX##_value_t* val) { \ - size_t i = chash_index_(*self, val), j = i, k, cap = self->bucket_count; \ - CX##_value_t* slot = self->table; \ - uint8_t* hashx = self->_hashx; \ - CX##_value_del(&slot[i]); \ + CX##_erase_entry(CX* self, CX##_value_t* _val) { \ + size_t i = chash_index_(*self, _val), j = i, k, _cap = self->bucket_count; \ + CX##_value_t* _slot = self->table; \ + uint8_t* _hashx = self->_hashx; \ + CX##_value_del(&_slot[i]); \ for (;;) { /* delete without leaving tombstone */ \ - if (++j == cap) j = 0; \ - if (! hashx[j]) \ + if (++j == _cap) j = 0; \ + if (! _hashx[j]) \ break; \ - CX##_rawkey_t raw = keyToRaw(KEY_REF_##C(slot+j)); \ - k = _c_SELECT(fastrange,CMAP_SIZE_T)(keyHashRaw(&raw, sizeof raw), cap); \ + CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(_slot+j)); \ + k = _c_SELECT(fastrange,CMAP_SIZE_T)(keyHashRaw(&_raw, sizeof _raw), _cap); \ if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ \ - memcpy((void *) &slot[i], &slot[j], sizeof *slot), hashx[i] = hashx[j], i = j; \ + memcpy((void *) &_slot[i], &_slot[j], sizeof *_slot), _hashx[i] = _hashx[j], i = j; \ } \ - hashx[i] = 0; \ + _hashx[i] = 0; \ --self->size; \ } diff --git a/stc/cvec.h b/stc/cvec.h index c6ca392a..9d2868ca 100644 --- a/stc/cvec.h +++ b/stc/cvec.h @@ -50,34 +50,47 @@ struct cvec_rep { size_t size, cap; void* data[]; }; #define _c_using_cvec(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ \ - typedef Value CX##_value_t; \ - typedef RawValue CX##_rawvalue_t; \ - typedef struct {CX##_value_t *ref;} CX##_iter_t; \ - typedef struct {CX##_value_t *data;} CX; \ + typedef Value CX##_value_t; \ + typedef RawValue CX##_rawvalue_t; \ + typedef struct {CX##_value_t *ref;} CX##_iter_t; \ + typedef struct {CX##_value_t *data;} CX; \ \ - STC_API CX CX##_init(void); \ - STC_API CX CX##_clone(CX vec); \ - STC_API void CX##_del(CX* self); \ - STC_API void CX##_clear(CX* self); \ - STC_API void CX##_reserve(CX* self, size_t cap); \ - STC_API void CX##_resize(CX* self, size_t size, Value fill_val); \ - STC_API int CX##_value_compare(const CX##_value_t* x, const CX##_value_t* y); \ - STC_API CX##_iter_t CX##_find_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \ - STC_API CX##_iter_t CX##_bsearch_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \ - STC_API void CX##_emplace_n(CX *self, const CX##_rawvalue_t arr[], size_t size); \ - STC_API void CX##_push_back(CX* self, Value value); \ - STC_API CX##_iter_t CX##_erase_range_p(CX* self, CX##_value_t* p1, CX##_value_t* p2); \ - STC_API CX##_iter_t CX##_insert_range_p(CX* self, CX##_value_t* pos, const CX##_value_t* p1, \ - const CX##_value_t* p2, bool clone); \ - STC_INLINE size_t CX##_size(CX vec) { return _cvec_rep(&vec)->size; } \ - STC_INLINE size_t CX##_capacity(CX vec) { return _cvec_rep(&vec)->cap; } \ - STC_INLINE bool CX##_empty(CX vec) {return !_cvec_rep(&vec)->size;} \ - STC_INLINE Value CX##_value_fromraw(RawValue raw) {return valueFromRaw(raw);} \ - STC_INLINE void CX##_swap(CX* a, CX* b) {c_swap(CX, *a, *b);} \ - STC_INLINE void CX##_emplace_back(CX* self, RawValue raw) \ - {CX##_push_back(self, valueFromRaw(raw));} \ - STC_INLINE void CX##_pop_back(CX* self) \ - {valueDel(&self->data[--_cvec_rep(self)->size]);} \ + STC_API CX CX##_init(void); \ + STC_API CX CX##_clone(CX vec); \ + STC_API void CX##_del(CX* self); \ + STC_API void CX##_clear(CX* self); \ + STC_API void CX##_reserve(CX* self, size_t cap); \ + STC_API void CX##_resize(CX* self, size_t size, Value fill_val); \ + STC_API int CX##_value_compare(const CX##_value_t* x, const CX##_value_t* y); \ + STC_API CX##_iter_t CX##_find_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \ + STC_API CX##_iter_t CX##_bsearch_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \ + STC_API void CX##_push_back(CX* self, Value value); \ + STC_API CX##_iter_t CX##_erase_range_p(CX* self, CX##_value_t* p1, CX##_value_t* p2); \ + STC_API CX##_iter_t CX##_insert_range_p(CX* self, CX##_value_t* pos, \ + const CX##_value_t* p1, const CX##_value_t* p2, bool clone); \ + STC_API CX##_iter_t CX##_emplace_range_p(CX* self, CX##_value_t* pos, \ + const CX##_rawvalue_t* p1, const CX##_rawvalue_t* p2); \ +\ + STC_INLINE size_t CX##_size(CX vec) { return _cvec_rep(&vec)->size; } \ + STC_INLINE size_t CX##_capacity(CX vec) { return _cvec_rep(&vec)->cap; } \ + STC_INLINE bool CX##_empty(CX vec) {return !_cvec_rep(&vec)->size;} \ + STC_INLINE Value CX##_value_fromraw(RawValue raw) {return valueFromRaw(raw);} \ + STC_INLINE void CX##_swap(CX* a, CX* b) {c_swap(CX, *a, *b);} \ + STC_INLINE CX##_value_t*CX##_front(const CX* self) {return self->data;} \ + STC_INLINE CX##_value_t*CX##_back(const CX* self) \ + {return self->data + _cvec_rep(self)->size - 1;} \ + STC_INLINE void CX##_emplace_back(CX* self, RawValue raw) \ + {CX##_push_back(self, valueFromRaw(raw));} \ + STC_INLINE void CX##_pop_back(CX* self) \ + {valueDel(&self->data[--_cvec_rep(self)->size]);} \ + STC_INLINE Value CX##_value_clone(CX##_value_t val) \ + {return valueFromRaw(valueToRaw(&val));} \ + STC_INLINE CX##_iter_t CX##_begin(const CX* self) \ + {CX##_iter_t it = {self->data}; return it;} \ + STC_INLINE CX##_iter_t CX##_end(const CX* self) \ + {CX##_iter_t it = {self->data + _cvec_rep(self)->size}; return it;} \ + STC_INLINE void CX##_next(CX##_iter_t* it) {++it->ref;} \ + STC_INLINE size_t CX##_index(CX vec, CX##_iter_t it) {return it.ref - vec.data;} \ \ STC_INLINE CX \ CX##_with_size(size_t size, Value null_val) { \ @@ -98,28 +111,31 @@ struct cvec_rep { size_t size, cap; void* data[]; }; CX x = CX##_clone(*self); \ CX##_del(self); *self = x; \ } \ -\ - STC_INLINE CX##_value_t \ - CX##_value_clone(CX##_value_t val) { \ - return valueFromRaw(valueToRaw(&val)); \ - } \ \ STC_INLINE CX##_iter_t \ CX##_insert(CX* self, CX##_iter_t it, Value value) { \ - it = CX##_insert_range_p(self, it.ref, &value, &value + 1, false); \ - *it.ref = value; return it; \ + return CX##_insert_range_p(self, it.ref, &value, &value + 1, false); \ } \ + STC_INLINE CX##_iter_t \ + CX##_insert_at(CX* self, size_t idx, const CX##_value_t arr[], size_t n) { \ + return CX##_insert_range_p(self, self->data + idx, arr, arr + n, false); \ + } \ +\ STC_INLINE CX##_iter_t \ CX##_emplace(CX* self, CX##_iter_t it, RawValue raw) { \ - return CX##_insert(self, it, valueFromRaw(raw)); \ + return CX##_emplace_range_p(self, it.ref, &raw, &raw + 1); \ } \ STC_INLINE CX##_iter_t \ - CX##_insert_range(CX* self, CX##_iter_t it, CX##_iter_t it1, CX##_iter_t it2) { \ + CX##_emplace_range(CX* self, CX##_iter_t it, CX##_iter_t it1, CX##_iter_t it2) { \ return CX##_insert_range_p(self, it.ref, it1.ref, it2.ref, true); \ } \ STC_INLINE CX##_iter_t \ - CX##_insert_at(CX* self, size_t idx, const CX##_value_t arr[], size_t n) { \ - return CX##_insert_range_p(self, self->data + idx, arr, arr + n, true); \ + CX##_emplace_at(CX* self, size_t idx, const CX##_rawvalue_t arr[], size_t n) { \ + return CX##_emplace_range_p(self, self->data + idx, arr, arr + n); \ + } \ + STC_INLINE void \ + CX##_emplace_n(CX *self, const CX##_rawvalue_t arr[], size_t n) { \ + CX##_emplace_range_p(self, self->data + _cvec_rep(self)->size, arr, arr + n); \ } \ \ STC_INLINE CX##_iter_t \ @@ -134,35 +150,24 @@ struct cvec_rep { size_t size, cap; void* data[]; }; CX##_erase_n(CX* self, size_t idx, size_t n) { \ return CX##_erase_range_p(self, self->data + idx, self->data + idx + n); \ } \ -\ - STC_INLINE CX##_value_t* \ - CX##_front(const CX* self) {return self->data;} \ - STC_INLINE CX##_value_t* \ - CX##_back(const CX* self) {return self->data + _cvec_rep(self)->size - 1;} \ \ STC_INLINE CX##_value_t* \ CX##_at(const CX* self, size_t idx) { \ assert(idx < _cvec_rep(self)->size); \ return self->data + idx; \ } \ -\ - STC_INLINE CX##_iter_t \ - CX##_begin(const CX* self) { \ - CX##_iter_t it = {self->data}; return it; \ - } \ - STC_INLINE CX##_iter_t \ - CX##_end(const CX* self) { \ - CX##_iter_t it = {self->data + _cvec_rep(self)->size}; return it; \ - } \ - STC_INLINE void \ - CX##_next(CX##_iter_t* it) {++it->ref;} \ - STC_INLINE size_t \ - CX##_index(CX vec, CX##_iter_t it) {return it.ref - vec.data;} \ \ STC_INLINE CX##_iter_t \ CX##_find(const CX* self, RawValue raw) { \ return CX##_find_in(CX##_begin(self), CX##_end(self), raw); \ } \ +\ + STC_INLINE CX##_value_t* \ + CX##_get(const CX* self, RawValue raw) { \ + CX##_iter_t end = CX##_end(self); \ + CX##_value_t* val = CX##_find_in(CX##_begin(self), end, raw).ref; \ + return val == end.ref ? NULL : val; \ + } \ \ STC_INLINE CX##_iter_t \ CX##_bsearch(const CX* self, RawValue raw) { \ @@ -170,8 +175,8 @@ struct cvec_rep { size_t size, cap; void* data[]; }; } \ STC_INLINE void \ CX##_sort_range(CX##_iter_t i1, CX##_iter_t i2, \ - int(*cmp)(const CX##_value_t*, const CX##_value_t*)) { \ - qsort(i1.ref, i2.ref - i1.ref, sizeof(CX##_value_t), (int(*)(const void*, const void*)) cmp); \ + int(*_cmp_)(const CX##_value_t*, const CX##_value_t*)) { \ + qsort(i1.ref, i2.ref - i1.ref, sizeof(CX##_value_t), (int(*)(const void*, const void*)) _cmp_); \ } \ STC_INLINE void \ CX##_sort(CX* self) { \ @@ -193,15 +198,6 @@ static struct cvec_rep _cvec_inits = {0, 0}; CX vec = {(CX##_value_t *) _cvec_inits.data}; \ return vec; \ } \ -\ - STC_DEF void \ - CX##_emplace_n(CX *self, const CX##_rawvalue_t arr[], size_t n) { \ - if (!n) return; \ - CX##_reserve(self, _cvec_rep(self)->size + n); \ - CX##_value_t* p = self->data + _cvec_rep(self)->size; \ - for (size_t i=0; i < n; ++i) *p++ = valueFromRaw(arr[i]); \ - _cvec_rep(self)->size += n; \ - } \ \ STC_DEF void \ CX##_clear(CX* self) { \ @@ -258,18 +254,33 @@ static struct cvec_rep _cvec_inits = {0, 0}; return out; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_insert_range_p(CX* self, CX##_value_t* pos, const CX##_value_t* p1, \ - const CX##_value_t* p2, bool clone) { \ - size_t len = p2 - p1, idx = pos - self->data, size = _cvec_rep(self)->size; \ - CX##_iter_t it = {pos}; \ - if (len == 0) return it; \ + STC_DEF CX##_value_t* \ + CX##_insert_space_(CX* self, CX##_value_t* pos, size_t len) { \ + size_t idx = pos - self->data, size = _cvec_rep(self)->size; \ + if (len == 0) return pos; \ if (size + len > CX##_capacity(*self)) \ CX##_reserve(self, 4 + (size + len)*1.5), \ - it.ref = pos = self->data + idx; \ + pos = self->data + idx; \ _cvec_rep(self)->size += len; \ memmove(pos + len, pos, (size - idx) * sizeof(Value)); \ + return pos; \ + } \ +\ + STC_DEF CX##_iter_t \ + CX##_insert_range_p(CX* self, CX##_value_t* pos, const CX##_value_t* p1, \ + const CX##_value_t* p2, bool clone) { \ + pos = CX##_insert_space_(self, pos, p2 - p1); \ + CX##_iter_t it = {pos}; \ if (clone) while (p1 != p2) *pos++ = valueFromRaw(valueToRaw(p1++)); \ + else memcpy(pos, p1, (p2 - p1)*sizeof *p1); \ + return it; \ + } \ +\ + STC_DEF CX##_iter_t \ + CX##_emplace_range_p(CX* self, CX##_value_t* pos, const CX##_rawvalue_t* p1, const CX##_rawvalue_t* p2) { \ + pos = CX##_insert_space_(self, pos, p2 - p1); \ + CX##_iter_t it = {pos}; \ + while (p1 != p2) *pos++ = valueFromRaw(*p1++); \ return it; \ } \ \ -- cgit v1.2.3