From d57b9bb7666753c7cf7ab5a0da6d7d11f303c2af Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 12 Dec 2021 21:33:22 +0100 Subject: - Added **cbox** type: container of one element: similar to std::unique_ptr / Rust Box. - Replaced example for **csptr** in docs. - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structural binding" as in c++. - Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. - Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*. - Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_ref` / `i_val_ref` when specifying containers with **csptr** or **cbox** elements. - Deprecated `i_cnt`. Use `i_type` instead to define the full container type name. - Bugfixes and docs updates. --- include/stc/cbox.h | 174 +++++++++++++++++++++++++++++++++++++++++++++++++ include/stc/ccommon.h | 99 +++++++++++++++------------- include/stc/clist.h | 1 + include/stc/csptr.h | 74 ++++++++++++++------- include/stc/csview.h | 4 +- include/stc/forward.h | 7 ++ include/stc/template.h | 150 ++++++++++++++++++++++++++---------------- 7 files changed, 383 insertions(+), 126 deletions(-) create mode 100644 include/stc/cbox.h (limited to 'include') diff --git a/include/stc/cbox.h b/include/stc/cbox.h new file mode 100644 index 00000000..445057dd --- /dev/null +++ b/include/stc/cbox.h @@ -0,0 +1,174 @@ +/* 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. + */ + +/* cbox: heap allocated boxed type +#include + +typedef struct { cstr name, last; } Person; + +Person Person_from(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} +void Person_del(Person* p) { + printf("del: %s %s\n", p->name.str, p->last.str); + c_del(cstr, &p->name, &p->last); +} + +#define i_val Person +#define i_valdel Person_del +#define i_valfrom Person_clone +#define i_opt c_no_compare // compare by .get addresses only +#define i_tag prs +#include + +int main() { + c_autovar (cbox_prs p = cbox_prs_new(Person_from("John", "Smiths")), cbox_prs_del(&p)) + c_autovar (cbox_prs q = cbox_prs_clone(p), cbox_prs_del(&q)) + { + cstr_assign(&q.get->name, "Joe"); + + printf("%s %s.\n", p.get->name.str, p.get->last.str); + printf("%s %s.\n", q.get->name.str, q.get->last.str); + } +} +*/ + +#ifndef CBOX_H_INCLUDED +#define CBOX_H_INCLUDED +#include "ccommon.h" +#include "forward.h" +#include + +#define cbox_null {NULL} +#endif // CBOX_H_INCLUDED + +#ifndef _i_prefix +#define _i_prefix cbox_ +#endif +#include "template.h" + +#if !c_option(c_is_fwd) +_cx_deftypes(_c_cbox_types, _cx_self, i_val); +#endif + +// constructors (takes ownsership) +STC_INLINE _cx_self +_cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } + +STC_INLINE _cx_self +_cx_memb(_with)(i_val* p) { return c_make(_cx_self){p}; } + +STC_INLINE _cx_self +_cx_memb(_new)(i_val val) { + return c_make(_cx_self){c_new(i_val, val)}; +} + +// destructor +STC_INLINE void +_cx_memb(_del)(_cx_self* self) { + if (self->get) { i_valdel(self->get); c_free(self->get); } +} + +STC_INLINE _cx_self +_cx_memb(_move)(_cx_self* self) { + _cx_self ptr = *self; self->get = NULL; + return ptr; +} + +STC_INLINE void +_cx_memb(_reset)(_cx_self* self) { + _cx_memb(_del)(self); self->get = NULL; +} + +// take ownership of *p +STC_INLINE void +_cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { + _cx_memb(_del)(self); self->get = p; +} + +// take ownership of val +STC_INLINE void +_cx_memb(_reset_new)(_cx_self* self, i_val val) { + if (self->get) { i_valdel(self->get); *self->get = val; } + else self->get = c_new(i_val, val); +} + +#if !c_option(c_no_clone) + STC_INLINE _cx_self + _cx_memb(_from)(i_valraw raw) { + return c_make(_cx_self){c_new(i_val, i_valfrom(raw))}; + } + + STC_INLINE void + _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) { + _cx_memb(_reset_new)(self, i_valfrom(raw)); + } + + STC_INLINE _cx_self + _cx_memb(_clone)(_cx_self other) { + if (!other.get) return other; + return c_make(_cx_self){c_new(i_val, i_valfrom(i_valto(other.get)))}; + } + + STC_INLINE void + _cx_memb(_copy)(_cx_self* self, _cx_self other) { + if (self->get == other.get) return; + if (other.get) _cx_memb(_reset_new)(self, *other.get); + else _cx_memb(_reset)(self); + } +#endif + +STC_INLINE void +_cx_memb(_take)(_cx_self* self, _cx_self other) { + if (other.get != self->get) _cx_memb(_del)(self); + *self = other; +} + +STC_INLINE uint64_t +_cx_memb(_hash)(const _cx_self* self, size_t n) { + #if c_option(c_no_compare) && SIZE_MAX >> 32 + return c_hash64(&self->get, 8); + #elif c_option(c_no_compare) + return c_hash32(&self->get, 4); + #else + i_valraw raw = i_valto(self->get); + return i_hash(&raw, sizeof raw); + #endif +} + +STC_INLINE int +_cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { + #if c_option(c_no_compare) + return (int)(x->get - y->get); + #else + i_valraw rx = i_valto(x->get); + i_valraw ry = i_valto(y->get); + return i_cmp(&rx, &ry); + #endif +} +#include "template.h" \ No newline at end of file diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 794948e6..e7775b58 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -92,60 +92,65 @@ # define c_free(p) free(p) #endif -#define c_delete(T, ptr) do { T* _p = ptr; T##_del(_p); c_free(_p); } while(0) +#define c_delete(T, ptr) do { T *_c_p = ptr; T##_del(_c_p); c_free(_c_p); } while (0) #define c_swap(T, x, y) do { T _c_t = x; x = y; y = _c_t; } while (0) #define c_arraylen(a) (sizeof (a)/sizeof (a)[0]) +#define c_less_compare(less, x, y) (less(y, x) - less(x, y)) +#define c_default_less(x, y) (*(x) < *(y)) #define c_default_compare(x, y) c_less_compare(c_default_less, x, y) -#define c_default_less(x, y) (*(x) < *(y)) #define c_default_equalto(x, y) (*(x) == *(y)) #define c_memcmp_equalto(x, y) (memcmp(x, y, sizeof *(x)) == 0) -#define c_less_compare(less, x, y) (less(y, x) - less(x, y)) #define c_rawstr_compare(x, y) strcmp(*(x), *(y)) #define c_rawstr_equalto(x, y) (strcmp(*(x), *(y)) == 0) -#define c_rawstr_hash(p, dummy) c_strhash(*(p)) +#define c_rawstr_hash(x, dummy) c_strhash(*(x)) + +#define c_default_clone(x) (x) +#define c_default_fromraw(x) (x) // [deprecated] +#define c_default_toraw(ptr) (*(ptr)) +#define c_default_del(ptr) ((void) (ptr)) #define c_option(flag) ((i_opt) & (flag)) #define c_is_fwd 1 -#define c_no_compare 2 +#define c_no_atomic 2 #define c_no_clone 4 -#define c_no_atomic 8 - -#define c_default_fromraw(x) (x) -#define c_default_toraw(ptr) (*(ptr)) -#define c_default_del(ptr) ((void) (ptr)) +#define c_no_compare 8 /* Generic algorithms */ -#define _c_rotl(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) +#define _c_ROTL(x, k) (x << (k) | x >> (8*sizeof(x) - (k))) STC_INLINE uint64_t c_strhash(const char *s) { int c; uint64_t h = *s++; if (h) while ((c = *s++)) h = (h << 10) - h + c; - return _c_rotl(h, 26) ^ h; + return _c_ROTL(h, 26) ^ h; } // len >= 1 STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { const uint8_t *x = (const uint8_t*) key; uint64_t h = *x++; while (--len) h = (h << 10) - h + *x++; - return _c_rotl(h, 26) ^ h; + return _c_ROTL(h, 26) ^ h; } #define c_hash32(data, len_is_4) \ ((*(const uint32_t*)data * 0xc6a4a7935bd1e99d) >> 15) #define c_hash64(data, len_is_8) \ (*(const uint64_t *)data * 0xc6a4a7935bd1e99d) -#define c_default_hash32 c_hash32 // [deprecated] -#define c_default_hash64 c_hash64 // [deprecated] #define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__) -#define c_foreach_3(it, CX, cnt) \ - for (CX##_iter it = CX##_begin(&cnt), it##_end_ = CX##_end(&cnt) \ - ; it.ref != it##_end_.ref; CX##_next(&it)) -#define c_foreach_4(it, CX, start, finish) \ - for (CX##_iter it = start, it##_end_ = finish \ - ; it.ref != it##_end_.ref; CX##_next(&it)) +#define c_foreach_3(it, C, cnt) \ + for (C##_iter it = C##_begin(&cnt), it##_end_ = C##_end(&cnt) \ + ; it.ref != it##_end_.ref; C##_next(&it)) +#define c_foreach_4(it, C, start, finish) \ + for (C##_iter it = start, it##_end_ = finish \ + ; it.ref != it##_end_.ref; C##_next(&it)) + +#define c_forpair(key, val, C, cnt) /* structured binding */ \ + for (struct {C##_iter _it, _end; C##_key key; C##_mapped val;} \ + _ = {C##_begin(&cnt), C##_end(&cnt)} \ + ; _._it.ref != _._end.ref && (_.key = _._it.ref->first, _.val = _._it.ref->second, true) \ + ; C##_next(&_._it)) #define c_forrange(...) c_MACRO_OVERLOAD(c_forrange, __VA_ARGS__) #define c_forrange_1(stop) for (size_t _c_ii=0, _c_end=stop; _c_ii < _c_end; ++_c_ii) @@ -156,20 +161,22 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { for (type i=start, _c_inc=step, _c_end=(stop) - (0 < _c_inc) \ ; (i <= _c_end) == (0 < _c_inc); i += _c_inc) -#define c_autoscope(init, ...) for (int _c_ii = (init, 0); !_c_ii; ++_c_ii, __VA_ARGS__) #define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__) +#define c_autoscope(init, ...) for (int _c_ii = (init, 0); !_c_ii; ++_c_ii, __VA_ARGS__) #define c_autodefer(...) for (int _c_ii = 0; !_c_ii; ++_c_ii, __VA_ARGS__) -#define c_exitauto continue #define c_auto(...) c_MACRO_OVERLOAD(c_auto, __VA_ARGS__) -#define c_auto_2(CX, a) \ - c_autovar(CX a = CX##_init(), CX##_del(&a)) -#define c_auto_3(CX, a, b) \ - c_autovar(c_EXPAND(CX a = CX##_init(), b = CX##_init()), \ - CX##_del(&b), CX##_del(&a)) -#define c_auto_4(CX, a, b, c) \ - c_autovar(c_EXPAND(CX a = CX##_init(), b = CX##_init(), c = CX##_init()), \ - CX##_del(&c), CX##_del(&b), CX##_del(&a)) +#define c_auto_2(C, a) \ + c_autovar(C a = C##_init(), C##_del(&a)) +#define c_auto_3(C, a, b) \ + c_autovar(c_EXPAND(C a = C##_init(), b = C##_init()), \ + C##_del(&b), C##_del(&a)) +#define c_auto_4(C, a, b, c) \ + c_autovar(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init()), \ + C##_del(&c), C##_del(&b), C##_del(&a)) +#define c_auto_5(C, a, b, c, d) \ + c_autovar(c_EXPAND(C a = C##_init(), b = C##_init(), c = C##_init(), d = C##_init()), \ + C##_del(&d), C##_del(&c), C##_del(&b), C##_del(&a)) #define c_autobuf(b, type, n) c_autobuf_N(b, type, n, 256) #define c_autobuf_N(b, type, n, BYTES) \ @@ -177,28 +184,28 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { *b = (n)*sizeof *b > (BYTES) ? c_alloc_n(type, n) : _c_b \ ; b; b != _c_b ? c_free(b) : (void)0, b = NULL) -#define c_apply(CX, method, cx, ...) do { \ - const CX##_rawvalue _c_arr[] = __VA_ARGS__; \ - CX* _c_cx = cx; \ +#define c_apply(C, method, cx, ...) do { \ + const C##_rawvalue _c_arr[] = __VA_ARGS__; \ + C* _c_cx = cx; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ - CX##_##method(_c_cx, _c_arr[_c_i]); \ + C##_##method(_c_cx, _c_arr[_c_i]); \ } while (0) -#define c_apply_pair(CX, method, cx, ...) do { \ - const CX##_rawvalue _c_arr[] = __VA_ARGS__; \ - CX* _c_cx = cx; \ +#define c_apply_pair(C, method, cx, ...) do { \ + const C##_rawvalue _c_arr[] = __VA_ARGS__; \ + C* _c_cx = cx; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ - CX##_##method(_c_cx, _c_arr[_c_i].first, _c_arr[_c_i].second); \ + C##_##method(_c_cx, _c_arr[_c_i].first, _c_arr[_c_i].second); \ } while (0) -#define c_apply_n(CX, method, cx, arr, n) do { \ - CX* _c_cx = cx; \ - for (const CX##_rawvalue *_c_i = arr, *_c_end = _c_i+(n); _c_i != _c_end; ++_c_i) \ - CX##_##method(_c_cx, *_c_i); \ +#define c_apply_n(C, method, cx, arr, n) do { \ + C* _c_cx = cx; \ + for (const C##_rawvalue *_c_i = arr, *_c_end = _c_i+(n); _c_i != _c_end; ++_c_i) \ + C##_##method(_c_cx, *_c_i); \ } while (0) -#define c_del(CX, ...) do { \ - CX* _c_arr[] = {__VA_ARGS__}; \ +#define c_del(C, ...) do { \ + C* _c_arr[] = {__VA_ARGS__}; \ for (size_t _c_i = 0; _c_i < c_arraylen(_c_arr); ++_c_i) \ - CX##_del(_c_arr[_c_i]); \ + C##_del(_c_arr[_c_i]); \ } while (0) #if defined(__SIZEOF_INT128__) diff --git a/include/stc/clist.h b/include/stc/clist.h index bb090a62..7cd2df50 100644 --- a/include/stc/clist.h +++ b/include/stc/clist.h @@ -125,6 +125,7 @@ _cx_memb(_copy)(_cx_self *self, _cx_self other) { } #endif STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL}; } +STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, size_t n) { return true; } STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.last == NULL; } STC_INLINE size_t _cx_memb(_count)(_cx_self cx) { return _clist_count((const clist_VOID*) &cx); } diff --git a/include/stc/csptr.h b/include/stc/csptr.h index a8496654..06790e01 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -26,7 +26,7 @@ typedef struct { cstr name, last; } Person; -Person Person_init(const char* name, const char* last) { +Person Person_from(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } void Person_del(Person* p) { @@ -40,7 +40,7 @@ void Person_del(Person* p) { #include int main() { - csptr_person p = csptr_person_make(Person_init("John", "Smiths")); + csptr_person p = csptr_person_new(Person_from("John", "Smiths")); csptr_person q = csptr_person_clone(p); // share the pointer printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count); @@ -54,7 +54,6 @@ int main() { #include "forward.h" #include -typedef long atomic_count_t; #if defined(__GNUC__) || defined(__clang__) #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) @@ -75,10 +74,9 @@ typedef long atomic_count_t; #ifndef _i_prefix #define _i_prefix csptr_ #endif -#define i_valfrom _not_to_be_used_ +#define _i_has_internal_clone #include "template.h" - #if !c_option(c_no_atomic) #define _i_atomic_inc(v) c_atomic_inc(v) #define _i_atomic_dec_and_test(v) c_atomic_dec_and_test(v) @@ -89,30 +87,38 @@ typedef long atomic_count_t; #if !c_option(c_is_fwd) _cx_deftypes(_c_csptr_types, _cx_self, i_val); #endif -_cx_csptr_rep { atomic_count_t counter; _cx_value value; }; +_cx_csptr_rep { long counter; i_val value; }; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } -STC_INLINE atomic_count_t +STC_INLINE long _cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } STC_INLINE _cx_self -_cx_memb(_from)(_cx_value* p) { +_cx_memb(_with)(_cx_value* p) { _cx_self ptr = {p}; - if (p) *(ptr.use_count = c_alloc(atomic_count_t)) = 1; + if (p) *(ptr.use_count = c_alloc(long)) = 1; + return ptr; +} + +STC_INLINE _cx_self +_cx_memb(_view)(const _cx_value* p) { + _cx_self ptr = {(_cx_value*) p}; return ptr; } STC_INLINE _cx_self -_cx_memb(_make)(_cx_value val) { +_cx_memb(_new)(i_val val) { _cx_self ptr; _cx_csptr_rep *rep = c_alloc(_cx_csptr_rep); *(ptr.use_count = &rep->counter) = 1; *(ptr.get = &rep->value) = val; return ptr; } +STC_INLINE _cx_self _cx_memb(_make)(i_val val) // [deprecated] + { return _cx_memb(_new)(val); } -STC_INLINE _cx_self +STC_INLINE _cx_self // does not use i_valfrom, so we can bypass c_no_clone _cx_memb(_clone)(_cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); return ptr; @@ -142,17 +148,29 @@ _cx_memb(_reset)(_cx_self* self) { } STC_INLINE void -_cx_memb(_reset_from)(_cx_self* self, _cx_value* p) { +_cx_memb(_reset_with)(_cx_self* self, _cx_value* p) { _cx_memb(_del)(self); - *self = _cx_memb(_from)(p); + *self = _cx_memb(_with)(p); } STC_INLINE void -_cx_memb(_reset_with)(_cx_self* self, _cx_value val) { +_cx_memb(_reset_new)(_cx_self* self, i_val val) { _cx_memb(_del)(self); - *self = _cx_memb(_make)(val); + *self = _cx_memb(_new)(val); } +#if !c_option(c_no_clone) + STC_INLINE _cx_self _cx_memb(_from)(i_valraw raw) { + return _cx_memb(_new)(i_valfrom(raw)); + } + + STC_INLINE void + _cx_memb(_reset_from)(_cx_self* self, i_valraw raw) { + _cx_memb(_del)(self); + *self = _cx_memb(_new)(i_valfrom(raw)); + } +#endif + STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); @@ -165,16 +183,28 @@ _cx_memb(_take)(_cx_self* self, _cx_self ptr) { *self = ptr; } -#if !c_option(c_no_compare) +STC_INLINE uint64_t +_cx_memb(_hash)(const _cx_self* self, size_t n) { + #if c_option(c_no_compare) && SIZE_MAX >> 32 + return c_hash64(&self->get, 8); + #elif c_option(c_no_compare) + return c_hash32(&self->get, 4); + #else + i_valraw raw = i_valto(self->get); + return i_hash(&raw, sizeof raw); + #endif +} + STC_INLINE int _cx_memb(_compare)(const _cx_self* x, const _cx_self* y) { -#ifdef _i_cmp_default - return c_default_compare(&x->get, &y->get); -#else - return i_cmp(x->get, y->get); -#endif + #if c_option(c_no_compare) + return (int)(x->get - y->get); + #else + i_valraw rx = i_valto(x->get); + i_valraw ry = i_valto(y->get); + return i_cmp(&rx, &ry); + #endif } -#endif #undef _i_atomic_inc #undef _i_atomic_dec_and_test #include "template.h" \ No newline at end of file diff --git a/include/stc/csview.h b/include/stc/csview.h index 87707d84..ce08bd1a 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -31,8 +31,8 @@ typedef char csview_value; #define csview_null c_make(csview){"", 0} #define csview_npos cstr_npos -#define csview_ARG(sv) (int)(sv).size, (sv).str - +#define c_svfmt "%.*s" +#define c_svarg(sv) (int)(sv).size, (sv).str #define c_sv(literal) csview_lit(literal) #define cstr_sv(s) csview_from_s(s) diff --git a/include/stc/forward.h b/include/stc/forward.h index 11a32550..bf2ba698 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -33,6 +33,7 @@ #define forward_csmap(CX, KEY, VAL) _c_aatree_types(CX, KEY, VAL, c_true, c_false) #define forward_cset(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, c_false, c_true) #define forward_csset(CX, KEY) _c_aatree_types(CX, KEY, KEY, c_false, c_true) +#define forward_cbox(CX, VAL) _c_cbox_types(CX, VAL) #define forward_csptr(CX, VAL) _c_csptr_types(CX, VAL) #define forward_cpque(CX, VAL) _c_cpque_types(CX, VAL) #define forward_cstack(CX, VAL) _c_cstack_types(CX, VAL) @@ -125,6 +126,12 @@ SELF##_node *nodes; \ } SELF +#define _c_cbox_types(SELF, VAL) \ + typedef VAL SELF##_value; \ + typedef struct { \ + SELF##_value* get; \ + } SELF + #define _c_csptr_types(SELF, VAL) \ typedef VAL SELF##_value; \ \ diff --git a/include/stc/template.h b/include/stc/template.h index b8f6dfc4..757f9443 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -41,63 +41,98 @@ #endif #if defined i_valraw && !(defined i_valto && defined i_valfrom) - #error if i_valraw or i_valto defined, i_valfrom must be defined + #error "if i_valraw or i_valto defined, i_valfrom must be defined" #endif #if defined i_keyraw && !(defined i_keyto && defined i_keyfrom) - #error if i_keyraw or i_keyto defined, i_keyfrom a must be defined + #error "if i_keyraw or i_keyto defined, i_keyfrom a must be defined" #endif - -#if defined i_key_str || defined i_val_str - #include "cstr.h" +#ifdef i_key_csptr // [deprecated] + #define i_key_ref i_key_csptr + #error "i_key_csptr no longer supported: use new name i_key_ref" +#endif +#ifdef i_val_csptr // [deprecated] + #define i_val_ref i_val_csptr + #error "i_val_csptr no longer supported: use new name i_val_ref" +#endif +#ifdef i_cnt // [deprecated] + #define i_type i_cnt + #error "i_cnt no longer supported: use new name i_type" #endif -#ifdef i_cnt - #define i_tag i_cnt +#ifdef i_type + #define i_tag i_type #undef _i_prefix #define _i_prefix #endif -#ifdef i_key_csptr - #define i_key i_key_csptr - #define i_cmp c_PASTE(i_key_csptr, _compare) - #define i_keydel c_PASTE(i_key_csptr, _del) - #define i_keyfrom c_PASTE(i_key_csptr, _clone) +#if defined i_key_str || defined i_val_str + #include "cstr.h" #endif -#ifdef i_key_str - #define i_key cstr +#if defined i_key_ref + #define i_key i_key_ref + #define i_keyfrom c_PASTE(i_key, _clone) #ifndef i_tag - #define i_tag str + #define i_tag ref + #endif + #ifndef i_cmp + #define i_cmp c_PASTE(i_key, _compare) #endif - #define i_cmp c_rawstr_compare - #define i_hash c_rawstr_hash - #define i_keydel cstr_del + #ifndef i_hash + #define i_hash c_PASTE(i_key, _hash) + #endif + #ifndef i_keydel + #define i_keydel c_PASTE(i_key, _del) + #endif + +#elif defined i_key_str + + #define i_key cstr #define i_keyfrom cstr_from - #define i_keyto cstr_str - #define i_keyraw const char* + #define i_keyto cstr_str + #define i_keyraw const char* + #ifndef i_tag + #define i_tag str + #endif + #ifndef i_cmp + #define i_cmp c_rawstr_compare + #endif + #ifndef i_hash + #define i_hash c_rawstr_hash + #endif + #if !defined i_keydel + #define i_keydel cstr_del + #endif #endif -#ifdef i_val_csptr - #define i_val i_val_csptr - #ifndef i_key - #define i_cmp c_PASTE(i_val_csptr, _compare) +#if defined i_val_ref + #define i_val i_val_ref + #define i_valfrom c_PASTE(i_val, _clone) + #if !defined i_tag && !defined i_key + #define i_tag ref #endif - #define i_valdel c_PASTE(i_val_csptr, _del) - #define i_valfrom c_PASTE(i_val_csptr, _clone) -#endif + #if !defined i_cmp && !defined i_key + #define i_cmp c_PASTE(i_val, _compare) + #endif + #if !defined i_valdel && !defined i_del + #define i_valdel c_PASTE(i_val, _del) + #endif + +#elif defined i_val_str -#ifdef i_val_str #define i_val cstr + #define i_valfrom cstr_from + #define i_valto cstr_str + #define i_valraw const char* #if !defined i_tag && !defined i_key #define i_tag str #endif - #ifndef i_key + #if !defined i_cmp && !defined 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* + #if !defined i_valdel && !defined i_del + #define i_valdel cstr_del + #endif #endif #if defined i_del && defined i_isset @@ -105,14 +140,14 @@ #elif defined i_del && !defined i_key #define i_valdel i_del #elif defined i_del - #error i_del not supported for maps, define i_keydel / i_valdel instead. + #error "i_del not supported for maps, define i_keydel / i_valdel instead." #endif #if defined i_from && defined i_isset #define i_keyfrom i_from #elif defined i_from && !defined i_key #define i_valfrom i_from #elif defined i_from - #error i_from not supported for maps, define i_keyfrom / i_valfrom instead. + #error "i_from not supported for maps, define i_keyfrom / i_valfrom instead." #endif #ifdef i_key @@ -122,10 +157,11 @@ #ifndef i_tag #define i_tag i_key #endif - #if defined i_keydel && !defined i_keyfrom && !c_option(c_no_clone) - #error i_keydel defined requires defining i_keyfrom or '#define i_opt c_no_clone' - #elif !defined i_keyfrom - #define i_keyfrom c_default_fromraw + #if !defined _i_has_internal_clone && defined i_keydel && !defined i_keyfrom && !c_option(c_no_clone) + #error "i_keydel defined but not i_keyfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" + #endif + #if !defined i_keyfrom + #define i_keyfrom c_default_clone #endif #ifndef i_keyraw #define i_keyraw i_key @@ -136,23 +172,21 @@ #elif !defined i_equ #define i_equ c_default_equalto #endif - #ifndef i_hash - #define i_hash c_default_hash - #endif #ifndef i_keydel #define i_keydel c_default_del #endif -#elif defined _i_isset || defined i_hash || defined i_equ - #error i_key define is missing. +#elif defined _i_isset + #error "i_key define is missing." #endif #ifndef i_tag #define i_tag i_val #endif -#if defined i_valdel && !defined i_valfrom && !c_option(c_no_clone) - #error i_del/i_valdel defined: requires also defining i_valfrom or '#define i_opt c_no_clone' -#elif !defined i_valfrom - #define i_valfrom c_default_fromraw +#if !defined _i_has_internal_clone && defined i_valdel && !defined i_valfrom && !c_option(c_no_clone) + #error "i_valdel/i_del defined but not i_valfrom (e.g. as c_default_clone), or no 'i_opt c_no_clone'" +#endif +#if !defined i_valfrom + #define i_valfrom c_default_clone #endif #ifndef i_valraw #define i_valraw i_val @@ -163,12 +197,14 @@ #endif #ifndef i_cmp #define i_cmp c_default_compare - #define _i_cmp_default +#endif +#ifndef i_hash + #define i_hash c_default_hash #endif #else // ------------------------------------------------------- -#undef i_cnt +#undef i_type #undef i_tag #undef i_imp #undef i_opt @@ -176,23 +212,25 @@ #undef i_del #undef i_equ #undef i_hash +#undef i_from + #undef i_val #undef i_val_str +#undef i_val_ref #undef i_valdel +#undef i_valraw #undef i_valfrom -#undef i_from #undef i_valto -#undef i_valraw + #undef i_key #undef i_key_str +#undef i_key_ref #undef i_keydel +#undef i_keyraw #undef i_keyfrom #undef i_keyto -#undef i_keyraw -#undef i_key_csptr -#undef i_val_csptr #undef _i_prefix -#undef _i_cmp_default +#undef _i_has_internal_clone #undef _i_template #endif -- cgit v1.2.3