From 44c64073662500684008c87e3a87f33b04e53c13 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 5 Sep 2021 23:12:53 +0200 Subject: New usage style. only cvec is functional. see vec_test_new.c --- include/stc/carray.h | 155 +++++------- include/stc/ccommon.h | 9 +- include/stc/cdeq.h | 354 ++++++++++++-------------- include/stc/clist.h | 290 ++++++++++----------- include/stc/cmap.h | 393 +++++++++++------------------ include/stc/cpque.h | 84 +++---- include/stc/cqueue.h | 50 ++-- include/stc/cset.h | 26 +- include/stc/csmap.h | 521 +++++++++++++++----------------------- include/stc/csptr.h | 94 +++---- include/stc/csset.h | 26 +- include/stc/cstack.h | 50 ++-- include/stc/cvec.h | 611 ++++++++++++++++++++++----------------------- include/stc/forward.h | 165 ++++++++++++ include/stc/template.h | 149 +++++++++++ include/stc/vec_test_new.c | 53 ++++ 16 files changed, 1499 insertions(+), 1531 deletions(-) create mode 100644 include/stc/forward.h create mode 100644 include/stc/template.h create mode 100644 include/stc/vec_test_new.c diff --git a/include/stc/carray.h b/include/stc/carray.h index d67c1410..0d28ff62 100644 --- a/include/stc/carray.h +++ b/include/stc/carray.h @@ -50,169 +50,140 @@ int main() { } } */ - -#define using_carray2(...) c_MACRO_OVERLOAD(using_carray2, __VA_ARGS__) - -#define using_carray2_2(X, Value) \ - _c_using_carray2(carray2##X, Value, c_default_del, c_default_fromraw) -#define using_carray2_3(X, Value, valueDel) \ - _c_using_carray2(carray2##X, Value, valueDel, c_no_clone) -#define using_carray2_4(X, Value, valueDel, valueClone) \ - _c_using_carray2(carray2##X, Value, valueDel, valueClone) - -#define _c_using_carray2(CX, Value, valueDel, valueClone) \ + defTypes( _c_carray2_types(Self, i_VAL); ) \ - typedef Value CX##_value_t; \ - typedef struct { CX##_value_t **data; size_t xdim, ydim; } CX; \ - typedef struct { CX##_value_t *ref; } CX##_iter_t; \ + STC_API Self cx_memb(_with_values)(size_t xdim, size_t ydim, i_VAL value); \ + STC_API Self cx_memb(_with_storage)(size_t xdim, size_t ydim, cx_value_t* storage); \ + STC_API Self cx_memb(_clone)(Self src); \ \ - STC_API CX CX##_with_values(size_t xdim, size_t ydim, Value value); \ - STC_API CX CX##_with_storage(size_t xdim, size_t ydim, CX##_value_t* storage); \ - STC_API CX CX##_clone(CX src); \ -\ - STC_INLINE CX CX##_init(size_t xdim, size_t ydim) { \ - return CX##_with_storage(xdim, ydim, c_new_n(CX##_value_t, xdim*ydim)); \ + STC_INLINE Self cx_memb(_init)(size_t xdim, size_t ydim) { \ + return cx_memb(_with_storage)(xdim, ydim, c_new_n(cx_value_t, xdim*ydim)); \ } \ - STC_INLINE size_t CX##_size(CX arr) { return arr.xdim*arr.ydim; } \ - STC_INLINE CX##_value_t *CX##_data(CX* self) { return *self->data; } \ - STC_INLINE CX##_value_t *CX##_at(CX* self, size_t x, size_t y) { \ + STC_INLINE size_t cx_memb(_size)(Self arr) { return arr.xdim*arr.ydim; } \ + STC_INLINE cx_value_t *cx_memb(_data)(Self* self) { return *self->data; } \ + STC_INLINE cx_value_t *cx_memb(_at)(Self* self, size_t x, size_t y) { \ return *self->data + self->ydim*x + y; \ } \ - STC_INLINE CX##_value_t *CX##_release(CX* self) { \ - CX##_value_t *t = *self->data; c_free(self->data); self->data = NULL; return t; \ + STC_INLINE cx_value_t *cx_memb(_release)(Self* self) { \ + cx_value_t *t = *self->data; c_free(self->data); self->data = NULL; return t; \ } \ \ - STC_INLINE CX##_iter_t CX##_begin(const CX* self) { \ - return c_make(CX##_iter_t){*self->data}; \ + 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##_end(const CX* self) { \ - return c_make(CX##_iter_t){*self->data + self->xdim*self->ydim}; \ + STC_INLINE cx_iter_t cx_memb(_end)(const Self* self) { \ + return c_make(cx_iter_t){*self->data + self->xdim*self->ydim}; \ } \ - STC_INLINE void CX##_next(CX##_iter_t* it) { ++it->ref; } \ + STC_INLINE void cx_memb(_next)(cx_iter_t* it) { ++it->ref; } \ \ - _c_implement_carray2(CX, Value, valueDel, valueClone) \ - STC_API void CX##_del(CX* self) + _c_implement_carray2(Self, i_VAL, i_VALDEL, i_VALFROM) \ + STC_API void cx_memb(_del)(Self* self) // carray3: -#define using_carray3(...) c_MACRO_OVERLOAD(using_carray3, __VA_ARGS__) - -#define using_carray3_2(X, Value) \ - _c_using_carray3(carray3##X, Value, c_default_del, c_default_fromraw) -#define using_carray3_3(X, Value, valueDel) \ - _c_using_carray3(carray3##X, Value, valueDel, c_no_clone) -#define using_carray3_4(X, Value, valueDel, valueClone) \ - _c_using_carray3(carray3##X, Value, valueDel, valueClone) -#define _c_using_carray3(CX, Value, valueDel, valueClone) \ -\ - typedef Value CX##_value_t; \ - typedef struct { CX##_value_t ***data; size_t xdim, ydim, zdim; } CX; \ - typedef struct { CX##_value_t *ref; } CX##_iter_t; \ + defTypes( _c_carray3_types(Self, i_VAL); ) \ - STC_API CX CX##_with_values(size_t xdim, size_t ydim, size_t zdim, Value value); \ - STC_API CX CX##_with_storage(size_t xdim, size_t ydim, size_t zdim, CX##_value_t* storage); \ - STC_API CX CX##_clone(CX src); \ + STC_API Self cx_memb(_with_values)(size_t xdim, size_t ydim, size_t zdim, i_VAL value); \ + STC_API Self cx_memb(_with_storage)(size_t xdim, size_t ydim, size_t zdim, cx_value_t* storage); \ + STC_API Self cx_memb(_clone)(Self src); \ \ - STC_INLINE CX CX##_init(size_t xdim, size_t ydim, size_t zdim) { \ - return CX##_with_storage(xdim, ydim, zdim, c_new_n(CX##_value_t, xdim*ydim*zdim)); \ + STC_INLINE Self cx_memb(_init)(size_t xdim, size_t ydim, size_t zdim) { \ + return cx_memb(_with_storage)(xdim, ydim, zdim, c_new_n(cx_value_t, xdim*ydim*zdim)); \ } \ - STC_INLINE size_t CX##_size(CX arr) { return arr.xdim*arr.ydim*arr.zdim; } \ - STC_INLINE CX##_value_t* CX##_data(CX* self) { return **self->data; } \ - STC_INLINE CX##_value_t* CX##_at(CX* self, size_t x, size_t y, size_t z) { \ + STC_INLINE size_t cx_memb(_size)(Self arr) { return arr.xdim*arr.ydim*arr.zdim; } \ + STC_INLINE cx_value_t* cx_memb(_data)(Self* self) { return **self->data; } \ + STC_INLINE cx_value_t* cx_memb(_at)(Self* self, size_t x, size_t y, size_t z) { \ return **self->data + self->zdim*(self->ydim*x + y) + z; \ } \ \ - STC_INLINE CX##_value_t* CX##_release(CX* self) { \ - CX##_value_t *values = **self->data; \ + STC_INLINE cx_value_t* cx_memb(_release)(Self* self) { \ + cx_value_t *values = **self->data; \ c_free(self->data); self->data = NULL; \ return values; \ } \ \ - STC_INLINE CX##_iter_t CX##_begin(const CX* self) { \ - return c_make(CX##_iter_t){**self->data}; \ + 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##_end(const CX* self) { \ - return c_make(CX##_iter_t){**self->data + CX##_size(*self)}; \ + STC_INLINE cx_iter_t cx_memb(_end)(const Self* self) { \ + return c_make(cx_iter_t){**self->data + cx_memb(_size)(*self)}; \ } \ - STC_INLINE void CX##_next(CX##_iter_t* it) { ++it->ref; } \ + STC_INLINE void cx_memb(_next)(cx_iter_t* it) { ++it->ref; } \ \ - _c_implement_carray3(CX, Value, valueDel, valueClone) \ - STC_API void CX##_del(CX* self) + _c_implement_carray3(Self, i_VAL, i_VALDEL, i_VALFROM) \ + STC_API void cx_memb(_del)(Self* self) /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_carray2(CX, Value, valueDel, valueClone) \ +#define _c_implement_carray2(Self, i_VAL, i_VALDEL, i_VALFROM) \ \ - STC_DEF CX CX##_with_storage(size_t xdim, size_t ydim, CX##_value_t* block) { \ - CX _arr = {c_new_n(CX##_value_t*, xdim), xdim, ydim}; \ + STC_DEF Self cx_memb(_with_storage)(size_t xdim, size_t ydim, cx_value_t* block) { \ + Self _arr = {c_new_n(cx_value_t*, xdim), xdim, ydim}; \ for (size_t x = 0; x < xdim; ++x, block += ydim) \ _arr.data[x] = block; \ return _arr; \ } \ \ - STC_DEF CX CX##_with_values(size_t xdim, size_t ydim, Value value) { \ - CX _arr = CX##_init(xdim, ydim); \ - for (CX##_value_t* p = _arr.data[0], *e = p + xdim*ydim; p != e; ++p) \ + STC_DEF Self cx_memb(_with_values)(size_t xdim, size_t ydim, i_VAL value) { \ + Self _arr = cx_memb(_init)(xdim, ydim); \ + for (cx_value_t* p = _arr.data[0], *e = p + xdim*ydim; p != e; ++p) \ *p = value; \ return _arr; \ } \ \ - STC_DEF CX CX##_clone(CX src) { \ - CX _arr = CX##_init(src.xdim, src.ydim); \ - for (CX##_value_t* p = _arr.data[0], *q = src.data[0], *e = p + CX##_size(src); p != e; ++p, ++q) \ - *p = valueClone(*q); \ + STC_DEF Self cx_memb(_clone)(Self src) { \ + Self _arr = cx_memb(_init)(src.xdim, src.ydim); \ + for (cx_value_t* p = _arr.data[0], *q = src.data[0], *e = p + cx_memb(_size)(src); p != e; ++p, ++q) \ + *p = i_VALFROM(*q); \ return _arr; \ } \ \ - STC_DEF void CX##_del(CX* self) { \ + STC_DEF void cx_memb(_del)(Self* self) { \ if (!self->data) return; \ - for (CX##_value_t* p = self->data[0], *e = p + CX##_size(*self); p != e; ++p) \ - valueDel(p); \ + for (cx_value_t* p = self->data[0], *e = p + cx_memb(_size)(*self); p != e; ++p) \ + i_VALDEL(p); \ c_free(self->data[0]); /* data */ \ c_free(self->data); /* pointers */ \ } // carray3 impl. -#define _c_implement_carray3(CX, Value, valueDel, valueClone) \ +#define _c_implement_carray3(Self, i_VAL, i_VALDEL, i_VALFROM) \ \ - STC_DEF CX CX##_with_storage(size_t xdim, size_t ydim, size_t zdim, CX##_value_t* block) { \ - CX _arr = {c_new_n(CX##_value_t**, xdim*(ydim + 1)), xdim, ydim, zdim}; \ - CX##_value_t** p = (CX##_value_t**) &_arr.data[xdim]; \ + STC_DEF Self cx_memb(_with_storage)(size_t xdim, size_t ydim, size_t zdim, cx_value_t* block) { \ + Self _arr = {c_new_n(cx_value_t**, xdim*(ydim + 1)), xdim, ydim, zdim}; \ + cx_value_t** p = (cx_value_t**) &_arr.data[xdim]; \ for (size_t x = 0, y; x < xdim; ++x, p += ydim) \ for (_arr.data[x] = p, y = 0; y < ydim; ++y, block += zdim) \ _arr.data[x][y] = block; \ return _arr; \ } \ \ - STC_DEF CX CX##_with_values(size_t xdim, size_t ydim, size_t zdim, Value value) { \ - CX _arr = CX##_init(xdim, ydim, zdim); \ - for (CX##_value_t* p = **_arr.data, *e = p + xdim*ydim*zdim; p != e; ++p) \ + STC_DEF Self cx_memb(_with_values)(size_t xdim, size_t ydim, size_t zdim, i_VAL value) { \ + Self _arr = cx_memb(_init)(xdim, ydim, zdim); \ + for (cx_value_t* p = **_arr.data, *e = p + xdim*ydim*zdim; p != e; ++p) \ *p = value; \ return _arr; \ } \ \ - STC_DEF CX CX##_clone(CX src) { \ - CX _arr = CX##_init(src.xdim, src.ydim, src.zdim); \ - for (CX##_value_t* p = **_arr.data, *q = **src.data, *e = p + CX##_size(src); p != e; ++p, ++q) \ - *p = valueClone(*q); \ + STC_DEF Self cx_memb(_clone)(Self src) { \ + Self _arr = cx_memb(_init)(src.xdim, src.ydim, src.zdim); \ + for (cx_value_t* p = **_arr.data, *q = **src.data, *e = p + cx_memb(_size)(src); p != e; ++p, ++q) \ + *p = i_VALFROM(*q); \ return _arr; \ } \ \ - STC_DEF void CX##_del(CX* self) { \ + STC_DEF void cx_memb(_del)(Self* self) { \ if (!self->data) return; \ - for (CX##_value_t* p = **self->data, *e = p + CX##_size(*self); p != e; ++p) \ - valueDel(p); \ + for (cx_value_t* p = **self->data, *e = p + cx_memb(_size)(*self); p != e; ++p) \ + i_VALDEL(p); \ c_free(self->data[0][0]); /* data */ \ c_free(self->data); /* pointers */ \ } -#else -#define _c_implement_carray2(CX, Value, valueDel, valueClone) -#define _c_implement_carray3(CX, Value, valueDel, valueClone) #endif #endif diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index b2501416..a8098e43 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -54,8 +54,11 @@ /* Macro overloading feature support based on: https://rextester.com/ONP80107 */ #define c_MACRO_OVERLOAD(name, ...) \ c_SELECT(name, c_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__) -#define c_SELECT(name, num) c_CONCAT(name ## _, num) -#define c_CONCAT(a, b) a ## b +#define c_SELECT(name, num) c_CONCAT3(name, _, num) +#define c_CONCAT(a, b) a##b +#define c_PASTE(a, b) c_CONCAT(a, b) +#define c_CONCAT3(a, b, c) a##b##c +#define c_PASTE3(a, b, c) c_CONCAT3(a, b, c) #define c_EXPAND(...) __VA_ARGS__ #define c_NUM_ARGS(...) _c_APPLY_ARG_N((__VA_ARGS__, _c_RSEQ_N)) @@ -109,6 +112,8 @@ #define c_true(...) __VA_ARGS__ #define c_false(...) +#define _c_deftypes_ c_false +#define _c_deftypes_i_FWD c_true /* Generic algorithms */ diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index d052e9eb..a5853301 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -27,178 +27,148 @@ #include #include -#define forward_cdeq(X, Value) _c_cdeq_types(cdeq_##X, Value) - -#define using_cdeq(...) c_MACRO_OVERLOAD(using_cdeq, __VA_ARGS__) - -#define using_cdeq_2(X, Value) \ - using_cdeq_3(X, Value, c_default_compare) -#define using_cdeq_3(X, Value, valueCompare) \ - using_cdeq_5(X, Value, valueCompare, c_default_del, c_default_fromraw) -#define using_cdeq_4(X, Value, valueCompare, valueDel) \ - using_cdeq_5(X, Value, valueCompare, valueDel, c_no_clone) -#define using_cdeq_5(X, Value, valueCompare, valueDel, valueClone) \ - using_cdeq_7(X, Value, valueCompare, valueDel, valueClone, c_default_toraw, Value) -#define using_cdeq_7(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ - _c_using_cdeq(cdeq_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, c_true) -#define using_cdeq_8(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \ - _c_using_cdeq(cdeq_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) - -#define using_cdeq_str() \ - using_cdeq_7(str, cstr, c_rawstr_compare, cstr_del, cstr_from, cstr_str, const char*) - - -struct cdeq_rep { size_t size, cap; void* base[]; }; -#define _cdeq_rep(self) c_container_of((self)->_base, struct cdeq_rep, base) - -#define _c_cdeq_types(CX, Value) \ - typedef Value CX##_value_t; \ - typedef struct {CX##_value_t *ref; } CX##_iter_t; \ - typedef struct {CX##_value_t *_base, *data;} CX - -#define _c_using_cdeq(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \ \ - defTypes( _c_cdeq_types(CX, Value); ) \ - typedef RawValue CX##_rawvalue_t; \ + defTypes( _c_cdeq_types(Self, i_VAL); ) \ + typedef i_VALRAW cx_rawvalue_t; \ \ - STC_API CX CX##_init(void); \ - STC_API CX CX##_clone(CX cx); \ - STC_API void CX##_clear(CX* self); \ - STC_API void CX##_del(CX* self); \ - STC_API CX##_iter_t CX##_find_in(CX##_iter_t p1, CX##_iter_t p2, RawValue raw); \ - STC_API int CX##_value_compare(const CX##_value_t* x, const CX##_value_t* y); \ - STC_API void CX##_push_back(CX* self, Value value); \ - STC_API void CX##_push_front(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_API void CX##_expand_right_(CX* self, size_t idx, size_t n); \ + STC_API Self cx_memb(_init)(void); \ + STC_API Self cx_memb(_clone)(Self cx); \ + STC_API void cx_memb(_clear)(Self* self); \ + STC_API void cx_memb(_del)(Self* self); \ + STC_API cx_iter_t cx_memb(_find_in)(cx_iter_t p1, cx_iter_t p2, i_VALRAW raw); \ + STC_API int cx_memb(_value_compare)(const cx_value_t* x, const cx_value_t* y); \ + STC_API void cx_memb(_push_back)(Self* self, i_VAL value); \ + STC_API void cx_memb(_push_front)(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_API void cx_memb(_expand_right_)(Self* self, size_t idx, size_t n); \ \ - STC_INLINE bool CX##_empty(CX cx) {return !_cdeq_rep(&cx)->size;} \ - STC_INLINE size_t CX##_size(CX cx) {return _cdeq_rep(&cx)->size;} \ - STC_INLINE size_t CX##_capacity(CX cx) {return _cdeq_rep(&cx)->cap;} \ - STC_INLINE void CX##_swap(CX* a, CX* b) {c_swap(CX, *a, *b);} \ - STC_INLINE Value CX##_value_fromraw(RawValue raw) {return valueFromRaw(raw);} \ - STC_INLINE RawValue CX##_value_toraw(CX##_value_t* pval) {return valueToRaw(pval);} \ - STC_INLINE Value CX##_value_clone(Value val) \ - {return valueFromRaw(valueToRaw(&val));} \ - STC_INLINE void CX##_emplace_back(CX* self, RawValue raw) \ - {CX##_push_back(self, valueFromRaw(raw));} \ - STC_INLINE void CX##_emplace_front(CX* self, RawValue raw) \ - {CX##_push_front(self, valueFromRaw(raw));} \ - STC_INLINE void CX##_pop_back(CX* self) \ - {valueDel(&self->data[--_cdeq_rep(self)->size]);} \ - STC_INLINE void CX##_pop_front(CX* self) \ - {valueDel(self->data++); --_cdeq_rep(self)->size;} \ - 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 + _cdeq_rep(self)->size - 1;} \ - STC_INLINE CX##_value_t* CX##_at(const CX* self, size_t idx) \ - {assert(idx < _cdeq_rep(self)->size); return self->data + idx;} \ - 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 + _cdeq_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 bool cx_memb(_empty)(Self cx) { return !_cdeq_rep(&cx)->size; } \ + STC_INLINE size_t cx_memb(_size)(Self cx) { return _cdeq_rep(&cx)->size; } \ + STC_INLINE size_t cx_memb(_capacity)(Self cx) { return _cdeq_rep(&cx)->cap; } \ + STC_INLINE void cx_memb(_swap)(Self* a, Self* b) {c_swap(Self, *a, *b); } \ + 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* pval) { return i_VALTO(pval); } \ + STC_INLINE i_VAL cx_memb(_value_clone)(i_VAL val) \ + { return i_VALFROM(i_VALTO(&val)); } \ + 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(_emplace_front)(Self* self, i_VALRAW raw) \ + {cx_memb(_push_front)(self, i_VALFROM(raw)); } \ + STC_INLINE void cx_memb(_pop_back)(Self* self) \ + {i_VALDEL(&self->data[--_cdeq_rep(self)->size]); } \ + STC_INLINE void cx_memb(_pop_front)(Self* self) \ + {i_VALDEL(self->data++); --_cdeq_rep(self)->size; } \ + 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 + _cdeq_rep(self)->size - 1; } \ + STC_INLINE cx_value_t* cx_memb(_at)(const Self* self, size_t idx) \ + {assert(idx < _cdeq_rep(self)->size); return self->data + idx; } \ + 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 + _cdeq_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 CX \ - CX##_with_capacity(size_t n) { \ - CX cx = CX##_init(); \ - CX##_expand_right_(&cx, 0, n); \ + STC_INLINE Self \ + cx_memb(_with_capacity)(size_t n) { \ + Self cx = cx_memb(_init)(); \ + cx_memb(_expand_right_)(&cx, 0, n); \ return cx; \ } \ \ STC_INLINE void \ - CX##_reserve(CX* self, size_t n) { \ + cx_memb(_reserve)(Self* self, size_t n) { \ size_t sz = _cdeq_rep(self)->size; \ - if (n > sz) CX##_expand_right_(self, sz, n - sz); \ + if (n > sz) cx_memb(_expand_right_)(self, sz, n - sz); \ } \ \ STC_INLINE void \ - CX##_shrink_to_fit(CX *self) { \ - CX cx = CX##_clone(*self); \ - CX##_del(self); *self = cx; \ + 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##_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_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##_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_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##_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_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##_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_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##_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_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##_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_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##_emplace_range(CX* self, CX##_iter_t it, CX##_iter_t it1, CX##_iter_t it2) { \ - return CX##_insert_range_p(self, it.ref, it1.ref, it2.ref, true); \ + STC_INLINE cx_iter_t \ + cx_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##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) { \ - CX##_emplace_range_p(self, self->data + _cdeq_rep(self)->size, arr, arr + n); \ + cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) { \ + cx_memb(_emplace_range_p)(self, self->data + _cdeq_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_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##_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_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##_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_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##_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_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##_iter_t \ - CX##_find(const CX* self, RawValue raw) { \ - return CX##_find_in(CX##_begin(self), CX##_end(self), raw); \ + 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##_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; \ + 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 void \ - CX##_sort_range(CX##_iter_t i1, CX##_iter_t i2, \ - int(*_cmp_)(const CX##_value_t*, const CX##_value_t*)) { \ + 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 *i1.ref, (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); \ + cx_memb(_sort)(Self* self) { \ + cx_memb(_sort_range)(cx_memb(_begin)(self), cx_memb(_end)(self), cx_memb(_value_compare)); \ } \ \ - _c_implement_cdeq(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ + _c_implement_cdeq(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -208,88 +178,88 @@ struct cdeq_rep { size_t size, cap; void* base[]; }; static struct cdeq_rep _cdeq_sentinel = {0, 0}; #define _cdeq_nfront(self) ((self)->data - (self)->_base) -#define _c_implement_cdeq(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ +#define _c_implement_cdeq(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ \ - STC_DEF CX \ - CX##_init(void) { \ - CX##_value_t *b = (CX##_value_t *) _cdeq_sentinel.base; \ - return c_make(CX){b, b}; \ + STC_DEF Self \ + cx_memb(_init)(void) { \ + cx_value_t *b = (cx_value_t *) _cdeq_sentinel.base; \ + return c_make(Self){b, b}; \ } \ \ STC_DEF void \ - CX##_clear(CX* self) { \ + cx_memb(_clear)(Self* self) { \ struct cdeq_rep* rep = _cdeq_rep(self); if (rep->cap) { \ - for (CX##_value_t *p = self->data, *q = p + rep->size; p != q; ++p) \ - valueDel(p); \ + for (cx_value_t *p = self->data, *q = p + rep->size; p != q; ++p) \ + i_VALDEL(p); \ rep->size = 0; \ } \ } \ \ STC_DEF void \ - CX##_del(CX* self) { \ - CX##_clear(self); \ + cx_memb(_del)(Self* self) { \ + cx_memb(_clear)(self); \ if (_cdeq_rep(self)->cap) \ c_free(_cdeq_rep(self)); \ } \ \ STC_DEF size_t \ - CX##_realloc_(CX* self, size_t n) { \ + cx_memb(_realloc_)(Self* self, size_t n) { \ struct cdeq_rep* rep = _cdeq_rep(self); \ size_t sz = rep->size, cap = (size_t) (sz*1.7) + n + 7; \ size_t nfront = _cdeq_nfront(self); \ rep = (struct cdeq_rep*) c_realloc(rep->cap ? rep : NULL, \ - offsetof(struct cdeq_rep, base) + cap*sizeof(Value)); \ + offsetof(struct cdeq_rep, base) + cap*sizeof(i_VAL)); \ rep->size = sz, rep->cap = cap; \ - self->_base = (CX##_value_t *) rep->base; \ + self->_base = (cx_value_t *) rep->base; \ self->data = self->_base + nfront; \ return cap; \ } \ \ STC_DEF void \ - CX##_expand_left_(CX* self, size_t idx, size_t n) { \ + cx_memb(_expand_left_)(Self* self, size_t idx, size_t n) { \ struct cdeq_rep* rep = _cdeq_rep(self); \ size_t sz = rep->size, cap = rep->cap; \ size_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; \ if (nfront >= n) { \ - self->data = (CX##_value_t *) memmove(self->data - n, self->data, idx*sizeof(Value)); \ + self->data = (cx_value_t *) memmove(self->data - n, self->data, idx*sizeof(i_VAL)); \ } else { \ - if (sz*1.3 + n > cap) cap = CX##_realloc_(self, n); \ + if (sz*1.3 + n > cap) cap = cx_memb(_realloc_)(self, n); \ size_t unused = cap - (sz + n); \ size_t pos = (nback*2 < unused) ? unused - nback : unused/2; \ - memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*sizeof(Value)); \ - self->data = (CX##_value_t *) memmove(self->_base + pos, self->data, idx*sizeof(Value)); \ + memmove(self->_base + pos + idx + n, self->data + idx, (sz - idx)*sizeof(i_VAL)); \ + self->data = (cx_value_t *) memmove(self->_base + pos, self->data, idx*sizeof(i_VAL)); \ } \ } \ \ STC_DEF void \ - CX##_expand_right_(CX* self, size_t idx, size_t n) { \ + cx_memb(_expand_right_)(Self* self, size_t idx, size_t n) { \ struct cdeq_rep* rep = _cdeq_rep(self); \ size_t sz = rep->size, cap = rep->cap; \ size_t nfront = _cdeq_nfront(self), nback = cap - sz - nfront; \ - if (nback >= n || sz*1.3 + n > cap && CX##_realloc_(self, n)) { \ - memmove(self->data + idx + n, self->data + idx, (sz - idx)*sizeof(Value)); \ + if (nback >= n || sz*1.3 + n > cap && cx_memb(_realloc_)(self, n)) { \ + memmove(self->data + idx + n, self->data + idx, (sz - idx)*sizeof(i_VAL)); \ } else { \ size_t unused = cap - (sz + n); \ size_t pos = (nfront*2 < unused) ? nfront : unused/2; \ - memmove(self->_base + pos, self->data, idx*sizeof(Value)); \ - memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*sizeof(Value)); \ - self->data = ((CX##_value_t *) self->_base) + pos; \ + memmove(self->_base + pos, self->data, idx*sizeof(i_VAL)); \ + memmove(self->data + pos + idx + n, self->data + idx, (sz - idx)*sizeof(i_VAL)); \ + self->data = ((cx_value_t *) self->_base) + pos; \ } \ } \ \ - STC_DEF CX##_value_t* \ - CX##_insert_space_(CX* self, CX##_value_t* pos, size_t n) { \ + STC_DEF cx_value_t* \ + cx_memb(_insert_space_)(Self* self, cx_value_t* pos, size_t n) { \ size_t idx = pos - self->data; \ - if (idx*2 < _cdeq_rep(self)->size) CX##_expand_left_(self, idx, n); \ - else CX##_expand_right_(self, idx, n); \ + if (idx*2 < _cdeq_rep(self)->size) cx_memb(_expand_left_)(self, idx, n); \ + else cx_memb(_expand_right_)(self, idx, n); \ if (n) _cdeq_rep(self)->size += n; /* do only if size > 0 */ \ return self->data + idx; \ } \ \ STC_DEF void \ - CX##_push_front(CX* self, Value value) { \ + cx_memb(_push_front)(Self* self, i_VAL value) { \ if (self->data == self->_base) \ - CX##_expand_left_(self, 0, 1); \ + cx_memb(_expand_left_)(self, 0, 1); \ else \ --self->data; \ *self->data = value; \ @@ -297,70 +267,70 @@ static struct cdeq_rep _cdeq_sentinel = {0, 0}; } \ \ STC_DEF void \ - CX##_push_back(CX* self, Value value) { \ + cx_memb(_push_back)(Self* self, i_VAL value) { \ struct cdeq_rep* rep = _cdeq_rep(self); \ if (_cdeq_nfront(self) + rep->size == rep->cap) \ - CX##_expand_right_(self, rep->size, 1); \ + cx_memb(_expand_right_)(self, rep->size, 1); \ self->data[_cdeq_rep(self)->size++] = value; \ } \ \ - STC_DEF CX \ - CX##_clone(CX cx) { \ + STC_DEF Self \ + cx_memb(_clone)(Self cx) { \ size_t sz = _cdeq_rep(&cx)->size; \ - CX out = CX##_with_capacity(sz); \ - CX##_insert_range_p(&out, out.data, cx.data, cx.data + sz, true); \ + Self out = cx_memb(_with_capacity)(sz); \ + cx_memb(_insert_range_p)(&out, out.data, cx.data, cx.data + sz, true); \ return out; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_insert_range_p(CX* self, CX##_value_t* pos, const CX##_value_t* p1, \ - const CX##_value_t* p2, bool clone) { \ - pos = CX##_insert_space_(self, pos, p2 - p1); \ - CX##_iter_t it = {pos}; \ - if (clone) while (p1 != p2) *pos++ = valueFromRaw(valueToRaw(p1++)); \ + 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; \ } \ \ - 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++); \ + 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##_erase_range_p(CX* self, CX##_value_t* p1, CX##_value_t* p2) { \ + STC_DEF cx_iter_t \ + cx_memb(_erase_range_p)(Self* self, cx_value_t* p1, cx_value_t* p2) { \ size_t n = p2 - p1; \ if (n > 0) { \ - CX##_value_t* p = p1, *end = self->data + _cdeq_rep(self)->size; \ - while (p != p2) valueDel(p++); \ + cx_value_t* p = p1, *end = self->data + _cdeq_rep(self)->size; \ + while (p != p2) i_VALDEL(p++); \ if (p1 == self->data) self->data += n; \ - else memmove(p1, p2, (end - p2) * sizeof(Value)); \ + else memmove(p1, p2, (end - p2) * sizeof(i_VAL)); \ _cdeq_rep(self)->size -= n; \ } \ - return c_make(CX##_iter_t){p1}; \ + return c_make(cx_iter_t){p1}; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_find_in(CX##_iter_t i1, CX##_iter_t i2, RawValue raw) { \ + 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) { \ - RawValue r = valueToRaw(i1.ref); \ - if (valueCompareRaw(&raw, &r) == 0) return i1; \ + i_VALRAW r = i_VALTO(i1.ref); \ + if (i_CMP(&raw, &r) == 0) return i1; \ } \ return i2; \ } \ \ 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); \ + 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); \ } #else -#define _c_implement_cdeq(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) +#define _c_implement_cdeq(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) #endif #endif diff --git a/include/stc/clist.h b/include/stc/clist.h index 75364a4f..9c79864a 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -56,181 +56,147 @@ #include "ccommon.h" #include -#define forward_clist(X, Value) _c_clist_types(clist_##X, Value) -#define using_clist(...) c_MACRO_OVERLOAD(using_clist, __VA_ARGS__) -#define using_clist_2(X, Value) \ - using_clist_3(X, Value, c_default_compare) -#define using_clist_3(X, Value, valueCompare) \ - using_clist_5(X, Value, valueCompare, c_default_del, c_default_fromraw) -#define using_clist_4(X, Value, valueCompare, valueDel) \ - using_clist_5(X, Value, valueCompare, valueDel, c_no_clone) -#define using_clist_5(X, Value, valueCompare, valueDel, valueClone) \ - using_clist_7(X, Value, valueCompare, valueDel, valueClone, c_default_toraw, Value) -#define using_clist_7(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ - _c_using_clist(clist_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, c_true) -#define using_clist_8(X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \ - _c_using_clist(clist_##X, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) - -#define using_clist_str() \ - using_clist_7(str, cstr, c_rawstr_compare, cstr_del, cstr_from, cstr_str, const char*) - - -#define _c_clist_types(CX, Value) \ - typedef Value CX##_value_t; \ - typedef struct CX##_node_t CX##_node_t; \ -\ - typedef struct { \ - CX##_node_t *const *_last, *prev; \ - CX##_value_t *ref; \ - } CX##_iter_t; \ -\ - typedef struct { \ - CX##_node_t *last; \ - } CX - -#define _c_clist_complete_types(CX) \ - struct CX##_node_t { \ - struct CX##_node_t *next; \ - CX##_value_t value; \ +#define _c_clist_complete_types(Self) \ + struct cx_node_t { \ + struct cx_node_t *next; \ + cx_value_t value; \ } _c_clist_types(clist_VOID, int); _c_clist_complete_types(clist_VOID); STC_API size_t _clist_count(const clist_VOID* self); -#define _clist_node(CX, vp) c_container_of(vp, CX##_node_t, value) +#define _clist_node(Self, vp) c_container_of(vp, cx_node_t, value) -#define _c_using_clist(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue, defTypes) \ -\ - defTypes( _c_clist_types(CX, Value); ) \ - _c_clist_complete_types(CX); \ - typedef RawValue CX##_rawvalue_t; \ + defTypes( _c_clist_types(Self, i_VAL); ) \ + _c_clist_complete_types(Self); \ + typedef i_VALRAW cx_rawvalue_t; \ \ - STC_API CX CX##_clone(CX cx); \ - STC_API void CX##_del(CX* self); \ - STC_API void CX##_push_back(CX* self, Value value); \ - STC_API void CX##_push_front(CX* self, Value value); \ - STC_API CX##_iter_t CX##_insert(CX* self, CX##_iter_t it, Value value); \ - STC_API void CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n); \ - STC_API CX##_iter_t CX##_erase_at(CX* self, CX##_iter_t it); \ - STC_API CX##_iter_t CX##_erase_range(CX* self, CX##_iter_t it1, CX##_iter_t it2); \ - STC_API size_t CX##_remove(CX* self, RawValue val); \ - STC_API CX##_iter_t CX##_splice(CX* self, CX##_iter_t it, CX* other); \ - STC_API CX CX##_split_off(CX* self, CX##_iter_t it1, CX##_iter_t it2); \ - STC_API void CX##_sort(CX* self); \ - STC_API CX##_iter_t CX##_find_in(CX##_iter_t it1, CX##_iter_t it2, RawValue val); \ - STC_API CX##_node_t* CX##_erase_after_(CX* self, CX##_node_t* node); \ + STC_API Self cx_memb(_clone)(Self cx); \ + STC_API void cx_memb(_del)(Self* self); \ + STC_API void cx_memb(_push_back)(Self* self, i_VAL value); \ + STC_API void cx_memb(_push_front)(Self* self, i_VAL value); \ + STC_API cx_iter_t cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value); \ + STC_API void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n); \ + STC_API cx_iter_t cx_memb(_erase_at)(Self* self, cx_iter_t it); \ + STC_API cx_iter_t cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2); \ + STC_API size_t cx_memb(_remove)(Self* self, i_VALRAW val); \ + STC_API cx_iter_t cx_memb(_splice)(Self* self, cx_iter_t it, Self* other); \ + STC_API Self cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2); \ + STC_API void cx_memb(_sort)(Self* self); \ + STC_API cx_iter_t cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val); \ + STC_API cx_node_t* cx_memb(_erase_after_)(Self* self, cx_node_t* node); \ \ - STC_INLINE CX CX##_init(void) {return c_make(CX){NULL};} \ - STC_INLINE bool CX##_empty(CX cx) {return cx.last == NULL;} \ - STC_INLINE size_t CX##_count(CX cx) \ - {return _clist_count((const clist_VOID*) &cx);} \ - STC_INLINE void CX##_clear(CX* self) {CX##_del(self);} \ - STC_INLINE Value CX##_value_fromraw(RawValue raw) {return valueFromRaw(raw);} \ - STC_INLINE RawValue CX##_value_toraw(CX##_value_t* pval) {return valueToRaw(pval);} \ - STC_INLINE Value CX##_value_clone(Value val) \ - {return valueFromRaw(valueToRaw(&val));} \ - STC_INLINE void CX##_pop_front(CX* self) \ - {CX##_erase_after_(self, self->last);} \ - STC_INLINE CX##_iter_t CX##_erase(CX* self, CX##_iter_t it) \ - {return CX##_erase_at(self, it);} \ - STC_INLINE void CX##_emplace_back(CX* self, RawValue raw) \ - {CX##_push_back(self, valueFromRaw(raw));} \ - STC_INLINE void CX##_emplace_front(CX* self, RawValue raw) \ - {CX##_push_front(self, valueFromRaw(raw));} \ - STC_INLINE CX##_iter_t CX##_emplace(CX* self, CX##_iter_t it, RawValue raw) \ - {return CX##_insert(self, it, valueFromRaw(raw));} \ - STC_INLINE CX##_value_t* CX##_front(const CX* self) {return &self->last->next->value;} \ - STC_INLINE CX##_value_t* CX##_back(const CX* self) {return &self->last->value;} \ + STC_INLINE Self cx_memb(_init)(void) { return c_make(Self){NULL}; } \ + STC_INLINE bool cx_memb(_empty)(Self cx) { return cx.last == NULL; } \ + STC_INLINE size_t cx_memb(_count)(Self cx) \ + { return _clist_count((const clist_VOID*) &cx); } \ + STC_INLINE void cx_memb(_clear)(Self* self) {cx_memb(_del)(self); } \ + 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* pval) { return i_VALTO(pval); } \ + STC_INLINE i_VAL cx_memb(_value_clone)(i_VAL val) \ + { return i_VALFROM(i_VALTO(&val)); } \ + STC_INLINE void cx_memb(_pop_front)(Self* self) \ + {cx_memb(_erase_after_)(self, self->last); } \ + STC_INLINE cx_iter_t cx_memb(_erase)(Self* self, cx_iter_t it) \ + { return cx_memb(_erase_at)(self, it); } \ + 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(_emplace_front)(Self* self, i_VALRAW raw) \ + {cx_memb(_push_front)(self, i_VALFROM(raw)); } \ + STC_INLINE cx_iter_t cx_memb(_emplace)(Self* self, cx_iter_t it, i_VALRAW raw) \ + { return cx_memb(_insert)(self, it, i_VALFROM(raw)); } \ + STC_INLINE cx_value_t* cx_memb(_front)(const Self* self) { return &self->last->next->value; } \ + STC_INLINE cx_value_t* cx_memb(_back)(const Self* self) { return &self->last->value; } \ \ - STC_INLINE CX##_iter_t \ - CX##_iter(const CX* self, CX##_node_t* prev) { \ - return c_make(CX##_iter_t){&self->last, prev, &prev->next->value}; \ + STC_INLINE cx_iter_t \ + cx_memb(_iter)(const Self* self, cx_node_t* prev) { \ + return c_make(cx_iter_t){&self->last, prev, &prev->next->value}; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_begin(const CX* self) { \ - CX##_value_t* head = self->last ? &self->last->next->value : NULL; \ - return c_make(CX##_iter_t){&self->last, self->last, head}; \ + STC_INLINE cx_iter_t \ + cx_memb(_begin)(const Self* self) { \ + cx_value_t* head = self->last ? &self->last->next->value : NULL; \ + return c_make(cx_iter_t){&self->last, self->last, head}; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_end(const CX* self) { \ - return c_make(CX##_iter_t){NULL}; \ + STC_INLINE cx_iter_t \ + cx_memb(_end)(const Self* self) { \ + return c_make(cx_iter_t){NULL}; \ } \ \ STC_INLINE void \ - CX##_next(CX##_iter_t* it) { \ - CX##_node_t* node = it->prev = _clist_node(CX, it->ref); \ + cx_memb(_next)(cx_iter_t* it) { \ + cx_node_t* node = it->prev = _clist_node(Self, it->ref); \ it->ref = (node == *it->_last ? NULL : &node->next->value); \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_fwd(CX##_iter_t it, size_t n) { \ - while (n-- && it.ref) CX##_next(&it); \ + STC_INLINE cx_iter_t \ + cx_memb(_fwd)(cx_iter_t it, size_t n) { \ + while (n-- && it.ref) cx_memb(_next)(&it); \ return it; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_splice_range(CX* self, CX##_iter_t it, \ - CX* other, CX##_iter_t it1, CX##_iter_t it2) { \ - CX tmp = CX##_split_off(other, it1, it2); \ - return CX##_splice(self, it, &tmp); \ + STC_INLINE cx_iter_t \ + cx_memb(_splice_range)(Self* self, cx_iter_t it, \ + Self* other, cx_iter_t it1, cx_iter_t it2) { \ + Self tmp = cx_memb(_split_off)(other, it1, it2); \ + return cx_memb(_splice)(self, it, &tmp); \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_find(const CX* self, RawValue val) { \ - return CX##_find_in(CX##_begin(self), CX##_end(self), val); \ + STC_INLINE cx_iter_t \ + cx_memb(_find)(const Self* self, i_VALRAW val) { \ + return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val); \ } \ \ - STC_INLINE CX##_value_t* \ - CX##_get(const CX* self, RawValue val) { \ - return CX##_find_in(CX##_begin(self), CX##_end(self), val).ref; \ + STC_INLINE cx_value_t* \ + cx_memb(_get)(const Self* self, i_VALRAW val) { \ + return cx_memb(_find_in)(cx_memb(_begin)(self), cx_memb(_end)(self), val).ref; \ } \ \ - _c_implement_clist(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ + _c_implement_clist(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_clist(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) \ +#define _c_implement_clist(Self, i_VAL, i_CMP, i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW) \ \ - STC_DEF CX \ - CX##_clone(CX cx) { \ - CX out = CX##_init(); \ - c_foreach_3 (it, CX, cx) CX##_emplace_back(&out, valueToRaw(it.ref)); \ + STC_DEF Self \ + cx_memb(_clone)(Self cx) { \ + Self out = cx_memb(_init)(); \ + c_foreach_3 (it, Self, cx) cx_memb(_emplace_back)(&out, i_VALTO(it.ref)); \ return out; \ } \ \ STC_DEF void \ - CX##_del(CX* self) { \ - while (self->last) CX##_erase_after_(self, self->last); \ + cx_memb(_del)(Self* self) { \ + while (self->last) cx_memb(_erase_after_)(self, self->last); \ } \ \ STC_DEF void \ - CX##_push_back(CX* self, Value value) { \ - _c_clist_insert_after(self, CX, self->last, value); \ + cx_memb(_push_back)(Self* self, i_VAL value) { \ + _c_clist_insert_after(self, Self, self->last, value); \ self->last = entry; \ } \ \ STC_DEF void \ - CX##_push_front(CX* self, Value value) { \ - _c_clist_insert_after(self, CX, self->last, value); \ + cx_memb(_push_front)(Self* self, i_VAL value) { \ + _c_clist_insert_after(self, Self, self->last, value); \ if (!self->last) self->last = entry; \ } \ \ STC_DEF void \ - CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) { \ - for (size_t i=0; ilast; \ - _c_clist_insert_after(self, CX, node, value); \ + STC_DEF cx_iter_t \ + cx_memb(_insert)(Self* self, cx_iter_t it, i_VAL value) { \ + cx_node_t* node = it.ref ? it.prev : self->last; \ + _c_clist_insert_after(self, Self, node, value); \ if (!self->last || !it.ref) { \ it.prev = self->last ? self->last : entry; \ self->last = entry; \ @@ -239,63 +205,63 @@ STC_API size_t _clist_count(const clist_VOID* self); return it; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_erase_at(CX* self, CX##_iter_t it) { \ - CX##_node_t *node = _clist_node(CX, it.ref); \ + STC_DEF cx_iter_t \ + cx_memb(_erase_at)(Self* self, cx_iter_t it) { \ + cx_node_t *node = _clist_node(Self, it.ref); \ it.ref = (node == self->last) ? NULL : &node->next->value; \ - CX##_erase_after_(self, it.prev); \ + cx_memb(_erase_after_)(self, it.prev); \ return it; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_erase_range(CX* self, CX##_iter_t it1, CX##_iter_t it2) { \ - CX##_node_t *node = it1.ref ? it1.prev : NULL, \ - *done = it2.ref ? _clist_node(CX, it2.ref) : NULL; \ + STC_DEF cx_iter_t \ + cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2) { \ + cx_node_t *node = it1.ref ? it1.prev : NULL, \ + *done = it2.ref ? _clist_node(Self, it2.ref) : NULL; \ while (node && node->next != done) \ - node = CX##_erase_after_(self, node); \ + node = cx_memb(_erase_after_)(self, node); \ return it2; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_find_in(CX##_iter_t it1, CX##_iter_t it2, RawValue val) { \ - c_foreach_4 (it, CX, it1, it2) { \ - RawValue r = valueToRaw(it.ref); \ - if (valueCompareRaw(&r, &val) == 0) return it; \ + STC_DEF cx_iter_t \ + cx_memb(_find_in)(cx_iter_t it1, cx_iter_t it2, i_VALRAW val) { \ + c_foreach_4 (it, Self, it1, it2) { \ + i_VALRAW r = i_VALTO(it.ref); \ + if (i_CMP(&r, &val) == 0) return it; \ } \ it2.ref = NULL; return it2; \ } \ \ - STC_DEF CX##_node_t* \ - CX##_erase_after_(CX* self, CX##_node_t* node) { \ - CX##_node_t* del = node->next, *next = del->next; \ + STC_DEF cx_node_t* \ + cx_memb(_erase_after_)(Self* self, cx_node_t* node) { \ + cx_node_t* del = node->next, *next = del->next; \ node->next = next; \ if (del == next) self->last = node = NULL; \ else if (self->last == del) self->last = node, node = NULL; \ - valueDel(&del->value); c_free(del); \ + i_VALDEL(&del->value); c_free(del); \ return node; \ } \ \ STC_DEF size_t \ - CX##_remove(CX* self, RawValue val) { \ + cx_memb(_remove)(Self* self, i_VALRAW val) { \ size_t n = 0; \ - CX##_node_t* prev = self->last, *node; \ + cx_node_t* prev = self->last, *node; \ while (prev) { \ node = prev->next; \ - RawValue r = valueToRaw(&node->value); \ - if (valueCompareRaw(&r, &val) == 0) \ - prev = CX##_erase_after_(self, prev), ++n; \ + i_VALRAW r = i_VALTO(&node->value); \ + if (i_CMP(&r, &val) == 0) \ + prev = cx_memb(_erase_after_)(self, prev), ++n; \ else \ prev = (node == self->last ? NULL : node); \ } \ return n; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_splice(CX* self, CX##_iter_t it, CX* other) { \ + STC_DEF cx_iter_t \ + cx_memb(_splice)(Self* self, cx_iter_t it, Self* other) { \ if (!self->last) \ self->last = other->last; \ else if (other->last) { \ - CX##_node_t *p = it.ref ? it.prev : self->last, *next = p->next; \ + cx_node_t *p = it.ref ? it.prev : self->last, *next = p->next; \ it.prev = other->last; \ p->next = it.prev->next; \ it.prev->next = next; \ @@ -304,33 +270,33 @@ STC_API size_t _clist_count(const clist_VOID* self); other->last = NULL; return it; \ } \ \ - STC_DEF CX \ - CX##_split_off(CX* self, CX##_iter_t it1, CX##_iter_t it2) { \ - CX cx = {NULL}; \ + STC_DEF Self \ + cx_memb(_split_off)(Self* self, cx_iter_t it1, cx_iter_t it2) { \ + Self cx = {NULL}; \ if (it1.ref == it2.ref) return cx; \ - CX##_node_t *p1 = it1.prev, \ + cx_node_t *p1 = it1.prev, \ *p2 = it2.ref ? it2.prev : self->last; \ - p1->next = p2->next, p2->next = _clist_node(CX, it1.ref); \ + p1->next = p2->next, p2->next = _clist_node(Self, it1.ref); \ if (self->last == p2) self->last = (p1 == p2) ? NULL : p1; \ cx.last = p2; \ return cx; \ } \ \ STC_DEF int \ - CX##_sort_cmp_(const clist_VOID_node_t* x, const clist_VOID_node_t* y) { \ - RawValue a = valueToRaw(&((const CX##_node_t *) x)->value); \ - RawValue b = valueToRaw(&((const CX##_node_t *) y)->value); \ - return valueCompareRaw(&a, &b); \ + cx_memb(_sort_cmp_)(const clist_VOID_node_t* x, const clist_VOID_node_t* y) { \ + i_VALRAW a = i_VALTO(&((const cx_node_t *) x)->value); \ + i_VALRAW b = i_VALTO(&((const cx_node_t *) y)->value); \ + return i_CMP(&a, &b); \ } \ STC_DEF void \ - CX##_sort(CX* self) { \ + cx_memb(_sort)(Self* self) { \ if (self->last) \ - self->last = (CX##_node_t *) _clist_mergesort((clist_VOID_node_t *) self->last->next, CX##_sort_cmp_); \ + self->last = (cx_node_t *) _clist_mergesort((clist_VOID_node_t *) self->last->next, cx_memb(_sort_cmp_)); \ } -#define _c_clist_insert_after(self, CX, node, val) \ - CX##_node_t *entry = c_new (CX##_node_t); \ +#define _c_clist_insert_after(self, Self, node, val) \ + cx_node_t *entry = c_new (cx_node_t); \ if (node) entry->next = node->next, node->next = entry; \ else entry->next = entry; \ entry->value = val @@ -396,8 +362,6 @@ _clist_mergesort(clist_VOID_node_t *list, int (*cmp)(const clist_VOID_node_t*, c } } -#else -#define _c_implement_clist(CX, Value, valueCompareRaw, valueDel, valueFromRaw, valueToRaw, RawValue) -#endif #endif +#endif diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 68a5fd4b..39d9fce8 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -51,276 +51,170 @@ int main(void) { #include #include -#define using_cmap(...) c_MACRO_OVERLOAD(using_cmap, __VA_ARGS__) -#define using_cmap_3(X, Key, Mapped) \ - using_cmap_5(X, Key, Mapped, c_default_equals, c_default_hash) -#define using_cmap_5(X, Key, Mapped, keyEquals, keyHash) \ - using_cmap_7(X, Key, Mapped, keyEquals, keyHash, \ - c_default_del, c_default_fromraw) -#define using_cmap_6(X, Key, Mapped, keyEquals, keyHash, mappedDel) \ - using_cmap_7(X, Key, Mapped, keyEquals, keyHash, \ - mappedDel, c_no_clone) -#define using_cmap_7(X, Key, Mapped, keyEquals, keyHash, mappedDel, mappedClone) \ - using_cmap_10(X, Key, Mapped, keyEquals, keyHash, \ - mappedDel, mappedClone, c_default_toraw, Mapped, c_true) -#define using_cmap_10(X, Key, Mapped, keyEquals, keyHash, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - using_cmap_14(X, Key, Mapped, keyEquals, keyHash, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - c_default_del, c_default_fromraw, c_default_toraw, Key, defTypes) -#define using_cmap_14(X, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_chash(cmap_##X, cmap_, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - - -#define using_cmap_keydef(...) c_MACRO_OVERLOAD(using_cmap_keydef, __VA_ARGS__) - -#define using_cmap_keydef_7(X, Key, Mapped, keyEquals, keyHash, keyDel, keyClone) \ - using_cmap_keydef_10(X, Key, Mapped, keyEquals, keyHash, \ - keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_cmap_keydef_10(X, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_chash(cmap_##X, cmap_, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - c_default_del, c_default_fromraw, c_default_toraw, Mapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define using_cmap_str() \ - _c_using_chash(cmap_str, cmap_, cstr, cstr, c_rawstr_equals, c_rawstr_hash, \ - cstr_del, cstr_from, cstr_str, const char*, \ - cstr_del, cstr_from, cstr_str, const char*, c_true) - - -#define using_cmap_strkey(...) c_MACRO_OVERLOAD(using_cmap_strkey, __VA_ARGS__) - -#define using_cmap_strkey_2(X, Mapped) \ - using_cmap_strkey_4(X, Mapped, c_default_del, c_default_fromraw) -#define using_cmap_strkey_3(X, Mapped, mappedDel) \ - using_cmap_strkey_4(X, Mapped, mappedDel, c_no_clone) -#define using_cmap_strkey_4(X, Mapped, mappedDel, mappedClone) \ - using_cmap_strkey_7(X, Mapped, mappedDel, mappedClone, c_default_toraw, Mapped, c_true) -#define using_cmap_strkey_7(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - _c_using_chash_strkey(X, cmap_, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) -#define _c_using_chash_strkey(X, C, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - _c_using_chash(C##X, C, cstr, Mapped, c_rawstr_equals, c_rawstr_hash, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - cstr_del, cstr_from, cstr_str, const char*, defTypes) - - -#define using_cmap_strval(...) c_MACRO_OVERLOAD(using_cmap_strval, __VA_ARGS__) - -#define using_cmap_strval_2(X, Key) \ - using_cmap_strval_4(X, Key, c_default_equals, c_default_hash) -#define using_cmap_strval_4(X, Key, keyEquals, keyHash) \ - using_cmap_strval_6(X, Key, keyEquals, keyHash, c_default_del, c_default_fromraw) -#define using_cmap_strval_5(X, Key, keyEquals, keyHash, keyDel) \ - using_cmap_strval_6(X, Key, keyEquals, keyHash, keyDel, c_no_clone) -#define using_cmap_strval_6(X, Key, keyEquals, keyHash, keyDel, keyClone) \ - using_cmap_strval_9(X, Key, keyEquals, keyHash, keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_cmap_strval_9(X, Key, keyEqualsRaw, keyHashRaw, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_chash(cmap_##X, cmap_, Key, cstr, keyEqualsRaw, keyHashRaw, \ - cstr_del, cstr_from, cstr_str, const char*, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define SET_ONLY_cmap_(...) -#define MAP_ONLY_cmap_(...) __VA_ARGS__ #define KEY_REF_cmap_(vp) (&(vp)->first) -#ifndef CMAP_SIZE_T -#define CMAP_SIZE_T uint32_t -#endif #define _cmap_inits {NULL, NULL, 0, 0, 0.85f} -typedef struct {size_t idx; uint_fast8_t hx;} chash_bucket_t; \ +typedef struct {size_t idx; uint_fast8_t hx; } chash_bucket_t; \ STC_API uint64_t c_default_hash(const void *data, size_t len); STC_INLINE uint64_t c_string_hash(const char *s) - {return c_default_hash(s, strlen(s));} + { return c_default_hash(s, strlen(s)); } STC_INLINE uint64_t c_default_hash32(const void* data, size_t ignored) - {return *(const uint32_t *)data * 0xc6a4a7935bd1e99d;} + { return *(const uint32_t *)data * 0xc6a4a7935bd1e99d; } STC_INLINE uint64_t c_default_hash64(const void* data, size_t ignored) - {return *(const uint64_t *)data * 0xc6a4a7935bd1e99d;} + { return *(const uint64_t *)data * 0xc6a4a7935bd1e99d; } -#define _c_chash_types(CX, C, Key, Mapped) \ - typedef Key CX##_key_t; \ - typedef Mapped CX##_mapped_t; \ - typedef CMAP_SIZE_T CX##_size_t; \ -\ - typedef SET_ONLY_##C( CX##_key_t ) \ - MAP_ONLY_##C( struct CX##_value_t ) \ - CX##_value_t; \ -\ - typedef struct { \ - CX##_value_t *ref; \ - bool inserted; \ - } CX##_result_t; \ -\ - typedef struct { \ - CX##_value_t *ref; \ - uint8_t* _hx; \ - } CX##_iter_t; \ -\ - typedef struct { \ - CX##_value_t* table; \ - uint8_t* _hashx; \ - CX##_size_t size, bucket_count; \ - float max_load_factor; \ - } CX -#define _c_using_chash(CX, C, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - defTypes( _c_chash_types(CX, C, Key, Mapped); ) \ + defTypes( _c_chash_types(Self, C, i_KEY, i_VAL); ) \ \ - MAP_ONLY_##C( struct CX##_value_t { \ - CX##_key_t first; \ - CX##_mapped_t second; \ + MAP_ONLY_##C( struct cx_value_t { \ + cx_key_t first; \ + cx_mapped_t second; \ }; ) \ \ - typedef RawKey CX##_rawkey_t; \ - typedef RawMapped CX##_rawmapped_t; \ - typedef SET_ONLY_##C( RawKey ) \ - MAP_ONLY_##C( struct { RawKey first; \ - RawMapped second; } ) \ - CX##_rawvalue_t; \ + typedef i_KEYRAW cx_rawkey_t; \ + typedef i_VALRAW cx_memb(_rawmapped_t); \ + typedef SET_ONLY_##C( i_KEYRAW ) \ + MAP_ONLY_##C( struct { i_KEYRAW first; \ + i_VALRAW second; } ) \ + cx_rawvalue_t; \ \ - STC_API CX CX##_with_capacity(size_t cap); \ - STC_API CX CX##_clone(CX map); \ - STC_API void CX##_del(CX* self); \ - STC_API void CX##_clear(CX* self); \ - STC_API void CX##_reserve(CX* self, size_t capacity); \ - STC_API chash_bucket_t CX##_bucket_(const CX* self, const CX##_rawkey_t* rkeyptr); \ - STC_API CX##_result_t CX##_insert_entry_(CX* self, RawKey rkey); \ - STC_API void CX##_erase_entry(CX* self, CX##_value_t* val); \ + STC_API Self cx_memb(_with_capacity)(size_t cap); \ + STC_API Self cx_memb(_clone)(Self map); \ + 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 capacity); \ + STC_API chash_bucket_t cx_memb(_bucket_)(const Self* self, const cx_rawkey_t* rkeyptr); \ + STC_API cx_result_t cx_memb(_insert_entry_)(Self* self, i_KEYRAW rkey); \ + STC_API void cx_memb(_erase_entry)(Self* self, cx_value_t* val); \ \ - STC_INLINE CX CX##_init(void) {return c_make(CX)_cmap_inits;} \ - STC_INLINE void CX##_shrink_to_fit(CX* self) {CX##_reserve(self, self->size);} \ - STC_INLINE void CX##_max_load_factor(CX* self, float ml) {self->max_load_factor = ml;} \ - STC_INLINE bool CX##_empty(CX m) {return m.size == 0;} \ - STC_INLINE size_t CX##_size(CX m) {return m.size;} \ - STC_INLINE size_t CX##_bucket_count(CX map) {return map.bucket_count;} \ - STC_INLINE size_t CX##_capacity(CX map) \ - {return (size_t) (map.bucket_count * map.max_load_factor);} \ - STC_INLINE void CX##_swap(CX *map1, CX *map2) {c_swap(CX, *map1, *map2);} \ - STC_INLINE bool CX##_contains(const CX* self, RawKey rkey) \ - {return self->size && self->_hashx[CX##_bucket_(self, &rkey).idx];} \ + STC_INLINE Self cx_memb(_init)(void) { return c_make(Self)_cmap_inits; } \ + STC_INLINE void cx_memb(_shrink_to_fit)(Self* self) {cx_memb(_reserve)(self, self->size); } \ + STC_INLINE void cx_memb(_max_load_factor)(Self* self, float ml) {self->max_load_factor = ml; } \ + STC_INLINE bool cx_memb(_empty)(Self m) { return m.size == 0; } \ + STC_INLINE size_t cx_memb(_size)(Self m) { return m.size; } \ + STC_INLINE size_t cx_memb(_bucket_count)(Self map) { return map.bucket_count; } \ + STC_INLINE size_t cx_memb(_capacity)(Self map) \ + { return (size_t) (map.bucket_count * map.max_load_factor); } \ + STC_INLINE void cx_memb(_swap)(Self *map1, Self *map2) {c_swap(Self, *map1, *map2); } \ + STC_INLINE bool cx_memb(_contains)(const Self* self, i_KEYRAW rkey) \ + { return self->size && self->_hashx[cx_memb(_bucket_)(self, &rkey).idx]; } \ \ STC_INLINE void \ - CX##_value_clone(CX##_value_t* _dst, CX##_value_t* _val) { \ - *KEY_REF_##C(_dst) = keyFromRaw(keyToRaw(KEY_REF_##C(_val))); \ - MAP_ONLY_##C( _dst->second = mappedFromRaw(mappedToRaw(&_val->second)); ) \ + cx_memb(_value_clone)(cx_value_t* _dst, cx_value_t* _val) { \ + *KEY_REF_##C(_dst) = i_KEYFROM(i_KEYTO(KEY_REF_##C(_val))); \ + MAP_ONLY_##C( _dst->second = i_VALFROM(i_VALTO(&_val->second)); ) \ } \ \ - STC_INLINE CX##_rawvalue_t \ - CX##_value_toraw(CX##_value_t* val) { \ - return SET_ONLY_##C( keyToRaw(val) ) \ - MAP_ONLY_##C( c_make(CX##_rawvalue_t){keyToRaw(&val->first), mappedToRaw(&val->second)} ); \ + STC_INLINE cx_rawvalue_t \ + cx_memb(_value_toraw)(cx_value_t* val) { \ + return SET_ONLY_##C( i_KEYTO(val) ) \ + MAP_ONLY_##C( c_make(cx_rawvalue_t){i_KEYTO(&val->first), i_VALTO(&val->second)} ); \ } \ \ STC_INLINE void \ - CX##_value_del(CX##_value_t* _val) { \ - keyDel(KEY_REF_##C(_val)); \ - MAP_ONLY_##C( mappedDel(&_val->second); ) \ + cx_memb(_value_del)(cx_value_t* _val) { \ + i_KEYDEL(KEY_REF_##C(_val)); \ + MAP_ONLY_##C( i_VALDEL(&_val->second); ) \ } \ \ - STC_INLINE CX##_result_t \ - CX##_emplace(CX* self, RawKey rkey MAP_ONLY_##C(, RawMapped rmapped)) { \ - CX##_result_t _res = CX##_insert_entry_(self, rkey); \ + STC_INLINE cx_result_t \ + cx_memb(_emplace)(Self* self, i_KEYRAW rkey MAP_ONLY_##C(, i_VALRAW rmapped)) { \ + cx_result_t _res = cx_memb(_insert_entry_)(self, rkey); \ if (_res.inserted) { \ - *KEY_REF_##C(_res.ref) = keyFromRaw(rkey); \ - MAP_ONLY_##C(_res.ref->second = mappedFromRaw(rmapped);) \ + *KEY_REF_##C(_res.ref) = i_KEYFROM(rkey); \ + MAP_ONLY_##C(_res.ref->second = i_VALFROM(rmapped);) \ } \ return _res; \ } \ \ STC_INLINE void \ - CX##_emplace_items(CX* self, const CX##_rawvalue_t arr[], size_t n) { \ - for (size_t i=0; isecond = _mapped; )} \ - else {keyDel(&_key); MAP_ONLY_##C( mappedDel(&_mapped); )} \ + else {i_KEYDEL(&_key); MAP_ONLY_##C( i_VALDEL(&_mapped); )} \ return _res; \ } \ \ MAP_ONLY_##C( \ - STC_INLINE CX##_result_t \ - CX##_insert_or_assign(CX* self, Key _key, Mapped _mapped) { \ - CX##_result_t _res = CX##_insert_entry_(self, keyToRaw(&_key)); \ + STC_INLINE cx_result_t \ + cx_memb(_insert_or_assign)(Self* self, i_KEY _key, i_VAL _mapped) { \ + cx_result_t _res = cx_memb(_insert_entry_)(self, i_KEYTO(&_key)); \ if (_res.inserted) _res.ref->first = _key; \ - else {keyDel(&_key); mappedDel(&_res.ref->second);} \ + else {i_KEYDEL(&_key); i_VALDEL(&_res.ref->second); } \ _res.ref->second = _mapped; return _res; \ } \ \ - STC_INLINE CX##_result_t \ - CX##_put(CX* self, Key k, Mapped m) { /* shorter, like operator[] */ \ - return CX##_insert_or_assign(self, k, m); \ + STC_INLINE cx_result_t \ + cx_memb(_put)(Self* self, i_KEY k, i_VAL m) { /* shorter, like operator[] */ \ + return cx_memb(_insert_or_assign)(self, k, m); \ } \ \ - STC_INLINE CX##_result_t \ - CX##_emplace_or_assign(CX* self, RawKey rkey, RawMapped rmapped) { \ - CX##_result_t _res = CX##_insert_entry_(self, rkey); \ - if (_res.inserted) _res.ref->first = keyFromRaw(rkey); \ - else mappedDel(&_res.ref->second); \ - _res.ref->second = mappedFromRaw(rmapped); return _res; \ + STC_INLINE cx_result_t \ + cx_memb(_emplace_or_assign)(Self* self, i_KEYRAW rkey, i_VALRAW rmapped) { \ + cx_result_t _res = cx_memb(_insert_entry_)(self, rkey); \ + if (_res.inserted) _res.ref->first = i_KEYFROM(rkey); \ + else i_VALDEL(&_res.ref->second); \ + _res.ref->second = i_VALFROM(rmapped); return _res; \ } \ \ - STC_INLINE CX##_mapped_t* \ - CX##_at(const CX* self, RawKey rkey) { \ - chash_bucket_t b = CX##_bucket_(self, &rkey); \ + STC_INLINE cx_mapped_t* \ + cx_memb(_at)(const Self* self, i_KEYRAW rkey) { \ + chash_bucket_t b = cx_memb(_bucket_)(self, &rkey); \ return &self->table[b.idx].second; \ }) \ \ - STC_INLINE CX##_iter_t \ - CX##_find(const CX* self, RawKey rkey) { \ - CX##_iter_t it = {NULL}; \ + STC_INLINE cx_iter_t \ + cx_memb(_find)(const Self* self, i_KEYRAW rkey) { \ + cx_iter_t it = {NULL}; \ if (self->size == 0) return it; \ - chash_bucket_t b = CX##_bucket_(self, &rkey); \ + chash_bucket_t b = cx_memb(_bucket_)(self, &rkey); \ if (*(it._hx = self->_hashx+b.idx)) it.ref = self->table+b.idx; \ return it; \ } \ \ - STC_INLINE CX##_value_t* \ - CX##_get(const CX* self, RawKey rkey) \ - {return CX##_find(self, rkey).ref;} \ + STC_INLINE cx_value_t* \ + cx_memb(_get)(const Self* self, i_KEYRAW rkey) \ + { return cx_memb(_find)(self, rkey).ref; } \ \ - STC_INLINE CX##_iter_t \ - CX##_begin(const CX* self) { \ - CX##_iter_t it = {self->table, self->_hashx}; \ + STC_INLINE cx_iter_t \ + cx_memb(_begin)(const Self* self) { \ + cx_iter_t it = {self->table, self->_hashx}; \ if (it._hx) while (*it._hx == 0) ++it.ref, ++it._hx; \ return it; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_end(const CX* self) \ - {return c_make(CX##_iter_t){self->table + self->bucket_count};} \ + STC_INLINE cx_iter_t \ + cx_memb(_end)(const Self* self) \ + { return c_make(cx_iter_t){self->table + self->bucket_count}; } \ \ STC_INLINE void \ - CX##_next(CX##_iter_t* it) \ - {while ((++it->ref, *++it->_hx == 0)) ;} \ + cx_memb(_next)(cx_iter_t* it) \ + {while ((++it->ref, *++it->_hx == 0)) ; } \ \ STC_INLINE size_t \ - CX##_erase(CX* self, RawKey rkey) { \ + cx_memb(_erase)(Self* self, i_KEYRAW rkey) { \ if (self->size == 0) return 0; \ - chash_bucket_t b = CX##_bucket_(self, &rkey); \ - return self->_hashx[b.idx] ? CX##_erase_entry(self, self->table + b.idx), 1 : 0; \ + chash_bucket_t b = cx_memb(_bucket_)(self, &rkey); \ + return self->_hashx[b.idx] ? cx_memb(_erase_entry)(self, self->table + b.idx), 1 : 0; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_erase_at(CX* self, CX##_iter_t it) { \ - CX##_erase_entry(self, it.ref); \ - if (*it._hx == 0) CX##_next(&it); \ + STC_INLINE cx_iter_t \ + cx_memb(_erase_at)(Self* self, cx_iter_t it) { \ + cx_memb(_erase_entry)(self, it.ref); \ + if (*it._hx == 0) cx_memb(_next)(&it); \ return it; \ } \ \ - _c_implement_chash(CX, C, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) \ + _c_implement_chash(Self, C, i_KEY, i_VAL, i_EQU, i_HASH, \ + i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW, \ + i_KEYDEL, i_KEYFROM, i_KEYTO, i_KEYRAW) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -329,63 +223,63 @@ STC_INLINE uint64_t c_default_hash64(const void* data, size_t ignored) #ifdef c_umul128 STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n) \ - {uint64_t l, h; c_umul128(x, n, &l, &h); return h;} + {uint64_t l, h; c_umul128(x, n, &l, &h); return h; } #endif #define fastrange_uint32_t(x, n) ((size_t) (((uint32_t)(x)*(uint64_t)(n)) >> 32)) #define chash_index_(h, entryPtr) ((entryPtr) - (h).table) -#define _c_implement_chash(CX, C, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) \ - STC_DEF CX \ - CX##_with_capacity(size_t cap) { \ - CX h = _cmap_inits; \ - CX##_reserve(&h, cap); \ +#define _c_implement_chash(Self, C, i_KEY, i_VAL, i_EQU, i_HASH, \ + i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW, \ + i_KEYDEL, i_KEYFROM, i_KEYTO, i_KEYRAW) \ + STC_DEF Self \ + cx_memb(_with_capacity)(size_t cap) { \ + Self h = _cmap_inits; \ + cx_memb(_reserve)(&h, cap); \ return h; \ } \ \ - STC_INLINE void CX##_wipe_(CX* self) { \ + STC_INLINE void cx_memb(_wipe_)(Self* self) { \ if (self->size == 0) return; \ - CX##_value_t* e = self->table, *end = e + self->bucket_count; \ + cx_value_t* e = self->table, *end = e + self->bucket_count; \ uint8_t *hx = self->_hashx; \ - for (; e != end; ++e) if (*hx++) CX##_value_del(e); \ + for (; e != end; ++e) if (*hx++) cx_memb(_value_del)(e); \ } \ \ - STC_DEF void CX##_del(CX* self) { \ - CX##_wipe_(self); \ + STC_DEF void cx_memb(_del)(Self* self) { \ + cx_memb(_wipe_)(self); \ c_free(self->_hashx); \ c_free((void *) self->table); \ } \ \ - STC_DEF void CX##_clear(CX* self) { \ - CX##_wipe_(self); \ + STC_DEF void cx_memb(_clear)(Self* self) { \ + cx_memb(_wipe_)(self); \ self->size = 0; \ memset(self->_hashx, 0, self->bucket_count); \ } \ \ STC_DEF chash_bucket_t \ - CX##_bucket_(const CX* self, const CX##_rawkey_t* rkeyptr) { \ - const uint64_t _hash = keyHashRaw(rkeyptr, sizeof *rkeyptr); \ + cx_memb(_bucket_)(const Self* self, const cx_rawkey_t* rkeyptr) { \ + const uint64_t _hash = i_HASH(rkeyptr, sizeof *rkeyptr); \ uint_fast8_t _hx; size_t _cap = self->bucket_count; \ chash_bucket_t b = {c_SELECT(fastrange,CMAP_SIZE_T)(_hash, _cap), (uint_fast8_t)(_hash | 0x80)}; \ const uint8_t* _hashx = self->_hashx; \ while ((_hx = _hashx[b.idx])) { \ if (_hx == b.hx) { \ - CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(self->table + b.idx)); \ - if (keyEqualsRaw(&_raw, rkeyptr)) break; \ + cx_rawkey_t _raw = i_KEYTO(KEY_REF_##C(self->table + b.idx)); \ + if (i_EQU(&_raw, rkeyptr)) break; \ } \ if (++b.idx == _cap) b.idx = 0; \ } \ return b; \ } \ \ - STC_DEF CX##_result_t \ - CX##_insert_entry_(CX* self, RawKey rkey) { \ - if (self->size + 1 >= (CX##_size_t) (self->bucket_count * self->max_load_factor)) \ - CX##_reserve(self, 8 + (self->size*13ull >> 3)); \ - chash_bucket_t b = CX##_bucket_(self, &rkey); \ - CX##_result_t res = {&self->table[b.idx], !self->_hashx[b.idx]}; \ + STC_DEF cx_result_t \ + cx_memb(_insert_entry_)(Self* self, i_KEYRAW rkey) { \ + if (self->size + 1 >= (cx_memb(_size_t)) (self->bucket_count * self->max_load_factor)) \ + cx_memb(_reserve)(self, 8 + (self->size*13ull >> 3)); \ + chash_bucket_t b = cx_memb(_bucket_)(self, &rkey); \ + cx_result_t res = {&self->table[b.idx], !self->_hashx[b.idx]}; \ if (res.inserted) { \ self->_hashx[b.idx] = b.hx; \ ++self->size; \ @@ -393,39 +287,39 @@ STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n) \ return res; \ } \ \ - STC_DEF CX \ - CX##_clone(CX m) { \ - CX clone = { \ - c_new_n(CX##_value_t, m.bucket_count), \ + STC_DEF Self \ + cx_memb(_clone)(Self m) { \ + Self clone = { \ + c_new_n(cx_value_t, m.bucket_count), \ (uint8_t *) memcpy(c_malloc(m.bucket_count + 1), m._hashx, m.bucket_count + 1), \ m.size, m.bucket_count, \ m.max_load_factor \ }; \ - CX##_value_t *e = m.table, *end = e + m.bucket_count, *dst = clone.table; \ + cx_value_t *e = m.table, *end = e + m.bucket_count, *dst = clone.table; \ for (uint8_t *hx = m._hashx; e != end; ++hx, ++e, ++dst) \ - if (*hx) CX##_value_clone(dst, e); \ + if (*hx) cx_memb(_value_clone)(dst, e); \ return clone; \ } \ \ STC_DEF void \ - CX##_reserve(CX* self, size_t _newcap) { \ + cx_memb(_reserve)(Self* self, size_t _newcap) { \ if (_newcap < self->size) return; \ size_t _oldcap = self->bucket_count; \ _newcap = (size_t) (2 + _newcap / self->max_load_factor) | 1; \ - CX _tmp = { \ - c_new_n(CX##_value_t, _newcap), \ + Self _tmp = { \ + c_new_n(cx_value_t, _newcap), \ (uint8_t *) c_calloc(_newcap + 1, sizeof(uint8_t)), \ - self->size, (CX##_size_t) _newcap, \ + self->size, (cx_memb(_size_t)) _newcap, \ self->max_load_factor \ }; \ /* Rehash: */ \ - _tmp._hashx[_newcap] = 0xff; c_swap(CX, *self, _tmp); \ - CX##_value_t* e = _tmp.table, *_slot = self->table; \ + _tmp._hashx[_newcap] = 0xff; c_swap(Self, *self, _tmp); \ + cx_value_t* e = _tmp.table, *_slot = self->table; \ uint8_t* _hashx = self->_hashx; \ for (size_t i = 0; i < _oldcap; ++i, ++e) \ if (_tmp._hashx[i]) { \ - CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(e)); \ - chash_bucket_t b = CX##_bucket_(self, &_raw); \ + cx_rawkey_t _raw = i_KEYTO(KEY_REF_##C(e)); \ + chash_bucket_t b = cx_memb(_bucket_)(self, &_raw); \ memcpy((void *) &_slot[b.idx], e, sizeof *e); \ _hashx[b.idx] = (uint8_t) b.hx; \ } \ @@ -434,17 +328,17 @@ STC_INLINE size_t fastrange_uint64_t(uint64_t x, uint64_t n) \ } \ \ STC_DEF void \ - CX##_erase_entry(CX* self, CX##_value_t* _val) { \ + cx_memb(_erase_entry)(Self* self, cx_value_t* _val) { \ size_t i = chash_index_(*self, _val), j = i, k, _cap = self->bucket_count; \ - CX##_value_t* _slot = self->table; \ + cx_value_t* _slot = self->table; \ uint8_t* _hashx = self->_hashx; \ - CX##_value_del(&_slot[i]); \ + cx_memb(_value_del)(&_slot[i]); \ for (;;) { /* delete without leaving tombstone */ \ if (++j == _cap) j = 0; \ if (! _hashx[j]) \ break; \ - CX##_rawkey_t _raw = keyToRaw(KEY_REF_##C(_slot+j)); \ - k = c_SELECT(fastrange,CMAP_SIZE_T)(keyHashRaw(&_raw, sizeof _raw), _cap); \ + cx_rawkey_t _raw = i_KEYTO(KEY_REF_##C(_slot+j)); \ + k = c_SELECT(fastrange,CMAP_SIZE_T)(i_HASH(&_raw, sizeof _raw), _cap); \ if ((j < i) ^ (k <= i) ^ (k > j)) /* is k outside (i, j]? */ \ memcpy((void *) &_slot[i], &_slot[j], sizeof *_slot), _hashx[i] = _hashx[j], i = j; \ } \ @@ -457,7 +351,7 @@ STC_DEF uint64_t c_default_hash(const void *key, size_t len) { const uint64_t m = 0xb5ad4eceda1ce2a9; uint64_t k, h = m + len; const uint8_t *p = (const uint8_t *)key, *end = p + (len & ~7ull); - for (; p != end; p += 8) {memcpy(&k, p, 8); h ^= m*k;} + for (; p != end; p += 8) {memcpy(&k, p, 8); h ^= m*k; } switch (len & 7) { case 7: h ^= (uint64_t) p[6] << 48; case 6: h ^= (uint64_t) p[5] << 40; @@ -470,10 +364,5 @@ STC_DEF uint64_t c_default_hash(const void *key, size_t len) { return h ^ (h >> 15); } -#else -#define _c_implement_chash(CX, C, Key, Mapped, keyEqualsRaw, keyHashRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) #endif - #endif diff --git a/include/stc/cpque.h b/include/stc/cpque.h index c6e0ed61..1958628c 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -55,36 +55,36 @@ #define using_cpque_2(X, ctype) \ _c_using_cpque(cpque_##X, ctype, ctype##_value_compare) -#define using_cpque_3(X, ctype, valueCompare) \ - _c_using_cpque(cpque_##X, ctype, valueCompare) +#define using_cpque_3(X, ctype, i_CMP) \ + _c_using_cpque(cpque_##X, ctype, i_CMP) -#define _c_using_cpque(CX, ctype, valueCompare) \ - typedef ctype CX; \ - typedef ctype##_value_t CX##_value_t; \ - typedef ctype##_rawvalue_t CX##_rawvalue_t; \ +#define _c_using_cpque(Self, ctype, i_CMP) \ + typedef ctype Self; \ + typedef ctype##_value_t cx_value_t; \ + typedef ctype##_rawvalue_t cx_rawvalue_t; \ \ - STC_INLINE CX CX##_init(void) {return ctype##_init();} \ - STC_INLINE CX CX##_clone(CX pq) {return ctype##_clone(pq);} \ - STC_INLINE CX##_value_t CX##_value_clone(CX##_value_t val) \ - {return ctype##_value_clone(val);} \ - STC_INLINE void CX##_clear(CX* self) {ctype##_clear(self);} \ - STC_INLINE void CX##_del(CX* self) {ctype##_del(self);} \ + STC_INLINE Self cx_memb(_init)(void) { return ctype##_init(); } \ + STC_INLINE Self cx_memb(_clone)(Self pq) { return ctype##_clone(pq); } \ + STC_INLINE cx_value_t cx_memb(_value_clone)(cx_value_t val) \ + { return ctype##_value_clone(val); } \ + STC_INLINE void cx_memb(_clear)(Self* self) {ctype##_clear(self); } \ + STC_INLINE void cx_memb(_del)(Self* self) {ctype##_del(self); } \ \ - STC_INLINE size_t CX##_size(CX pq) {return ctype##_size(pq);} \ - STC_INLINE bool CX##_empty(CX pq) {return ctype##_empty(pq);} \ + STC_INLINE size_t cx_memb(_size)(Self pq) { return ctype##_size(pq); } \ + STC_INLINE bool cx_memb(_empty)(Self pq) { return ctype##_empty(pq); } \ \ - STC_API void CX##_make_heap(CX* self); \ - STC_API void CX##_erase_at(CX* self, size_t idx); \ + STC_API void cx_memb(_make_heap)(Self* self); \ + STC_API void cx_memb(_erase_at)(Self* self, size_t idx); \ STC_INLINE \ - const CX##_value_t* CX##_top(const CX* self) {return &self->data[0];} \ - STC_INLINE void CX##_pop(CX* self) {CX##_erase_at(self, 0);} \ + const cx_value_t* cx_memb(_top)(const Self* self) { return &self->data[0]; } \ + STC_INLINE void cx_memb(_pop)(Self* self) {cx_memb(_erase_at)(self, 0); } \ \ - STC_API void CX##_push(CX* self, CX##_value_t value); \ - STC_INLINE void CX##_emplace(CX* self, CX##_rawvalue_t raw) \ - {CX##_push(self, ctype##_value_fromraw(raw));} \ - STC_API void CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n); \ + STC_API void cx_memb(_push)(Self* self, cx_value_t value); \ + STC_INLINE void cx_memb(_emplace)(Self* self, cx_rawvalue_t raw) \ + {cx_memb(_push)(self, ctype##_value_fromraw(raw)); } \ + STC_API void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n); \ \ - _c_implement_cpque(CX, ctype, valueCompare) \ + _c_implement_cpque(Self, ctype, i_CMP) \ struct stc_trailing_semicolon @@ -92,15 +92,15 @@ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_cpque(CX, ctype, valueCompare) \ +#define _c_implement_cpque(Self, ctype, i_CMP) \ \ STC_INLINE void \ - CX##_sift_down_(CX##_value_t* arr, size_t i, size_t n) { \ + cx_memb(_sift_down_)(cx_value_t* arr, size_t i, size_t n) { \ size_t r = i, c = i << 1; \ while (c <= n) { \ - c += (c < n && valueCompare(&arr[c], &arr[c + 1]) < 0); \ - if (valueCompare(&arr[r], &arr[c]) < 0) { \ - CX##_value_t tmp = arr[r]; arr[r] = arr[c]; arr[r = c] = tmp; \ + c += (c < n && i_CMP(&arr[c], &arr[c + 1]) < 0); \ + if (i_CMP(&arr[r], &arr[c]) < 0) { \ + cx_value_t tmp = arr[r]; arr[r] = arr[c]; arr[r = c] = tmp; \ } else \ return; \ c <<= 1; \ @@ -108,39 +108,39 @@ } \ \ STC_API void \ - CX##_make_heap(CX* self) { \ - size_t n = CX##_size(*self); \ - CX##_value_t *arr = self->data - 1; \ + cx_memb(_make_heap)(Self* self) { \ + size_t n = cx_memb(_size)(*self); \ + cx_value_t *arr = self->data - 1; \ for (size_t k = n >> 1; k != 0; --k) \ - CX##_sift_down_(arr, k, n); \ + cx_memb(_sift_down_)(arr, k, n); \ } \ \ STC_API void \ - CX##_erase_at(CX* self, size_t idx) { \ - size_t n = CX##_size(*self) - 1; \ + cx_memb(_erase_at)(Self* self, size_t idx) { \ + size_t n = cx_memb(_size)(*self) - 1; \ self->data[idx] = self->data[n]; \ ctype##_pop_back(self); \ - CX##_sift_down_(self->data - 1, idx + 1, n); \ + cx_memb(_sift_down_)(self->data - 1, idx + 1, n); \ } \ \ STC_API void \ - CX##_push(CX* self, CX##_value_t value) { \ + cx_memb(_push)(Self* self, cx_value_t value) { \ ctype##_push_back(self, value); /* sift-up the value */ \ - size_t n = CX##_size(*self), c = n; \ - CX##_value_t *arr = self->data - 1; \ - for (; c > 1 && valueCompare(&arr[c >> 1], &value) < 0; c >>= 1) \ + size_t n = cx_memb(_size)(*self), c = n; \ + cx_value_t *arr = self->data - 1; \ + for (; c > 1 && i_CMP(&arr[c >> 1], &value) < 0; c >>= 1) \ arr[c] = arr[c >> 1]; \ if (c != n) arr[c] = value; \ } \ \ STC_API void \ - CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) { \ + cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) { \ for (size_t i = 0; i < n; ++i) \ - CX##_push(self, ctype##_value_fromraw(arr[i])); \ + cx_memb(_push)(self, ctype##_value_fromraw(arr[i])); \ } \ #else -#define _c_implement_cpque(CX, ctype, valueCompare) +#define _c_implement_cpque(Self, ctype, i_CMP) #endif #endif diff --git a/include/stc/cqueue.h b/include/stc/cqueue.h index b89291c8..596f50a9 100644 --- a/include/stc/cqueue.h +++ b/include/stc/cqueue.h @@ -59,35 +59,35 @@ #define using_cqueue(X, ctype) \ _c_using_cqueue(cqueue_##X, ctype) -#define _c_using_cqueue(CX, ctype) \ - typedef struct { ctype rep; size_t size; } CX; \ - typedef ctype##_value_t CX##_value_t; \ - typedef ctype##_rawvalue_t CX##_rawvalue_t; \ - typedef ctype##_iter_t CX##_iter_t; \ +#define _c_using_cqueue(Self, ctype) \ + typedef struct { ctype rep; size_t size; } Self; \ + typedef ctype##_value_t cx_value_t; \ + typedef ctype##_rawvalue_t cx_rawvalue_t; \ + typedef ctype##_iter_t cx_iter_t; \ \ - STC_INLINE CX CX##_init(void) {return c_make(CX){ctype##_init(), 0};} \ - STC_INLINE CX CX##_clone(CX q) {return c_make(CX){ctype##_clone(q.rep), q.size};} \ - STC_INLINE CX##_value_t CX##_value_clone(CX##_value_t val) \ - {return ctype##_value_clone(val);} \ - STC_INLINE void CX##_clear(CX* self) {ctype##_clear(&self->rep); self->size = 0;} \ - STC_INLINE void CX##_del(CX* self) {ctype##_del(&self->rep);} \ + STC_INLINE Self cx_memb(_init)(void) { return c_make(Self){ctype##_init(), 0}; } \ + STC_INLINE Self cx_memb(_clone)(Self q) { return c_make(Self){ctype##_clone(q.rep), q.size}; } \ + STC_INLINE cx_value_t cx_memb(_value_clone)(cx_value_t val) \ + { return ctype##_value_clone(val); } \ + STC_INLINE void cx_memb(_clear)(Self* self) {ctype##_clear(&self->rep); self->size = 0; } \ + STC_INLINE void cx_memb(_del)(Self* self) {ctype##_del(&self->rep); } \ \ - STC_INLINE size_t CX##_size(CX q) {return q.size;} \ - STC_INLINE bool CX##_empty(CX q) {return q.size == 0;} \ - STC_INLINE CX##_value_t* CX##_front(const CX* self) {return ctype##_front(&self->rep);} \ - STC_INLINE CX##_value_t* CX##_back(const CX* self) {return ctype##_back(&self->rep);} \ + STC_INLINE size_t cx_memb(_size)(Self q) { return q.size; } \ + STC_INLINE bool cx_memb(_empty)(Self q) { return q.size == 0; } \ + STC_INLINE cx_value_t* cx_memb(_front)(const Self* self) { return ctype##_front(&self->rep); } \ + STC_INLINE cx_value_t* cx_memb(_back)(const Self* self) { return ctype##_back(&self->rep); } \ \ - STC_INLINE void CX##_pop(CX* self) {ctype##_pop_front(&self->rep); --self->size;} \ - STC_INLINE void CX##_push(CX* self, ctype##_value_t value) \ - {ctype##_push_back(&self->rep, value); ++self->size;} \ - STC_INLINE void CX##_emplace(CX* self, CX##_rawvalue_t raw) \ - {ctype##_emplace_back(&self->rep, raw); ++self->size;} \ - STC_INLINE void CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) \ - {ctype##_emplace_items(&self->rep, arr, n); self->size += n;} \ + STC_INLINE void cx_memb(_pop)(Self* self) {ctype##_pop_front(&self->rep); --self->size; } \ + STC_INLINE void cx_memb(_push)(Self* self, ctype##_value_t value) \ + {ctype##_push_back(&self->rep, value); ++self->size; } \ + STC_INLINE void cx_memb(_emplace)(Self* self, cx_rawvalue_t raw) \ + {ctype##_emplace_back(&self->rep, raw); ++self->size; } \ + STC_INLINE void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) \ + {ctype##_emplace_items(&self->rep, arr, n); self->size += n; } \ \ - STC_INLINE CX##_iter_t CX##_begin(const CX* self) {return ctype##_begin(&self->rep);} \ - STC_INLINE CX##_iter_t CX##_end(const CX* self) {return ctype##_end(&self->rep);} \ - STC_INLINE void CX##_next(CX##_iter_t* it) {ctype##_next(it);} \ + STC_INLINE cx_iter_t cx_memb(_begin)(const Self* self) { return ctype##_begin(&self->rep); } \ + STC_INLINE cx_iter_t cx_memb(_end)(const Self* self) { return ctype##_end(&self->rep); } \ + STC_INLINE void cx_memb(_next)(cx_iter_t* it) {ctype##_next(it); } \ struct stc_trailing_semicolon #endif diff --git a/include/stc/cset.h b/include/stc/cset.h index 6979311a..e1ea8497 100644 --- a/include/stc/cset.h +++ b/include/stc/cset.h @@ -41,30 +41,8 @@ int main(void) { } */ +#define i_CNT cmap +#define KEY_REF_cset(vp) (vp) #include "cmap.h" -#define forward_cset(X, Key) _c_chash_types(cset_##X, cset_, Key, Key) - -#define using_cset(...) c_MACRO_OVERLOAD(using_cset, __VA_ARGS__) - -#define using_cset_2(X, Key) \ - using_cset_4(X, Key, c_default_equals, c_default_hash) -#define using_cset_4(X, Key, keyEquals, keyHash) \ - using_cset_6(X, Key, keyEquals, keyHash, c_default_del, c_default_fromraw) -#define using_cset_5(X, Key, keyEquals, keyHash, keyDel) \ - using_cset_6(X, Key, keyEquals, keyHash, keyDel, c_no_clone) -#define using_cset_6(X, Key, keyEquals, keyHash, keyDel, keyClone) \ - using_cset_9(X, Key, keyEquals, keyHash, keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_cset_9(X, Key, keyEqualsRaw, keyHashRaw, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_chash(cset_##X, cset_, Key, Key, keyEqualsRaw, keyHashRaw, \ - @@, @@, @@, void, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define using_cset_str() \ - using_cset_9(str, cstr, c_rawstr_equals, c_rawstr_hash, cstr_del, \ - cstr_from, cstr_str, const char*, c_true) - -#define SET_ONLY_cset_(...) __VA_ARGS__ -#define MAP_ONLY_cset_(...) -#define KEY_REF_cset_(vp) (vp) - #endif diff --git a/include/stc/csmap.h b/include/stc/csmap.h index bf7fd6ab..4437757d 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -47,269 +47,165 @@ int main(void) { } */ #include "ccommon.h" +#include "template.h" #include #include -#define forward_csmap(X, Key, Mapped) _c_aatree_types(csmap_##X, csmap_, Key, Mapped) - - -#define using_csmap(...) c_MACRO_OVERLOAD(using_csmap, __VA_ARGS__) - -#define using_csmap_3(X, Key, Mapped) \ - using_csmap_4(X, Key, Mapped, c_default_compare) -#define using_csmap_4(X, Key, Mapped, keyCompare) \ - using_csmap_6(X, Key, Mapped, keyCompare, c_default_del, c_default_fromraw) -#define using_csmap_5(X, Key, Mapped, keyCompare, mappedDel) \ - using_csmap_6(X, Key, Mapped, keyCompare, mappedDel, c_no_clone) -#define using_csmap_6(X, Key, Mapped, keyCompare, mappedDel, mappedClone) \ - using_csmap_9(X, Key, Mapped, keyCompare, mappedDel, mappedClone, c_default_toraw, Mapped, c_true) -#define using_csmap_9(X, Key, Mapped, keyCompare, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - using_csmap_13(X, Key, Mapped, keyCompare, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - c_default_del, c_default_fromraw, c_default_toraw, Key, defTypes) -#define using_csmap_13(X, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_aatree(csmap_##X, csmap_, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - - -#define using_csmap_keydef(...) c_MACRO_OVERLOAD(using_csmap_keydef, __VA_ARGS__) - -#define using_csmap_keydef_6(X, Key, Mapped, keyCompare, keyDel, keyClone) \ - using_csmap_keydef_9(X, Key, Mapped, keyCompare, \ - keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_csmap_keydef_9(X, Key, Mapped, keyCompareRaw, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_aatree(csmap_##X, csmap_, Key, Mapped, keyCompareRaw, \ - c_default_del, c_default_fromraw, c_default_toraw, Mapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define using_csmap_str() \ - _c_using_aatree(csmap_str, csmap_, cstr, cstr, c_rawstr_compare, \ - cstr_del, cstr_from, cstr_str, const char*, \ - cstr_del, cstr_from, cstr_str, const char*, c_true) - - -#define using_csmap_strkey(...) c_MACRO_OVERLOAD(using_csmap_strkey, __VA_ARGS__) - -#define using_csmap_strkey_2(X, Mapped) \ - using_csmap_strkey_4(X, Mapped, c_default_del, c_default_fromraw) -#define using_csmap_strkey_3(X, Mapped, mappedDel) \ - using_csmap_strkey_4(X, Mapped, mappedDel, c_no_clone) -#define using_csmap_strkey_4(X, Mapped, mappedDel, mappedClone) \ - using_csmap_strkey_7(X, Mapped, mappedDel, mappedClone, c_default_toraw, Mapped, c_true) -#define using_csmap_strkey_7(X, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - _c_using_aatree_strkey(X, csmap_, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) -#define _c_using_aatree_strkey(X, C, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, defTypes) \ - _c_using_aatree(C##X, C, cstr, Mapped, c_rawstr_compare, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - cstr_del, cstr_from, cstr_str, const char*, defTypes) - - -#define using_csmap_strval(...) c_MACRO_OVERLOAD(using_csmap_strval, __VA_ARGS__) - -#define using_csmap_strval_2(X, Key) \ - using_csmap_strval_3(X, Key, c_default_compare) -#define using_csmap_strval_3(X, Key, keyCompare) \ - using_csmap_strval_5(X, Key, keyCompare, c_default_del, c_default_fromraw) -#define using_csmap_strval_4(X, Key, keyCompare, keyDel) \ - using_csmap_strval_5(X, Key, keyCompare, keyDel, c_no_clone) -#define using_csmap_strval_5(X, Key, keyCompare, keyDel, keyClone) \ - using_csmap_strval_8(X, Key, keyCompare, keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_csmap_strval_8(X, Key, keyCompareRaw, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_aatree(csmap_##X, csmap_, Key, cstr, keyCompareRaw, \ - cstr_del, cstr_from, cstr_str, const char*, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define SET_ONLY_csmap_(...) -#define MAP_ONLY_csmap_(...) __VA_ARGS__ #define KEY_REF_csmap_(vp) (&(vp)->first) -#ifndef CSMAP_SIZE_T -#define CSMAP_SIZE_T uint32_t -#endif struct csmap_rep { size_t root, disp, head, size, cap; void* nodes[]; }; #define _csmap_rep(self) c_container_of((self)->nodes, struct csmap_rep, nodes) -#define _c_aatree_types(CX, C, Key, Mapped) \ - typedef Key CX##_key_t; \ - typedef Mapped CX##_mapped_t; \ - typedef CSMAP_SIZE_T CX##_size_t; \ -\ - typedef SET_ONLY_##C( CX##_key_t ) \ - MAP_ONLY_##C( struct CX##_value_t ) \ - CX##_value_t; \ -\ - typedef struct { \ - CX##_value_t *ref; \ - bool inserted; \ - } CX##_result_t; \ -\ - typedef struct CX##_node_t CX##_node_t; \ -\ - typedef struct { \ - CX##_value_t *ref; \ - CX##_node_t *_d; \ - int _top; \ - CX##_size_t _tn, _st[36]; \ - } CX##_iter_t; \ -\ - typedef struct { \ - CX##_node_t *nodes; \ - } CX +#if !defined cx_forwarded + _c_aatree_types(Self, C, i_KEY, i_VAL); +#endif -#define _c_using_aatree(CX, C, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - defTypes( _c_aatree_types(CX, C, Key, Mapped); ) \ -\ - MAP_ONLY_##C( struct CX##_value_t { \ - CX##_key_t first; \ - CX##_mapped_t second; \ +\ + MAP_ONLY_##C( struct cx_value_t { \ + cx_key_t first; \ + cx_mapped_t second; \ }; ) \ \ - struct CX##_node_t { \ - CX##_size_t link[2]; \ + struct cx_node_t { \ + cx_memb(_size_t) link[2]; \ int8_t level; \ - CX##_value_t value; \ + cx_value_t value; \ }; \ \ - typedef RawKey CX##_rawkey_t; \ - typedef RawMapped CX##_rawmapped_t; \ - typedef SET_ONLY_##C( RawKey ) \ - MAP_ONLY_##C( struct { RawKey first; \ - RawMapped second; } ) \ - CX##_rawvalue_t; \ -\ - STC_API CX CX##_init(void); \ - STC_API CX CX##_clone(CX tree); \ - STC_API void CX##_del(CX* self); \ - STC_API void CX##_reserve(CX* self, size_t cap); \ - STC_API CX##_value_t* CX##_find_it(const CX* self, RawKey rkey, CX##_iter_t* out); \ - STC_API CX##_iter_t CX##_lower_bound(const CX* self, RawKey rkey); \ - STC_API CX##_value_t* CX##_front(const CX* self); \ - STC_API CX##_value_t* CX##_back(const CX* self); \ - STC_API int CX##_erase(CX* self, RawKey rkey); \ - STC_API CX##_iter_t CX##_erase_at(CX* self, CX##_iter_t it); \ - STC_API CX##_iter_t CX##_erase_range(CX* self, CX##_iter_t it1, CX##_iter_t it2); \ - STC_API CX##_result_t CX##_insert_entry_(CX* self, RawKey rkey); \ - STC_API void CX##_next(CX##_iter_t* it); \ -\ - STC_INLINE bool CX##_empty(CX tree) {return _csmap_rep(&tree)->size == 0;} \ - STC_INLINE size_t CX##_size(CX tree) {return _csmap_rep(&tree)->size;} \ - STC_INLINE size_t CX##_capacity(CX tree) {return _csmap_rep(&tree)->cap;} \ - STC_INLINE void CX##_clear(CX* self) {CX##_del(self); *self = CX##_init();} \ - STC_INLINE void CX##_swap(CX* a, CX* b) {c_swap(CX, *a, *b);} \ - STC_INLINE bool CX##_contains(const CX* self, RawKey rkey) \ - {CX##_iter_t it; return CX##_find_it(self, rkey, &it) != NULL;} \ - STC_INLINE CX##_value_t* CX##_get(const CX* self, RawKey rkey) \ - {CX##_iter_t it; return CX##_find_it(self, rkey, &it);} \ -\ - STC_INLINE CX \ - CX##_with_capacity(size_t size) { \ - CX tree = CX##_init(); \ - CX##_reserve(&tree, size); \ + typedef i_KEYRAW cx_rawkey_t; \ + typedef i_VALRAW cx_memb(_rawmapped_t); \ + typedef SET_ONLY_##C( i_KEYRAW ) \ + MAP_ONLY_##C( struct { i_KEYRAW first; \ + i_VALRAW second; } ) \ + cx_rawvalue_t; \ +\ + STC_API Self cx_memb(_init)(void); \ + STC_API Self cx_memb(_clone)(Self tree); \ + STC_API void cx_memb(_del)(Self* self); \ + STC_API void cx_memb(_reserve)(Self* self, size_t cap); \ + STC_API cx_value_t* cx_memb(_find_it)(const Self* self, i_KEYRAW rkey, cx_iter_t* out); \ + STC_API cx_iter_t cx_memb(_lower_bound)(const Self* self, i_KEYRAW rkey); \ + STC_API cx_value_t* cx_memb(_front)(const Self* self); \ + STC_API cx_value_t* cx_memb(_back)(const Self* self); \ + STC_API int cx_memb(_erase)(Self* self, i_KEYRAW rkey); \ + STC_API cx_iter_t cx_memb(_erase_at)(Self* self, cx_iter_t it); \ + STC_API cx_iter_t cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2); \ + STC_API cx_result_t cx_memb(_insert_entry_)(Self* self, i_KEYRAW rkey); \ + STC_API void cx_memb(_next)(cx_iter_t* it); \ +\ + STC_INLINE bool cx_memb(_empty)(Self tree) { return _csmap_rep(&tree)->size == 0; } \ + STC_INLINE size_t cx_memb(_size)(Self tree) { return _csmap_rep(&tree)->size; } \ + STC_INLINE size_t cx_memb(_capacity)(Self tree) { return _csmap_rep(&tree)->cap; } \ + STC_INLINE void cx_memb(_clear)(Self* self) {cx_memb(_del)(self); *self = cx_memb(_init)(); } \ + STC_INLINE void cx_memb(_swap)(Self* a, Self* b) {c_swap(Self, *a, *b); } \ + STC_INLINE bool cx_memb(_contains)(const Self* self, i_KEYRAW rkey) \ + {cx_iter_t it; return cx_memb(_find_it)(self, rkey, &it) != NULL; } \ + STC_INLINE cx_value_t* cx_memb(_get)(const Self* self, i_KEYRAW rkey) \ + {cx_iter_t it; return cx_memb(_find_it)(self, rkey, &it); } \ +\ + STC_INLINE Self \ + cx_memb(_with_capacity)(size_t size) { \ + Self tree = cx_memb(_init)(); \ + cx_memb(_reserve)(&tree, size); \ return tree; \ } \ \ - STC_INLINE CX##_rawvalue_t \ - CX##_value_toraw(CX##_value_t* val) { \ - return SET_ONLY_##C( keyToRaw(val) ) \ - MAP_ONLY_##C( c_make(CX##_rawvalue_t){keyToRaw(&val->first), mappedToRaw(&val->second)} ); \ + STC_INLINE cx_rawvalue_t \ + cx_memb(_value_toraw)(cx_value_t* val) { \ + return SET_ONLY_##C( i_KEYTO(val) ) \ + MAP_ONLY_##C( c_make(cx_rawvalue_t){i_KEYTO(&val->first), i_VALTO(&val->second)} ); \ } \ STC_INLINE void \ - CX##_value_del(CX##_value_t* val) { \ - keyDel(KEY_REF_##C(val)); \ - MAP_ONLY_##C( mappedDel(&val->second); ) \ + cx_memb(_value_del)(cx_value_t* val) { \ + i_KEYDEL(KEY_REF_##C(val)); \ + MAP_ONLY_##C( i_VALDEL(&val->second); ) \ } \ STC_INLINE void \ - CX##_value_clone(CX##_value_t* dst, CX##_value_t* val) { \ - *KEY_REF_##C(dst) = keyFromRaw(keyToRaw(KEY_REF_##C(val))); \ - MAP_ONLY_##C( dst->second = mappedFromRaw(mappedToRaw(&val->second)); ) \ + cx_memb(_value_clone)(cx_value_t* dst, cx_value_t* val) { \ + *KEY_REF_##C(dst) = i_KEYFROM(i_KEYTO(KEY_REF_##C(val))); \ + MAP_ONLY_##C( dst->second = i_VALFROM(i_VALTO(&val->second)); ) \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_find(const CX* self, RawKey rkey) { \ - CX##_iter_t it; \ - CX##_find_it(self, rkey, &it); \ + STC_INLINE cx_iter_t \ + cx_memb(_find)(const Self* self, i_KEYRAW rkey) { \ + cx_iter_t it; \ + cx_memb(_find_it)(self, rkey, &it); \ return it; \ } \ \ - STC_INLINE CX##_result_t \ - CX##_emplace(CX* self, RawKey rkey MAP_ONLY_##C(, RawMapped rmapped)) { \ - CX##_result_t res = CX##_insert_entry_(self, rkey); \ + STC_INLINE cx_result_t \ + cx_memb(_emplace)(Self* self, i_KEYRAW rkey MAP_ONLY_##C(, i_VALRAW rmapped)) { \ + cx_result_t res = cx_memb(_insert_entry_)(self, rkey); \ if (res.inserted) { \ - *KEY_REF_##C(res.ref) = keyFromRaw(rkey); \ - MAP_ONLY_##C(res.ref->second = mappedFromRaw(rmapped);) \ + *KEY_REF_##C(res.ref) = i_KEYFROM(rkey); \ + MAP_ONLY_##C(res.ref->second = i_VALFROM(rmapped);) \ } \ return res; \ } \ \ STC_INLINE void \ - CX##_emplace_items(CX* self, const CX##_rawvalue_t arr[], size_t n) { \ - for (size_t i=0; isecond = mapped; )} \ - else {keyDel(&key); MAP_ONLY_##C( mappedDel(&mapped); )} \ + else {i_KEYDEL(&key); MAP_ONLY_##C( i_VALDEL(&mapped); )} \ return res; \ } \ \ MAP_ONLY_##C( \ - STC_INLINE CX##_result_t \ - CX##_insert_or_assign(CX* self, Key key, Mapped mapped) { \ - CX##_result_t res = CX##_insert_entry_(self, keyToRaw(&key)); \ + STC_INLINE cx_result_t \ + cx_memb(_insert_or_assign)(Self* self, i_KEY key, i_VAL mapped) { \ + cx_result_t res = cx_memb(_insert_entry_)(self, i_KEYTO(&key)); \ if (res.inserted) res.ref->first = key; \ - else {keyDel(&key); mappedDel(&res.ref->second);} \ + else {i_KEYDEL(&key); i_VALDEL(&res.ref->second); } \ res.ref->second = mapped; return res; \ } \ \ - STC_INLINE CX##_result_t \ - CX##_put(CX* self, Key key, Mapped mapped) { \ - return CX##_insert_or_assign(self, key, mapped); \ + STC_INLINE cx_result_t \ + cx_memb(_put)(Self* self, i_KEY key, i_VAL mapped) { \ + return cx_memb(_insert_or_assign)(self, key, mapped); \ } \ \ - STC_INLINE CX##_result_t \ - CX##_emplace_or_assign(CX* self, RawKey rkey, RawMapped rmapped) { \ - CX##_result_t res = CX##_insert_entry_(self, rkey); \ - if (res.inserted) res.ref->first = keyFromRaw(rkey); \ - else mappedDel(&res.ref->second); \ - res.ref->second = mappedFromRaw(rmapped); return res; \ + STC_INLINE cx_result_t \ + cx_memb(_emplace_or_assign)(Self* self, i_KEYRAW rkey, i_VALRAW rmapped) { \ + cx_result_t res = cx_memb(_insert_entry_)(self, rkey); \ + if (res.inserted) res.ref->first = i_KEYFROM(rkey); \ + else i_VALDEL(&res.ref->second); \ + res.ref->second = i_VALFROM(rmapped); return res; \ } \ \ - STC_INLINE CX##_mapped_t* \ - CX##_at(const CX* self, RawKey rkey) { \ - CX##_iter_t it; \ - return &CX##_find_it(self, rkey, &it)->second; \ + STC_INLINE cx_mapped_t* \ + cx_memb(_at)(const Self* self, i_KEYRAW rkey) { \ + cx_iter_t it; \ + return &cx_memb(_find_it)(self, rkey, &it)->second; \ }) \ \ - STC_INLINE CX##_iter_t \ - CX##_begin(const CX* self) { \ - CX##_iter_t it; it._d = self->nodes, it._top = 0; \ - it._tn = (CX##_size_t) _csmap_rep(self)->root; \ - if (it._tn) CX##_next(&it); \ + STC_INLINE cx_iter_t \ + cx_memb(_begin)(const Self* self) { \ + cx_iter_t it; it._d = self->nodes, it._top = 0; \ + it._tn = (cx_memb(_size_t)) _csmap_rep(self)->root; \ + if (it._tn) cx_memb(_next)(&it); \ return it; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_end(const CX* self) {\ - return c_make(CX##_iter_t){.ref = NULL}; \ + STC_INLINE cx_iter_t \ + cx_memb(_end)(const Self* self) {\ + return c_make(cx_iter_t){.ref = NULL}; \ } \ \ - STC_INLINE CX##_iter_t \ - CX##_fwd(CX##_iter_t it, size_t n) { \ - while (n-- && it.ref) CX##_next(&it); \ + STC_INLINE cx_iter_t \ + cx_memb(_fwd)(cx_iter_t it, size_t n) { \ + while (n-- && it.ref) cx_memb(_next)(&it); \ return it; \ } \ \ - _c_implement_aatree(CX, C, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) \ + _c_implement_aatree(Self, C, i_KEY, i_VAL, i_CMP, \ + i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW, \ + i_KEYDEL, i_KEYFROM, i_KEYTO, i_KEYRAW) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -317,68 +213,68 @@ struct csmap_rep { size_t root, disp, head, size, cap; void* nodes[]; }; #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; -#define _c_implement_aatree(CX, C, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) \ - STC_DEF CX \ - CX##_init(void) { \ - CX tree = {(CX##_node_t *) _csmap_sentinel.nodes}; \ +#define _c_implement_aatree(Self, C, i_KEY, i_VAL, i_CMP, \ + i_VALDEL, i_VALFROM, i_VALTO, i_VALRAW, \ + i_KEYDEL, i_KEYFROM, i_KEYTO, i_KEYRAW) \ + STC_DEF Self \ + cx_memb(_init)(void) { \ + Self tree = {(cx_node_t *) _csmap_sentinel.nodes}; \ return tree; \ } \ \ - STC_DEF CX##_value_t* \ - CX##_front(const CX* self) { \ - CX##_node_t *d = self->nodes; \ - CX##_size_t tn = (CX##_size_t) _csmap_rep(self)->root; \ + STC_DEF cx_value_t* \ + cx_memb(_front)(const Self* self) { \ + cx_node_t *d = self->nodes; \ + cx_memb(_size_t) tn = (cx_memb(_size_t)) _csmap_rep(self)->root; \ while (d[tn].link[0]) tn = d[tn].link[0]; \ return &d[tn].value; \ } \ \ - STC_DEF CX##_value_t* \ - CX##_back(const CX* self) { \ - CX##_node_t *d = self->nodes; \ - CX##_size_t tn = (CX##_size_t) _csmap_rep(self)->root; \ + STC_DEF cx_value_t* \ + cx_memb(_back)(const Self* self) { \ + cx_node_t *d = self->nodes; \ + cx_memb(_size_t) tn = (cx_memb(_size_t)) _csmap_rep(self)->root; \ while (d[tn].link[1]) tn = d[tn].link[1]; \ return &d[tn].value; \ } \ \ STC_DEF void \ - CX##_reserve(CX* self, size_t cap) { \ + cx_memb(_reserve)(Self* self, size_t cap) { \ struct csmap_rep* rep = _csmap_rep(self); \ - CX##_size_t oldcap = rep->cap; \ + cx_memb(_size_t) oldcap = rep->cap; \ if (cap > oldcap) { \ rep = (struct csmap_rep*) c_realloc(oldcap ? rep : NULL, \ - sizeof(struct csmap_rep) + (cap + 1)*sizeof(CX##_node_t)); \ + sizeof(struct csmap_rep) + (cap + 1)*sizeof(cx_node_t)); \ if (oldcap == 0) \ - memset(rep, 0, sizeof(struct csmap_rep) + sizeof(CX##_node_t)); \ + memset(rep, 0, sizeof(struct csmap_rep) + sizeof(cx_node_t)); \ rep->cap = cap; \ - self->nodes = (CX##_node_t *) rep->nodes; \ + self->nodes = (cx_node_t *) rep->nodes; \ } \ } \ \ - STC_DEF CX##_size_t \ - CX##_node_new_(CX* self, int level) { \ + STC_DEF cx_memb(_size_t) \ + cx_memb(_node_new_)(Self* self, int level) { \ size_t 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##_reserve(self, 4 + (tn*13 >> 3)); \ + if ((tn = rep->head + 1) > rep->cap) cx_memb(_reserve)(self, 4 + (tn*13 >> 3)); \ ++_csmap_rep(self)->head; /* do after reserve */ \ } \ - CX##_node_t* dn = &self->nodes[tn]; \ + cx_node_t* dn = &self->nodes[tn]; \ dn->link[0] = dn->link[1] = 0; dn->level = level; \ - return (CX##_size_t) tn; \ + return (cx_memb(_size_t)) tn; \ } \ \ - STC_DEF CX##_value_t* \ - CX##_find_it(const CX* self, RawKey rkey, CX##_iter_t* out) { \ - CX##_size_t tn = _csmap_rep(self)->root; \ - CX##_node_t *d = out->_d = self->nodes; \ + STC_DEF cx_value_t* \ + cx_memb(_find_it)(const Self* self, i_KEYRAW rkey, cx_iter_t* out) { \ + cx_memb(_size_t) tn = _csmap_rep(self)->root; \ + cx_node_t *d = out->_d = self->nodes; \ out->_top = 0; \ while (tn) { \ - int c; CX##_rawkey_t raw = keyToRaw(KEY_REF_##C(&d[tn].value)); \ - if ((c = keyCompareRaw(&raw, &rkey)) < 0) \ + int c; cx_rawkey_t raw = i_KEYTO(KEY_REF_##C(&d[tn].value)); \ + if ((c = i_CMP(&raw, &rkey)) < 0) \ tn = d[tn].link[1]; \ else if (c > 0) \ { out->_st[out->_top++] = tn; tn = d[tn].link[0]; } \ @@ -388,12 +284,12 @@ static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; return (out->ref = NULL); \ } \ \ - STC_DEF CX##_iter_t \ - CX##_lower_bound(const CX* self, RawKey rkey) { \ - CX##_iter_t it; \ - CX##_find_it(self, rkey, &it); \ + STC_DEF cx_iter_t \ + cx_memb(_lower_bound)(const Self* self, i_KEYRAW rkey) { \ + cx_iter_t it; \ + cx_memb(_find_it)(self, rkey, &it); \ if (!it.ref && it._top) { \ - CX##_size_t tn = it._st[--it._top]; \ + cx_memb(_size_t) tn = it._st[--it._top]; \ it._tn = it._d[tn].link[1]; \ it.ref = &it._d[tn].value; \ } \ @@ -401,8 +297,8 @@ static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; } \ \ STC_DEF void \ - CX##_next(CX##_iter_t *it) { \ - CX##_size_t tn = it->_tn; \ + cx_memb(_next)(cx_iter_t *it) { \ + cx_memb(_size_t) tn = it->_tn; \ if (it->_top || tn) { \ while (tn) { \ it->_st[it->_top++] = tn; \ @@ -415,20 +311,20 @@ static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; it->ref = NULL; \ } \ \ - static CX##_size_t \ - CX##_skew_(CX##_node_t *d, CX##_size_t tn) { \ + static cx_memb(_size_t) \ + cx_memb(_skew_)(cx_node_t *d, cx_memb(_size_t) tn) { \ if (tn && d[d[tn].link[0]].level == d[tn].level) { \ - CX##_size_t tmp = d[tn].link[0]; \ + cx_memb(_size_t) tmp = d[tn].link[0]; \ d[tn].link[0] = d[tmp].link[1]; \ d[tmp].link[1] = tn; \ tn = tmp; \ } \ return tn; \ } \ - static CX##_size_t \ - CX##_split_(CX##_node_t *d, CX##_size_t tn) { \ + static cx_memb(_size_t) \ + cx_memb(_split_)(cx_node_t *d, cx_memb(_size_t) tn) { \ if (d[d[d[tn].link[1]].link[1]].level == d[tn].level) { \ - CX##_size_t tmp = d[tn].link[1]; \ + cx_memb(_size_t) tmp = d[tn].link[1]; \ d[tn].link[1] = d[tmp].link[0]; \ d[tmp].link[0] = tn; \ tn = tmp; \ @@ -437,62 +333,62 @@ static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; return tn; \ } \ \ - STC_DEF CX##_size_t \ - CX##_insert_entry_i_(CX* self, CX##_size_t tn, const CX##_rawkey_t* rkey, CX##_result_t* res) { \ - CX##_size_t up[64], tx = tn; \ - CX##_node_t* d = self->nodes; \ + STC_DEF cx_memb(_size_t) \ + cx_memb(_insert_entry_i_)(Self* self, cx_memb(_size_t) tn, const cx_rawkey_t* rkey, cx_result_t* res) { \ + cx_memb(_size_t) up[64], tx = tn; \ + cx_node_t* d = self->nodes; \ int c, top = 0, dir = 0; \ while (tx) { \ up[top++] = tx; \ - RawKey raw = keyToRaw(KEY_REF_##C(&d[tx].value)); \ - if ((c = keyCompareRaw(&raw, rkey)) == 0) {res->ref = &d[tx].value; return tn;} \ + i_KEYRAW raw = i_KEYTO(KEY_REF_##C(&d[tx].value)); \ + if ((c = i_CMP(&raw, rkey)) == 0) {res->ref = &d[tx].value; return tn; } \ dir = (c < 0); \ tx = d[tx].link[dir]; \ } \ - tx = CX##_node_new_(self, 1); d = self->nodes; \ + tx = cx_memb(_node_new_)(self, 1); d = self->nodes; \ res->ref = &d[tx].value, res->inserted = true; \ if (top == 0) return tx; \ d[up[top - 1]].link[dir] = tx; \ while (top--) { \ if (top) dir = (d[up[top - 1]].link[1] == up[top]); \ - up[top] = CX##_skew_(d, up[top]); \ - up[top] = CX##_split_(d, up[top]); \ + up[top] = cx_memb(_skew_)(d, up[top]); \ + up[top] = cx_memb(_split_)(d, up[top]); \ if (top) d[up[top - 1]].link[dir] = up[top]; \ } \ return up[0]; \ } \ \ - STC_DEF CX##_result_t \ - CX##_insert_entry_(CX* self, RawKey rkey) { \ - CX##_result_t res = {NULL, false}; \ - CX##_size_t tn = CX##_insert_entry_i_(self, (CX##_size_t) _csmap_rep(self)->root, &rkey, &res); \ + STC_DEF cx_result_t \ + cx_memb(_insert_entry_)(Self* self, i_KEYRAW rkey) { \ + cx_result_t res = {NULL, false}; \ + cx_memb(_size_t) tn = cx_memb(_insert_entry_i_)(self, (cx_memb(_size_t)) _csmap_rep(self)->root, &rkey, &res); \ _csmap_rep(self)->root = tn; \ _csmap_rep(self)->size += res.inserted; \ return res; \ } \ \ - STC_DEF CX##_size_t \ - CX##_erase_r_(CX##_node_t *d, CX##_size_t tn, const CX##_rawkey_t* rkey, int *erased) { \ + STC_DEF cx_memb(_size_t) \ + cx_memb(_erase_r_)(cx_node_t *d, cx_memb(_size_t) tn, const cx_rawkey_t* rkey, int *erased) { \ if (tn == 0) return 0; \ - RawKey raw = keyToRaw(KEY_REF_##C(&d[tn].value)); \ - CX##_size_t tx; int c = keyCompareRaw(&raw, rkey); \ + i_KEYRAW raw = i_KEYTO(KEY_REF_##C(&d[tn].value)); \ + cx_memb(_size_t) tx; int c = i_CMP(&raw, rkey); \ if (c != 0) \ - d[tn].link[c < 0] = CX##_erase_r_(d, d[tn].link[c < 0], rkey, erased); \ + d[tn].link[c < 0] = cx_memb(_erase_r_)(d, d[tn].link[c < 0], rkey, erased); \ else { \ - if (!(*erased)++) CX##_value_del(&d[tn].value); \ + if (!(*erased)++) cx_memb(_value_del)(&d[tn].value); \ if (d[tn].link[0] && d[tn].link[1]) { \ tx = d[tn].link[0]; \ while (d[tx].link[1]) \ tx = d[tx].link[1]; \ memcpy((void *) &d[tn].value, &d[tx].value, sizeof d[0].value); /* move */ \ - raw = keyToRaw(KEY_REF_##C(&d[tn].value)); \ - d[tn].link[0] = CX##_erase_r_(d, d[tn].link[0], &raw, erased); \ + raw = i_KEYTO(KEY_REF_##C(&d[tn].value)); \ + d[tn].link[0] = cx_memb(_erase_r_)(d, d[tn].link[0], &raw, erased); \ } else { /* unlink node */ \ tx = tn; \ tn = d[tn].link[ d[tn].link[0] == 0 ]; \ /* move it to disposed nodes list */ \ struct csmap_rep *rep = c_container_of(d, struct csmap_rep, nodes); \ - d[tx].link[1] = (CX##_size_t) rep->disp; \ + d[tx].link[1] = (cx_memb(_size_t)) rep->disp; \ rep->disp = tx; \ } \ } \ @@ -500,84 +396,79 @@ static struct csmap_rep _csmap_sentinel = {0, 0, 0, 0, 0}; if (d[d[tn].link[0]].level < d[tn].level - 1 || d[tx].level < d[tn].level - 1) { \ if (d[tx].level > --d[tn].level) \ d[tx].level = d[tn].level; \ - tn = CX##_skew_(d, tn); \ - tx = d[tn].link[1] = CX##_skew_(d, d[tn].link[1]); \ - d[tx].link[1] = CX##_skew_(d, d[tx].link[1]); \ - tn = CX##_split_(d, tn); \ - d[tn].link[1] = CX##_split_(d, d[tn].link[1]); \ + tn = cx_memb(_skew_)(d, tn); \ + tx = d[tn].link[1] = cx_memb(_skew_)(d, d[tn].link[1]); \ + d[tx].link[1] = cx_memb(_skew_)(d, d[tx].link[1]); \ + tn = cx_memb(_split_)(d, tn); \ + d[tn].link[1] = cx_memb(_split_)(d, d[tn].link[1]); \ } \ return tn; \ } \ \ STC_DEF int \ - CX##_erase(CX* self, RawKey rkey) { \ + cx_memb(_erase)(Self* self, i_KEYRAW rkey) { \ int erased = 0; \ - CX##_size_t root = CX##_erase_r_(self->nodes, (CX##_size_t) _csmap_rep(self)->root, &rkey, &erased); \ + cx_memb(_size_t) root = cx_memb(_erase_r_)(self->nodes, (cx_memb(_size_t)) _csmap_rep(self)->root, &rkey, &erased); \ return erased ? (_csmap_rep(self)->root = root, --_csmap_rep(self)->size, 1) : 0; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_erase_at(CX* self, CX##_iter_t it) { \ - CX##_rawkey_t raw = keyToRaw(KEY_REF_##C(it.ref)), nxt; \ - CX##_next(&it); \ - if (it.ref) nxt = keyToRaw(KEY_REF_##C(it.ref)); \ - CX##_erase(self, raw); \ - if (it.ref) CX##_find_it(self, nxt, &it); \ + STC_DEF cx_iter_t \ + cx_memb(_erase_at)(Self* self, cx_iter_t it) { \ + cx_rawkey_t raw = i_KEYTO(KEY_REF_##C(it.ref)), nxt; \ + cx_memb(_next)(&it); \ + if (it.ref) nxt = i_KEYTO(KEY_REF_##C(it.ref)); \ + cx_memb(_erase)(self, raw); \ + if (it.ref) cx_memb(_find_it)(self, nxt, &it); \ return it; \ } \ \ - STC_DEF CX##_iter_t \ - CX##_erase_range(CX* self, CX##_iter_t it1, CX##_iter_t it2) { \ - if (!it2.ref) { while (it1.ref) it1 = CX##_erase_at(self, it1); \ + STC_DEF cx_iter_t \ + cx_memb(_erase_range)(Self* self, cx_iter_t it1, cx_iter_t it2) { \ + if (!it2.ref) { while (it1.ref) it1 = cx_memb(_erase_at)(self, it1); \ return it1; } \ - CX##_key_t k1 = *KEY_REF_##C(it1.ref), k2 = *KEY_REF_##C(it2.ref); \ - CX##_rawkey_t r1 = keyToRaw(&k1); \ + cx_key_t k1 = *KEY_REF_##C(it1.ref), k2 = *KEY_REF_##C(it2.ref); \ + cx_rawkey_t r1 = i_KEYTO(&k1); \ for (;;) { \ if (memcmp(&k1, &k2, sizeof k1) == 0) return it1; \ - CX##_next(&it1); k1 = *KEY_REF_##C(it1.ref); \ - CX##_erase(self, r1); \ - CX##_find_it(self, (r1 = keyToRaw(&k1)), &it1); \ + cx_memb(_next)(&it1); k1 = *KEY_REF_##C(it1.ref); \ + cx_memb(_erase)(self, r1); \ + cx_memb(_find_it)(self, (r1 = i_KEYTO(&k1)), &it1); \ } \ } \ \ - static CX##_size_t \ - CX##_clone_r_(CX* self, CX##_node_t* src, CX##_size_t sn) { \ + static cx_memb(_size_t) \ + cx_memb(_clone_r_)(Self* self, cx_node_t* src, cx_memb(_size_t) sn) { \ if (sn == 0) return 0; \ - CX##_size_t tx, tn = CX##_node_new_(self, src[sn].level); \ - CX##_value_clone(&self->nodes[tn].value, &src[sn].value); \ - tx = CX##_clone_r_(self, src, src[sn].link[0]); self->nodes[tn].link[0] = tx; \ - tx = CX##_clone_r_(self, src, src[sn].link[1]); self->nodes[tn].link[1] = tx; \ + cx_memb(_size_t) tx, tn = cx_memb(_node_new_)(self, src[sn].level); \ + cx_memb(_value_clone)(&self->nodes[tn].value, &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; \ return tn; \ } \ - STC_DEF CX \ - CX##_clone(CX tree) { \ - CX clone = CX##_with_capacity(_csmap_rep(&tree)->size); \ - CX##_size_t root = CX##_clone_r_(&clone, tree.nodes, (CX##_size_t) _csmap_rep(&tree)->root); \ + STC_DEF Self \ + cx_memb(_clone)(Self tree) { \ + Self clone = cx_memb(_with_capacity)(_csmap_rep(&tree)->size); \ + cx_memb(_size_t) root = cx_memb(_clone_r_)(&clone, tree.nodes, (cx_memb(_size_t)) _csmap_rep(&tree)->root); \ _csmap_rep(&clone)->root = root; \ _csmap_rep(&clone)->size = _csmap_rep(&tree)->size; \ return clone; \ } \ \ STC_DEF void \ - CX##_del_r_(CX##_node_t* d, CX##_size_t tn) { \ + cx_memb(_del_r_)(cx_node_t* d, cx_memb(_size_t) tn) { \ if (tn) { \ - CX##_del_r_(d, d[tn].link[0]); \ - CX##_del_r_(d, d[tn].link[1]); \ - CX##_value_del(&d[tn].value); \ + cx_memb(_del_r_)(d, d[tn].link[0]); \ + cx_memb(_del_r_)(d, d[tn].link[1]); \ + cx_memb(_value_del)(&d[tn].value); \ } \ } \ STC_DEF void \ - CX##_del(CX* self) { \ + cx_memb(_del)(Self* self) { \ if (_csmap_rep(self)->root) { \ - CX##_del_r_(self->nodes, (CX##_size_t) _csmap_rep(self)->root); \ + cx_memb(_del_r_)(self->nodes, (cx_memb(_size_t)) _csmap_rep(self)->root); \ c_free(_csmap_rep(self)); \ } \ } -#else -#define _c_implement_aatree(CX, C, Key, Mapped, keyCompareRaw, \ - mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ - keyDel, keyFromRaw, keyToRaw, RawKey) #endif - #endif diff --git a/include/stc/csptr.h b/include/stc/csptr.h index 4f183498..1729235e 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -68,112 +68,92 @@ typedef long atomic_count_t; } #endif -#define forward_csptr(X, Value) _csptr_types(csptr_##X, Value) +#define forward_csptr(X, i_VAL) _csptr_types(csptr_##X, i_VAL) #define csptr_null {NULL, NULL} -#define using_csptr(...) c_MACRO_OVERLOAD(using_csptr, __VA_ARGS__) - -#define using_csptr_2(X, Value) \ - using_csptr_3(X, Value, c_default_compare) -#define using_csptr_3(X, Value, valueCompare) \ - using_csptr_4(X, Value, valueCompare, c_default_del) -#define using_csptr_4(X, Value, valueCompare, valueDel) \ - _c_using_csptr(csptr_##X, Value, valueCompare, valueDel, c_true) -#define using_csptr_5(X, Value, valueCompare, valueDel, defTypes) \ - _c_using_csptr(csptr_##X, Value, valueCompare, valueDel, defTypes) - -#define _csptr_types(CX, Value) \ - typedef Value CX##_value_t; \ -\ - typedef struct { \ - CX##_value_t* get; \ - atomic_count_t* use_count; \ - } CX - -#define _c_using_csptr(CX, Value, valueCompare, valueDel, defTypes) \ - defTypes( _csptr_types(CX, Value); ) \ - struct CX##_rep_ {atomic_count_t cnt; CX##_value_t val;}; \ + defTypes( _csptr_types(Self, i_VAL); ) \ + struct cx_memb(_rep_) {atomic_count_t cnt; cx_value_t val; }; \ \ - STC_INLINE CX \ - CX##_init() { return c_make(CX){NULL, NULL}; } \ + STC_INLINE Self \ + cx_memb(_init)() { return c_make(Self){NULL, NULL}; } \ \ STC_INLINE atomic_count_t \ - CX##_use_count(CX ptr) { return ptr.use_count ? *ptr.use_count : 0; } \ + cx_memb(_use_count)(Self ptr) { return ptr.use_count ? *ptr.use_count : 0; } \ \ - STC_INLINE CX \ - CX##_from(CX##_value_t* p) { \ - CX ptr = {p}; \ + STC_INLINE Self \ + cx_memb(_from)(cx_value_t* p) { \ + Self ptr = {p}; \ if (p) *(ptr.use_count = c_new(atomic_count_t)) = 1; \ return ptr; \ } \ \ - STC_INLINE CX \ - CX##_make(CX##_value_t val) { \ - CX ptr; struct CX##_rep_ *rep = c_new(struct CX##_rep_); \ + STC_INLINE Self \ + cx_memb(_make)(cx_value_t val) { \ + Self ptr; struct cx_memb(_rep_) *rep = c_new(struct cx_memb(_rep_)); \ *(ptr.use_count = &rep->cnt) = 1; \ *(ptr.get = &rep->val) = val; \ return ptr; \ } \ \ - STC_INLINE CX \ - CX##_clone(CX ptr) { \ + STC_INLINE Self \ + cx_memb(_clone)(Self ptr) { \ if (ptr.use_count) c_atomic_increment(ptr.use_count); \ return ptr; \ } \ \ - STC_INLINE CX \ - CX##_move(CX* self) { \ - CX ptr = *self; \ + STC_INLINE Self \ + cx_memb(_move)(Self* self) { \ + Self ptr = *self; \ self->get = NULL, self->use_count = NULL; \ return ptr; \ } \ \ STC_INLINE void \ - CX##_del(CX* self) { \ + cx_memb(_del)(Self* self) { \ if (self->use_count && c_atomic_decrement(self->use_count) == 0) { \ - valueDel(self->get); \ - if (self->get != &((struct CX##_rep_*)self->use_count)->val) c_free(self->get); \ + i_VALDEL(self->get); \ + if (self->get != &((struct cx_memb(_rep_)*)self->use_count)->val) c_free(self->get); \ c_free(self->use_count); \ } \ } \ \ STC_INLINE void \ - CX##_reset(CX* self) { \ - CX##_del(self); \ + cx_memb(_reset)(Self* self) { \ + cx_memb(_del)(self); \ self->use_count = NULL, self->get = NULL; \ } \ \ - STC_INLINE CX##_value_t* \ - CX##_reset_with(CX* self, CX##_value_t* p) { \ - CX##_del(self); \ - *self = CX##_from(p); \ + STC_INLINE cx_value_t* \ + cx_memb(_reset_with)(Self* self, cx_value_t* p) { \ + cx_memb(_del)(self); \ + *self = cx_memb(_from)(p); \ return self->get; \ } \ \ - STC_INLINE CX##_value_t* \ - CX##_reset_make(CX* self, CX##_value_t val) { \ - CX##_del(self); \ - *self = CX##_make(val); \ + STC_INLINE cx_value_t* \ + cx_memb(_reset_make)(Self* self, cx_value_t val) { \ + cx_memb(_del)(self); \ + *self = cx_memb(_make)(val); \ return self->get; \ } \ \ - STC_INLINE CX##_value_t* \ - CX##_copy(CX* self, CX ptr) { \ - CX##_del(self); \ + STC_INLINE cx_value_t* \ + cx_memb(_copy)(Self* self, Self ptr) { \ + cx_memb(_del)(self); \ *self = ptr; \ if (self->use_count) c_atomic_increment(self->use_count); \ return self->get; \ } \ \ STC_INLINE int \ - CX##_compare(const CX* x, const CX* y) { \ - return valueCompare(x->get, y->get); \ + cx_memb(_compare)(const Self* x, const Self* y) { \ + return i_CMP(x->get, y->get); \ } \ \ STC_INLINE bool \ - CX##_equals(const CX* x, const CX* y) { \ - return valueCompare(x->get, y->get) == 0; \ + cx_memb(_equals)(const Self* x, const Self* y) { \ + return i_CMP(x->get, y->get) == 0; \ } \ struct stc_trailing_semicolon diff --git a/include/stc/csset.h b/include/stc/csset.h index 747307e4..a5e1499c 100644 --- a/include/stc/csset.h +++ b/include/stc/csset.h @@ -43,30 +43,8 @@ int main(void) { } */ +#define i_CNT csset +#define KEY_REF_csset(vp) (vp) #include "csmap.h" -#define forward_csset(X, Key) _c_aatree_types(csset_##X, csset_, Key, Key) - -#define using_csset(...) c_MACRO_OVERLOAD(using_csset, __VA_ARGS__) - -#define using_csset_2(X, Key) \ - using_csset_3(X, Key, c_default_compare) -#define using_csset_3(X, Key, keyCompare) \ - using_csset_5(X, Key, keyCompare, c_default_del, c_default_fromraw) -#define using_csset_4(X, Key, keyCompare, keyDel) \ - using_csset_5(X, Key, keyCompare, keyDel, c_no_clone) -#define using_csset_5(X, Key, keyCompare, keyDel, keyClone) \ - using_csset_8(X, Key, keyCompare, keyDel, keyClone, c_default_toraw, Key, c_true) -#define using_csset_8(X, Key, keyCompareRaw, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) \ - _c_using_aatree(csset_##X, csset_, Key, Key, keyCompareRaw, \ - @@, @@, @@, void, keyDel, keyFromRaw, keyToRaw, RawKey, defTypes) - -#define using_csset_str() \ - using_csset_8(str, cstr, c_rawstr_compare, cstr_del, \ - cstr_from, cstr_str, const char*, c_true) - -#define SET_ONLY_csset_(...) __VA_ARGS__ -#define MAP_ONLY_csset_(...) -#define KEY_REF_csset_(vp) (vp) - #endif diff --git a/include/stc/cstack.h b/include/stc/cstack.h index d6b1b3ad..30fc4f71 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -47,36 +47,36 @@ #include "cvec.h" #define using_cstack(X, ctype) \ - _c_using_cstack(cstack_##X, ctype) + _c_using_cstack(cstack_##X, ctype) -#define _c_using_cstack(CX, ctype) \ - typedef ctype CX; \ - typedef ctype##_value_t CX##_value_t; \ - typedef ctype##_rawvalue_t CX##_rawvalue_t; \ - typedef ctype##_iter_t CX##_iter_t; \ +#define _c_using_cstack(Self, ctype) \ + typedef ctype Self; \ + typedef ctype##_value_t cx_value_t; \ + typedef ctype##_rawvalue_t cx_rawvalue_t; \ + typedef ctype##_iter_t cx_iter_t; \ \ - STC_INLINE CX CX##_init(void) {return ctype##_init();} \ - STC_INLINE CX CX##_clone(CX st) {return ctype##_clone(st);} \ - STC_INLINE CX##_value_t CX##_value_clone(CX##_value_t val) \ - {return ctype##_value_clone(val);} \ - STC_INLINE void CX##_clear(CX* self) {ctype##_clear(self);} \ - STC_INLINE void CX##_del(CX* self) {ctype##_del(self);} \ + STC_INLINE Self cx_memb(_init)(void) { return ctype##_init(); } \ + STC_INLINE Self cx_memb(_clone)(Self st) { return ctype##_clone(st); } \ + STC_INLINE cx_value_t cx_memb(_value_clone)(cx_value_t val) \ + { return ctype##_value_clone(val); } \ + STC_INLINE void cx_memb(_clear)(Self* self) {ctype##_clear(self); } \ + STC_INLINE void cx_memb(_del)(Self* self) {ctype##_del(self); } \ \ - STC_INLINE size_t CX##_size(CX st) {return ctype##_size(st);} \ - STC_INLINE bool CX##_empty(CX st) {return ctype##_empty(st);} \ - STC_INLINE CX##_value_t* CX##_top(const CX* self) {return ctype##_back(self);} \ + STC_INLINE size_t cx_memb(_size)(Self st) { return ctype##_size(st); } \ + STC_INLINE bool cx_memb(_empty)(Self st) { return ctype##_empty(st); } \ + STC_INLINE cx_value_t* cx_memb(_top)(const Self* self) { return ctype##_back(self); } \ \ - STC_INLINE void CX##_pop(CX* self) {ctype##_pop_back(self);} \ - STC_INLINE void CX##_push(CX* self, ctype##_value_t value) \ - {ctype##_push_back(self, value);} \ - STC_INLINE void CX##_emplace(CX* self, CX##_rawvalue_t raw) \ - {ctype##_emplace_back(self, raw);} \ - STC_INLINE void CX##_emplace_items(CX *self, const CX##_rawvalue_t arr[], size_t n) \ - {ctype##_emplace_items(self, arr, n);} \ + STC_INLINE void cx_memb(_pop)(Self* self) {ctype##_pop_back(self); } \ + STC_INLINE void cx_memb(_push)(Self* self, ctype##_value_t value) \ + {ctype##_push_back(self, value); } \ + STC_INLINE void cx_memb(_emplace)(Self* self, cx_rawvalue_t raw) \ + {ctype##_emplace_back(self, raw); } \ + STC_INLINE void cx_memb(_emplace_items)(Self *self, const cx_rawvalue_t arr[], size_t n) \ + {ctype##_emplace_items(self, arr, n); } \ \ - STC_INLINE CX##_iter_t CX##_begin(const CX* self) {return ctype##_begin(self);} \ - STC_INLINE CX##_iter_t CX##_end(const CX* self) {return ctype##_end(self);} \ - STC_INLINE void CX##_next(CX##_iter_t* it) {ctype##_next(it);} \ + STC_INLINE cx_iter_t cx_memb(_begin)(const Self* self) { return ctype##_begin(self); } \ + STC_INLINE cx_iter_t cx_memb(_end)(const Self* self) { return ctype##_end(self); } \ + STC_INLINE void cx_memb(_next)(cx_iter_t* it) {ctype##_next(it); } \ struct stc_trailing_semicolon #endif 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 #include -#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" diff --git a/include/stc/forward.h b/include/stc/forward.h new file mode 100644 index 00000000..2c904aa7 --- /dev/null +++ b/include/stc/forward.h @@ -0,0 +1,165 @@ +/* MIT License + * + * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef STC_FORWARD_H_INCLUDED +#define STC_FORWARD_H_INCLUDED + +#define forward_carray2(TAG, VAL) _c_carray2_types(carray2##TAG, VAL) +#define forward_carray3(TAG, VAL) _c_carray3_types(carray2##TAG, VAL) +#define forward_cdeq(TAG, VAL) _c_cdeq_types(cdeq_##TAG, VAL) +#define forward_clist(TAG, VAL) _c_clist_types(clist_##TAG, VAL) +#define forward_cmap(TAG, KEY, VAL) _c_chash_types(csmap_##TAG, cmap, KEY, VAL) +#define forward_csmap(TAG, KEY, VAL) _c_aatree_types(csmap_##TAG, csmap, KEY, VAL) +#define forward_cset(TAG, KEY) _c_chash_types(cset_##TAG, cset, KEY, KEY) +#define forward_csset(TAG, KEY) _c_aatree_types(csset_##TAG, csset, KEY, KEY) +#define forward_csptr(TAG, VAL) _csptr_types(csptr_##TAG, VAL) +#define forward_cpque(TAG, ctype) _c_cpque_types(cpque_##TAG, ctype) +#define forward_cqueue(TAG, ctype) _c_cqueue_types(cqueue_##TAG, ctype) +#define forward_cstack(TAG, ctype) _c_cstack_types(cstack_##TAG, ctype) +#define forward_cvec(TAG, VAL) _c_cvec_types(cvec_##TAG, VAL) + +#define SET_ONLY_cmap_(...) +#define MAP_ONLY_cmap_(...) __VA_ARGS__ +#define SET_ONLY_cset_(...) __VA_ARGS__ +#define MAP_ONLY_cset_(...) + +#define SET_ONLY_csmap_(...) +#define MAP_ONLY_csmap_(...) __VA_ARGS__ +#define SET_ONLY_csset_(...) __VA_ARGS__ +#define MAP_ONLY_csset_(...) + +#ifndef MAP_SIZE_T +#define MAP_SIZE_T uint32_t +#endif + +#define _c_carray2_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ + typedef struct { SELF##_value_t *ref; } SELF##_iter_t; \ + typedef struct { SELF##_value_t **data; size_t xdim, ydim; } SELF + +#define _c_carray3_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ + typedef struct { SELF##_value_t *ref; } SELF##_iter_t; \ + typedef struct { SELF##_value_t ***data; size_t xdim, ydim, zdim; } SELF + +#define _c_cdeq_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ + typedef struct {SELF##_value_t *ref; } SELF##_iter_t; \ + typedef struct {SELF##_value_t *_base, *data;} SELF + +#define _c_clist_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ + typedef struct SELF##_node_t SELF##_node_t; \ +\ + typedef struct { \ + SELF##_node_t *const *_last, *prev; \ + SELF##_value_t *ref; \ + } SELF##_iter_t; \ +\ + typedef struct { \ + SELF##_node_t *last; \ + } SELF + +#define _c_chash_types(SELF, C, KEY, VAL) \ + typedef KEY SELF##_key_t; \ + typedef VAL SELF##_mapped_t; \ + typedef MAP_SIZE_T SELF##_size_t; \ +\ + typedef SET_ONLY_##C( SELF##_key_t ) \ + MAP_ONLY_##C( struct SELF##_value_t ) \ + SELF##_value_t; \ +\ + typedef struct { \ + SELF##_value_t *ref; \ + bool inserted; \ + } SELF##_result_t; \ +\ + typedef struct { \ + SELF##_value_t *ref; \ + uint8_t* _hx; \ + } SELF##_iter_t; \ +\ + typedef struct { \ + SELF##_value_t* table; \ + uint8_t* _hashx; \ + SELF##_size_t size, bucket_count; \ + float max_load_factor; \ + } SELF + +#define _c_aatree_types(SELF, C, KEY, VAL) \ + typedef KEY SELF##_key_t; \ + typedef VAL SELF##_mapped_t; \ + typedef MAP_SIZE_T SELF##_size_t; \ +\ + typedef SET_ONLY_##C( SELF##_key_t ) \ + MAP_ONLY_##C( struct SELF##_value_t ) \ + SELF##_value_t; \ +\ + typedef struct { \ + SELF##_value_t *ref; \ + bool inserted; \ + } SELF##_result_t; \ +\ + typedef struct SELF##_node_t SELF##_node_t; \ +\ + typedef struct { \ + SELF##_value_t *ref; \ + SELF##_node_t *_d; \ + int _top; \ + SELF##_size_t _tn, _st[36]; \ + } SELF##_iter_t; \ +\ + typedef struct { \ + SELF##_node_t *nodes; \ + } SELF + +#define _csptr_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ +\ + typedef struct { \ + SELF##_value_t* get; \ + long* use_count; \ + } SELF + +#define _c_cpque_types(SELF, ctype) \ + typedef ctype##_value_t SELF##_value_t; \ + typedef ctype##_rawvalue_t SELF##_rawvalue_t; \ + typedef ctype SELF + +#define _c_cqueue_types(SELF, ctype) \ + typedef ctype##_value_t SELF##_value_t; \ + typedef ctype##_rawvalue_t SELF##_rawvalue_t; \ + typedef ctype##_iter_t SELF##_iter_t; \ + typedef struct { ctype rep; size_t size; } SELF + +#define _c_cstack_types(SELF, ctype) \ + typedef ctype##_value_t SELF##_value_t; \ + typedef ctype##_rawvalue_t SELF##_rawvalue_t; \ + typedef ctype##_iter_t SELF##_iter_t; \ + typedef ctype SELF + +#define _c_cvec_types(SELF, VAL) \ + typedef VAL SELF##_value_t; \ + typedef struct { SELF##_value_t *ref; } SELF##_iter_t; \ + typedef struct { SELF##_value_t *data; } SELF + +#endif // STC_FORWARD_H_INCLUDED \ No newline at end of file diff --git a/include/stc/template.h b/include/stc/template.h new file mode 100644 index 00000000..46059bf9 --- /dev/null +++ b/include/stc/template.h @@ -0,0 +1,149 @@ +#ifndef STC_TEMPLATE_INCLUDED +#define STC_TEMPLATE_INCLUDED + +#if defined I_TAG + #define i_TAG I_TAG + #define i_IMP +#endif +#if defined f_TAG + #define i_TAG f_TAG + #define i_FWD +#endif +#if defined F_TAG + #define i_TAG F_TAG + #define i_FWD + #define i_IMP +#endif + +#if defined i_KEY_str + #define i_KEY cstr + #define i_CMP c_rawstr_compare + #define i_EQU c_rawstr_equals + #define i_HASH c_rawstr_hash + #define i_KEYDEL cstr_del + #define i_KEYFROM cstr_from + #define i_KEYTO cstr_str + #define i_KEYRAW const char* +#endif +#if defined i_VAL_str + #define i_VAL cstr + #ifndef i_KEY + #define i_CMP c_rawstr_compare + #endif + #define i_VALDEL cstr_del + #define i_VALFROM cstr_from + #define i_VALTO cstr_str + #define i_VALRAW const char* +#endif + +#if !defined i_TAG && (defined i_KEY_str || defined i_VAL_str) + #define i_TAG str +#endif +#if !defined i_TAG && defined i_KEY + #define i_TAG i_KEY +#elif !defined i_TAG && defined i_VAL + #define i_TAG i_VAL +#endif + +#define Self c_PASTE3(i_CNT, _, i_TAG) +#define cx_memb(name) c_PASTE(Self, name) + +#define cx_value_t cx_memb(_value_t) +#define cx_rawvalue_t cx_memb(_rawvalue_t) +#define cx_iter_t cx_memb(_iter_t) + +#if defined i_VALTO ^ defined i_VALRAW + #error i_VALTO and i_VALRAW must both be defined +#endif +#if defined i_KEYTO ^ defined i_KEYRAW + #error i_KEYTO and i_KEYRAW must both be defined +#endif + +#if defined i_KEY + #define cx_key_t cx_memb(_key_t) + #define cx_rawkey_t cx_memb(_rawkey_t) + #define cx_mapped_t cx_memb(_mapped_t) + #define cx_rawmapped_t cx_memb(_rawmapped_t) + #define cx_result_t cx_memb(_result_t) + + #if !defined i_KEYFROM && defined i_KEYDEL + #define i_KEYFROM c_no_clone + #elif !defined i_KEYFROM + #define i_KEYFROM c_default_fromraw + #endif + #ifndef i_KEYRAW + #define i_KEYRAW i_KEY + #define i_KEYTO c_default_toraw + #endif +#endif + +#if !defined i_VALFROM && defined i_VALDEL + #define i_VALFROM c_no_clone +#elif !defined i_VALFROM + #define i_VALFROM c_default_fromraw +#endif +#ifndef i_VALRAW + #define i_VALRAW i_VAL + #define i_VALTO c_default_toraw +#endif + +#ifndef i_KEYDEL + #define i_KEYDEL c_default_del +#endif +#ifndef i_VALDEL + #define i_VALDEL c_default_del +#endif +#ifndef i_EQU + #define i_EQU c_default_equals +#endif +#ifndef i_HASH + #define i_HASH c_default_hash +#endif +#ifndef i_CMP + #define i_CMP c_default_compare +#endif + +// typedef container types defined in forward.h +#define cx_deftypes(macro, Self, ...) macro(Self, __VA_ARGS__) +// criteria for implementation +#if !defined i_IMP && (defined STC_IMPLEMENTATION || !defined STC_HEADER) +#define i_IMP +#endif + +#else // ------------------------------------------------------- + +#undef i_CNT +#undef i_TAG +#undef f_TAG +#undef i_IMP +#undef i_FWD +#undef i_CMP +#undef i_EQU +#undef i_HASH +#undef i_VAL +#undef i_VAL_str +#undef i_VALDEL +#undef i_VALFROM +#undef i_VALTO +#undef i_VALRAW +#undef i_KEY +#undef i_KEY_str +#undef i_KEYDEL +#undef i_KEYFROM +#undef i_KEYTO +#undef i_KEYRAW + +#undef Self +#undef cx_memb +#undef cx_deftypes +#undef cx_value_t +#undef cx_rawvalue_t +#undef cx_iter_t +#undef cx_key_t +#undef cx_rawkey_t +#undef cx_mapped_t +#undef cx_rawmapped_t +#undef cx_result_t + +#undef STC_TEMPLATE_INCLUDED +#endif diff --git a/include/stc/vec_test_new.c b/include/stc/vec_test_new.c new file mode 100644 index 00000000..65bb0ff9 --- /dev/null +++ b/include/stc/vec_test_new.c @@ -0,0 +1,53 @@ +#include "cstr.h" +#include "forward.h" + +forward_cvec(i32, int); +forward_cvec(pnt, struct Point); + +struct MyStruct { + cvec_i32 intvec; + cvec_pnt pntvec; +} typedef MyStruct; + + +#define f_TAG i32 +#define i_VAL int +#include "cvec.h" + +#define i_TAG f32 +#define i_VAL float +#include "cvec.h" + +struct Point { int x, y; } typedef Point; +int point_compare(const Point* a, const Point* b) { + int c = c_default_compare(&a->x, &b->x); + return c ? c : c_default_compare(&a->y, &b->y); +} +#define f_TAG pnt +#define i_VAL Point +#define i_CMP point_compare +#include "cvec.h" + +#define i_VAL_str +#include "cvec.h" + + +int main() +{ + cvec_i32 vec = cvec_i32_init(); + cvec_i32_push_back(&vec, 123); + + cvec_f32 fvec = cvec_f32_init(); + cvec_f32_push_back(&fvec, 123.3); + + cvec_pnt pvec = cvec_pnt_init(); + cvec_pnt_push_back(&pvec, (Point){42, 14}); + cvec_pnt_push_back(&pvec, (Point){32, 94}); + cvec_pnt_push_back(&pvec, (Point){62, 81}); + cvec_pnt_sort(&pvec); + c_foreach (i, cvec_pnt, pvec) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + cvec_str svec = cvec_str_init(); + cvec_str_emplace_back(&svec, "Hello, friend"); +} \ No newline at end of file -- cgit v1.2.3