From 82d139295e3488656855270a420447af65088ae4 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Sun, 1 May 2022 06:25:31 +0200 Subject: - Array expansions (insert, reserve, clone) are now checked for malloc nomem, and result can be checked by user in cvec, cdeq, cmap, csmap (cvec/cdeq insert functions now returns pointer, not iter). - Refactoring. --- docs/cdeq_api.md | 16 +++++------ docs/cvec_api.md | 16 +++++------ include/stc/cdeq.h | 49 +++++++++++++++++---------------- include/stc/cmap.h | 41 ++++++++++++++-------------- include/stc/csmap.h | 48 ++++++++++++++++++++------------- include/stc/cstack.h | 11 +++++--- include/stc/cvec.h | 75 ++++++++++++++++++++++++++------------------------- include/stc/forward.h | 4 +-- 8 files changed, 140 insertions(+), 120 deletions(-) diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index aa528aa2..fb24c8d3 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -56,17 +56,17 @@ 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() void cdeq_X_pop_back(cdeq_X* self); -cdeq_X_iter cdeq_X_insert(cdeq_X* self, size_t idx, i_val value); // move value -cdeq_X_iter cdeq_X_insert_n(cdeq_X* self, size_t idx, const i_val[] arr, size_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_p(cdeq_X* self, i_val* pos, +cdeq_X_value* cdeq_X_insert(cdeq_X* self, size_t idx, i_val value); // move value +cdeq_X_value* cdeq_X_insert_n(cdeq_X* self, size_t idx, const i_val[] arr, size_t n); // move arr values +cdeq_X_value* cdeq_X_insert_at(cdeq_X* self, cdeq_X_iter it, i_val value); // move value +cdeq_X_value* cdeq_X_insert_range_p(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2); -cdeq_X_iter cdeq_X_emplace_n(cdeq_X* self, size_t idx, const i_valraw[] arr, size_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, cdeq_X_iter it, // will clone +cdeq_X_value* cdeq_X_emplace_n(cdeq_X* self, size_t idx, const i_valraw[] arr, size_t n); +cdeq_X_value* cdeq_X_emplace_at(cdeq_X* self, cdeq_X_iter it, i_valraw raw); +cdeq_X_value* cdeq_X_emplace_range(cdeq_X* self, cdeq_X_iter it, // will clone cdeq_X_iter it1, cdeq_X_iter it2); -cdeq_X_iter cdeq_X_emplace_range_p(cdeq_X* self, i_val* pos, +cdeq_X_value* cdeq_X_emplace_range_p(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2); cdeq_X_iter cdeq_X_erase_n(cdeq_X* self, size_t idx, size_t n); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index d5d87b7b..a28ad289 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -69,17 +69,17 @@ cvec_X_value* cvec_X_emplace_back(cvec_X* self, i_valraw raw); 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, size_t idx, i_val value); // move value -cvec_X_iter cvec_X_insert_n(cvec_X* self, size_t idx, const i_val[] arr, size_t n); // move n 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_p(cvec_X* self, i_val* pos, +cvec_X_value* cvec_X_insert(cvec_X* self, size_t idx, i_val value); // move value +cvec_X_value* cvec_X_insert_n(cvec_X* self, size_t idx, const i_val[] arr, size_t n); // move n values +cvec_X_value* cvec_X_insert_at(cvec_X* self, cvec_X_iter it, i_val value); // move value +cvec_X_value* cvec_X_insert_range_p(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2); -cvec_X_iter cvec_X_emplace_n(cvec_X* self, size_t idx, const i_valraw[] arr, size_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, cvec_X_iter it, // will clone +cvec_X_value* cvec_X_emplace_n(cvec_X* self, size_t idx, const i_valraw[] arr, size_t n); +cvec_X_value* cvec_X_emplace_at(cvec_X* self, cvec_X_iter it, i_valraw raw); +cvec_X_value* cvec_X_emplace_range(cvec_X* self, cvec_X_iter it, // will clone cvec_X_iter it1, cvec_X_iter it2); -cvec_X_iter cvec_X_emplace_range_p(cvec_X* self, i_val* pos, +cvec_X_value* cvec_X_emplace_range_p(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2); cvec_X_iter cvec_X_erase_n(cvec_X* self, size_t idx, size_t n); diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index de4221ef..6c92ba4a 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -50,10 +50,10 @@ STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); #if !defined _i_queue #if !defined _i_no_clone -STC_API _cx_iter _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, +STC_API _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2); #if !defined _i_no_emplace -STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, +STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2); #endif // _i_no_emplace #endif // !_i_no_clone @@ -64,7 +64,7 @@ STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value #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_p)(_cx_self* self, _cx_value* pos, +STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2); #endif // !_i_queue @@ -118,15 +118,15 @@ STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); } @@ -145,12 +145,13 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { } #if !defined _i_no_clone && !defined _i_no_emplace -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); } -STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, i_keyraw raw) { +STC_INLINE _cx_value* +_cx_memb(_emplace_front)(_cx_self* self, i_keyraw raw) { return _cx_memb(_push_front)(self, i_keyfrom(raw)); } @@ -158,11 +159,11 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_keyraw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_keyraw raw) { return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); } @@ -309,9 +310,11 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t sz = cdeq_rep_(&cx)->size; _cx_self out = _cx_memb(_with_capacity)(sz); - cdeq_rep_(&out)->size = sz; - for (size_t i = 0; i < sz; ++i) - out.data[i] = i_keyclone(cx.data[i]); + if (cdeq_rep_(&out)->cap) { + cdeq_rep_(&out)->size = sz; + for (size_t i = 0; i < sz; ++i) + out.data[i] = i_keyclone(cx.data[i]); + } return out; } #endif @@ -355,13 +358,12 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { return self->data; } -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return it; + if (pos) memcpy(pos, p1, (p2 - p1)*sizeof *p1); + return pos; } STC_DEF _cx_iter @@ -379,21 +381,22 @@ _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { #if !defined _i_no_clone #if !defined _i_no_emplace -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - for (; p1 != p2; ++p1) *pos++ = i_keyfrom((*p1)); + _cx_value* it = pos; + if (pos) for (; p1 != p2; ++p1) + *pos++ = i_keyfrom((*p1)); return it; } #endif // !_i_no_emplace -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - for (; p1 != p2; ++p1) + _cx_value* it = pos; + if (pos) for (; p1 != p2; ++p1) *pos++ = i_keyclone((*p1)); return it; } diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 259dea22..3da6b071 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -106,7 +106,7 @@ STC_INLINE bool _cx_memb(_empty)(_cx_self m) { return m.size == 0; } STC_INLINE size_t _cx_memb(_size)(_cx_self m) { return m.size; } STC_INLINE size_t _cx_memb(_bucket_count)(_cx_self map) { return map.bucket_count; } STC_INLINE size_t _cx_memb(_capacity)(_cx_self map) - { return (size_t)(map.bucket_count ? (map.bucket_count - 2)*map.max_load_factor : 0.f); } + { return map.bucket_count ? (size_t)((map.bucket_count - 2)*map.max_load_factor) : 0u; } STC_INLINE void _cx_memb(_swap)(_cx_self *map1, _cx_self *map2) {c_swap(_cx_self, *map1, *map2); } STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey) { return self->size && self->_hashx[_cx_memb(_bucket_)(self, &rkey).idx]; } @@ -311,10 +311,11 @@ _cx_memb(_bucket_)(const _cx_self* self, const _cx_rawkey* rkeyptr) { STC_DEF _cx_result _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey) { + bool nomem = false; if (self->size + 1 >= (i_size)(self->bucket_count*self->max_load_factor)) - _cx_memb(_reserve)(self, ((size_t)self->size*3 >> 1) + 4); + nomem = !_cx_memb(_reserve)(self, ((size_t)self->size*3 >> 1) + 4); chash_bucket_t b = _cx_memb(_bucket_)(self, &rkey); - _cx_result res = {&self->table[b.idx], !self->_hashx[b.idx]}; + _cx_result res = {&self->table[b.idx], !self->_hashx[b.idx], nomem}; if (res.inserted) { self->_hashx[b.idx] = b.hx; ++self->size; @@ -342,28 +343,28 @@ _cx_memb(_reserve)(_cx_self* self, const size_t _newcap) { const i_size _oldbuckets = self->bucket_count; const i_size _nbuckets = ((i_size)(_newcap/self->max_load_factor) + 2) | 1; if (_newcap != self->size && _newcap <= _oldbuckets) return true; - _cx_self _tmp = { + _cx_self m = { c_alloc_n(_cx_value, _nbuckets), - (uint8_t *) c_calloc(_nbuckets + 1, sizeof(uint8_t)), - self->size, (i_size) _nbuckets, + (uint8_t *) c_calloc(_nbuckets + 1, 1), + self->size, (i_size)_nbuckets, self->max_load_factor }; - bool ret; /* Rehash: */ - if ((ret = _tmp.table && _tmp._hashx)) { - _tmp._hashx[_nbuckets] = 0xff; - c_swap(_cx_self, *self, _tmp); - _cx_value* e = _tmp.table, *_slot = self->table; - uint8_t* _hashx = self->_hashx; - for (size_t i = 0; i < _oldbuckets; ++i, ++e) if (_tmp._hashx[i]) { - _cx_rawkey _raw = i_keyto(_i_keyref(e)); - chash_bucket_t b = _cx_memb(_bucket_)(self, &_raw); - _slot[b.idx] = *e; - _hashx[b.idx] = (uint8_t) b.hx; + 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 (size_t i = 0; i < _oldbuckets; ++i, ++e) if (*h++) { + _cx_rawkey r = i_keyto(_i_keyref(e)); + chash_bucket_t b = _cx_memb(_bucket_)(&m, &r); + m.table[b.idx] = *e; + m._hashx[b.idx] = (uint8_t)b.hx; } + c_swap(_cx_self, *self, m); } - c_free(_tmp._hashx); - c_free((void *) _tmp.table); - return ret; + c_free(m._hashx); + c_free(m.table); + return ok; } STC_DEF void diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 75e7a5ee..89881444 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -253,8 +253,8 @@ _cx_memb(_reserve)(_cx_self* self, const size_t cap) { if (cap >= rep->size) { // second test is bogus, but supresses gcc warning: oldrep = rep->cap && rep != &_csmap_sentinel ? rep : NULL; - rep = (struct csmap_rep*) c_realloc(oldrep, - sizeof(struct csmap_rep) + (cap + 1)*sizeof(_cx_node)); + rep = (struct csmap_rep*) c_realloc(oldrep, sizeof(struct csmap_rep) + + (cap + 1)*sizeof(_cx_node)); if (!rep) return false; if (oldrep == NULL) memset(rep, 0, sizeof(struct csmap_rep) + sizeof(_cx_node)); @@ -265,18 +265,20 @@ _cx_memb(_reserve)(_cx_self* self, const size_t cap) { } static i_size -_cx_memb(_node_new_)(_cx_self* self, int level) { - size_t tn; struct csmap_rep *rep = _csmap_rep(self); +_cx_memb(_new_node_)(_cx_self* self, int level) { + i_size tn; struct csmap_rep *rep = _csmap_rep(self); if (rep->disp) { tn = rep->disp; rep->disp = self->nodes[tn].link[1]; } else { - if ((tn = rep->head + 1) > rep->cap) _cx_memb(_reserve)(self, 4 + (tn*3 >> 1)); - ++_csmap_rep(self)->head; /* do after reserve */ + if (rep->head == rep->cap) + if (!_cx_memb(_reserve)(self, rep->head*3/2 + 4)) + return 0; + tn = ++_csmap_rep(self)->head; /* start with 1, 0 is nullnode. */ } _cx_node* dn = &self->nodes[tn]; dn->link[0] = dn->link[1] = 0; dn->level = level; - return (i_size) tn; + return tn; } static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey); @@ -292,7 +294,8 @@ _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)) { 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); + if (_res.inserted) *_res.ref = _val; + else _cx_memb(_value_drop)(&_val); return _res; } @@ -300,18 +303,24 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { 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))); - if (res.inserted) res.ref->first = key; - else { i_keydrop((&key)); i_valdrop((&res.ref->second)); } - res.ref->second = mapped; return res; + if (!res.nomem_error) { + if (res.inserted) res.ref->first = key; + else { i_keydrop((&key)); i_valdrop((&res.ref->second)); } + res.ref->second = mapped; + } + return res; } #if !defined _i_no_clone && !defined _i_no_emplace STC_DEF _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { _cx_result res = _cx_memb(_insert_entry_)(self, rkey); - if (res.inserted) res.ref->first = i_keyfrom(rkey); - else { i_valdrop((&res.ref->second)); } - res.ref->second = i_valfrom(rmapped); return res; + if (!res.nomem_error) { + if (res.inserted) res.ref->first = i_keyfrom(rkey); + else { i_valdrop((&res.ref->second)); } + res.ref->second = i_valfrom(rmapped); + } + return res; } #endif // !_i_no_clone && !_i_no_emplace #endif // !_i_isset @@ -391,11 +400,14 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, i_size tn, const _cx_rawkey* rkey, _c while (tx) { up[top++] = tx; i_keyraw raw = i_keyto(_i_keyref(&d[tx].value)); - if (!(c = i_cmp((&raw), rkey))) { res->ref = &d[tx].value; return tn; } + if (!(c = i_cmp((&raw), rkey))) + { res->ref = &d[tx].value; return tn; } dir = (c < 0); tx = d[tx].link[dir]; } - tx = _cx_memb(_node_new_)(self, 1); d = self->nodes; + if ((tx = _cx_memb(_new_node_)(self, 1)) == 0) + { res->nomem_error = true; return 0; } + d = self->nodes; res->ref = &d[tx].value, res->inserted = true; if (top == 0) return tx; d[up[top - 1]].link[dir] = tx; @@ -410,7 +422,7 @@ _cx_memb(_insert_entry_i_)(_cx_self* self, i_size tn, const _cx_rawkey* rkey, _c static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey) { - _cx_result res = {NULL, false}; + _cx_result res = {NULL}; i_size tn = _cx_memb(_insert_entry_i_)(self, (i_size) _csmap_rep(self)->root, &rkey, &res); _csmap_rep(self)->root = tn; _csmap_rep(self)->size += res.inserted; @@ -492,7 +504,7 @@ _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { static i_size _cx_memb(_clone_r_)(_cx_self* self, _cx_node* src, i_size sn) { if (sn == 0) return 0; - i_size tx, tn = _cx_memb(_node_new_)(self, src[sn].level); + i_size 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; diff --git a/include/stc/cstack.h b/include/stc/cstack.h index ee283cec..3705c247 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -73,7 +73,8 @@ STC_INLINE size_t _cx_memb(_capacity)(_cx_self v) STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { if (n < self->size) return true; _cx_value *t = (_cx_value *)c_realloc(self->data, n*sizeof *t); - return t ? (self->data = t, self->capacity = n) : 0; + if (t) { self->capacity = n, self->data = t; return true; } + return false; } STC_INLINE _cx_value* @@ -92,8 +93,9 @@ STC_INLINE _cx_value* _cx_memb(_top)(const _cx_self* self) STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, _cx_value val) { if (self->size == self->capacity) - _cx_memb(_reserve)(self, self->size*3/2 + 4); - _cx_value* vp = self->data + self->size++; + if (!_cx_memb(_reserve)(self, self->size*3/2 + 4)) + return NULL; + _cx_value* vp = self->data + self->size++; *vp = val; return vp; } STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, _cx_value val) @@ -119,7 +121,8 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) STC_INLINE _cx_self _cx_memb(_clone)(_cx_self v) { _cx_self out = {(_cx_value *) c_malloc(v.size*sizeof(_cx_value)), v.size, v.size}; - for (size_t i = 0; i < v.size; ++v.data) + if (!out.data) out.capacity = 0; + else for (size_t i = 0; i < v.size; ++v.data) out.data[i++] = i_keyclone((*v.data)); return out; } diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 7b032ff0..24cf8249 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -84,8 +84,9 @@ STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t cap); STC_API bool _cx_memb(_resize)(_cx_self* self, size_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_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); +STC_API _cx_value* _cx_memb(_expand_uninitialized_at_p)(_cx_self* self, _cx_value* pos, const size_t n); #if !c_option(c_no_cmp) STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, i_keyraw raw); @@ -94,7 +95,7 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, #if !defined _i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_API _cx_iter _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, +STC_API _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2); STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) { return i_keyclone(val); } @@ -105,21 +106,21 @@ STC_INLINE void _cx_memb(_copy)(_cx_self *self, _cx_self other) { *self = _cx_memb(_clone)(other); } #if !defined _i_no_emplace -STC_API _cx_iter _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, +STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2); STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, i_keyraw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, i_keyraw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, i_keyraw raw) { return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); } @@ -168,22 +169,19 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { } STC_INLINE _cx_value* -_cx_memb(_expand_uninitialized)(_cx_self *self, size_t n) { - size_t len = _cx_memb(_size)(*self); - if (!_cx_memb(_reserve)(self, len + n)) return NULL; - cvec_rep_(self)->size += n; - return self->data + len; +_cx_memb(_expand_uninitialized)(_cx_self *self, const size_t n) { + return _cx_memb(_expand_uninitialized_at_p)(self, self->data + _cx_memb(_size)(*self), n); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_iter +STC_INLINE _cx_value* _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); } @@ -314,35 +312,36 @@ STC_DEF _cx_value* _cx_memb(_push)(_cx_self* self, i_key value) { struct cvec_rep *r = cvec_rep_(self); if (r->size == r->cap) { - _cx_memb(_reserve)(self, (r->size*3 >> 1) + 4); + if (!_cx_memb(_reserve)(self, (r->size*3 >> 1) + 4)) + return NULL; r = cvec_rep_(self); } _cx_value *v = self->data + r->size++; *v = value; return v; } -static _cx_value* -_cx_memb(_insert_space_)(_cx_self* self, _cx_value* pos, const size_t len) { +STC_DEF _cx_value* +_cx_memb(_expand_uninitialized_at_p)(_cx_self* self, _cx_value* pos, const size_t n) { const size_t idx = pos - self->data; struct cvec_rep* r = cvec_rep_(self); - if (!len) return pos; - if (r->size + len > r->cap) { - _cx_memb(_reserve)(self, (r->size*3 >> 1) + len); + if (!n) return pos; + if (r->size + n > r->cap) { + if (!_cx_memb(_reserve)(self, r->size*3/2 + n)) + return NULL; r = cvec_rep_(self); pos = self->data + idx; } - memmove(pos + len, pos, (r->size - idx) * sizeof *pos); - r->size += len; + memmove(pos + n, pos, (r->size - idx)*sizeof *pos); + r->size += n; return pos; } -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return it; + pos = _cx_memb(_expand_uninitialized_at_p)(self, pos, p2 - p1); + if (pos) memcpy(pos, p1, (p2 - p1)*sizeof *p1); + return pos; } STC_DEF _cx_iter @@ -362,27 +361,29 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t len = cvec_rep_(&cx)->size; _cx_self out = _cx_memb(_with_capacity)(len); - _cx_memb(_clone_range_p)(&out, out.data, cx.data, cx.data + len); + if (cvec_rep_(&out)->cap) + _cx_memb(_clone_range_p)(&out, out.data, cx.data, cx.data + len); return out; } -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - for (; p1 != p2; ++p1) + pos = _cx_memb(_expand_uninitialized_at_p)(self, pos, p2 - p1); + _cx_value* it = pos; + if (pos) for (; p1 != p2; ++p1) *pos++ = i_keyclone((*p1)); return it; } #if !defined _i_no_emplace -STC_DEF _cx_iter +STC_DEF _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { - pos = _cx_memb(_insert_space_)(self, pos, p2 - p1); - _cx_iter it = {pos}; - for (; p1 != p2; ++p1) *pos++ = i_keyfrom((*p1)); + pos = _cx_memb(_expand_uninitialized_at_p)(self, pos, p2 - p1); + _cx_value* it = pos; + if (pos) for (; p1 != p2; ++p1) + *pos++ = i_keyfrom((*p1)); return it; } #endif // !_i_no_emplace diff --git a/include/stc/forward.h b/include/stc/forward.h index a62c8af4..6af17c2b 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -113,7 +113,7 @@ typedef char csview_value; \ typedef struct { \ SELF##_value *ref; \ - bool inserted; \ + bool inserted, nomem_error; \ } SELF##_result; \ \ typedef struct { \ @@ -140,7 +140,7 @@ typedef char csview_value; \ typedef struct { \ SELF##_value *ref; \ - bool inserted; \ + bool inserted, nomem_error; \ } SELF##_result; \ \ typedef struct { \ -- cgit v1.2.3