summaryrefslogtreecommitdiffhomepage
path: root/include/stc/cvec.h
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-09-05 23:12:53 +0200
committerTyge Løvset <[email protected]>2021-09-05 23:12:53 +0200
commit44c64073662500684008c87e3a87f33b04e53c13 (patch)
tree6a927fe91e6d2eee073cdce5d30ff87f5e709ce6 /include/stc/cvec.h
parentb2dc4c367030232068338b9e7b3faee03c2db0a8 (diff)
downloadSTC-modified-44c64073662500684008c87e3a87f33b04e53c13.tar.gz
STC-modified-44c64073662500684008c87e3a87f33b04e53c13.zip
New usage style. only cvec is functional. see vec_test_new.c
Diffstat (limited to 'include/stc/cvec.h')
-rw-r--r--include/stc/cvec.h611
1 files changed, 293 insertions, 318 deletions
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 567c22ae..daa95170 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -20,332 +20,307 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifndef CVEC_H_INCLUDED
-#define CVEC_H_INCLUDED
+#ifndef CVEC_H_INCLUDED
#include "ccommon.h"
+#include "forward.h"
#include <stdlib.h>
#include <string.h>
-#define forward_cvec(X, Value) _c_cvec_types(cvec_##X, Value)
-
-#define using_cvec(...) c_MACRO_OVERLOAD(using_cvec, __VA_ARGS__)
-
-#define using_cvec_2(X, Value) \
- using_cvec_3(X, Value, c_default_compare)
-#define using_cvec_3(X, Value, valueCompare) \
- using_cvec_5(X, Value, valueCompare, c_default_del, c_default_fromraw)
-#define using_cvec_4(X, Value, valueCompare, valueDel) \
- using_cvec_5(X, Value, valueCompare, valueDel, c_no_clone)
-#define using_cvec_5(X, Value, valueCompare, valueDel, valueClone) \
- using_cvec_7(X, Value, valueCompare, valueDel, valueClone, c_default_toraw, Value)
-#define using_cvec_7(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \
- _c_using_cvec(cvec_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, c_true)
-#define using_cvec_8(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \
- _c_using_cvec(cvec_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes)
-
-#define using_cvec_str() \
- using_cvec_7(str, cstr, c_rawstr_compare, cstr_del, cstr_from, cstr_str, const char*)
-
-struct cvec_rep { size_t size, cap; void* data[]; };
-#define _cvec_rep(self) c_container_of((self)->data, struct cvec_rep, data)
-
-#define _c_cvec_types(CX, Value) \
- typedef Value CX##_value_t; \
- typedef struct { CX##_value_t *ref; } CX##_iter_t; \
- typedef struct { CX##_value_t *data; } CX
-
-#define _c_using_cvec(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \
-\
- defTypes( _c_cvec_types(CX, Value); ) \
- typedef RawValue CX##_rawvalue_t; \
-\
- STC_API CX CX##_init(void); \
- STC_API CX CX##_clone(CX cx); \
- STC_API void CX##_del(CX* self); \
- STC_API void CX##_clear(CX* self); \
- STC_API void CX##_reserve(CX* self, size_t cap); \
- STC_API void CX##_resize(CX* self, size_t size, Value fill_val); \
- STC_API int CX##_value_compare(const CX##_value_t* x, const CX##_value_t* y); \
- STC_API CX##_iter_t CX##_find_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \
- STC_API CX##_iter_t CX##_bsearch_in(CX##_iter_t it1, CX##_iter_t it2, RawValue raw); \
- STC_API void CX##_push_back(CX* self, Value value); \
- STC_API CX##_iter_t CX##_erase_range_p(CX* self, CX##_value_t* p1, CX##_value_t* p2); \
- STC_API CX##_iter_t CX##_insert_range_p(CX* self, CX##_value_t* pos, \
- const CX##_value_t* p1, const CX##_value_t* p2, bool clone); \
- STC_API CX##_iter_t CX##_emplace_range_p(CX* self, CX##_value_t* pos, \
- const CX##_rawvalue_t* p1, const CX##_rawvalue_t* p2); \
-\
- STC_INLINE size_t CX##_size(CX cx) { return _cvec_rep(&cx)->size; } \
- STC_INLINE size_t CX##_capacity(CX cx) { return _cvec_rep(&cx)->cap; } \
- STC_INLINE bool CX##_empty(CX cx) {return !_cvec_rep(&cx)->size;} \
- STC_INLINE Value CX##_value_fromraw(RawValue raw) {return valueFromRaw(raw);} \
- STC_INLINE RawValue CX##_value_toraw(CX##_value_t* val) {return valueToRaw(val);} \
- STC_INLINE Value CX##_value_clone(CX##_value_t val) \
- {return valueFromRaw(valueToRaw(&val));} \
- STC_INLINE void CX##_swap(CX* a, CX* b) {c_swap(CX, *a, *b);} \
- STC_INLINE CX##_value_t*CX##_front(const CX* self) {return self->data;} \
- STC_INLINE CX##_value_t*CX##_back(const CX* self) \
- {return self->data + _cvec_rep(self)->size - 1;} \
- STC_INLINE void CX##_emplace_back(CX* self, RawValue raw) \
- {CX##_push_back(self, valueFromRaw(raw));} \
- STC_INLINE void CX##_pop_back(CX* self) \
- {valueDel(&self->data[--_cvec_rep(self)->size]);} \
- STC_INLINE CX##_iter_t CX##_begin(const CX* self) \
- {return c_make(CX##_iter_t){self->data};} \
- STC_INLINE CX##_iter_t CX##_end(const CX* self) \
- {return c_make(CX##_iter_t){self->data + _cvec_rep(self)->size};} \
- STC_INLINE void CX##_next(CX##_iter_t* it) {++it->ref;} \
- STC_INLINE CX##_iter_t CX##_adv(CX##_iter_t it, intptr_t offs) {it.ref += offs; return it;} \
- STC_INLINE size_t CX##_idx(CX cx, CX##_iter_t it) {return it.ref - cx.data;} \
-\
- STC_INLINE CX \
- CX##_with_size(size_t size, Value null_val) { \
- CX cx = CX##_init(); \
- CX##_resize(&cx, size, null_val); \
- return cx; \
- } \
-\
- STC_INLINE CX \
- CX##_with_capacity(size_t size) { \
- CX cx = CX##_init(); \
- CX##_reserve(&cx, size); \
- return cx; \
- } \
-\
- STC_INLINE void \
- CX##_shrink_to_fit(CX *self) { \
- CX cx = CX##_clone(*self); \
- CX##_del(self); *self = cx; \
- } \
-\
- STC_INLINE CX##_iter_t \
- CX##_insert(CX* self, size_t idx, Value value) { \
- return CX##_insert_range_p(self, self->data + idx, &value, &value + 1, false); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_insert_n(CX* self, size_t idx, const CX##_value_t arr[], size_t n) { \
- return CX##_insert_range_p(self, self->data + idx, arr, arr + n, false); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_insert_at(CX* self, CX##_iter_t it, Value value) { \
- return CX##_insert_range_p(self, it.ref, &value, &value + 1, false); \
- } \
-\
- STC_INLINE CX##_iter_t \
- CX##_emplace(CX* self, size_t idx, RawValue raw) { \
- return CX##_emplace_range_p(self, self->data + idx, &raw, &raw + 1); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_emplace_n(CX* self, size_t idx, const CX##_rawvalue_t arr[], size_t n) { \
- return CX##_emplace_range_p(self, self->data + idx, arr, arr + n); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_emplace_at(CX* self, CX##_iter_t it, RawValue raw) { \
- return CX##_emplace_range_p(self, it.ref, &raw, &raw + 1); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_emplace_range(CX* self, CX##_iter_t it, CX##_iter_t it1, CX##_iter_t it2) { \
- return CX##_insert_range_p(self, it.ref, it1.ref, it2.ref, true); \
- } \
- STC_INLINE void \
- CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) { \
- CX##_emplace_range_p(self, self->data + _cvec_rep(self)->size, arr, arr + n); \
- } \
-\
- STC_INLINE CX##_iter_t \
- CX##_erase(CX* self, size_t idx) { \
- return CX##_erase_range_p(self, self->data + idx, self->data + idx + 1); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_erase_n(CX* self, size_t idx, size_t n) { \
- return CX##_erase_range_p(self, self->data + idx, self->data + idx + n); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_erase_at(CX* self, CX##_iter_t it) { \
- return CX##_erase_range_p(self, it.ref, it.ref + 1); \
- } \
- STC_INLINE CX##_iter_t \
- CX##_erase_range(CX* self, CX##_iter_t it1, CX##_iter_t it2) { \
- return CX##_erase_range_p(self, it1.ref, it2.ref); \
- } \
-\
- STC_INLINE CX##_value_t* \
- CX##_at(const CX* self, size_t idx) { \
- assert(idx < _cvec_rep(self)->size); \
- return self->data + idx; \
- } \
-\
- STC_INLINE CX##_iter_t \
- CX##_find(const CX* self, RawValue raw) { \
- return CX##_find_in(CX##_begin(self), CX##_end(self), raw); \
- } \
-\
- STC_INLINE CX##_value_t* \
- CX##_get(const CX* self, RawValue raw) { \
- CX##_iter_t end = CX##_end(self); \
- CX##_value_t* val = CX##_find_in(CX##_begin(self), end, raw).ref; \
- return val == end.ref ? NULL : val; \
- } \
-\
- STC_INLINE CX##_iter_t \
- CX##_bsearch(const CX* self, RawValue raw) { \
- return CX##_bsearch_in(CX##_begin(self), CX##_end(self), raw); \
- } \
- STC_INLINE void \
- CX##_sort_range(CX##_iter_t i1, CX##_iter_t i2, \
- int(*_cmp_)(const CX##_value_t*, const CX##_value_t*)) { \
- qsort(i1.ref, i2.ref - i1.ref, sizeof(CX##_value_t), (int(*)(const void*, const void*)) _cmp_); \
- } \
- STC_INLINE void \
- CX##_sort(CX* self) { \
- CX##_sort_range(CX##_begin(self), CX##_end(self), CX##_value_compare); \
- } \
-\
- _c_implement_cvec(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \
- struct stc_trailing_semicolon
+struct cvec_Rep_ { size_t size, cap; void* data[]; };
+#define cvec_rep_(self) c_container_of((self)->data, struct cvec_Rep_, data)
+#endif // CVEC_H_INCLUDED
+
+#define i_CNT cvec
+#include "template.h"
+
+#if !defined i_FWD
+ cx_deftypes(_c_cvec_types, Self, i_VAL);
+#endif
+typedef i_VALRAW cx_rawvalue_t;
+
+STC_API Self cx_memb(_init)(void);
+STC_API Self cx_memb(_clone)(Self cx);
+STC_API void cx_memb(_del)(Self* self);
+STC_API void cx_memb(_clear)(Self* self);
+STC_API void cx_memb(_reserve)(Self* self, size_t cap);
+STC_API void cx_memb(_resize)(Self* self, size_t size, i_VAL fill_val);
+STC_API int cx_memb(_value_compare)(const cx_value_t* x, const cx_value_t* y);
+STC_API cx_iter_t cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW raw);
+STC_API cx_iter_t cx_memb(_bsearch_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW raw);
+STC_API void cx_memb(_push_back)(Self* self, i_VAL value);
+STC_API cx_iter_t cx_memb(_erase_range_p)(Self* self, cx_value_t* p1, cx_value_t* p2);
+STC_API cx_iter_t cx_memb(_insert_range_p)(Self* self, cx_value_t* pos,
+ const cx_value_t* p1, const cx_value_t* p2, bool clone);
+STC_API cx_iter_t cx_memb(_emplace_range_p)(Self* self, cx_value_t* pos,
+ const cx_rawvalue_t* p1, const cx_rawvalue_t* p2);
+
+STC_INLINE size_t cx_memb(_size)(Self cx) { return cvec_rep_(&cx)->size; }
+STC_INLINE size_t cx_memb(_capacity)(Self cx) { return cvec_rep_(&cx)->cap; }
+STC_INLINE bool cx_memb(_empty)(Self cx) { return !cvec_rep_(&cx)->size; }
+STC_INLINE i_VAL cx_memb(_value_fromraw)(i_VALRAW raw) { return i_VALFROM(raw); }
+STC_INLINE i_VALRAW cx_memb(_value_toraw)(cx_value_t* val) { return i_VALTO(val); }
+STC_INLINE i_VAL cx_memb(_value_clone)(cx_value_t val)
+ { return i_VALFROM(i_VALTO(&val)); }
+STC_INLINE void cx_memb(_swap)(Self* a, Self* b) {c_swap(Self, *a, *b); }
+STC_INLINE cx_value_t* cx_memb(_front)(const Self* self) { return self->data; }
+STC_INLINE cx_value_t* cx_memb(_back)(const Self* self)
+ { return self->data + cvec_rep_(self)->size - 1; }
+STC_INLINE void cx_memb(_emplace_back)(Self* self, i_VALRAW raw)
+ { cx_memb(_push_back)(self, i_VALFROM(raw)); }
+STC_INLINE void cx_memb(_pop_back)(Self* self)
+ { i_VALDEL(&self->data[--cvec_rep_(self)->size]); }
+STC_INLINE cx_iter_t cx_memb(_begin)(const Self* self)
+ { return c_make(cx_iter_t){self->data}; }
+STC_INLINE cx_iter_t cx_memb(_end)(const Self* self)
+ { return c_make(cx_iter_t){self->data + cvec_rep_(self)->size}; }
+STC_INLINE void cx_memb(_next)(cx_iter_t* it) {++it->ref; }
+STC_INLINE cx_iter_t cx_memb(_adv)(cx_iter_t it, intptr_t offs) {it.ref += offs; return it; }
+STC_INLINE size_t cx_memb(_idx)(Self cx, cx_iter_t it) { return it.ref - cx.data; }
+
+STC_INLINE Self
+cx_memb(_with_size)(size_t size, i_VAL null_val) {
+ Self cx = cx_memb(_init)();
+ cx_memb(_resize)(&cx, size, null_val);
+ return cx;
+}
+
+STC_INLINE Self
+cx_memb(_with_capacity)(size_t size) {
+ Self cx = cx_memb(_init)();
+ cx_memb(_reserve)(&cx, size);
+ return cx;
+}
+
+STC_INLINE void
+cx_memb(_shrink_to_fit)(Self *self) {
+ Self cx = cx_memb(_clone)(*self);
+ cx_memb(_del)(self); *self = cx;
+}
+
+STC_INLINE cx_iter_t
+cx_memb(_insert)(Self* self, size_t idx, i_VAL value) {
+ return cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1, false);
+}
+STC_INLINE cx_iter_t
+cx_memb(_insert_n)(Self* self, size_t idx, const cx_value_t arr[], size_t n) {
+ return cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n, false);
+}
+STC_INLINE cx_iter_t
+cx_memb(_insert_at)(Self* self, cx_iter_t it, i_VAL value) {
+ return cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1, false);
+}
+
+STC_INLINE cx_iter_t
+cx_memb(_emplace)(Self* self, size_t idx, i_VALRAW raw) {
+ return cx_memb(_emplace_range_p)(self, self->data + idx, &raw, &raw + 1);
+}
+STC_INLINE cx_iter_t
+cx_memb(_emplace_n)(Self* self, size_t idx, const cx_rawvalue_t arr[], size_t n) {
+ return cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n);
+}
+STC_INLINE cx_iter_t
+cx_memb(_emplace_at)(Self* self, cx_iter_t it, i_VALRAW raw) {
+ return cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1);
+}
+STC_INLINE cx_iter_t
+cx_memb(_emplace_range)(Self* self, cx_iter_t it, cx_iter_t it1, cx_iter_t it2) {
+ return cx_memb(_insert_range_p)(self, it.ref, it1.ref, it2.ref, true);
+}
+STC_INLINE void
+cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) {
+ cx_memb(_emplace_range_p)(self, self->data + cvec_rep_(self)->size, arr, arr + n);
+}
+
+STC_INLINE cx_iter_t
+cx_memb(_erase)(Self* self, size_t idx) {
+ return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + 1);
+}
+STC_INLINE cx_iter_t
+cx_memb(_erase_n)(Self* self, size_t idx, size_t n) {
+ return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n);
+}
+STC_INLINE cx_iter_t
+cx_memb(_erase_at)(Self* self, cx_iter_t it) {
+ return cx_memb(_erase_range_p)(self, it.ref, it.ref + 1);
+}
+STC_INLINE cx_iter_t
+cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2) {
+ return cx_memb(_erase_range_p)(self, it1.ref, it2.ref);
+}
+
+STC_INLINE cx_value_t*
+cx_memb(_at)(const Self* self, size_t idx) {
+ assert(idx < cvec_rep_(self)->size);
+ return self->data + idx;
+}
+
+STC_INLINE cx_iter_t
+cx_memb(_find)(const Self* self, i_VALRAW raw) {
+ return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), raw);
+}
+
+STC_INLINE cx_value_t*
+cx_memb(_get)(const Self* self, i_VALRAW raw) {
+ cx_iter_t end = cx_memb(_end)(self);
+ cx_value_t* val = cx_memb(_find_in)(cx_memb(_begin)(self), end, raw).ref;
+ return val == end.ref ? NULL : val;
+}
+
+STC_INLINE cx_iter_t
+cx_memb(_bsearch)(const Self* self, i_VALRAW raw) {
+ return cx_memb(_bsearch_in)(cx_memb(_begin)(self), cx_memb(_end)(self), raw);
+}
+STC_INLINE void
+cx_memb(_sort_range)(cx_iter_t i1, cx_iter_t i2,
+ int(*_cmp_)(const cx_value_t*, const cx_value_t*)) {
+ qsort(i1.ref, i2.ref - i1.ref, sizeof(cx_value_t), (int(*)(const void*, const void*)) _cmp_);
+}
+STC_INLINE void
+cx_memb(_sort)(Self* self) {
+ cx_memb(_sort_range)(cx_memb(_begin)(self), cx_memb(_end)(self), cx_memb(_value_compare));
+}
/* -------------------------- IMPLEMENTATION ------------------------- */
-#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
-static struct cvec_rep _cvec_sentinel = {0, 0};
-
-#define _c_implement_cvec(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \
-\
- STC_DEF CX \
- CX##_init(void) { \
- CX cx = {(CX##_value_t *) _cvec_sentinel.data}; \
- return cx; \
- } \
-\
- STC_DEF void \
- CX##_clear(CX* self) { \
- struct cvec_rep* rep = _cvec_rep(self); if (rep->cap) { \
- for (CX##_value_t *p = self->data, *q = p + rep->size; p != q; ++p) \
- valueDel(p); \
- rep->size = 0; \
- } \
- } \
-\
- STC_DEF void \
- CX##_del(CX* self) { \
- CX##_clear(self); \
- if (_cvec_rep(self)->cap) \
- c_free(_cvec_rep(self)); \
- } \
-\
- STC_DEF void \
- CX##_reserve(CX* self, size_t cap) { \
- struct cvec_rep* rep = _cvec_rep(self); \
- size_t len = rep->size, oldcap = rep->cap; \
- if (cap > oldcap) { \
- rep = (struct cvec_rep*) c_realloc(oldcap ? rep : NULL, \
- offsetof(struct cvec_rep, data) + cap*sizeof(Value)); \
- self->data = (CX##_value_t*) rep->data; \
- rep->size = len; \
- rep->cap = cap; \
- } \
- } \
-\
- STC_DEF void \
- CX##_resize(CX* self, size_t len, Value null_val) { \
- CX##_reserve(self, len); \
- struct cvec_rep* rep = _cvec_rep(self); \
- size_t i, n = rep->size; \
- for (i = len; i < n; ++i) valueDel(self->data + i); \
- for (i = n; i < len; ++i) self->data[i] = null_val; \
- if (rep->cap) rep->size = len; \
- } \
-\
- STC_DEF void \
- CX##_push_back(CX* self, Value value) { \
- size_t len = _cvec_rep(self)->size; \
- if (len == CX##_capacity(*self)) \
- CX##_reserve(self, (len*13 >> 3) + 4); \
- self->data[_cvec_rep(self)->size++] = value; \
- } \
-\
- STC_DEF CX \
- CX##_clone(CX cx) { \
- size_t len = _cvec_rep(&cx)->size; \
- CX out = CX##_with_capacity(len); \
- CX##_insert_range_p(&out, out.data, cx.data, cx.data + len, true); \
- return out; \
- } \
-\
- STC_DEF CX##_value_t* \
- CX##_insert_space_(CX* self, CX##_value_t* pos, size_t len) { \
- size_t idx = pos - self->data, size = _cvec_rep(self)->size; \
- if (len == 0) return pos; \
- if (size + len > CX##_capacity(*self)) \
- CX##_reserve(self, (size*13 >> 3) + len), \
- pos = self->data + idx; \
- _cvec_rep(self)->size += len; \
- memmove(pos + len, pos, (size - idx) * sizeof(Value)); \
- return pos; \
- } \
-\
- STC_DEF CX##_iter_t \
- CX##_insert_range_p(CX* self, CX##_value_t* pos, const CX##_value_t* p1, \
- const CX##_value_t* p2, bool clone) { \
- pos = CX##_insert_space_(self, pos, p2 - p1); \
- CX##_iter_t it = {pos}; \
- if (clone) while (p1 != p2) *pos++ = valueFromRaw(valueToRaw(p1++)); \
- else memcpy(pos, p1, (p2 - p1)*sizeof *p1); \
- return it; \
- } \
-\
- STC_DEF CX##_iter_t \
- CX##_emplace_range_p(CX* self, CX##_value_t* pos, const CX##_rawvalue_t* p1, const CX##_rawvalue_t* p2) { \
- pos = CX##_insert_space_(self, pos, p2 - p1); \
- CX##_iter_t it = {pos}; \
- while (p1 != p2) *pos++ = valueFromRaw(*p1++); \
- return it; \
- } \
-\
- STC_DEF CX##_iter_t \
- CX##_erase_range_p(CX* self, CX##_value_t* p1, CX##_value_t* p2) { \
- intptr_t len = p2 - p1; \
- if (len > 0) { \
- CX##_value_t* p = p1, *end = self->data + _cvec_rep(self)->size; \
- while (p != p2) valueDel(p++); \
- memmove(p1, p2, (end - p2) * sizeof(Value)); \
- _cvec_rep(self)->size -= len; \
- } \
- return c_make(CX##_iter_t){.ref = p1}; \
- } \
-\
- STC_DEF CX##_iter_t \
- CX##_find_in(CX##_iter_t i1, CX##_iter_t i2, RawValue raw) { \
- for (; i1.ref != i2.ref; ++i1.ref) { \
- RawValue r = valueToRaw(i1.ref); \
- if (valueCompareRaw(&raw, &r) == 0) return i1; \
- } \
- return i2; \
- } \
-\
- STC_DEF CX##_iter_t \
- CX##_bsearch_in(CX##_iter_t i1, CX##_iter_t i2, RawValue raw) { \
- CX##_iter_t mid, last = i2; \
- while (i1.ref != i2.ref) { \
- mid.ref = i1.ref + ((i2.ref - i1.ref)>>1); \
- int c; RawValue m = valueToRaw(mid.ref); \
- if ((c = valueCompareRaw(&raw, &m)) == 0) return mid; \
- else if (c < 0) i2.ref = mid.ref; \
- else i1.ref = mid.ref + 1; \
- } \
- return last; \
- } \
-\
- STC_DEF int \
- CX##_value_compare(const CX##_value_t* x, const CX##_value_t* y) { \
- RawValue rx = valueToRaw(x); \
- RawValue ry = valueToRaw(y); \
- return valueCompareRaw(&rx, &ry); \
+#if defined i_IMP
+#ifndef CVEC_H_INCLUDED
+static struct cvec_Rep_ _cvec_sentinel = {0, 0};
+#endif
+
+STC_DEF Self
+cx_memb(_init)(void) {
+ Self cx = {(cx_value_t *) _cvec_sentinel.data};
+ return cx;
+}
+
+STC_DEF void
+cx_memb(_clear)(Self* self) {
+ struct cvec_Rep_* rep = cvec_rep_(self); if (rep->cap) {
+ for (cx_value_t *p = self->data, *q = p + rep->size; p != q; ++p)
+ i_VALDEL(p);
+ rep->size = 0;
}
+}
-#else
-#define _c_implement_cvec(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue)
-#endif
+STC_DEF void
+cx_memb(_del)(Self* self) {
+ cx_memb(_clear)(self);
+ if (cvec_rep_(self)->cap)
+ c_free(cvec_rep_(self));
+}
+
+STC_DEF void
+cx_memb(_reserve)(Self* self, size_t cap) {
+ struct cvec_Rep_* rep = cvec_rep_(self);
+ size_t len = rep->size, oldcap = rep->cap;
+ if (cap > oldcap) {
+ rep = (struct cvec_Rep_*) c_realloc(oldcap ? rep : NULL,
+ offsetof(struct cvec_Rep_, data) + cap*sizeof(i_VAL));
+ self->data = (cx_value_t*) rep->data;
+ rep->size = len;
+ rep->cap = cap;
+ }
+}
+
+STC_DEF void
+cx_memb(_resize)(Self* self, size_t len, i_VAL null_val) {
+ cx_memb(_reserve)(self, len);
+ struct cvec_Rep_* rep = cvec_rep_(self);
+ size_t i, n = rep->size;
+ for (i = len; i < n; ++i) i_VALDEL(self->data + i);
+ for (i = n; i < len; ++i) self->data[i] = null_val;
+ if (rep->cap) rep->size = len;
+}
+
+STC_DEF void
+cx_memb(_push_back)(Self* self, i_VAL value) {
+ size_t len = cvec_rep_(self)->size;
+ if (len == cx_memb(_capacity)(*self))
+ cx_memb(_reserve)(self, (len*13 >> 3) + 4);
+ self->data[cvec_rep_(self)->size++] = value;
+}
+
+STC_DEF Self
+cx_memb(_clone)(Self cx) {
+ size_t len = cvec_rep_(&cx)->size;
+ Self out = cx_memb(_with_capacity)(len);
+ cx_memb(_insert_range_p)(&out, out.data, cx.data, cx.data + len, true);
+ return out;
+}
+
+STC_DEF cx_value_t*
+cx_memb(_insert_space_)(Self* self, cx_value_t* pos, size_t len) {
+ size_t idx = pos - self->data, size = cvec_rep_(self)->size;
+ if (len == 0) return pos;
+ if (size + len > cx_memb(_capacity)(*self))
+ cx_memb(_reserve)(self, (size*13 >> 3) + len),
+ pos = self->data + idx;
+ cvec_rep_(self)->size += len;
+ memmove(pos + len, pos, (size - idx) * sizeof(i_VAL));
+ return pos;
+}
+
+STC_DEF cx_iter_t
+cx_memb(_insert_range_p)(Self* self, cx_value_t* pos, const cx_value_t* p1,
+ const cx_value_t* p2, bool clone) {
+ pos = cx_memb(_insert_space_)(self, pos, p2 - p1);
+ cx_iter_t it = {pos};
+ if (clone) while (p1 != p2) *pos++ = i_VALFROM(i_VALTO(p1++));
+ else memcpy(pos, p1, (p2 - p1)*sizeof *p1);
+ return it;
+}
-#endif \ No newline at end of file
+STC_DEF cx_iter_t
+cx_memb(_emplace_range_p)(Self* self, cx_value_t* pos, const cx_rawvalue_t* p1,
+ const cx_rawvalue_t* p2) {
+ pos = cx_memb(_insert_space_)(self, pos, p2 - p1);
+ cx_iter_t it = {pos};
+ while (p1 != p2) *pos++ = i_VALFROM(*p1++);
+ return it;
+}
+
+STC_DEF cx_iter_t
+cx_memb(_erase_range_p)(Self* self, cx_value_t* p1, cx_value_t* p2) {
+ intptr_t len = p2 - p1;
+ if (len > 0) {
+ cx_value_t* p = p1, *end = self->data + cvec_rep_(self)->size;
+ while (p != p2) i_VALDEL(p++);
+ memmove(p1, p2, (end - p2) * sizeof(i_VAL));
+ cvec_rep_(self)->size -= len;
+ }
+ return c_make(cx_iter_t){.ref = p1};
+}
+
+STC_DEF cx_iter_t
+cx_memb(_find_in)(cx_iter_t i1, cx_iter_t i2, i_VALRAW raw) {
+ for (; i1.ref != i2.ref; ++i1.ref) {
+ i_VALRAW r = i_VALTO(i1.ref);
+ if (i_CMP(&raw, &r) == 0) return i1;
+ }
+ return i2;
+}
+
+STC_DEF cx_iter_t
+cx_memb(_bsearch_in)(cx_iter_t i1, cx_iter_t i2, i_VALRAW raw) {
+ cx_iter_t mid, last = i2;
+ while (i1.ref != i2.ref) {
+ mid.ref = i1.ref + ((i2.ref - i1.ref)>>1);
+ int c; i_VALRAW m = i_VALTO(mid.ref);
+ if ((c = i_CMP(&raw, &m)) == 0) return mid;
+ else if (c < 0) i2.ref = mid.ref;
+ else i1.ref = mid.ref + 1;
+ }
+ return last;
+}
+
+STC_DEF int
+cx_memb(_value_compare)(const cx_value_t* x, const cx_value_t* y) {
+ i_VALRAW rx = i_VALTO(x);
+ i_VALRAW ry = i_VALTO(y);
+ return i_CMP(&rx, &ry);
+}
+
+#endif
+#define CVEC_H_INCLUDED
+#include "template.h"