summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-05-04 13:37:30 +0200
committerTyge Løvset <[email protected]>2021-05-04 13:37:30 +0200
commit8970472ccac02ffdbab3b2c5caf677da4ffb2cc2 (patch)
treeacf1ea02a184b16cf075c8b79b09858421d40b9c
parent560244381db1158b52eb92856b5df87eea1f6438 (diff)
downloadSTC-modified-8970472ccac02ffdbab3b2c5caf677da4ffb2cc2.tar.gz
STC-modified-8970472ccac02ffdbab3b2c5caf677da4ffb2cc2.zip
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.
-rw-r--r--docs/cdeq_api.md2
-rw-r--r--docs/cvec_api.md15
-rw-r--r--stc/ccommon.h9
-rw-r--r--stc/cdeq.h12
-rw-r--r--stc/clist.h5
-rw-r--r--stc/cmap.h128
-rw-r--r--stc/cvec.h159
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<T*>(c_malloc(sizeof(T))
+#define c_new_n(T, n) static_cast<T*>(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
@@ -164,10 +164,17 @@ struct cdeq_rep { size_t size, cap; void* base[]; };
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
@@ -175,6 +175,11 @@ STC_API size_t _clist_count(const clist_VOID* self);
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) { \
@@ -99,27 +112,30 @@ struct cvec_rep { size_t size, cap; void* data[]; };
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 \
@@ -136,42 +152,31 @@ struct cvec_rep { size_t size, cap; void* data[]; };
} \
\
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) { \
return CX##_bsearch_in(CX##_begin(self), CX##_end(self), raw); \
} \
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) { \
@@ -195,15 +200,6 @@ static struct cvec_rep _cvec_inits = {0, 0};
} \
\
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) { \
struct cvec_rep* rep = _cvec_rep(self); if (rep->cap) { \
for (CX##_value_t *p = self->data, *q = p + rep->size; p != q; ++p) \
@@ -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; \
} \
\