summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-12-12 21:33:22 +0100
committerTyge Løvset <[email protected]>2021-12-12 21:33:22 +0100
commitd57b9bb7666753c7cf7ab5a0da6d7d11f303c2af (patch)
tree258690df4a5ab62055261579967d6dfffaf5b0fd /include
parent9cd20ebfc4f1e10153ff814085499223265ef902 (diff)
downloadSTC-modified-d57b9bb7666753c7cf7ab5a0da6d7d11f303c2af.tar.gz
STC-modified-d57b9bb7666753c7cf7ab5a0da6d7d11f303c2af.zip
- 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.
Diffstat (limited to 'include')
-rw-r--r--include/stc/cbox.h174
-rw-r--r--include/stc/ccommon.h99
-rw-r--r--include/stc/clist.h1
-rw-r--r--include/stc/csptr.h74
-rw-r--r--include/stc/csview.h4
-rw-r--r--include/stc/forward.h7
-rw-r--r--include/stc/template.h150
7 files changed, 383 insertions, 126 deletions
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 <stc/cstr.h>
+
+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 <stc/cbox.h>
+
+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 <stdlib.h>
+
+#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 <stc/csptr.h>
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 <stdlib.h>
-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