summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorTyge Lovset <[email protected]>2023-05-18 11:49:31 +0200
committerTyge Lovset <[email protected]>2023-05-18 11:49:31 +0200
commit50a16934dde8e65bbcf628d6342c1649f7e09365 (patch)
treea14f3347622979858ff60b95630877029cb46ef6 /include
parentbe7d9913d4a284bdeb7f0431482b5731b5ef31df (diff)
downloadSTC-modified-50a16934dde8e65bbcf628d6342c1649f7e09365.tar.gz
STC-modified-50a16934dde8e65bbcf628d6342c1649f7e09365.zip
Huge update: cqueue and cdeq completely rewritten. cvec and cdeq API harmonized. Docs update/improved.
Diffstat (limited to 'include')
-rw-r--r--include/stc/algo/sort.h (renamed from include/stc/algo/csort.h)49
-rw-r--r--include/stc/ccommon.h10
-rw-r--r--include/stc/cdeq.h453
-rw-r--r--include/stc/clist.h9
-rw-r--r--include/stc/cmap.h9
-rw-r--r--include/stc/cqueue.h226
-rw-r--r--include/stc/cvec.h121
-rw-r--r--include/stc/forward.h13
-rw-r--r--include/stc/priv/template.h8
-rw-r--r--include/stc/priv/template2.h5
10 files changed, 406 insertions, 497 deletions
diff --git a/include/stc/algo/csort.h b/include/stc/algo/sort.h
index e01a2893..20b7e1b3 100644
--- a/include/stc/algo/csort.h
+++ b/include/stc/algo/sort.h
@@ -24,17 +24,17 @@
template params:
#define i_val - value type [required]
#define i_less - less function. default: *x < *y
-#define i_tag NAME - define csort_NAME(). default {i_val}
+#define i_tag name - define namearray_qsort(). i_tag defaults {i_val}
// test:
#include <stdio.h>
#define i_val int
-#include <stc/algo/csort.h>
+#include <stc/algo/sort.h>
int main() {
int arr[] = {23, 321, 5434, 25, 245, 1, 654, 33, 543, 21};
- csort_int(arr, c_arraylen(arr));
+ intarray_qsort(arr, c_arraylen(arr));
for (int i = 0; i < c_arraylen(arr); i++)
printf(" %d", arr[i]);
@@ -42,33 +42,42 @@ int main() {
}
*/
#include "../ccommon.h"
-#define _i_prefix csort_
+#ifndef i_type
+ #define i_at(arr, idx) (&arr[idx])
+ #ifndef i_tag
+ #define i_tag i_val
+ #endif
+ #define i_type c_PASTE(i_tag, array)
+ typedef i_val i_type;
+#endif
+#ifndef i_at
+ #define i_at(arr, idx) _cx_memb(_at_mut)(arr, idx)
+#endif
#include "../priv/template.h"
-typedef i_val _cx_value;
-static inline void _cx_memb(_insertion)(i_val arr[], intptr_t lo, intptr_t hi) {
+static inline void _cx_memb(_insertsort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) {
for (intptr_t j = lo, i = lo + 1; i <= hi; j = i, ++i) {
- i_val key = arr[i];
- while (j >= 0 && (i_less((&key), (&arr[j])))) {
- arr[j + 1] = arr[j];
+ i_val key = *i_at(arr, i);
+ while (j >= 0 && (i_less((&key), i_at(arr, j)))) {
+ *i_at(arr, j + 1) = *i_at(arr, j);
--j;
}
- arr[j + 1] = key;
+ *i_at(arr, j + 1) = key;
}
}
-static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) {
+static inline void _cx_memb(_sort_ij)(_cx_self* arr, intptr_t lo, intptr_t hi) {
intptr_t i = lo, j;
while (lo < hi) {
- i_val pivot = arr[lo + (hi - lo)*7/16];
+ i_val pivot = *i_at(arr, lo + (hi - lo)*7/16);
j = hi;
while (i <= j) {
- while (i_less((&arr[i]), (&pivot))) ++i;
- while (i_less((&pivot), (&arr[j]))) --j;
+ while (i_less(i_at(arr, i), (&pivot))) ++i;
+ while (i_less((&pivot), i_at(arr, j))) --j;
if (i <= j) {
- c_swap(i_val, arr+i, arr+j);
+ c_swap(i_val, i_at(arr, i), i_at(arr, j));
++i; --j;
}
}
@@ -77,13 +86,15 @@ static inline void _cx_memb(_quicksort)(i_val arr[], intptr_t lo, intptr_t hi) {
c_swap(intptr_t, &hi, &j);
}
- if (j - lo > 64) _cx_memb(_quicksort)(arr, lo, j);
- else if (j > lo) _cx_memb(_insertion)(arr, lo, j);
+ if (j - lo > 64) _cx_memb(_sort_ij)(arr, lo, j);
+ else if (j > lo) _cx_memb(_insertsort_ij)(arr, lo, j);
lo = i;
}
}
-static inline void _cx_self(i_val arr[], intptr_t n)
- { _cx_memb(_quicksort)(arr, 0, n - 1); }
+static inline void _cx_memb(_sort_n)(_cx_self* arr, intptr_t len) {
+ _cx_memb(_sort_ij)(arr, 0, len - 1);
+}
#include "../priv/template2.h"
+#undef i_at
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index fd673696..07c72e2f 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -171,6 +171,16 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
return NULL;
}
+STC_INLINE intptr_t cnextpow2(intptr_t n) {
+ n--;
+ n |= n >> 1, n |= n >> 2;
+ n |= n >> 4, n |= n >> 8;
+ n |= n >> 16;
+ #if INTPTR_SIZE == INT64_SIZE
+ n |= n >> 32;
+ #endif
+ return n + 1;
+}
/* Control block macros */
#define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__)
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index ff6e744f..80dd1dbe 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -20,166 +20,82 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include "ccommon.h"
-
-#ifndef CDEQ_H_INCLUDED
-#include "forward.h"
-#include <stdlib.h>
-#include <string.h>
-
-#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref)
-#define _it_ptr(it) (it.ref ? it.ref : it.end)
-#endif // CDEQ_H_INCLUDED
-
-#ifndef _i_prefix
#define _i_prefix cdeq_
+#define _pop _pop_front
+#ifdef i_more
+ #include "cqueue.h"
+ #define i_more
+#else
+ #define i_more
+ #include "cqueue.h"
#endif
-#include "priv/template.h"
-
-#ifndef i_is_forward
-_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
-#endif
-typedef i_keyraw _cx_raw;
-
-STC_API _cx_self _cx_memb(_init)(void);
-STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n);
-STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n);
-STC_API void _cx_memb(_clear)(_cx_self* self);
-STC_API void _cx_memb(_drop)(_cx_self* self);
-STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value);
-STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self);
-STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
- { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
-STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
- { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; }
-STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
-#if !defined _i_queue
-#if !defined i_no_emplace
-STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2);
-#endif // i_no_emplace
-
-#if !defined i_no_cmp || defined _i_has_eq
-STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw);
-#endif
-#ifndef i_no_cmp
-STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y);
-#endif
-STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value);
-STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
-#endif // !_i_queue
+#undef _pop
-#if !defined i_no_emplace
-STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-#endif
+STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value);
+STC_API _cx_iter _cx_memb(_insert_n)(_cx_self* self, intptr_t idx, const _cx_value* arr, intptr_t n);
+STC_API _cx_iter _cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw* raw, intptr_t n);
+STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n);
+STC_API void _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n);
-#if !defined i_no_clone
-#if !defined _i_queue
-STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
+STC_INLINE const _cx_value*
+_cx_memb(_at)(const _cx_self* self, intptr_t idx)
+ { return self->data + _cdeq_topos(self, idx); }
-STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) {
- if (self->data == other->data) return;
- _cx_memb(_clear)(self);
- _cx_memb(_copy_range)(self, self->data,
- other->data, other->data + other->_len);
- }
-#endif // !_i_queue
-STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
-STC_INLINE i_key _cx_memb(_value_clone)(i_key val)
- { return i_keyclone(val); }
-#endif // !i_no_clone
-STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self) { return self->_len; }
-STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) { return self->_cap; }
-STC_INLINE bool _cx_memb(_empty)(const _cx_self* self) { return !self->_len; }
-STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); }
-STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return self->data; }
-STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self)
- { return self->data + self->_len - 1; }
-STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _i_queue
- { i_keydrop(self->data); ++self->data; --self->_len; }
+STC_INLINE _cx_value*
+_cx_memb(_at_mut)(_cx_self* self, intptr_t idx)
+ { return self->data + _cdeq_topos(self, idx); }
-STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) {
- intptr_t n = self->_len;
- return c_LITERAL(_cx_iter){n ? self->data : NULL, self->data + n};
+STC_INLINE _cx_value*
+_cx_memb(_push_back)(_cx_self* self, _cx_value val) {
+ return _cx_memb(_push)(self, val);
}
-STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self)
- { return c_LITERAL(_cx_iter){NULL, self->data + self->_len}; }
-
-STC_INLINE void _cx_memb(_next)(_cx_iter* it)
- { if (++it->ref == it->end) it->ref = NULL; }
-
-STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n)
- { if ((it.ref += n) >= it.end) it.ref = NULL; return it; }
-
-#if !defined _i_queue
-
-STC_INLINE intptr_t _cx_memb(_index)(const _cx_self* self, _cx_iter it)
- { return (it.ref - self->data); }
-STC_INLINE void _cx_memb(_pop_back)(_cx_self* self)
- { _cx_value* p = &self->data[--self->_len]; i_keydrop(p); }
-
-STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, const intptr_t idx) {
- assert(idx < self->_len); return self->data + idx;
-}
-STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const intptr_t idx) {
- assert(idx < self->_len); return self->data + idx;
+STC_INLINE void
+_cx_memb(_pop_back)(_cx_self* self) {
+ assert(!_cx_memb(_empty)(self));
+ self->end = (self->end - 1) & self->capmask;
+ i_keydrop((self->data + self->end));
}
-STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) {
- return _cx_memb(_push)(self, value);
-}
-STC_INLINE _cx_iter
-_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) {
- return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1);
-}
-STC_INLINE _cx_iter
-_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) {
- return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n);
-}
STC_INLINE _cx_iter
-_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) {
- return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1);
+_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const _cx_value val) {
+ intptr_t idx = _cdeq_toidx(self, it.pos);
+ return _cx_memb(_insert_n)(self, idx, &val, 1);
}
STC_INLINE _cx_iter
-_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n);
-}
-STC_INLINE _cx_iter
_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
- return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1);
+ _cx_memb(_erase_n)(self, _cdeq_toidx(self, it.pos), 1);
+ if (it.pos == self->end) it.ref = NULL;
+ return it;
}
+
STC_INLINE _cx_iter
-_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) {
- return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2));
+_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) {
+ intptr_t idx1 = _cdeq_toidx(self, it1.pos);
+ intptr_t idx2 = _cdeq_toidx(self, it2.pos);
+ _cx_memb(_erase_n)(self, idx1, idx2 - idx1);
+ if (it1.pos == self->end) it1.ref = NULL;
+ return it1;
}
#if !defined i_no_emplace
STC_INLINE _cx_value*
-_cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) {
- return _cx_memb(_push_front)(self, i_keyfrom(raw));
-}
+_cx_memb(_emplace_front)(_cx_self* self, const _cx_raw raw)
+ { return _cx_memb(_push_front)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) {
- return _cx_memb(_push)(self, i_keyfrom(raw));
-}
+STC_INLINE _cx_value*
+_cx_memb(_emplace_back)(_cx_self* self, const _cx_raw raw)
+ { return _cx_memb(_push)(self, i_keyfrom(raw)); }
STC_INLINE _cx_iter
-_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) {
- return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n);
-}
-STC_INLINE _cx_iter
-_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
- return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1);
-}
-#endif // !i_no_emplace
+_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, const _cx_raw raw)
+ { return _cx_memb(_insert_at)(self, it, i_keyfrom(raw)); }
+#endif
-#if !defined i_no_cmp || defined _i_has_eq
+#if defined _i_has_eq || defined _i_has_cmp
+STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw);
+STC_API bool _cx_memb(_eq)(const _cx_self* self, const _cx_self* other);
STC_INLINE _cx_iter
_cx_memb(_find)(const _cx_self* self, _cx_raw raw) {
@@ -194,253 +110,88 @@ _cx_memb(_get)(const _cx_self* self, _cx_raw raw) {
STC_INLINE _cx_value*
_cx_memb(_get_mut)(_cx_self* self, _cx_raw raw)
{ return (_cx_value *) _cx_memb(_get)(self, raw); }
-
-STC_INLINE bool
-_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
- if (self->_len != other->_len) return false;
- for (intptr_t i = 0; i < self->_len; ++i) {
- const _cx_raw _rx = i_keyto(self->data+i), _ry = i_keyto(other->data+i);
- if (!(i_eq((&_rx), (&_ry)))) return false;
- }
- return true;
-}
#endif
-#ifndef i_no_cmp
-
-STC_INLINE void
-_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) {
- qsort(i1.ref, (size_t)(_it2_ptr(i1, i2) - i1.ref), sizeof *i1.ref,
- (int(*)(const void*, const void*)) cmp);
-}
-
-STC_INLINE void
-_cx_memb(_sort)(_cx_self* self) {
- _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp));
-}
-#endif // !c_no_cmp
-#endif // _i_queue
/* -------------------------- IMPLEMENTATION ------------------------- */
#if defined(i_implement)
-#define _cdeq_nfront(self) ((self)->data - (self)->_base)
-
-STC_DEF _cx_self
-_cx_memb(_init)(void) {
- _cx_self cx = {NULL};
- return cx;
-}
-
-STC_DEF void
-_cx_memb(_clear)(_cx_self* self) {
- if (self->_cap) {
- for (_cx_value *p = self->data, *q = p + self->_len; p != q; )
- { --q; i_keydrop(q); }
- self->_len = 0;
- self->data = self->_base;
- }
-}
-
-STC_DEF void
-_cx_memb(_shrink_to_fit)(_cx_self *self) {
- if (self->_len != self->_cap) {
- c_memmove(self->_base, self->data, self->_len*c_sizeof(i_key));
- _cx_value* d = (_cx_value*)i_realloc(self->_base, self->_len*c_sizeof(i_key));
- if (d) {
- self->_base = d;
- self->_cap = self->_len;
- }
- self->data = self->_base;
- }
-}
-
-STC_DEF void
-_cx_memb(_drop)(_cx_self* self) {
- if (self->_base) {
- _cx_memb(_clear)(self);
- i_free(self->_base);
- }
-}
-
-static intptr_t
-_cx_memb(_realloc_)(_cx_self* self, const intptr_t n) {
- const intptr_t cap = (intptr_t)((float)self->_len*1.7f) + n + 7;
- const intptr_t nfront = _cdeq_nfront(self);
- _cx_value* d = (_cx_value*)i_realloc(self->_base, cap*c_sizeof(i_key));
- if (!d)
- return 0;
- self->_cap = cap;
- self->_base = d;
- self->data = d + nfront;
- return cap;
-}
-
-static bool
-_cx_memb(_expand_right_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- const intptr_t sz = self->_len, cap = self->_cap;
- const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront;
- if (nback >= n || (intptr_t)((float)sz*1.3f) + n > cap) {
- if (!_cx_memb(_realloc_)(self, n))
- return false;
- c_memmove(self->data + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- } else {
-#if !defined _i_queue
- const intptr_t unused = cap - (sz + n);
- const intptr_t pos = (nfront*2 < unused) ? nfront : unused/2;
-#else
- const intptr_t pos = 0;
-#endif
- c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key));
- c_memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- self->data = self->_base + pos;
- }
- return true;
-}
-
-STC_DEF _cx_self
-_cx_memb(_with_capacity)(const intptr_t n) {
- _cx_self cx = _cx_memb(_init)();
- _cx_memb(_expand_right_half_)(&cx, 0, n);
- return cx;
-}
-
-STC_DEF bool
-_cx_memb(_reserve)(_cx_self* self, const intptr_t n) {
- const intptr_t sz = self->_len;
- return n <= sz || _cx_memb(_expand_right_half_)(self, sz, n - sz);
-}
STC_DEF _cx_value*
-_cx_memb(_push)(_cx_self* self, i_key value) {
- if (_cdeq_nfront(self) + self->_len == self->_cap)
- _cx_memb(_expand_right_half_)(self, self->_len, 1);
- _cx_value *v = self->data + self->_len++;
+_cx_memb(_push_front)(_cx_self* self, i_key value) {
+ intptr_t start = (self->start - 1) & self->capmask;
+ if (start == self->end) { // full
+ _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand
+ start = (self->start - 1) & self->capmask;
+ }
+ _cx_value *v = self->data + start;
+ self->start = start;
*v = value;
return v;
}
-#if !defined i_no_clone
-STC_DEF _cx_self
-_cx_memb(_clone)(_cx_self cx) {
- _cx_self out = _cx_memb(_with_capacity)(cx._len);
- if (out._base)
- for (intptr_t i = 0; i < cx._len; ++i)
- out.data[i] = i_keyclone(cx.data[i]);
- return out;
-}
-#endif
-
-#if !defined _i_queue
-
-static void
-_cx_memb(_expand_left_half_)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- intptr_t cap = self->_cap;
- const intptr_t sz = self->_len;
- const intptr_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront;
- if (nfront >= n) {
- self->data = (_cx_value *)c_memmove(self->data - n, self->data, idx*c_sizeof(i_key));
- } else {
- if ((intptr_t)((float)sz*1.3f) + n > cap)
- cap = _cx_memb(_realloc_)(self, n);
- const intptr_t unused = cap - (sz + n);
- const intptr_t pos = (nback*2 < unused) ? unused - nback : unused/2;
- c_memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*c_sizeof(i_key));
- self->data = (_cx_value *)c_memmove(self->_base + pos, self->data, idx*c_sizeof(i_key));
- }
-}
-
-static _cx_iter
-_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) {
- if (n) {
- if (!pos) pos = self->data + self->_len;
- const intptr_t idx = (pos - self->data);
- if (idx*2 < self->_len)
- _cx_memb(_expand_left_half_)(self, idx, n);
- else
- _cx_memb(_expand_right_half_)(self, idx, n);
- self->_len += n;
- pos = self->data + idx;
- }
- return c_LITERAL(_cx_iter){pos, self->data + self->_len};
-}
-
-STC_DEF _cx_value*
-_cx_memb(_push_front)(_cx_self* self, i_key value) {
- if (self->data == self->_base)
- _cx_memb(_expand_left_half_)(self, 0, 1);
- else
- --self->data;
- ++self->_len;
- *self->data = value;
- return self->data;
+STC_DEF void
+_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ const intptr_t len = _cx_memb(_size)(self);
+ for (intptr_t i = idx + n - 1; i >= idx; --i)
+ i_keydrop(_cx_memb(_at_mut)(self, i));
+ for (intptr_t i = idx, j = i + n; j < len; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j);
+ self->end = (self->end - n) & self->capmask;
}
STC_DEF _cx_iter
-_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1);
+_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ const intptr_t len = _cx_memb(_size)(self);
+ _cx_iter it = {._s=self};
+ if (len + n > self->capmask)
+ if (!_cx_memb(_reserve)(self, len + n))
+ return it;
+ for (intptr_t j = len - 1, i = j + n; j >= idx; --j, --i)
+ *_cx_memb(_at_mut)(self, i) = *_cx_memb(_at)(self, j);
+ self->end = (self->end + n) & self->capmask;
+ it.pos = _cdeq_topos(self, idx);
+ it.ref = self->data + it.pos;
return it;
}
STC_DEF _cx_iter
-_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) {
- assert(p1 && p2);
- intptr_t len = p2 - p1;
- _cx_value* p = p1, *end = self->data + self->_len;
- for (; p != p2; ++p)
- { i_keydrop(p); }
- c_memmove(p1, p2, (end - p2)*c_sizeof *p1);
- self->_len -= len;
- return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len};
-}
-
-#if !defined i_no_clone
-STC_DEF _cx_iter
-_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyclone((*p1));
+_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value* arr, const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ for (intptr_t i = idx, j = 0; j < n; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = arr[j];
return it;
}
-#endif // !i_no_clone
-#if !defined i_no_emplace
STC_DEF _cx_iter
-_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyfrom((*p1));
+_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw* raw, const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ for (intptr_t i = idx, j = 0; j < n; ++i, ++j)
+ *_cx_memb(_at_mut)(self, i) = i_keyfrom(raw[j]);
return it;
}
-#endif // !i_no_emplace
-#if !defined i_no_cmp || defined _i_has_eq
+#if defined _i_has_eq || defined _i_has_cmp
STC_DEF _cx_iter
_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) {
- const _cx_value* p2 = _it2_ptr(i1, i2);
- for (; i1.ref != p2; ++i1.ref) {
+ for (; i1.ref; _cx_memb(_next)(&i1)) {
const _cx_raw r = i_keyto(i1.ref);
if (i_eq((&raw), (&r)))
- return i1;
+ break;
}
- i2.ref = NULL;
- return i2;
+ return i1;
}
-#endif
-#ifndef i_no_cmp
-STC_DEF int
-_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
- const _cx_raw rx = i_keyto(x);
- const _cx_raw ry = i_keyto(y);
- return i_cmp((&rx), (&ry));
+
+STC_DEF bool
+_cx_memb(_eq)(const _cx_self* self, const _cx_self* other) {
+ if (_cx_memb(_size)(self) != _cx_memb(_size)(other)) return false;
+ for (_cx_iter i = _cx_memb(_begin)(self), j = _cx_memb(_begin)(other);
+ i.ref; _cx_memb(_next)(&i), _cx_memb(_next)(&j))
+ {
+ const _cx_raw _rx = i_keyto(i.ref), _ry = i_keyto(j.ref);
+ if (!(i_eq((&_rx), (&_ry)))) return false;
+ }
+ return true;
}
-#endif // !c_no_cmp
-#endif // !_i_queue
+#endif
#endif // IMPLEMENTATION
#define CDEQ_H_INCLUDED
#include "priv/template2.h"
diff --git a/include/stc/clist.h b/include/stc/clist.h
index 65a1ac87..128e848d 100644
--- a/include/stc/clist.h
+++ b/include/stc/clist.h
@@ -109,8 +109,9 @@ STC_API _cx_value* _cx_memb(_push_back_node)(_cx_self* self, _cx_node* node
STC_API _cx_value* _cx_memb(_insert_after_node)(_cx_self* self, _cx_node* ref, _cx_node* node);
STC_API _cx_node* _cx_memb(_unlink_after_node)(_cx_self* self, _cx_node* ref);
STC_API void _cx_memb(_erase_after_node)(_cx_self* self, _cx_node* ref);
-STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* vp) { return _clist_tonode(vp); }
-
+STC_INLINE _cx_node* _cx_memb(_get_node)(_cx_value* pval) { return _clist_tonode(pval); }
+STC_INLINE _cx_node* _cx_memb(_unlink_front_node)(_cx_self* self)
+ { return _cx_memb(_unlink_after_node)(self, self->last); }
#if !defined i_no_clone
STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
STC_INLINE i_key _cx_memb(_value_clone)(i_key val) { return i_keyclone(val); }
@@ -144,10 +145,10 @@ STC_INLINE _cx_value* _cx_memb(_push)(_cx_self* self, i_key value)
{ return _cx_memb(_push_back)(self, value); }
STC_INLINE void _cx_memb(_pop_front)(_cx_self* self)
{ assert(!_cx_memb(_empty)(self)); _cx_memb(_erase_after_node)(self, self->last); }
-STC_INLINE _cx_node* _cx_memb(_unlink_node_front)(_cx_self* self)
- { return _cx_memb(_unlink_after_node)(self, self->last); }
STC_INLINE _cx_value* _cx_memb(_front)(const _cx_self* self) { return &self->last->next->value; }
STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return &self->last->value; }
+STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval) { return i_keyto(pval); }
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* pval) { i_keydrop(pval); }
STC_INLINE intptr_t
_cx_memb(_count)(const _cx_self* self) {
diff --git a/include/stc/cmap.h b/include/stc/cmap.h
index ec3238f6..4ba6156b 100644
--- a/include/stc/cmap.h
+++ b/include/stc/cmap.h
@@ -276,13 +276,6 @@ STC_INLINE intptr_t fastrange_1(uint64_t x, uint64_t n)
STC_INLINE intptr_t fastrange_2(uint64_t x, uint64_t n)
{ return (intptr_t)(x & (n - 1)); } // n power of 2.
-STC_INLINE uint64_t next_power_of_2(uint64_t n) {
- n--;
- n |= n >> 1, n |= n >> 2;
- n |= n >> 4, n |= n >> 8;
- n |= n >> 16, n |= n >> 32;
- return n + 1;
-}
#endif // CMAP_H_INCLUDED
STC_DEF _cx_iter _cx_memb(_begin)(const _cx_self* self) {
@@ -422,7 +415,7 @@ _cx_memb(_reserve)(_cx_self* self, const intptr_t _newcap) {
return true;
intptr_t _newbucks = (intptr_t)((float)_newcap / (i_max_load_factor)) | 1;
#if i_expandby == 2
- _newbucks = (intptr_t)next_power_of_2((uint64_t)_newbucks);
+ _newbucks = cnextpow2(_newbucks);
#endif
_cx_self m = {
(_cx_value *)i_malloc(_newbucks*c_sizeof(_cx_value)),
diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h
index 254bc834..09a747e5 100644
--- a/include/stc/cqueue.h
+++ b/include/stc/cqueue.h
@@ -20,44 +20,198 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-// STC queue
-/*
-#include <stc/crand.h>
-#include <stdio.h>
-
-#define i_key int
-#include <stc/cqueue.h>
-
-int main() {
- int n = 10000000;
- crand_t rng = crand_init(1234);
- crand_unif_t dist = crand_unif_init(0, n);
-
- c_auto (cqueue_int, Q)
- {
- // Push ten million random numbers onto the queue.
- for (int i=0; i<n; ++i)
- cqueue_int_push(&Q, crand_unif(&rng, &dist));
-
- // Push or pop on the queue ten million times
- printf("before: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q));
- for (int i=n; i>0; --i) {
- int r = crand_unif(&rng, &dist);
- if (r & 1)
- ++n, cqueue_int_push(&Q, r);
- else
- --n, cqueue_int_pop(&Q);
- }
- printf("after: size, capacity: %d, %d\n", n, cqueue_int_size(&Q), cqueue_int_capacity(&Q));
+#include "ccommon.h"
+
+#ifndef CQUEUE_H_INCLUDED
+#include "forward.h"
+#include <stdlib.h>
+#include <string.h>
+#endif // CQUEUE_H_INCLUDED
+
+#ifndef _i_prefix
+#define _i_prefix cqueue_
+#endif
+#include "priv/template.h"
+
+#ifndef i_is_forward
+_cx_deftypes(_c_cdeq_types, _cx_self, i_key);
+#endif
+typedef i_keyraw _cx_raw;
+
+STC_API _cx_self _cx_memb(_with_capacity)(const intptr_t n);
+STC_API bool _cx_memb(_reserve)(_cx_self* self, const intptr_t n);
+STC_API void _cx_memb(_clear)(_cx_self* self);
+STC_API void _cx_memb(_drop)(_cx_self* self);
+STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); // push_back
+STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self);
+STC_API _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n);
+
+#define _cdeq_toidx(self, pos) (((pos) - (self)->start) & (self)->capmask)
+#define _cdeq_topos(self, idx) (((self)->start + (idx)) & (self)->capmask)
+
+STC_INLINE _cx_self _cx_memb(_init)(void)
+ { _cx_self cx = {0}; return cx; }
+STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
+ { while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
+STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
+ { _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; }
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
+
+#if !defined i_no_emplace
+STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
+ { return _cx_memb(_push)(self, i_keyfrom(raw)); }
+#endif
+
+#if !defined i_no_clone
+STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
+STC_INLINE i_key _cx_memb(_value_clone)(i_key val)
+ { return i_keyclone(val); }
+#endif // !i_no_clone
+STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self)
+ { return _cdeq_toidx(self, self->end); }
+STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self)
+ { return self->capmask; }
+STC_INLINE bool _cx_memb(_empty)(const _cx_self* self)
+ { return self->start == self->end; }
+STC_INLINE _cx_raw _cx_memb(_value_toraw)(const _cx_value* pval)
+ { return i_keyto(pval); }
+
+STC_INLINE _cx_value*
+_cx_memb(_front)(const _cx_self* self)
+ { return self->data + self->start; }
+
+STC_INLINE _cx_value*
+_cx_memb(_back)(const _cx_self* self)
+ { return self->data + ((self->end - 1) & self->capmask); }
+
+STC_INLINE void
+_cx_memb(_pop)(_cx_self* self) { // pop_front
+ c_ASSERT(!_cx_memb(_empty)(self));
+ i_keydrop((self->data + self->start));
+ self->start = (self->start + 1) & self->capmask;
+}
+
+STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) {
+ if (self->data == other->data) return;
+ _cx_memb(_drop)(self);
+ *self = _cx_memb(_clone)(*other);
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_begin)(const _cx_self* self) {
+ return c_LITERAL(_cx_iter){
+ _cx_memb(_empty)(self) ? NULL : self->data + self->start,
+ self->start, self
+ };
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_end)(const _cx_self* self)
+ { return c_LITERAL(_cx_iter){NULL, self->end, self}; }
+
+STC_INLINE void
+_cx_memb(_next)(_cx_iter* it) {
+ if (it->pos != it->_s->capmask) { ++it->ref; ++it->pos; }
+ else { it->ref -= it->pos; it->pos = 0; }
+ if (it->pos == it->_s->end) it->ref = NULL;
+}
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+STC_DEF _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t n) {
+ intptr_t len = _cx_memb(_size)(it._s);
+ intptr_t pos = it.pos, idx = _cdeq_toidx(it._s, pos);
+ it.pos = (pos + n) & it._s->capmask;
+ it.ref += it.pos - pos;
+ if (!c_LTu(idx + n, len)) it.ref = NULL;
+ return it;
+}
+
+STC_DEF void
+_cx_memb(_clear)(_cx_self* self) {
+ c_foreach (i, _cx_self, *self)
+ { i_keydrop(i.ref); }
+ self->start = 0, self->end = 0;
+}
+
+STC_DEF void
+_cx_memb(_drop)(_cx_self* self) {
+ _cx_memb(_clear)(self);
+ i_free(self->data);
+}
+
+STC_DEF _cx_self
+_cx_memb(_with_capacity)(const intptr_t n) {
+ _cx_self cx = {0};
+ _cx_memb(_reserve)(&cx, n);
+ return cx;
+}
+
+STC_DEF bool
+_cx_memb(_reserve)(_cx_self* self, const intptr_t n) {
+ if (n <= self->capmask)
+ return true;
+ intptr_t oldcap = self->capmask + 1, newcap = cnextpow2(n + 1);
+ _cx_value* data = (_cx_value *)i_realloc(self->data, newcap*c_sizeof *self->data);
+ if (!data)
+ return false;
+ intptr_t head = oldcap - self->start;
+ if (self->start < self->end || self->start == 0)
+ ;
+ else if (head < self->end) {
+ self->start = newcap - head;
+ c_memmove(data + self->start, data + oldcap - head, head*c_sizeof *data);
+ } else {
+ c_memmove(data + oldcap, data, self->end*c_sizeof *data);
+ self->end += oldcap;
}
+ self->capmask = newcap - 1;
+ self->data = data;
+ return true;
}
-*/
-#define _i_prefix cqueue_
-#define _i_queue
-#define _pop_front _pop
+STC_DEF _cx_value*
+_cx_memb(_push)(_cx_self* self, i_key value) { // push_back
+ intptr_t end = (self->end + 1) & self->capmask;
+ if (end == self->start) { // full
+ _cx_memb(_reserve)(self, self->capmask + 3); // => 2x expand
+ end = (self->end + 1) & self->capmask;
+ }
+ _cx_value *v = self->data + self->end;
+ self->end = end;
+ *v = value;
+ return v;
+}
+
+STC_DEF void
+_cx_memb(_shrink_to_fit)(_cx_self *self) {
+ intptr_t sz = _cx_memb(_size)(self), j = 0;
+ if (sz > self->capmask/2)
+ return;
+ _cx_self out = _cx_memb(_with_capacity)(sz);
+ if (!out.data)
+ return;
+ c_foreach (i, _cx_self, *self)
+ out.data[j++] = *i.ref;
+ out.end = sz;
+ i_free(self->data);
+ *self = out;
+}
-#include "cdeq.h"
+#if !defined i_no_clone
+STC_DEF _cx_self
+_cx_memb(_clone)(_cx_self cx) {
+ intptr_t sz = _cx_memb(_size)(&cx), j = 0;
+ _cx_self out = _cx_memb(_with_capacity)(sz);
+ if (out.data)
+ c_foreach (i, _cx_self, cx)
+ out.data[j++] = i_keyclone((*i.ref));
+ out.end = sz;
+ return out;
+}
-#undef _pop_front
-#undef _i_queue
+#endif // i_no_clone
+#endif // IMPLEMENTATION
+#include "priv/template2.h"
+#define CQUEUE_H_INCLUDED
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 3cbd90b7..a7eb1a05 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -81,10 +81,8 @@ STC_API void _cx_memb(_clear)(_cx_self* self);
STC_API bool _cx_memb(_reserve)(_cx_self* self, intptr_t cap);
STC_API bool _cx_memb(_resize)(_cx_self* self, intptr_t size, i_key null);
STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value);
-STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
-STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n);
+STC_API _cx_iter _cx_memb(_erase_n)(_cx_self* self, intptr_t idx, intptr_t n);
+STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, intptr_t idx, intptr_t n);
#if !defined i_no_cmp || defined _i_has_eq
STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw);
#endif
@@ -95,26 +93,23 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2,
STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
#if !defined i_no_emplace
-STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2);
-STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw)
- { return _cx_memb(_push)(self, i_keyfrom(raw)); }
-STC_INLINE _cx_iter
-_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw arr[], const intptr_t n) {
- return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n);
+STC_API _cx_iter
+_cx_memb(_emplace_n)(_cx_self* self, intptr_t idx, const _cx_raw raw[], intptr_t n);
+
+STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) {
+ return _cx_memb(_push)(self, i_keyfrom(raw));
}
-STC_INLINE _cx_iter
-_cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
- return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1);
+STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) {
+ return _cx_memb(_push)(self, i_keyfrom(raw));
+}
+STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) {
+ return _cx_memb(_emplace_n)(self, _it_ptr(it) - self->data, &raw, 1);
}
#endif // !i_no_emplace
#if !defined i_no_clone
STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
-STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2);
+STC_API _cx_iter _cx_memb(_copy_n)(_cx_self* self, intptr_t idx, const _cx_value arr[], intptr_t n);
STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, intptr_t n)
{ while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
@@ -124,8 +119,7 @@ STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val)
STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) {
if (self->data == other->data) return;
_cx_memb(_clear)(self);
- _cx_memb(_copy_range)(self, self->data, other->data,
- other->data + other->_len);
+ _cx_memb(_copy_n)(self, 0, other->data, other->_len);
}
#endif // !i_no_clone
@@ -161,31 +155,29 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) {
_cx_memb(_reserve)(self, _cx_memb(_size)(self));
}
-
-STC_INLINE _cx_iter
-_cx_memb(_insert)(_cx_self* self, const intptr_t idx, i_key value) {
- return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1);
-}
STC_INLINE _cx_iter
_cx_memb(_insert_n)(_cx_self* self, const intptr_t idx, const _cx_value arr[], const intptr_t n) {
- return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n);
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
+ if (it.ref)
+ c_memcpy(it.ref, arr, n*c_sizeof *arr);
+ return it;
}
STC_INLINE _cx_iter
-_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) {
- return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1);
+_cx_memb(_insert)(_cx_self* self, const intptr_t idx, const i_key value) {
+ return _cx_memb(_insert_n)(self, idx, &value, 1);
}
-
STC_INLINE _cx_iter
-_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t n) {
- return _cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n);
+_cx_memb(_insert_at)(_cx_self* self, _cx_iter it, const i_key value) {
+ return _cx_memb(_insert_n)(self, _it_ptr(it) - self->data, &value, 1);
}
+
STC_INLINE _cx_iter
_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
- return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1);
+ return _cx_memb(_erase_n)(self, it.ref - self->data, 1);
}
STC_INLINE _cx_iter
_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) {
- return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2));
+ return _cx_memb(_erase_n)(self, i1.ref - self->data, _it2_ptr(i1, i2) - i1.ref);
}
STC_INLINE const _cx_value*
@@ -329,73 +321,58 @@ _cx_memb(_push)(_cx_self* self, i_key value) {
}
STC_DEF _cx_iter
-_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const intptr_t n) {
- if (n) {
- if (!pos) pos = self->data + self->_len;
- const intptr_t idx = (pos - self->data);
- if (self->_len + n > self->_cap) {
- if (!_cx_memb(_reserve)(self, self->_len*3/2 + n))
- return _cx_memb(_end)(self);
- pos = self->data + idx;
- }
- c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos);
- self->_len += n;
- }
+_cx_memb(_insert_uninit)(_cx_self* self, const intptr_t idx, const intptr_t n) {
+ if (self->_len + n > self->_cap)
+ if (!_cx_memb(_reserve)(self, self->_len*3/2 + n))
+ return _cx_memb(_end)(self);
+
+ _cx_value* pos = self->data + idx;
+ c_memmove(pos + n, pos, (self->_len - idx)*c_sizeof *pos);
+ self->_len += n;
return c_LITERAL(_cx_iter){pos, self->data + self->_len};
}
STC_DEF _cx_iter
-_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
- if (it.ref)
- c_memcpy(it.ref, p1, (p2 - p1)*c_sizeof *p1);
- return it;
-}
-
-STC_DEF _cx_iter
-_cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) {
- intptr_t len = (p2 - p1);
- _cx_value* p = p1, *end = self->data + self->_len;
- for (; p != p2; ++p)
+_cx_memb(_erase_n)(_cx_self* self, const intptr_t idx, const intptr_t len) {
+ _cx_value* d = self->data + idx, *p = d, *end = self->data + self->_len;
+ for (intptr_t i = 0; i < len; ++i, ++p)
{ i_keydrop(p); }
- c_memmove(p1, p2, (end - p2)*c_sizeof *p1);
+ c_memmove(d, p, (end - p)*c_sizeof *d);
self->_len -= len;
- return c_LITERAL(_cx_iter){p2 == end ? NULL : p1, end - len};
+ return c_LITERAL(_cx_iter){p == end ? NULL : d, end - len};
}
#if !defined i_no_clone
STC_DEF _cx_self
_cx_memb(_clone)(_cx_self cx) {
_cx_self out = _cx_memb(_init)();
- _cx_memb(_copy_range)(&out, out.data, cx.data, cx.data + cx._len);
+ _cx_memb(_copy_n)(&out, 0, cx.data, cx._len);
return out;
}
STC_DEF _cx_iter
-_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos,
- const _cx_value* p1, const _cx_value* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
+_cx_memb(_copy_n)(_cx_self* self, const intptr_t idx,
+ const _cx_value arr[], const intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyclone((*p1));
+ for (_cx_value* p = it.ref, *q = p + n; p != q; ++arr)
+ *p++ = i_keyclone((*arr));
return it;
}
#endif // !i_no_clone
#if !defined i_no_emplace
STC_DEF _cx_iter
-_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
- const _cx_raw* p1, const _cx_raw* p2) {
- _cx_iter it = _cx_memb(_insert_uninit)(self, pos, (p2 - p1));
+_cx_memb(_emplace_n)(_cx_self* self, const intptr_t idx, const _cx_raw raw[], intptr_t n) {
+ _cx_iter it = _cx_memb(_insert_uninit)(self, idx, n);
if (it.ref)
- for (_cx_value* p = it.ref; p1 != p2; ++p1)
- *p++ = i_keyfrom((*p1));
+ for (_cx_value* p = it.ref; n--; ++raw, ++p)
+ *p = i_keyfrom((*raw));
return it;
}
#endif // !i_no_emplace
-
#if !defined i_no_cmp || defined _i_has_eq
+
STC_DEF _cx_iter
_cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) {
const _cx_value* p2 = _it2_ptr(i1, i2);
diff --git a/include/stc/forward.h b/include/stc/forward.h
index b534e48b..9eafb857 100644
--- a/include/stc/forward.h
+++ b/include/stc/forward.h
@@ -81,12 +81,17 @@ typedef union {
#define _c_cdeq_types(SELF, VAL) \
typedef VAL SELF##_value; \
- typedef struct { SELF##_value *ref, *end; } SELF##_iter; \
\
typedef struct SELF { \
- SELF##_value *_base, *data; \
- intptr_t _len, _cap; \
- } SELF
+ SELF##_value *data; \
+ intptr_t start, end, capmask; \
+ } SELF; \
+\
+ typedef struct { \
+ SELF##_value *ref; \
+ intptr_t pos; \
+ const SELF* _s; \
+ } SELF##_iter
#define _c_clist_types(SELF, VAL) \
typedef VAL SELF##_value; \
diff --git a/include/stc/priv/template.h b/include/stc/priv/template.h
index 2605a434..f70281c7 100644
--- a/include/stc/priv/template.h
+++ b/include/stc/priv/template.h
@@ -20,9 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifdef _i_template
- #error template.h already included
-#endif
+#ifndef _i_template
#define _i_template
#ifndef STC_TEMPLATE_H_INCLUDED
@@ -107,6 +105,9 @@
#ifdef i_eq
#define _i_has_eq
#endif
+#if defined i_cmp || defined i_less
+ #define _i_has_cmp
+#endif
#if defined i_key_str
#define i_keyclass cstr
@@ -288,3 +289,4 @@
#ifndef _i_has_from
#define i_no_emplace
#endif
+#endif
diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h
index 2e8a6c8d..66ed7739 100644
--- a/include/stc/priv/template2.h
+++ b/include/stc/priv/template2.h
@@ -20,6 +20,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#ifdef i_more
+#undef i_more
+#else
#undef i_type
#undef i_tag
#undef i_imp
@@ -74,4 +77,6 @@
#undef _i_expandby
#undef _i_has_from
#undef _i_has_eq
+#undef _i_has_cmp
#undef _i_template
+#endif \ No newline at end of file