summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Lovset <[email protected]>2022-05-01 06:25:31 +0200
committerTyge Lovset <[email protected]>2022-05-01 06:25:31 +0200
commit82d139295e3488656855270a420447af65088ae4 (patch)
tree9d04a9be997637c7c88e19ae09720c743a168b53
parentf46f405d4c28de4e087bc275edee1409e6596000 (diff)
downloadSTC-modified-82d139295e3488656855270a420447af65088ae4.tar.gz
STC-modified-82d139295e3488656855270a420447af65088ae4.zip
- 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.
-rw-r--r--docs/cdeq_api.md16
-rw-r--r--docs/cvec_api.md16
-rw-r--r--include/stc/cdeq.h49
-rw-r--r--include/stc/cmap.h41
-rw-r--r--include/stc/csmap.h48
-rw-r--r--include/stc/cstack.h11
-rw-r--r--include/stc/cvec.h75
-rw-r--r--include/stc/forward.h4
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 { \