diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/stc/alt/csmap.h | 2 | ||||
| -rw-r--r-- | include/stc/alt/cstr.h | 47 | ||||
| -rw-r--r-- | include/stc/carc.h | 45 | ||||
| -rw-r--r-- | include/stc/carr2.h | 13 | ||||
| -rw-r--r-- | include/stc/carr3.h | 13 | ||||
| -rw-r--r-- | include/stc/cbits.h | 2 | ||||
| -rw-r--r-- | include/stc/cbox.h | 37 | ||||
| -rw-r--r-- | include/stc/ccommon.h | 51 | ||||
| -rw-r--r-- | include/stc/cdeq.h | 204 | ||||
| -rw-r--r-- | include/stc/clist.h | 5 | ||||
| -rw-r--r-- | include/stc/cmap.h | 41 | ||||
| -rw-r--r-- | include/stc/cpque.h | 12 | ||||
| -rw-r--r-- | include/stc/cregex.h | 5 | ||||
| -rw-r--r-- | include/stc/csmap.h | 2 | ||||
| -rw-r--r-- | include/stc/cstack.h | 15 | ||||
| -rw-r--r-- | include/stc/cstr.h | 125 | ||||
| -rw-r--r-- | include/stc/csview.h | 21 | ||||
| -rw-r--r-- | include/stc/cvec.h | 206 | ||||
| -rw-r--r-- | include/stc/forward.h | 18 | ||||
| -rw-r--r-- | include/stc/template.h | 14 |
20 files changed, 474 insertions, 404 deletions
diff --git a/include/stc/alt/csmap.h b/include/stc/alt/csmap.h index 60a1b72a..4b90fb78 100644 --- a/include/stc/alt/csmap.h +++ b/include/stc/alt/csmap.h @@ -32,7 +32,7 @@ #include <stc/csmap.h> int main(void) { - c_autovar (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) + c_with (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) { csmap_sx_emplace(&m, "Testing one", 1.234); csmap_sx_emplace(&m, "Testing two", 12.34); diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index c669c620..a2233432 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -56,8 +56,8 @@ STC_API cstr* cstr_append_n(cstr* self, const char* str, size_t n); STC_API cstr cstr_replace_sv(csview str, csview find, csview repl, unsigned count); STC_DEF void cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl); STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n); -STC_API size_t cstr_find(cstr s, const char* needle); -STC_API size_t cstr_find_at(cstr s, size_t pos, const char* needle); +STC_API size_t cstr_find(const cstr* self, const char* needle); +STC_API size_t cstr_find_at(const cstr* self, size_t pos, const char* needle); STC_API bool cstr_getdelim(cstr *self, int delim, FILE *stream); STC_INLINE cstr cstr_init() { return cstr_null; } @@ -70,7 +70,7 @@ STC_INLINE csview cstr_sv(const cstr* self) STC_INLINE cstr cstr_from(const char* str) { return cstr_from_n(str, strlen(str)); } STC_INLINE char* cstr_data(cstr* self) { return self->str; } -STC_INLINE size_t cstr_size(cstr s) { return _cstr_p(&s)->size; } +STC_INLINE size_t cstr_size(const cstr* self) { return _cstr_p(self)->size; } STC_INLINE size_t cstr_capacity(cstr s) { return _cstr_p(&s)->cap; } STC_INLINE bool cstr_empty(cstr s) { return _cstr_p(&s)->size == 0; } STC_INLINE void cstr_drop(cstr* self) @@ -106,12 +106,12 @@ STC_INLINE void cstr_erase(cstr* self, const size_t pos) STC_INLINE char* cstr_front(cstr* self) { return self->str; } STC_INLINE char* cstr_back(cstr* self) { return self->str + _cstr_p(self)->size - 1; } -STC_INLINE bool cstr_equals(cstr s, const char* str) - { return strcmp(s.str, str) == 0; } -STC_INLINE bool cstr_equals_s(cstr s1, cstr s2) - { return strcmp(s1.str, s2.str) == 0; } -STC_INLINE bool cstr_contains(cstr s, const char* needle) - { return strstr(s.str, needle) != NULL; } +STC_INLINE bool cstr_equals(const cstr* self, const char* str) + { return strcmp(self->str, str) == 0; } +STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) + { return strcmp(self->str, s.str) == 0; } +STC_INLINE bool cstr_contains(const cstr* self, const char* needle) + { return strstr(self->str, needle) != NULL; } STC_INLINE bool cstr_getline(cstr *self, FILE *stream) { return cstr_getdelim(self, '\n', stream); } @@ -133,7 +133,7 @@ STC_INLINE cstr cstr_with_size(const size_t len, const char fill) { } STC_INLINE char* cstr_append_uninit(cstr *self, size_t n) { - size_t len = cstr_size(*self); char* d; + size_t len = cstr_size(self); char* d; if (!(d = cstr_reserve(self, len + n))) return NULL; _cstr_p(self)->size += n; return d + len; @@ -152,14 +152,15 @@ STC_INLINE cstr cstr_move(cstr* self) { return tmp; } -STC_INLINE bool cstr_starts_with(cstr s, const char* sub) { - while (*sub && *s.str == *sub) ++s.str, ++sub; +STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { + const char* p = self->str; + while (*sub && *p == *sub) ++p, ++sub; return *sub == 0; } -STC_INLINE bool cstr_ends_with(cstr s, const char* sub) { - const size_t n = strlen(sub), sz = _cstr_p(&s)->size; - return n <= sz && !memcmp(s.str + sz - n, sub, n); +STC_INLINE bool cstr_ends_with(const cstr* self, const char* sub) { + const size_t n = strlen(sub), sz = _cstr_p(self)->size; + return n <= sz && !memcmp(self->str + sz - n, sub, n); } STC_INLINE int c_strncasecmp(const char* s1, const char* s2, size_t nmax) { @@ -309,7 +310,7 @@ STC_INLINE void _cstr_internal_move(cstr* self, const size_t pos1, const size_t STC_DEF void cstr_replace_at_sv(cstr* self, const size_t pos, size_t len, csview repl) { - const size_t sz = cstr_size(*self); + const size_t sz = cstr_size(self); if (len > sz - pos) len = sz - pos; c_autobuf (xstr, char, repl.size) { memcpy(xstr, repl.str, repl.size); @@ -366,16 +367,16 @@ cstr_getdelim(cstr *self, const int delim, FILE *fp) { } STC_DEF size_t -cstr_find(cstr s, const char* needle) { - char* res = strstr(s.str, needle); - return res ? res - s.str : cstr_npos; +cstr_find(const cstr* self, const char* needle) { + char* res = strstr(self->str, needle); + return res ? res - self->str : cstr_npos; } STC_DEF size_t -cstr_find_at(cstr s, const size_t pos, const char* needle) { - if (pos > _cstr_p(&s)->size) return cstr_npos; - char* res = strstr(s.str + pos, needle); - return res ? res - s.str : cstr_npos; +cstr_find_at(const cstr* self, const size_t pos, const char* needle) { + if (pos > _cstr_p(self)->size) return cstr_npos; + char* res = strstr(self->str + pos, needle); + return res ? res - self->str : cstr_npos; } #endif diff --git a/include/stc/carc.h b/include/stc/carc.h index 57f00899..6e8f7d38 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -34,18 +34,18 @@ void Person_drop(Person* p) { c_drop(cstr, &p->name, &p->last); } -#define i_tag person +#define i_type ArcPers #define i_key Person #define i_keydrop Person_drop #define i_opt c_no_cmp #include <stc/carc.h> int main() { - carc_person p = carc_person_make(Person_new("John", "Smiths")); - carc_person q = carc_person_clone(p); // share the pointer + ArcPers p = ArcPers_from(Person_new("John", "Smiths")); + ArcPers q = ArcPers_clone(p); // share the pointer printf("%s %s. uses: %" PRIuMAX "\n", cstr_str(&q.get->name), cstr_str(&q.get->last), *q.use_count); - c_drop(carc_person, &p, &q); + c_drop(ArcPers, &p, &q); } */ #include "ccommon.h" @@ -56,14 +56,17 @@ int main() { #include <stdlib.h> #if defined(__GNUC__) || defined(__clang__) + typedef long catomic_long; #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) #elif defined(_MSC_VER) #include <intrin.h> + typedef long catomic_long; #define c_atomic_inc(v) (void)_InterlockedIncrement(v) #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) #else #include <stdatomic.h> + typedef _Atomic long catomic_long; #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) #endif @@ -88,23 +91,23 @@ typedef i_keyraw _cx_raw; #if !c_option(c_is_fwd) _cx_deftypes(_c_carc_types, _cx_self, i_key); #endif -_cx_carc_rep { long counter; i_key value; }; +_cx_carc_rep { catomic_long counter; i_key value; }; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } -STC_INLINE long _cx_memb(_use_count)(_cx_self ptr) - { return ptr.use_count ? *ptr.use_count : 0; } +STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) + { return self->use_count ? *self->use_count : 0; } STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { _cx_self ptr = {p}; if (p) - *(ptr.use_count = c_alloc(long)) = 1; + *(ptr.use_count = c_alloc(catomic_long)) = 1; return ptr; } // c++: std::make_shared<_cx_value>(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { +STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) { _cx_self ptr; _cx_carc_rep *rep = c_alloc(_cx_carc_rep); *(ptr.use_count = &rep->counter) = 1; @@ -112,12 +115,12 @@ STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { return ptr; } +STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) // [deprecated] + { return _cx_memb(_from)(val); } + STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } -STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) - { return *self->get; } - STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { _cx_self ptr = *self; self->get = NULL, self->use_count = NULL; @@ -129,7 +132,7 @@ STC_INLINE void _cx_memb(_drop)(_cx_self* self) { i_keydrop(self->get); if ((char *)self->get != (char *)self->use_count + offsetof(_cx_carc_rep, value)) c_free(self->get); - c_free(self->use_count); + c_free((long*)self->use_count); } } @@ -144,8 +147,8 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { } #if !defined _i_no_clone && !defined _i_no_emplace - STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } + STC_INLINE _cx_self _cx_memb(_new)(_cx_raw raw) + { return _cx_memb(_from)(i_keyfrom(raw)); } #endif // !_i_no_clone // does not use i_keyclone, so OK to always define. @@ -155,7 +158,7 @@ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) { return ptr; } -STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) { +STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); _cx_memb(_drop)(self); @@ -194,6 +197,16 @@ STC_INLINE bool _cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { return i_eq((&rx), (&ry)); #endif } + +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) + { return _cx_memb(_value_hash)(x->get); } + +STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_cmp)(x->get, y->get); } + +STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_eq)(x->get, y->get); } + #undef _i_atomic_inc #undef _i_atomic_dec_and_test #include "template.h" diff --git a/include/stc/carr2.h b/include/stc/carr2.h index 66a98f58..ffedb07d 100644 --- a/include/stc/carr2.h +++ b/include/stc/carr2.h @@ -35,7 +35,7 @@ int main() { int w = 7, h = 5; - c_autovar (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image)) + c_with (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image)) { int *dat = carr2_int_data(&image); for (int i = 0; i < carr2_int_size(&image); ++i) @@ -88,14 +88,17 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y) { return self->ydim*x + y; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){*self->data}; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = self->xdim*self->ydim; + return c_make(_cx_iter){n ? *self->data : NULL, *self->data + n}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){*self->data + self->xdim*self->ydim}; } + { return c_make(_cx_iter){NULL, *self->data + self->xdim*self->ydim}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { ++it->ref; } + { if (++it->ref == it->end) it->ref = NULL; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) diff --git a/include/stc/carr3.h b/include/stc/carr3.h index 8ff1670e..07eac2a1 100644 --- a/include/stc/carr3.h +++ b/include/stc/carr3.h @@ -35,7 +35,7 @@ int main() { int w = 7, h = 5, d = 3; - c_autovar (carr3_int image = carr3_int_new_uninit(w, h, d), carr3_int_drop(&image)) + c_with (carr3_int image = carr3_int_new_uninit(w, h, d), carr3_int_drop(&image)) { int *dat = carr3_int_data(&image); for (int i = 0; i < carr3_int_size(&image); ++i) @@ -91,14 +91,17 @@ STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y, size_ return self->zdim*(self->ydim*x + y) + z; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){**self->data}; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = _cx_memb(_size)(self); + return c_make(_cx_iter){n ? **self->data : NULL, **self->data + n}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){**self->data + _cx_memb(_size)(self)}; } + { return c_make(_cx_iter){NULL, **self->data + _cx_memb(_size)(self)}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { ++it->ref; } + { if (++it->ref == it->end) it->ref = NULL; } /* -------------------------- IMPLEMENTATION ------------------------- */ #if defined(i_implement) diff --git a/include/stc/cbits.h b/include/stc/cbits.h index 3f75226d..a1b84acd 100644 --- a/include/stc/cbits.h +++ b/include/stc/cbits.h @@ -27,7 +27,7 @@ Similar to boost::dynamic_bitset / std::bitset #include "cbits.h" int main() { - c_autovar (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) + c_with (cbits bset = cbits_with_size(23, true), cbits_drop(&bset)) { cbits_reset(&bset, 9); cbits_resize(&bset, 43, false); diff --git a/include/stc/cbox.h b/include/stc/cbox.h index c3a9dd02..02a73fdc 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -48,7 +48,7 @@ void Person_drop(Person* p) { int main() { c_auto (PBox, p, q) { - p = PBox_make(Person_from("John Smiths", "[email protected]")); + p = PBox_from(Person_from("John Smiths", "[email protected]")); q = PBox_clone(p); cstr_assign(&q.get->name, "Joe Smiths"); @@ -82,24 +82,24 @@ _cx_deftypes(_c_cbox_types, _cx_self, i_key); STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } -STC_INLINE long _cx_memb(_use_count)(_cx_self box) - { return (long)(box.get != NULL); } +STC_INLINE long _cx_memb(_use_count)(const _cx_self* self) + { return (long)(self->get != NULL); } STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { return c_make(_cx_self){p}; } // c++: std::make_unique<i_key>(val) -STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { +STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) { _cx_self ptr = {c_alloc(_cx_value)}; *ptr.get = val; return ptr; } +// [deprecated] +STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) + { return _cx_memb(_from)(val); } STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } -STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) - { return *self->get; } - // destructor STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->get) { @@ -126,11 +126,11 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { self->get = p; } -#if !defined _i_no_clone #if !defined _i_no_emplace - STC_INLINE _cx_self _cx_memb(_from)(_cx_raw raw) - { return _cx_memb(_make)(i_keyfrom(raw)); } + STC_INLINE _cx_self _cx_memb(_new)(_cx_raw raw) + { return _cx_memb(_from)(i_keyfrom(raw)); } #endif +#if !defined _i_no_clone STC_INLINE _cx_self _cx_memb(_clone)(_cx_self other) { if (!other.get) return other; @@ -138,13 +138,6 @@ STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { *out.get = i_keyclone(*other.get); return out; } - - STC_INLINE void _cx_memb(_assign)(_cx_self* self, const _cx_self ptr) { - if (self->get == ptr.get) - return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(ptr); - } #endif // !_i_no_clone STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self other) { @@ -179,4 +172,14 @@ STC_INLINE bool _cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { return i_eq((&rx), (&ry)); #endif } + +STC_INLINE uint64_t _cx_memb(_hash)(const _cx_self* x) + { return _cx_memb(_value_hash)(x->get); } + +STC_INLINE int _cx_memb(_cmp)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_cmp)(x->get, y->get); } + +STC_INLINE bool _cx_memb(_eq)(const _cx_self* x, const _cx_self* y) + { return _cx_memb(_value_eq)(x->get, y->get); } + #include "template.h" diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index e2c63b8c..58d74ddf 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -157,16 +157,14 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, #define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__) #define c_foreach3(it, C, cnt) \ - for (C##_iter it = C##_begin(&cnt), it##_end_ = C##_end(&cnt) \ - ; it.ref != it##_end_.ref; C##_next(&it)) + for (C##_iter it = C##_begin(&cnt); it.ref; C##_next(&it)) #define c_foreach4(it, C, start, finish) \ - for (C##_iter it = start, it##_end_ = finish \ - ; it.ref != it##_end_.ref; C##_next(&it)) + for (C##_iter it = start, *_endref = (C##_iter*)(finish).ref \ + ; it.ref != (C##_value*)_endref; C##_next(&it)) #define c_forpair(key, val, C, cnt) /* structured binding */ \ - for (struct {C##_iter _it; C##_value* _endref; const C##_key* key; C##_mapped* val;} \ - _ = {C##_begin(&cnt), C##_end(&cnt).ref} \ - ; _._it.ref != _._endref && (_.key = &_._it.ref->first, _.val = &_._it.ref->second) \ + for (struct {C##_iter _it; const C##_key* key; C##_mapped* val;} _ = {C##_begin(&cnt)} \ + ; _._it.ref && (_.key = &_._it.ref->first, _.val = &_._it.ref->second) \ ; C##_next(&_._it)) #define c_forrange(...) c_MACRO_OVERLOAD(c_forrange, __VA_ARGS__) @@ -178,24 +176,28 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, for (itype i=start, _inc=step, _end=(stop) - (0 < _inc) \ ; (i <= _end) == (0 < _inc); i += _inc) -#define c_autovar(...) c_MACRO_OVERLOAD(c_autovar, __VA_ARGS__) -#define c_autovar2(declvar, drop) for (declvar, **_c_i = NULL; !_c_i; ++_c_i, drop) -#define c_autovar3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop) -#define c_autoscope(init, drop) for (int _c_i = (init, 0); !_c_i; ++_c_i, drop) -#define c_autodefer(...) for (int _c_i = 0; !_c_i; ++_c_i, __VA_ARGS__) +#define c_autovar c_with // [deprecated] +#define c_autoscope c_scope // [deprecated] +#define c_autodefer c_defer // [deprecated] + +#define c_with(...) c_MACRO_OVERLOAD(c_with, __VA_ARGS__) +#define c_with2(declvar, drop) for (declvar, **_c_i = NULL; !_c_i; ++_c_i, drop) +#define c_with3(declvar, pred, drop) for (declvar, **_c_i = NULL; !_c_i && (pred); ++_c_i, drop) +#define c_scope(init, drop) for (int _c_i = (init, 0); !_c_i; ++_c_i, drop) +#define c_defer(...) for (int _c_i = 0; !_c_i; ++_c_i, __VA_ARGS__) #define c_breakauto continue #define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) #define c_auto2(C, a) \ - c_autovar2(C a = C##_init(), C##_drop(&a)) + c_with2(C a = C##_init(), C##_drop(&a)) #define c_auto3(C, a, b) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init()), \ (C##_drop(&b), C##_drop(&a))) #define c_auto4(C, a, b, c) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init()), \ (C##_drop(&c), C##_drop(&b), C##_drop(&a))) #define c_auto5(C, a, b, c, d) \ - c_autovar2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ + c_with2(c_expand(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ (C##_drop(&d), C##_drop(&c), C##_drop(&b), C##_drop(&a))) #define c_autobuf(b, type, n) c_autobuf_N(b, type, n, 256) @@ -221,16 +223,19 @@ STC_INLINE char* c_strnstrn(const char *s, const char *needle, #define c_pair(v) (v)->first, (v)->second #define c_drop(C, ...) do { c_forarray_p(C*, _p, {__VA_ARGS__}) C##_drop(*_p); } while(0) -#define c_find_if(C, cnt, it, pred) \ - c_find_in(C, C##_begin(&cnt), C##_end(&cnt), it, pred) +// it.ref == NULL when not found: +#define c_find_if(it, C, cnt, pred) do { \ + size_t index = 0; \ + for (it = C##_begin(&cnt); it.ref && !(pred); C##_next(&it)) \ + ++index; \ +} while (0) -// NB: it.ref == NULL when not found, not end.ref: -#define c_find_in(C, start, end, it, pred) do { \ +#define c_find_in(it, C, start, end, pred) do { \ size_t index = 0; \ - C##_iter _end = end; \ - for (it = start; it.ref != _end.ref && !(pred); C##_next(&it)) \ + const C##_value* _endref = (end).ref; \ + for (it = start; it.ref != _endref && !(pred); C##_next(&it)) \ ++index; \ - if (it.ref == _end.ref) it.ref = NULL; \ + if (it.ref == _endref) it.ref = NULL; \ } while (0) #endif // CCOMMON_H_INCLUDED diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index c5e08393..a8c880f2 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -29,6 +29,8 @@ struct cdeq_rep { size_t size, cap; unsigned base[1]; }; #define cdeq_rep_(self) c_unchecked_container_of((self)->_base, struct cdeq_rep, base) +#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref) +#define _it_ptr(it) (it.ref ? it.ref : it.end) #endif // CDEQ_H_INCLUDED #ifndef _i_prefix @@ -48,15 +50,12 @@ STC_API void _cx_memb(_clear)(_cx_self* self); STC_API void _cx_memb(_drop)(_cx_self* self); STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); STC_API void _cx_memb(_shrink_to_fit)(_cx_self *self); + #if !defined _i_queue #if !defined _i_no_emplace -STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); +STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2); #endif // _i_no_emplace -#if !defined _i_no_clone -STC_API _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -#endif // !_i_no_clone #if !c_option(c_no_cmp) STC_API _cx_iter _cx_memb(_find_in)(_cx_iter p1, _cx_iter p2, _cx_raw raw); @@ -64,23 +63,30 @@ STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value #endif STC_API _cx_value* _cx_memb(_push_front)(_cx_self* self, i_key value); STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); #endif // !_i_queue -#if !defined _i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self cx); #if !defined _i_no_emplace STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } #endif -STC_INLINE i_key _cx_memb(_value_clone)(i_key val) - { return i_keyclone(val); } + +#if !defined _i_no_clone +#if !defined _i_queue +STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); + STC_INLINE void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_memb(_clear)(self); + _cx_memb(_copy_range)(self, self->data, other->data, + other->data + cdeq_rep_(other)->size); } +#endif // !_i_queue +STC_API _cx_self _cx_memb(_clone)(_cx_self cx); +STC_INLINE i_key _cx_memb(_value_clone)(i_key val) + { return i_keyclone(val); } #endif // !_i_no_clone STC_INLINE size_t _cx_memb(_size)(const _cx_self* cx) { return cdeq_rep_(cx)->size; } STC_INLINE size_t _cx_memb(_capacity)(const _cx_self* cx) { return cdeq_rep_(cx)->cap; } @@ -92,13 +98,6 @@ STC_INLINE _cx_value* _cx_memb(_back)(const _cx_self* self) { return self->data + cdeq_rep_(self)->size - 1; } STC_INLINE void _cx_memb(_pop_front)(_cx_self* self) // == _pop() when _i_queue { i_keydrop(self->data); ++self->data; --cdeq_rep_(self)->size; } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){self->data}; } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){self->data + cdeq_rep_(self)->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } #if !defined _i_queue @@ -117,17 +116,17 @@ STC_INLINE _cx_value* _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); + return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); + return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); } STC_INLINE _cx_iter @@ -139,16 +138,25 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { + return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); } -#if !defined _i_no_clone -STC_INLINE _cx_value* -_cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = cdeq_rep_(self)->size; + return c_make(_cx_iter){n ? self->data : NULL, self->data + n}; } -#endif // !_i_no_clone + +STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL, self->data + cdeq_rep_(self)->size}; } + +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } + +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } + #if !defined _i_no_emplace STC_INLINE _cx_value* _cx_memb(_emplace_front)(_cx_self* self, _cx_raw raw) { @@ -159,13 +167,13 @@ STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); + return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); } #endif // !_i_no_emplace @@ -178,9 +186,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_raw raw) { STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - _cx_iter end = _cx_memb(_end)(self); - _cx_value* val = _cx_memb(_find_in)(_cx_memb(_begin)(self), end, raw).ref; - return val == end.ref ? NULL : val; + return _cx_memb(_find_in)(_cx_memb(_begin)(self), _cx_memb(_end)(self), raw).ref; } STC_INLINE _cx_value* @@ -188,9 +194,9 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_raw raw) { return (_cx_value *) _cx_memb(_get)(self, raw); } STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, - int(*_cmp_)(const _cx_value*, const _cx_value*)) { - qsort(i1.ref, i2.ref - i1.ref, sizeof *i1.ref, (int(*)(const void*, const void*)) _cmp_); +_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { + qsort(i1.ref, _it2_ptr(i1, i2) - i1.ref, sizeof *i1.ref, + (int(*)(const void*, const void*)) cmp); } STC_INLINE void @@ -222,6 +228,7 @@ _cx_memb(_clear)(_cx_self* self) { --q; i_keydrop(q); } rep->size = 0; + self->data = self->_base; } } @@ -231,7 +238,8 @@ _cx_memb(_shrink_to_fit)(_cx_self *self) { struct cdeq_rep* rep = cdeq_rep_(self); const size_t sz = rep->size; memmove(self->_base, self->data, sz*sizeof(i_key)); - rep = (struct cdeq_rep*) c_realloc(rep, offsetof(struct cdeq_rep, base) + sz*sizeof(i_key)); + rep = (struct cdeq_rep*) c_realloc(rep, offsetof(struct cdeq_rep, base) + + sz*sizeof(i_key)); if (rep) { self->_base = self->data = (_cx_value*)rep->base; rep->cap = sz; @@ -316,10 +324,10 @@ STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t sz = cdeq_rep_(&cx)->size; _cx_self out = _cx_memb(_with_capacity)(sz); - if (cdeq_rep_(&out)->cap) { - cdeq_rep_(&out)->size = sz; - for (size_t i = 0; i < sz; ++i) - out.data[i] = i_keyclone(cx.data[i]); + struct cdeq_rep* r = cdeq_rep_(&out); + if (r->cap) { + for (size_t i = 0; i < sz; ++i) out.data[i] = i_keyclone(cx.data[i]); + r->size = sz; } return out; } @@ -345,16 +353,21 @@ _cx_memb(_expand_left_half_)(_cx_self* self, const size_t idx, const size_t n) { } } -static _cx_value* -_cx_memb(_insert_uninit_p)(_cx_self* self, const _cx_value* pos, const size_t n) { - const size_t idx = pos - self->data; - if (idx*2 < cdeq_rep_(self)->size) - _cx_memb(_expand_left_half_)(self, idx, n); - else - _cx_memb(_expand_right_half_)(self, idx, n); - if (n) - cdeq_rep_(self)->size += n; /* do only if size > 0 */ - return self->data + idx; +static _cx_iter +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { + struct cdeq_rep* r = cdeq_rep_(self); + if (n) { + if (!pos) pos = self->data + r->size; + const size_t idx = pos - self->data; + if (idx*2 < r->size) + _cx_memb(_expand_left_half_)(self, idx, n); + else + _cx_memb(_expand_right_half_)(self, idx, n); + r = cdeq_rep_(self); + r->size += n; + pos = self->data + idx; + } + return c_make(_cx_iter){pos, self->data + r->size}; } STC_DEF _cx_value* @@ -368,62 +381,63 @@ _cx_memb(_push_front)(_cx_self* self, i_key value) { return self->data; } -STC_DEF _cx_value* -_cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, +STC_DEF _cx_iter +_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - if (pos) - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return pos; + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + memcpy(it.ref, p1, (p2 - p1)*sizeof *p1); + return it; } STC_DEF _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { - const size_t n = p2 - p1; - if (n > 0) { - _cx_value* p = p1, *end = self->data + cdeq_rep_(self)->size; - for (; p != p2; ++p) { i_keydrop(p); } - if (p1 == self->data) - self->data += n; - else memmove(p1, p2, (end - p2) * sizeof(i_key)); - cdeq_rep_(self)->size -= n; - } - return c_make(_cx_iter){p1}; + assert(p1 && p2); + intptr_t len = p2 - p1; + struct cdeq_rep* r = cdeq_rep_(self); + _cx_value* p = p1, *end = self->data + r->size; + for (; p != p2; ++p) + { i_keydrop(p); } + memmove(p1, p2, (end - p2) * sizeof *p1); + r->size -= len; + return c_make(_cx_iter){p2 == end ? NULL : p1, end - len}; } -#if !defined _i_no_emplace -STC_DEF _cx_value* -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, const _cx_raw* p1, const _cx_raw* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyfrom((*p1)); +#if !defined _i_no_clone +STC_DEF _cx_iter +_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyclone((*p1)); return it; } -#endif // !_i_no_emplace +#endif // !_i_no_clone -#if !defined _i_no_clone -STC_DEF _cx_value* -_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyclone((*p1)); +#if !defined _i_no_emplace +STC_DEF _cx_iter +_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyfrom((*p1)); return it; } -#endif // !_i_no_clone +#endif // !_i_no_emplace #if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - for (; i1.ref != i2.ref; ++i1.ref) { - _cx_raw r = i_keyto(i1.ref); + const _cx_value* p2 = _it2_ptr(i1, i2); + for (; i1.ref != p2; ++i1.ref) { + const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) return i1; } - return i2; + i2.ref = NULL; return i2; // NB! } STC_DEF int diff --git a/include/stc/clist.h b/include/stc/clist.h index 229db32c..5b9cf0d3 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -159,9 +159,8 @@ _cx_memb(_begin)(const _cx_self* self) { } STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) { - return c_make(_cx_iter){NULL}; -} +_cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL}; } STC_INLINE void _cx_memb(_next)(_cx_iter* it) { diff --git a/include/stc/cmap.h b/include/stc/cmap.h index 84957e69..58774fb2 100644 --- a/include/stc/cmap.h +++ b/include/stc/cmap.h @@ -31,7 +31,7 @@ #include <stc/cmap.h> int main(void) { - c_autovar (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m)) + c_with (cmap_ichar m = cmap_ichar_init(), cmap_ichar_drop(&m)) { cmap_ichar_emplace(&m, 5, 'a'); cmap_ichar_emplace(&m, 8, 'b'); @@ -188,12 +188,29 @@ _cx_memb(_push)(_cx_self* self, _cx_value _val) { return _res; } + +STC_INLINE _cx_iter +_cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL}; } + +STC_INLINE void +_cx_memb(_next)(_cx_iter* it) { + while ((++it->ref, *++it->_hx == 0)) ; + if (it->ref == it->end) it->ref = NULL; +} + +STC_INLINE _cx_iter +_cx_memb(_advance)(_cx_iter it, size_t n) { + while (n-- && it.ref) _cx_memb(_next)(&it); + return it; +} + STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, _cx_rawkey rkey) { i_size idx; if (!(self->size && self->_hashx[idx = _cx_memb(_bucket_)(self, &rkey).idx])) - idx = self->bucket_count; - return c_make(_cx_iter){self->table+idx, self->_hashx+idx}; + return _cx_memb(_end)(self); + return c_make(_cx_iter){self->table+idx, self->table+self->bucket_count, self->_hashx+idx}; } STC_INLINE const _cx_value* @@ -210,25 +227,11 @@ _cx_memb(_get_mut)(_cx_self* self, _cx_rawkey rkey) STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - _cx_iter it = {self->table, self->_hashx}; + _cx_iter it = {self->table, self->table+self->bucket_count, self->_hashx}; if (it._hx) while (*it._hx == 0) ++it.ref, ++it._hx; - return it; -} - -STC_INLINE _cx_iter -_cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){self->table + self->bucket_count}; } - -STC_INLINE void -_cx_memb(_next)(_cx_iter* it) - { while ((++it->ref, *++it->_hx == 0)) ; } - -STC_INLINE _cx_iter -_cx_memb(_advance)(_cx_iter it, size_t n) { - // UB if n > elements left - while (n--) _cx_memb(_next)(&it); + if (it.ref == it.end) it.ref = NULL; return it; } diff --git a/include/stc/cpque.h b/include/stc/cpque.h index bb7c207e..79d12b95 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -110,9 +110,9 @@ STC_INLINE void _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) STC_DEF void _cx_memb(_sift_down_)(_cx_value* arr, const size_t idx, const size_t n) { - for (size_t r = idx, c = idx << 1; c <= n; c <<= 1) { - c += (c < n && (i_cmp((&arr[c]), (&arr[c + 1]))) < 0); - if ((i_cmp((&arr[r]), (&arr[c]))) >= 0) return; + for (size_t r = idx, c = idx*2; c <= n; c *= 2) { + c += (c < n && (i_less((&arr[c]), (&arr[c + 1])))); + if (!(i_less((&arr[r]), (&arr[c])))) return; _cx_value t = arr[r]; arr[r] = arr[c]; arr[r = c] = t; } } @@ -121,7 +121,7 @@ STC_DEF void _cx_memb(_make_heap)(_cx_self* self) { size_t n = self->size; _cx_value *arr = self->data - 1; - for (size_t k = n >> 1; k != 0; --k) + for (size_t k = n/2; k != 0; --k) _cx_memb(_sift_down_)(arr, k, n); } @@ -148,8 +148,8 @@ _cx_memb(_push)(_cx_self* self, _cx_value value) { _cx_memb(_reserve)(self, self->size*3/2 + 4); _cx_value *arr = self->data - 1; /* base 1 */ size_t c = ++self->size; - for (; c > 1 && (i_cmp((&arr[c >> 1]), (&value))) < 0; c >>= 1) - arr[c] = arr[c >> 1]; + for (; c > 1 && (i_less((&arr[c/2]), (&value))); c /= 2) + arr[c] = arr[c/2]; arr[c] = value; } diff --git a/include/stc/cregex.h b/include/stc/cregex.h index d19d518f..4812bff2 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -76,8 +76,9 @@ typedef struct { csview ref[cre_MAXCAPTURES]; } cregex_iter; -#define c_foreach_match(i, _re, _input) \ - for (cregex_iter i = {_re, _input}; cregex_find(i.input, i.re, i.ref, cre_m_next) == cre_success;) +#define c_foreach_match(it, Re, Input) \ + for (cregex_iter it = {Re, Input}; \ + cregex_find(it.input, it.re, it.ref, cre_m_next) == cre_success;) static inline cregex cregex_init(void) { diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 97f1fce1..c773e70f 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -32,7 +32,7 @@ #include <stc/csmap.h> int main(void) { - c_autovar (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) + c_with (csmap_sx m = csmap_sx_init(), csmap_sx_drop(&m)) { csmap_sx_emplace(&m, "Testing one", 1.234); csmap_sx_emplace(&m, "Testing two", 12.34); diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 46d209ca..e1839d37 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -169,15 +169,18 @@ STC_INLINE i_keyraw _cx_memb(_value_toraw)(const _cx_value* val) { return i_keyto(val); } #endif // !_i_no_clone -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){(_cx_value*)self->data}; } +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + return c_make(_cx_iter){self->size ? (_cx_value*)self->data : NULL, + (_cx_value*)self->data + self->size}; +} STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){(_cx_value*)self->data + self->size}; } + { return c_make(_cx_iter){NULL, (_cx_value*)self->data + self->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL ; return it; } #include "template.h" diff --git a/include/stc/cstr.h b/include/stc/cstr.h index aae52ea0..99b60e49 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -80,7 +80,7 @@ STC_API char* _cstr_internal_move(cstr* self, size_t pos1, size_t pos2); STC_API char* cstr_reserve(cstr* self, size_t cap); STC_API void cstr_shrink_to_fit(cstr* self); STC_API void cstr_resize(cstr* self, size_t size, char value); -STC_API size_t cstr_find_at(cstr s, size_t pos, const char* search); +STC_API size_t cstr_find_at(const cstr* self, size_t pos, const char* search); STC_API char* cstr_assign_n(cstr* self, const char* str, size_t len); STC_API char* cstr_append_n(cstr* self, const char* str, size_t len); STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); @@ -161,14 +161,14 @@ STC_INLINE char* cstr_data(cstr* self) STC_INLINE const char* cstr_str(const cstr* self) { return SSO_CALL(self, data(self)); } -STC_INLINE bool cstr_empty(cstr s) - { return s.sml.last == cstr_s_cap; } +STC_INLINE bool cstr_empty(const cstr* self) + { return self->sml.last == cstr_s_cap; } -STC_INLINE size_t cstr_size(cstr s) - { return SSO_CALL(&s, size(&s)); } +STC_INLINE size_t cstr_size(const cstr* self) + { return SSO_CALL(self, size(self)); } -STC_INLINE size_t cstr_capacity(cstr s) - { return cstr_is_long(&s) ? cstr_l_cap(&s) : cstr_s_cap; } +STC_INLINE size_t cstr_capacity(const cstr* self) + { return cstr_is_long(self) ? cstr_l_cap(self) : cstr_s_cap; } // utf8 methods defined in/depending on src/utf8code.c: @@ -200,11 +200,11 @@ STC_INLINE bool cstr_valid_utf8(const cstr* self) // other utf8 -STC_INLINE size_t cstr_u8_size(cstr s) - { return utf8_size(cstr_str(&s)); } +STC_INLINE size_t cstr_u8_size(const cstr* self) + { return utf8_size(cstr_str(self)); } -STC_INLINE size_t cstr_u8_size_n(cstr s, size_t nbytes) - { return utf8_size_n(cstr_str(&s), nbytes); } +STC_INLINE size_t cstr_u8_size_n(const cstr* self, size_t nbytes) + { return utf8_size_n(cstr_str(self), nbytes); } STC_INLINE size_t cstr_u8_to_pos(const cstr* self, size_t u8idx) { return utf8_pos(cstr_str(self), u8idx); } @@ -223,16 +223,18 @@ STC_INLINE csview cstr_u8_chr(const cstr* self, size_t u8idx) { // utf8 iterator STC_INLINE cstr_iter cstr_begin(const cstr* self) { - const char* str = cstr_str(self); - return c_make(cstr_iter){.chr = {str, utf8_chr_size(str)}}; + csview sv = cstr_sv(self); + if (!sv.size) return c_make(cstr_iter){NULL}; + return c_make(cstr_iter){.u8 = {{sv.str, utf8_chr_size(sv.str)}, sv.str + sv.size}}; } STC_INLINE cstr_iter cstr_end(const cstr* self) { csview sv = cstr_sv(self); - return c_make(cstr_iter){sv.str + sv.size}; + return c_make(cstr_iter){.u8 = {{NULL}, sv.str + sv.size}}; } STC_INLINE void cstr_next(cstr_iter* it) { - it->ref += it->chr.size; - it->chr.size = utf8_chr_size(it->ref); + it->ref += it->u8.chr.size; + it->u8.chr.size = utf8_chr_size(it->ref); + if (it->ref == it->u8.end) it->ref = NULL; } @@ -240,7 +242,7 @@ STC_INLINE void cstr_clear(cstr* self) { _cstr_set_size(self, 0); } STC_INLINE char* cstr_append_uninit(cstr *self, size_t len) { - size_t sz = cstr_size(*self); + size_t sz = cstr_size(self); char* d = cstr_reserve(self, sz + len); if (!d) return NULL; _cstr_set_size(self, sz + len); @@ -259,75 +261,75 @@ STC_INLINE bool cstr_eq(const cstr* s1, const cstr* s2) { } -STC_INLINE bool cstr_equals(cstr s1, const char* str) - { return !strcmp(cstr_str(&s1), str); } +STC_INLINE bool cstr_equals(const cstr* self, const char* str) + { return !strcmp(cstr_str(self), str); } -STC_INLINE bool cstr_equals_sv(cstr s, csview sv) - { return sv.size == cstr_size(s) && !memcmp(cstr_str(&s), sv.str, sv.size); } +STC_INLINE bool cstr_equals_sv(const cstr* self, csview sv) + { return sv.size == cstr_size(self) && !memcmp(cstr_str(self), sv.str, sv.size); } -STC_INLINE bool cstr_equals_s(cstr s1, cstr s2) - { return !cstr_cmp(&s1, &s2); } +STC_INLINE bool cstr_equals_s(const cstr* self, cstr s) + { return !cstr_cmp(self, &s); } -STC_INLINE bool cstr_iequals(cstr s1, const char* str) - { return !utf8_icmp(cstr_str(&s1), str); } +STC_INLINE bool cstr_iequals(const cstr* self, const char* str) + { return !utf8_icmp(cstr_str(self), str); } -STC_INLINE size_t cstr_find(cstr s, const char* search) { - const char *str = cstr_str(&s), *res = strstr((char*)str, search); +STC_INLINE size_t cstr_find(const cstr* self, const char* search) { + const char *str = cstr_str(self), *res = strstr((char*)str, search); return res ? res - str : cstr_npos; } -STC_API size_t cstr_find_sv(cstr s, csview search); +STC_API size_t cstr_find_sv(const cstr* self, csview search); -STC_INLINE size_t cstr_find_s(cstr s, cstr search) - { return cstr_find(s, cstr_str(&search)); } +STC_INLINE size_t cstr_find_s(const cstr* self, cstr search) + { return cstr_find(self, cstr_str(&search)); } -STC_INLINE bool cstr_contains(cstr s, const char* search) - { return strstr(cstr_data(&s), search) != NULL; } +STC_INLINE bool cstr_contains(const cstr* self, const char* search) + { return strstr((char*)cstr_str(self), search) != NULL; } -STC_INLINE bool cstr_contains_sv(cstr s, csview search) - { return cstr_find_sv(s, search) != cstr_npos; } +STC_INLINE bool cstr_contains_sv(const cstr* self, csview search) + { return cstr_find_sv(self, search) != cstr_npos; } -STC_INLINE bool cstr_contains_s(cstr s, cstr search) - { return strstr(cstr_data(&s), cstr_str(&search)) != NULL; } +STC_INLINE bool cstr_contains_s(const cstr* self, cstr search) + { return strstr((char*)cstr_str(self), cstr_str(&search)) != NULL; } -STC_INLINE bool cstr_starts_with_sv(cstr s, csview sub) { - if (sub.size > cstr_size(s)) return false; - return !memcmp(cstr_str(&s), sub.str, sub.size); +STC_INLINE bool cstr_starts_with_sv(const cstr* self, csview sub) { + if (sub.size > cstr_size(self)) return false; + return !memcmp(cstr_str(self), sub.str, sub.size); } -STC_INLINE bool cstr_starts_with(cstr s, const char* sub) { - const char* str = cstr_str(&s); +STC_INLINE bool cstr_starts_with(const cstr* self, const char* sub) { + const char* str = cstr_str(self); while (*sub && *str == *sub) ++str, ++sub; return !*sub; } -STC_INLINE bool cstr_starts_with_s(cstr s, cstr sub) - { return cstr_starts_with_sv(s, cstr_sv(&sub)); } +STC_INLINE bool cstr_starts_with_s(const cstr* self, cstr sub) + { return cstr_starts_with_sv(self, cstr_sv(&sub)); } -STC_INLINE bool cstr_istarts_with(cstr s, const char* sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_istarts_with(const cstr* self, const char* sub) { + csview sv = cstr_sv(self); size_t len = strlen(sub); return len <= sv.size && !utf8_icmp_sv(sv, c_sv(sub, len)); } -STC_INLINE bool cstr_ends_with_sv(cstr s, csview sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_ends_with_sv(const cstr* self, csview sub) { + csview sv = cstr_sv(self); if (sub.size > sv.size) return false; return !memcmp(sv.str + sv.size - sub.size, sub.str, sub.size); } -STC_INLINE bool cstr_ends_with_s(cstr s, cstr sub) - { return cstr_ends_with_sv(s, cstr_sv(&sub)); } +STC_INLINE bool cstr_ends_with_s(const cstr* self, cstr sub) + { return cstr_ends_with_sv(self, cstr_sv(&sub)); } -STC_INLINE bool cstr_ends_with(cstr s, const char* sub) - { return cstr_ends_with_sv(s, c_sv(sub, strlen(sub))); } +STC_INLINE bool cstr_ends_with(const cstr* self, const char* sub) + { return cstr_ends_with_sv(self, c_sv(sub, strlen(sub))); } -STC_INLINE bool cstr_iends_with(cstr s, const char* sub) { - csview sv = cstr_sv(&s); +STC_INLINE bool cstr_iends_with(const cstr* self, const char* sub) { + csview sv = cstr_sv(self); size_t n = strlen(sub); return n <= sv.size && !utf8_icmp(sv.str + sv.size - n, sub); } @@ -368,11 +370,8 @@ STC_INLINE void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* STC_INLINE void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl) { cstr_replace_at_sv(self, pos, len, cstr_sv(&repl)); } -STC_INLINE void cstr_u8_replace_at(cstr* self, size_t u8pos, size_t u8len, csview repl) { - csview sv = cstr_sv(self); - const char* p = utf8_at(sv.str, u8pos); - cstr_replace_at_sv(self, p - sv.str, utf8_pos(p, u8len), repl); -} +STC_INLINE void cstr_u8_replace(cstr* self, size_t pos, size_t u8len, csview repl) + { cstr_replace_at_sv(self, pos, utf8_pos(cstr_str(self) + pos, u8len), repl); } STC_INLINE void cstr_insert(cstr* self, size_t pos, const char* str) @@ -400,9 +399,9 @@ STC_DEF uint64_t cstr_hash(const cstr *self) { return c_fasthash(sv.str, sv.size); } -STC_DEF size_t cstr_find_sv(cstr s, csview search) { - char* res = c_strnstrn(cstr_str(&s), search.str, cstr_size(s), search.size); - return res ? res - cstr_str(&s) : cstr_npos; +STC_DEF size_t cstr_find_sv(const cstr* self, csview search) { + char* res = c_strnstrn(cstr_str(self), search.str, cstr_size(self), search.size); + return res ? res - cstr_str(self) : cstr_npos; } STC_DEF char* _cstr_internal_move(cstr* self, const size_t pos1, const size_t pos2) { @@ -472,8 +471,8 @@ STC_DEF void cstr_resize(cstr* self, const size_t size, const char value) { _cstr_set_size(self, size); } -STC_DEF size_t cstr_find_at(cstr s, const size_t pos, const char* search) { - csview sv = cstr_sv(&s); +STC_DEF size_t cstr_find_at(const cstr* self, const size_t pos, const char* search) { + csview sv = cstr_sv(self); if (pos > sv.size) return cstr_npos; const char* res = strstr((char*)sv.str + pos, search); return res ? res - sv.str : cstr_npos; diff --git a/include/stc/csview.h b/include/stc/csview.h index 2efeff5b..dbff8620 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -69,15 +69,22 @@ STC_INLINE csview csview_slice(csview sv, size_t p1, size_t p2) { return sv; } -/* iterator */ -STC_INLINE csview_iter csview_begin(const csview* self) - { return c_make(csview_iter){.chr = {self->str, utf8_chr_size(self->str)}}; } +/* utf8 iterator */ +STC_INLINE csview_iter csview_begin(const csview* self) { + if (!self->size) return c_make(csview_iter){NULL}; + return c_make(csview_iter){.u8 = {{self->str, utf8_chr_size(self->str)}, + self->str + self->size}}; +} + +STC_INLINE csview_iter csview_end(const csview* self) + { return c_make(csview_iter){.u8 = {{NULL}, self->str + self->size}}; } -STC_INLINE csview_iter csview_end(const csview* self) - { return c_make(csview_iter){self->str + self->size}; } +STC_INLINE void csview_next(csview_iter* it) { + it->ref += it->u8.chr.size; + it->u8.chr.size = utf8_chr_size(it->ref); + if (it->ref == it->u8.end) it->ref = NULL; +} -STC_INLINE void csview_next(csview_iter* it) - { it->ref += it->chr.size; it->chr.size = utf8_chr_size(it->ref); } /* utf8 */ STC_INLINE size_t csview_u8_size(csview sv) diff --git a/include/stc/cvec.h b/include/stc/cvec.h index 81678293..6b120ff0 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -66,6 +66,8 @@ int main() { struct cvec_rep { size_t size, cap; unsigned data[1]; }; #define cvec_rep_(self) c_unchecked_container_of((self)->data, struct cvec_rep, data) +#define _it2_ptr(it1, it2) (it1.ref && !it2.ref ? it2.end : it2.ref) +#define _it_ptr(it) (it.ref ? it.ref : it.end) #endif // CVEC_H_INCLUDED #ifndef _i_prefix @@ -84,9 +86,9 @@ STC_API bool _cx_memb(_reserve)(_cx_self* self, size_t cap); STC_API bool _cx_memb(_resize)(_cx_self* self, size_t size, i_key null); STC_API _cx_value* _cx_memb(_push)(_cx_self* self, i_key value); STC_API _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); -STC_API _cx_value* _cx_memb(_insert_uninit_p)(_cx_self* self, _cx_value* pos, const size_t n); +STC_API _cx_iter _cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n); #if !c_option(c_no_cmp) STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y); STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw); @@ -94,37 +96,34 @@ STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, #endif #if !defined _i_no_emplace -STC_API _cx_value* _cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2); +STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2); STC_INLINE _cx_value* _cx_memb(_emplace)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } STC_INLINE _cx_value* _cx_memb(_emplace_back)(_cx_self* self, _cx_raw raw) { return _cx_memb(_push)(self, i_keyfrom(raw)); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_n)(_cx_self* self, const size_t idx, const _cx_raw arr[], const size_t n) { - return _cx_memb(_emplace_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_emplace_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_emplace_at)(_cx_self* self, _cx_iter it, _cx_raw raw) { - return _cx_memb(_emplace_range_p)(self, it.ref, &raw, &raw + 1); + return _cx_memb(_emplace_range)(self, _it_ptr(it), &raw, &raw + 1); } #endif // !_i_no_emplace #if !defined _i_no_clone STC_API _cx_self _cx_memb(_clone)(_cx_self cx); -STC_API _cx_value* _cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2); +STC_API _cx_iter _cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2); STC_INLINE i_key _cx_memb(_value_clone)(_cx_value val) { return i_keyclone(val); } STC_INLINE void _cx_memb(_copy)(_cx_self* self, const _cx_self* other) { if (self->data == other->data) return; - _cx_memb(_drop)(self); - *self = _cx_memb(_clone)(*other); + _cx_memb(_clear)(self); + _cx_memb(_copy_range)(self, self->data, other->data, + other->data + cvec_rep_(other)->size); } -STC_INLINE _cx_value* -_cx_memb(_emplace_range)(_cx_self* self, _cx_iter it, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_clone_range_p)(self, it.ref, it1.ref, it2.ref); -} #endif // !_i_no_clone STC_INLINE size_t _cx_memb(_size)(const _cx_self* cx) { return cvec_rep_(cx)->size; } @@ -140,14 +139,6 @@ STC_INLINE void _cx_memb(_pop)(_cx_self* self) STC_INLINE _cx_value* _cx_memb(_push_back)(_cx_self* self, i_key value) { return _cx_memb(_push)(self, value); } STC_INLINE void _cx_memb(_pop_back)(_cx_self* self) { _cx_memb(_pop)(self); } -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) - { return c_make(_cx_iter){self->data}; } -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_make(_cx_iter){self->data + cvec_rep_(self)->size}; } -STC_INLINE void _cx_memb(_next)(_cx_iter* it) { ++it->ref; } -STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, intptr_t offs) - { it.ref += offs; return it; } -STC_INLINE size_t _cx_memb(_index)(const _cx_self* cx, _cx_iter it) { return it.ref - cx->data; } STC_INLINE _cx_self _cx_memb(_with_size)(const size_t size, i_key null) { @@ -168,22 +159,18 @@ _cx_memb(_shrink_to_fit)(_cx_self* self) { _cx_memb(_reserve)(self, _cx_memb(_size)(self)); } -STC_INLINE _cx_value* -_cx_memb(_append_uninit)(_cx_self* self, const size_t n) { - return _cx_memb(_insert_uninit_p)(self, self->data + _cx_memb(_size)(self), n); -} -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert)(_cx_self* self, const size_t idx, i_key value) { - return _cx_memb(_insert_range_p)(self, self->data + idx, &value, &value + 1); + return _cx_memb(_insert_range)(self, self->data + idx, &value, &value + 1); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_n)(_cx_self* self, const size_t idx, const _cx_value arr[], const size_t n) { - return _cx_memb(_insert_range_p)(self, self->data + idx, arr, arr + n); + return _cx_memb(_insert_range)(self, self->data + idx, arr, arr + n); } -STC_INLINE _cx_value* +STC_INLINE _cx_iter _cx_memb(_insert_at)(_cx_self* self, _cx_iter it, i_key value) { - return _cx_memb(_insert_range_p)(self, it.ref, &value, &value + 1); + return _cx_memb(_insert_range)(self, _it_ptr(it), &value, &value + 1); } STC_INLINE _cx_iter @@ -195,8 +182,8 @@ _cx_memb(_erase_at)(_cx_self* self, _cx_iter it) { return _cx_memb(_erase_range_p)(self, it.ref, it.ref + 1); } STC_INLINE _cx_iter -_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) { - return _cx_memb(_erase_range_p)(self, it1.ref, it2.ref); +_cx_memb(_erase_range)(_cx_self* self, _cx_iter i1, _cx_iter i2) { + return _cx_memb(_erase_range_p)(self, i1.ref, _it2_ptr(i1, i2)); } STC_INLINE const _cx_value* @@ -208,6 +195,24 @@ _cx_memb(_at_mut)(_cx_self* self, const size_t idx) { assert(idx < cvec_rep_(self)->size); return self->data + idx; } + +STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { + size_t n = cvec_rep_(self)->size; + return c_make(_cx_iter){n ? self->data : NULL, self->data + n}; +} + +STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) + { return c_make(_cx_iter){NULL, self->data + cvec_rep_(self)->size}; } + +STC_INLINE void _cx_memb(_next)(_cx_iter* it) + { if (++it->ref == it->end) it->ref = NULL; } + +STC_INLINE _cx_iter _cx_memb(_advance)(_cx_iter it, size_t n) + { if ((it.ref += n) >= it.end) it.ref = NULL; return it; } + +STC_INLINE size_t _cx_memb(_index)(const _cx_self* cx, _cx_iter it) + { return it.ref - cx->data; } + #if !c_option(c_no_cmp) STC_INLINE _cx_iter @@ -217,9 +222,7 @@ _cx_memb(_find)(const _cx_self* self, _cx_raw raw) { STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, _cx_raw raw) { - _cx_iter end = _cx_memb(_end)(self); - _cx_value* val = _cx_memb(_find)(self, raw).ref; - return val == end.ref ? NULL : val; + return _cx_memb(_find)(self, raw).ref; } STC_INLINE _cx_value* @@ -240,10 +243,11 @@ _cx_memb(_lower_bound)(const _cx_self* self, _cx_raw raw) { } STC_INLINE void -_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, - int(*_cmp_)(const _cx_value*, const _cx_value*)) { - qsort(i1.ref, i2.ref - i1.ref, sizeof(_cx_value), (int(*)(const void*, const void*)) _cmp_); +_cx_memb(_sort_range)(_cx_iter i1, _cx_iter i2, int(*cmp)(const _cx_value*, const _cx_value*)) { + qsort(i1.ref, _it2_ptr(i1, i2) - i1.ref, sizeof(_cx_value), + (int(*)(const void*, const void*)) cmp); } + STC_INLINE void _cx_memb(_sort)(_cx_self* self) { _cx_memb(_sort_range)(_cx_memb(_begin)(self), _cx_memb(_end)(self), _cx_memb(_value_cmp)); @@ -289,7 +293,8 @@ _cx_memb(_reserve)(_cx_self* self, const size_t cap) { const size_t len = rep->size; if (cap > rep->cap || (cap && cap == len)) { rep = (struct cvec_rep*) c_realloc(rep->cap ? rep : NULL, - offsetof(struct cvec_rep, data) + cap*sizeof(i_key)); + offsetof(struct cvec_rep, data) + + cap*sizeof(i_key)); if (!rep) return false; self->data = (_cx_value*) rep->data; @@ -325,103 +330,106 @@ _cx_memb(_push)(_cx_self* self, i_key value) { *v = value; return v; } -STC_DEF _cx_value* -_cx_memb(_insert_uninit_p)(_cx_self* self, _cx_value* pos, const size_t n) { - const size_t idx = pos - self->data; +STC_DEF _cx_iter +_cx_memb(_insert_uninit)(_cx_self* self, _cx_value* pos, const size_t n) { struct cvec_rep* r = cvec_rep_(self); - if (!n) - return pos; - if (r->size + n > r->cap) { - if (!_cx_memb(_reserve)(self, r->size*3/2 + n)) - return NULL; - r = cvec_rep_(self); - pos = self->data + idx; + if (n) { + if (!pos) pos = self->data + r->size; + const size_t idx = pos - self->data; + if (r->size + n > r->cap) { + if (!_cx_memb(_reserve)(self, r->size*3/2 + n)) + return _cx_memb(_end)(self); + r = cvec_rep_(self); + pos = self->data + idx; + } + memmove(pos + n, pos, (r->size - idx)*sizeof *pos); + r->size += n; } - memmove(pos + n, pos, (r->size - idx)*sizeof *pos); - r->size += n; - return pos; + return c_make(_cx_iter){pos, self->data + r->size}; } -STC_DEF _cx_value* -_cx_memb(_insert_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - if (pos) - memcpy(pos, p1, (p2 - p1)*sizeof *p1); - return pos; +STC_DEF _cx_iter +_cx_memb(_insert_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + memcpy(it.ref, p1, (p2 - p1)*sizeof *p1); + return it; } STC_DEF _cx_iter _cx_memb(_erase_range_p)(_cx_self* self, _cx_value* p1, _cx_value* p2) { + assert(p1 && p2); intptr_t len = p2 - p1; - if (len > 0) { - _cx_value* p = p1, *end = self->data + cvec_rep_(self)->size; - for (; p != p2; ++p) - { i_keydrop(p); } - memmove(p1, p2, (end - p2) * sizeof(i_key)); - cvec_rep_(self)->size -= len; - } - return c_make(_cx_iter){.ref = p1}; + struct cvec_rep* r = cvec_rep_(self); + _cx_value* p = p1, *end = self->data + r->size; + for (; p != p2; ++p) + { i_keydrop(p); } + memmove(p1, p2, (end - p2) * sizeof *p1); + r->size -= len; + return c_make(_cx_iter){p2 == end ? NULL : p1, end - len}; } #if !defined _i_no_clone STC_DEF _cx_self _cx_memb(_clone)(_cx_self cx) { const size_t len = cvec_rep_(&cx)->size; - _cx_self out = _cx_memb(_with_capacity)(len); - if (cvec_rep_(&out)->cap) - _cx_memb(_clone_range_p)(&out, out.data, cx.data, cx.data + len); + _cx_self out = _cx_memb(_init)(); + _cx_memb(_copy_range)(&out, out.data, cx.data, cx.data + len); return out; } -STC_DEF _cx_value* -_cx_memb(_clone_range_p)(_cx_self* self, _cx_value* pos, - const _cx_value* p1, const _cx_value* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyclone((*p1)); +STC_DEF _cx_iter +_cx_memb(_copy_range)(_cx_self* self, _cx_value* pos, + const _cx_value* p1, const _cx_value* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyclone((*p1)); return it; } +#endif // !_i_no_clone #if !defined _i_no_emplace -STC_DEF _cx_value* -_cx_memb(_emplace_range_p)(_cx_self* self, _cx_value* pos, - const _cx_raw* p1, const _cx_raw* p2) { - pos = _cx_memb(_insert_uninit_p)(self, pos, p2 - p1); - _cx_value* it = pos; - if (pos) for (; p1 != p2; ++p1) - *pos++ = i_keyfrom((*p1)); +STC_DEF _cx_iter +_cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos, + const _cx_raw* p1, const _cx_raw* p2) { + _cx_iter it = _cx_memb(_insert_uninit)(self, pos, p2 - p1); + if (it.ref) + for (_cx_value* p = it.ref; p1 != p2; ++p1) + *p++ = i_keyfrom((*p1)); return it; } #endif // !_i_no_emplace -#endif // !_i_no_clone #if !c_option(c_no_cmp) STC_DEF _cx_iter _cx_memb(_find_in)(_cx_iter i1, _cx_iter i2, _cx_raw raw) { - for (; i1.ref != i2.ref; ++i1.ref) { + const _cx_value* p2 = _it2_ptr(i1, i2); + for (; i1.ref != p2; ++i1.ref) { const _cx_raw r = i_keyto(i1.ref); if (i_eq((&raw), (&r))) return i1; } - return i2; + i2.ref = NULL; return i2; // NB! } STC_DEF _cx_iter -_cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, _cx_iter* lower_bound) { - _cx_iter mid, last = i2; - while (i1.ref != i2.ref) { - mid.ref = i1.ref + (i2.ref - i1.ref)/2; +_cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw, + _cx_iter* lower_bound) { + const _cx_value* p2 = _it2_ptr(i1, i2); + _cx_iter mid = i1; + while (i1.ref != p2) { + mid.ref = i1.ref + (p2 - i1.ref)/2; const _cx_raw m = i_keyto(mid.ref); const int c = i_cmp((&raw), (&m)); if (!c) return *lower_bound = mid; - else if (c < 0) i2.ref = mid.ref; + else if (c < 0) p2 = mid.ref; else i1.ref = mid.ref + 1; } - *lower_bound = i1; - return last; + *lower_bound = i1.ref == i2.end ? i2 : i1; + i2.ref = NULL; return i2; // NB! } STC_DEF int diff --git a/include/stc/forward.h b/include/stc/forward.h index 04566b98..264d6939 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -57,7 +57,7 @@ typedef struct { const char* str; size_t size; } csview; typedef char csview_value; typedef union { const char *ref; - csview chr; + struct { csview chr; const char *end; } u8; } csview_iter, cstr_iter; #define c_true(...) __VA_ARGS__ @@ -68,17 +68,17 @@ typedef union { \ typedef struct { \ SELF##_value* get; \ - long* use_count; \ + catomic_long* use_count; \ } SELF #define _c_carr2_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value **data; size_t xdim, ydim; } SELF #define _c_carr3_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value ***data; size_t xdim, ydim, zdim; } SELF #define _c_cbox_types(SELF, VAL) \ @@ -89,7 +89,7 @@ typedef union { #define _c_cdeq_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct {SELF##_value *ref; } SELF##_iter; \ + typedef struct {SELF##_value *ref, *end; } SELF##_iter; \ typedef struct {SELF##_value *_base, *data;} SELF #define _c_clist_types(SELF, VAL) \ @@ -120,7 +120,7 @@ typedef union { } SELF##_result; \ \ typedef struct { \ - SELF##_value *ref; \ + SELF##_value *ref, *end; \ uint8_t* _hx; \ } SELF##_iter; \ \ @@ -186,7 +186,7 @@ typedef union { #endif #define _c_cstack_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct SELF { \ SELF##_value* data; \ size_t size, capacity; \ @@ -194,7 +194,7 @@ typedef union { #define _c_cstack_fixed(SELF, VAL, CAP) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct SELF { \ SELF##_value data[CAP]; \ size_t size; \ @@ -209,7 +209,7 @@ typedef union { #define _c_cvec_types(SELF, VAL) \ typedef VAL SELF##_value; \ - typedef struct { SELF##_value *ref; } SELF##_iter; \ + typedef struct { SELF##_value *ref, *end; } SELF##_iter; \ typedef struct { SELF##_value *data; } SELF #endif // STC_FORWARD_H_INCLUDED diff --git a/include/stc/template.h b/include/stc/template.h index cb0c7ef2..4597e02c 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -110,7 +110,8 @@ #elif defined i_key_arcbox #define i_key_bind i_key_arcbox #define i_keyraw c_paste(i_key_arcbox, _value) - #define i_keyto c_paste(i_key_arcbox, _toval) + #define i_keyfrom c_paste(i_key_arcbox, _from) + #define i_keyto(x) *(x)->get #define i_eq c_paste(i_key_arcbox, _value_eq) #endif @@ -167,7 +168,7 @@ #define i_keydrop c_default_drop #endif -// i_eq, i_less, i_cmp, i_hash +// i_eq, i_less, i_cmp #if !defined i_eq && (defined i_cmp || defined i_less) #define i_eq(x, y) !(i_cmp(x, y)) #elif !defined i_eq @@ -175,10 +176,13 @@ #endif #if !defined i_less && !defined i_cmp #define i_less c_default_less +#elif !defined i_less + #define i_less(x, y) (i_cmp(x, y)) < 0 #endif #ifndef i_cmp #define i_cmp(x, y) (i_less(y, x)) - (i_less(x, y)) #endif + #ifndef i_hash #define i_hash c_default_hash #endif @@ -197,7 +201,8 @@ #elif defined i_val_arcbox #define i_val_bind i_val_arcbox #define i_valraw c_paste(i_val_arcbox, _value) - #define i_valto c_paste(i_val_arcbox, _toval) + #define i_valfrom c_paste(i_val_arcbox, _from) + #define i_valto(x) *(x)->get #endif #ifdef i_val_bind @@ -213,6 +218,9 @@ #endif #endif +#ifndef i_val + #error "i_val* must be defined for maps" +#endif #if defined i_valraw ^ defined i_valto #error "both i_valto and i_valraw must be defined, if any" #elif defined i_valfrom && !defined i_valraw |
