summaryrefslogtreecommitdiffhomepage
path: root/misc/archived
diff options
context:
space:
mode:
Diffstat (limited to 'misc/archived')
-rw-r--r--misc/archived/carr2.h152
-rw-r--r--misc/archived/carr3.h157
-rw-r--r--misc/archived/csmap.h512
-rw-r--r--misc/archived/cstr.h384
-rw-r--r--misc/archived/new_arr.c57
5 files changed, 1262 insertions, 0 deletions
diff --git a/misc/archived/carr2.h b/misc/archived/carr2.h
new file mode 100644
index 00000000..aebaec81
--- /dev/null
+++ b/misc/archived/carr2.h
@@ -0,0 +1,152 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 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.
+ */
+#include <stc/ccommon.h>
+
+#ifndef CARR2_H_INCLUDED
+#define CARR2_H_INCLUDED
+#include <stc/forward.h>
+#include <stdlib.h>
+#endif
+/*
+// carr2- 2D dynamic array in one memory block with easy indexing.
+#define i_key int
+#include <stc/carr2.h>
+#include <stdio.h>
+
+int main() {
+ int w = 7, h = 5;
+ 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)
+ dat[i] = i;
+
+ for (int x = 0; x < image.xdim; ++x)
+ for (int y = 0; y < image.ydim; ++y)
+ printf(" %d", image.data[x][y]);
+ puts("\n");
+
+ c_foreach (i, carr2_int, image)
+ printf(" %d", *i.ref);
+ puts("");
+ }
+}
+*/
+
+#ifndef _i_prefix
+#define _i_prefix carr2_
+#endif
+#include <stc/priv/template.h>
+#if !c_option(c_is_forward)
+_cx_deftypes(_c_carr2_types, _cx_self, i_key);
+#endif
+
+STC_API _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, i_key null);
+STC_API _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, _cx_value* storage);
+STC_API _cx_value* _cx_memb(_release)(_cx_self* self);
+STC_API void _cx_memb(_drop)(_cx_self* self);
+#if !defined i_no_clone
+STC_API _cx_self _cx_memb(_clone)(_cx_self src);
+STC_API void _cx_memb(_copy)(_cx_self *self, const _cx_self* other);
+#endif
+
+STC_INLINE _cx_self _cx_memb(_new_uninit)(size_t xdim, size_t ydim) {
+ return _cx_memb(_with_data)(xdim, ydim, c_alloc_n(_cx_value, xdim*ydim));
+}
+STC_INLINE size_t _cx_memb(_size)(const _cx_self* self)
+ { return self->xdim*self->ydim; }
+
+STC_INLINE _cx_value *_cx_memb(_data)(_cx_self* self)
+ { return *self->data; }
+
+STC_INLINE const _cx_value *_cx_memb(_at)(const _cx_self* self, size_t x, size_t y) {
+ assert(x < self->xdim && y < self->ydim);
+ return *self->data + self->ydim*x + y;
+}
+
+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) {
+ size_t n = self->xdim*self->ydim;
+ return c_INIT(_cx_iter){n ? *self->data : NULL, *self->data + n};
+}
+
+STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self)
+ { return c_INIT(_cx_iter){NULL, *self->data + self->xdim*self->ydim}; }
+
+STC_INLINE void _cx_memb(_next)(_cx_iter* it)
+ { if (++it->ref == it->end) it->ref = NULL; }
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+STC_DEF _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, _cx_value* block) {
+ _cx_self _arr = {c_alloc_n(_cx_value*, xdim), xdim, ydim};
+ for (size_t x = 0; x < xdim; ++x, block += ydim)
+ _arr.data[x] = block;
+ return _arr;
+}
+
+STC_DEF _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, i_key null) {
+ _cx_self _arr = _cx_memb(_new_uninit)(xdim, ydim);
+ for (_cx_value* p = _arr.data[0], *e = p + xdim*ydim; p != e; ++p)
+ *p = null;
+ return _arr;
+}
+
+#if !defined i_no_clone
+
+STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) {
+ _cx_self _arr = _cx_memb(_new_uninit)(src.xdim, src.ydim);
+ for (_cx_value* p = _arr.data[0], *q = src.data[0], *e = p + _cx_memb(_size)(&src); p != e; ++p, ++q)
+ *p = i_keyclone((*q));
+ return _arr;
+}
+
+STC_DEF 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);
+}
+#endif
+
+STC_DEF _cx_value *_cx_memb(_release)(_cx_self* self) {
+ _cx_value *values = self->data[0];
+ c_free(self->data);
+ self->data = NULL;
+ return values;
+}
+
+STC_DEF void _cx_memb(_drop)(_cx_self* self) {
+ if (!self->data) return;
+ for (_cx_value* p = self->data[0], *q = p + _cx_memb(_size)(self); p != q; ) {
+ --q; i_keydrop(q);
+ }
+ c_free(self->data[0]); /* values */
+ c_free(self->data); /* pointers */
+}
+
+#endif
+#include <stc/priv/template.h>
diff --git a/misc/archived/carr3.h b/misc/archived/carr3.h
new file mode 100644
index 00000000..a0148992
--- /dev/null
+++ b/misc/archived/carr3.h
@@ -0,0 +1,157 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 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.
+ */
+#include <stc/ccommon.h>
+
+#ifndef CARR3_H_INCLUDED
+#define CARR3_H_INCLUDED
+#include <stc/forward.h>
+#include <stdlib.h>
+#endif
+/*
+// carr3 - 3D dynamic array in one memory block with easy indexing.
+#define i_key int
+#include <stc/carr3.h>
+#include <stdio.h>
+
+int main() {
+ int w = 7, h = 5, d = 3;
+ 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)
+ dat[i] = i;
+
+ for (int x = 0; x < image.xdim; ++x)
+ for (int y = 0; y < image.ydim; ++y)
+ for (int z = 0; z < image.zdim; ++z)
+ printf(" %d", image.data[x][y][z]);
+ puts("\n");
+
+ c_foreach (i, carr3_int, image)
+ printf(" %d", *i.ref);
+ puts("");
+ }
+}
+*/
+
+#ifndef _i_prefix
+#define _i_prefix carr3_
+#endif
+#include <stc/priv/template.h>
+
+#if !c_option(c_is_forward)
+_cx_deftypes(_c_carr3_types, _cx_self, i_key);
+#endif
+
+STC_API _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, size_t zdim, i_key null);
+STC_API _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, size_t zdim, _cx_value* storage);
+STC_API _cx_value* _cx_memb(_release)(_cx_self* self);
+STC_API void _cx_memb(_drop)(_cx_self* self);
+#if !defined i_no_clone
+STC_API _cx_self _cx_memb(_clone)(_cx_self src);
+STC_API void _cx_memb(_copy)(_cx_self *self, const _cx_self* other);
+#endif
+
+STC_INLINE _cx_self _cx_memb(_new_uninit)(size_t xdim, size_t ydim, size_t zdim) {
+ return _cx_memb(_with_data)(xdim, ydim, zdim, c_alloc_n(_cx_value, xdim*ydim*zdim));
+}
+
+STC_INLINE size_t _cx_memb(_size)(const _cx_self* self)
+ { return self->xdim*self->ydim*self->zdim; }
+
+STC_INLINE _cx_value* _cx_memb(_data)(_cx_self* self)
+ { return **self->data; }
+
+STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, size_t x, size_t y, size_t z) {
+ assert(x < self->xdim && y < self->ydim && z < self->zdim);
+ return **self->data + self->zdim*(self->ydim*x + y) + z;
+}
+
+STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y, size_t z) {
+ return self->zdim*(self->ydim*x + y) + z;
+}
+
+
+STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) {
+ size_t n = _cx_memb(_size)(self);
+ return c_INIT(_cx_iter){n ? **self->data : NULL, **self->data + n};
+}
+
+STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self)
+ { return c_INIT(_cx_iter){NULL, **self->data + _cx_memb(_size)(self)}; }
+
+STC_INLINE void _cx_memb(_next)(_cx_iter* it)
+ { if (++it->ref == it->end) it->ref = NULL; }
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+STC_DEF _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, size_t zdim, _cx_value* block) {
+ _cx_self _arr = {c_alloc_n(_cx_value**, xdim*(ydim + 1)), xdim, ydim, zdim};
+ _cx_value** p = (_cx_value**) &_arr.data[xdim];
+ for (size_t x = 0, y; x < xdim; ++x, p += ydim)
+ for (y = 0, _arr.data[x] = p; y < ydim; ++y, block += zdim)
+ p[y] = block;
+ return _arr;
+}
+
+STC_DEF _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, size_t zdim, i_key null) {
+ _cx_self _arr = _cx_memb(_new_uninit)(xdim, ydim, zdim);
+ for (_cx_value* p = **_arr.data, *e = p + xdim*ydim*zdim; p != e; ++p)
+ *p = null;
+ return _arr;
+}
+
+#if !defined i_no_clone
+
+STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) {
+ _cx_self _arr = _cx_memb(_new_uninit)(src.xdim, src.ydim, src.zdim);
+ for (_cx_value* p = **_arr.data, *q = **src.data, *e = p + _cx_memb(_size)(&src); p != e; ++p, ++q)
+ *p = i_keyclone((*q));
+ return _arr;
+}
+
+STC_DEF 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);
+}
+#endif
+
+STC_DEF _cx_value* _cx_memb(_release)(_cx_self* self) {
+ _cx_value *values = self->data[0][0];
+ c_free(self->data);
+ self->data = NULL;
+ return values;
+}
+
+STC_DEF void _cx_memb(_drop)(_cx_self* self) {
+ if (!self->data) return;
+ for (_cx_value* p = **self->data, *q = p + _cx_memb(_size)(self); p != q; ) {
+ --q; i_keydrop(q);
+ }
+ c_free(self->data[0][0]); /* data */
+ c_free(self->data); /* pointers */
+}
+
+#endif
+#include <stc/priv/template.h>
diff --git a/misc/archived/csmap.h b/misc/archived/csmap.h
new file mode 100644
index 00000000..4b4e764c
--- /dev/null
+++ b/misc/archived/csmap.h
@@ -0,0 +1,512 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 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.
+ */
+
+// Sorted/Ordered set and map - implemented as an AA-tree.
+/*
+#include <stdio.h>
+#include <stc/cstr.h>
+
+#define i_tag sx // Sorted map<cstr, double>
+#define i_key_str
+#define i_val double
+#include <stc/csmap.h>
+
+int main(void) {
+ 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);
+ csmap_sx_emplace(&m, "Testing three", 123.4);
+
+ csmap_sx_value *v = csmap_sx_get(&m, "Testing five"); // NULL
+ double num = *csmap_sx_at(&m, "Testing one");
+ csmap_sx_emplace_or_assign(&m, "Testing three", 1000.0); // update
+ csmap_sx_erase(&m, "Testing two");
+
+ c_foreach (i, csmap_sx, m)
+ printf("map %s: %g\n", cstr_str(&i.ref->first), i.ref->second);
+ }
+}
+*/
+#include <stc/ccommon.h>
+
+#ifndef CSMAP_H_INCLUDED
+#define STC_CSMAP_V1 1
+#include <stc/forward.h>
+#include <stdlib.h>
+#include <string.h>
+#endif // CSMAP_H_INCLUDED
+
+#ifndef _i_prefix
+#define _i_prefix csmap_
+#endif
+#ifdef _i_isset
+ #define _i_MAP_ONLY c_false
+ #define _i_SET_ONLY c_true
+ #define _i_keyref(vp) (vp)
+#else
+ #define _i_ismap
+ #define _i_MAP_ONLY c_true
+ #define _i_SET_ONLY c_false
+ #define _i_keyref(vp) (&(vp)->first)
+#endif
+#include <stc/priv/template.h>
+
+#if !c_option(c_is_forward)
+_cx_deftypes(_c_aatree_types, _cx_self, i_key, i_val, i_size, _i_MAP_ONLY, _i_SET_ONLY);
+#endif
+
+_i_MAP_ONLY( struct _cx_value {
+ _cx_key first;
+ _cx_mapped second;
+}; )
+struct _cx_node {
+ struct _cx_node *link[2];
+ uint8_t level;
+ _cx_value value;
+};
+
+typedef i_keyraw _cx_rawkey;
+typedef i_valraw _cx_memb(_rawmapped);
+typedef _i_SET_ONLY( i_keyraw )
+ _i_MAP_ONLY( struct { i_keyraw first; i_valraw second; } )
+ _cx_raw;
+
+#if !defined i_no_clone
+STC_API _cx_self _cx_memb(_clone)(_cx_self cx);
+#if !defined i_no_emplace
+STC_API _cx_result _cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped));
+#endif // !i_no_emplace
+#endif // !i_no_clone
+STC_API _cx_self _cx_memb(_init)(void);
+STC_API _cx_result _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped));
+STC_API _cx_result _cx_memb(_push)(_cx_self* self, _cx_value _val);
+STC_API void _cx_memb(_drop)(_cx_self* self);
+STC_API _cx_value* _cx_memb(_find_it)(const _cx_self* self, i_keyraw rkey, _cx_iter* out);
+STC_API _cx_iter _cx_memb(_lower_bound)(const _cx_self* self, i_keyraw rkey);
+STC_API _cx_value* _cx_memb(_front)(const _cx_self* self);
+STC_API _cx_value* _cx_memb(_back)(const _cx_self* self);
+STC_API int _cx_memb(_erase)(_cx_self* self, i_keyraw rkey);
+STC_API _cx_iter _cx_memb(_erase_at)(_cx_self* self, _cx_iter it);
+STC_API _cx_iter _cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2);
+STC_API void _cx_memb(_next)(_cx_iter* it);
+
+STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.size == 0; }
+STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cx.size; }
+STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) { c_swap(_cx_self, *a, *b); }
+STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_keyraw rkey)
+ { _cx_iter it; _cx_memb(_find_it)(self, rkey, &it); return it; }
+STC_INLINE bool _cx_memb(_contains)(const _cx_self* self, i_keyraw rkey)
+ { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it) != NULL; }
+STC_INLINE const _cx_value* _cx_memb(_get)(const _cx_self* self, i_keyraw rkey)
+ { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); }
+STC_INLINE _cx_value* _cx_memb(_get_mut)(_cx_self* self, i_keyraw rkey)
+ { _cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); }
+
+STC_INLINE void
+_cx_memb(_clear)(_cx_self* self)
+ { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); }
+
+STC_INLINE _cx_raw
+_cx_memb(_value_toraw)(_cx_value* val) {
+ return _i_SET_ONLY( i_keyto(val) )
+ _i_MAP_ONLY( c_INIT(_cx_raw){i_keyto((&val->first)),
+ i_valto((&val->second))} );
+}
+
+STC_INLINE int
+_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
+ _cx_rawkey rx = i_keyto(_i_keyref(x)), ry = i_keyto(_i_keyref(y));
+ return i_cmp((&rx), (&ry));
+}
+
+STC_INLINE void
+_cx_memb(_value_drop)(_cx_value* val) {
+ i_keydrop(_i_keyref(val));
+ _i_MAP_ONLY( i_valdrop((&val->second)); )
+}
+
+#if !defined i_no_clone
+STC_INLINE _cx_value
+_cx_memb(_value_clone)(_cx_value _val) {
+ *_i_keyref(&_val) = i_keyclone((*_i_keyref(&_val)));
+ _i_MAP_ONLY( _val.second = i_valclone(_val.second); )
+ return _val;
+}
+
+STC_INLINE void
+_cx_memb(_copy)(_cx_self *self, const _cx_self* other) {
+ if (self->root == other->root)
+ return;
+ _cx_memb(_drop)(self);
+ *self = _cx_memb(_clone)(*other);
+}
+#endif // !i_no_clone
+
+#ifndef _i_isset
+ #if !defined i_no_clone && !defined i_no_emplace
+ STC_API _cx_result _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped);
+ #endif
+ STC_API _cx_result _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped);
+
+ STC_INLINE const _cx_mapped*
+ _cx_memb(_at)(const _cx_self* self, i_keyraw rkey)
+ { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; }
+ STC_INLINE _cx_mapped*
+ _cx_memb(_at_mut)(_cx_self* self, i_keyraw rkey)
+ { _cx_iter it; return &_cx_memb(_find_it)(self, rkey, &it)->second; }
+#endif // !_i_isset
+
+STC_INLINE _cx_iter
+_cx_memb(_begin)(const _cx_self* self) {
+ _cx_iter it;
+ it.ref = NULL, it._top = 0, it._tn = self->root;
+ _cx_memb(_next)(&it);
+ return it;
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_end)(const _cx_self* self) {
+ (void)self;
+ _cx_iter it; it.ref = NULL, it._top = 0, it._tn = NULL;
+ return it;
+}
+
+STC_INLINE _cx_iter
+_cx_memb(_advance)(_cx_iter it, size_t n) {
+ while (n-- && it.ref)
+ _cx_memb(_next)(&it);
+ return it;
+}
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+#ifndef CSMAP_H_INCLUDED
+static struct { void *link[2]; uint8_t level; }
+_csmap_sentinel = {{&_csmap_sentinel, &_csmap_sentinel}, 0};
+#endif
+
+static _cx_result _cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey);
+
+STC_DEF _cx_self
+_cx_memb(_init)(void) {
+ _cx_self cx = {(_cx_node *)&_csmap_sentinel, 0};
+ return cx;
+}
+
+STC_DEF _cx_value*
+_cx_memb(_front)(const _cx_self* self) {
+ _cx_node *tn = self->root;
+ while (tn->link[0]->level)
+ tn = tn->link[0];
+ return &tn->value;
+}
+
+STC_DEF _cx_value*
+_cx_memb(_back)(const _cx_self* self) {
+ _cx_node *tn = self->root;
+ while (tn->link[1]->level)
+ tn = tn->link[1];
+ return &tn->value;
+}
+
+STC_DEF _cx_result
+_cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)) {
+ _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto((&key)));
+ if (res.inserted)
+ { *_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )}
+ else
+ { i_keydrop((&key)); _i_MAP_ONLY( i_valdrop((&mapped)); )}
+ return res;
+}
+
+STC_DEF _cx_result
+_cx_memb(_push)(_cx_self* self, _cx_value _val) {
+ _cx_result _res = _cx_memb(_insert_entry_)(self, i_keyto(_i_keyref(&_val)));
+ if (_res.inserted)
+ *_res.ref = _val;
+ else
+ _cx_memb(_value_drop)(&_val);
+ return _res;
+}
+
+#ifndef _i_isset
+ STC_DEF _cx_result
+ _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped) {
+ _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto((&key)));
+ if (res.inserted)
+ res.ref->first = key;
+ else
+ { i_keydrop((&key)); i_valdrop((&res.ref->second)); }
+ res.ref->second = mapped;
+ return res;
+ }
+ #if !defined i_no_clone && !defined i_no_emplace
+ STC_DEF _cx_result
+ _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) {
+ _cx_result res = _cx_memb(_insert_entry_)(self, rkey);
+ if (res.inserted)
+ res.ref->first = i_keyfrom(rkey);
+ else
+ { i_valdrop((&res.ref->second)); }
+ res.ref->second = i_valfrom(rmapped);
+ return res;
+ }
+ #endif // !i_no_clone && !i_no_emplace
+#endif // !_i_isset
+
+STC_DEF _cx_value*
+_cx_memb(_find_it)(const _cx_self* self, _cx_rawkey rkey, _cx_iter* out) {
+ _cx_node *tn = self->root;
+ out->_top = 0;
+ while (tn->level) {
+ int c; _cx_rawkey raw = i_keyto(_i_keyref(&tn->value));
+ if ((c = i_cmp((&raw), (&rkey))) < 0)
+ tn = tn->link[1];
+ else if (c > 0)
+ { out->_st[out->_top++] = tn; tn = tn->link[0]; }
+ else
+ { out->_tn = tn->link[1]; return (out->ref = &tn->value); }
+ }
+ return (out->ref = NULL);
+}
+
+STC_DEF _cx_iter
+_cx_memb(_lower_bound)(const _cx_self* self, i_keyraw rkey) {
+ _cx_iter it;
+ _cx_memb(_find_it)(self, rkey, &it);
+ if (!it.ref && it._top) {
+ _cx_node *tn = it._st[--it._top];
+ it._tn = tn->link[1];
+ it.ref = &tn->value;
+ }
+ return it;
+}
+
+STC_DEF void
+_cx_memb(_next)(_cx_iter *it) {
+ _cx_node *tn = it->_tn;
+ if (it->_top || tn->level) {
+ while (tn->level) {
+ it->_st[it->_top++] = tn;
+ tn = tn->link[0];
+ }
+ tn = it->_st[--it->_top];
+ it->_tn = tn->link[1];
+ it->ref = &tn->value;
+ } else
+ it->ref = NULL;
+}
+
+static _cx_node *
+_cx_memb(_skew_)(_cx_node *tn) {
+ if (tn && tn->link[0]->level == tn->level && tn->level) {
+ _cx_node *tmp = tn->link[0];
+ tn->link[0] = tmp->link[1];
+ tmp->link[1] = tn;
+ tn = tmp;
+ }
+ return tn;
+}
+
+static _cx_node *
+_cx_memb(_split_)(_cx_node *tn) {
+ if (tn->link[1]->link[1]->level == tn->level && tn->level) {
+ _cx_node *tmp = tn->link[1];
+ tn->link[1] = tmp->link[0];
+ tmp->link[0] = tn;
+ tn = tmp;
+ ++tn->level;
+ }
+ return tn;
+}
+
+static _cx_node*
+_cx_memb(_insert_entry_i_)(_cx_node* tn, const _cx_rawkey* rkey, _cx_result* res) {
+ _cx_node *up[64], *tx = tn;
+ int c, top = 0, dir = 0;
+ while (tx->level) {
+ up[top++] = tx;
+ _cx_rawkey r = i_keyto(_i_keyref(&tx->value));
+ if (!(c = (i_cmp((&r), rkey))))
+ { res->ref = &tx->value; return tn; }
+ dir = (c < 0);
+ tx = tx->link[dir];
+ }
+ tn = c_alloc(_cx_node);
+ tn->link[0] = tn->link[1] = (_cx_node*)&_csmap_sentinel;
+ tn->level = 1;
+ res->ref = &tn->value, res->inserted = true;
+ if (top == 0)
+ return tn;
+ up[top - 1]->link[dir] = tn;
+ while (top--) {
+ if (top)
+ dir = (up[top - 1]->link[1] == up[top]);
+ up[top] = _cx_memb(_skew_)(up[top]);
+ up[top] = _cx_memb(_split_)(up[top]);
+ if (top)
+ up[top - 1]->link[dir] = up[top];
+ }
+ return up[0];
+}
+
+STC_DEF _cx_result
+_cx_memb(_insert_entry_)(_cx_self* self, i_keyraw rkey) {
+ _cx_result res = {NULL};
+ self->root = _cx_memb(_insert_entry_i_)(self->root, &rkey, &res);
+ self->size += res.inserted;
+ return res;
+}
+
+static _cx_node*
+_cx_memb(_erase_r_)(_cx_node *tn, const _cx_rawkey* rkey, int *erased) {
+ if (tn->level == 0)
+ return tn;
+ _cx_rawkey raw = i_keyto(_i_keyref(&tn->value));
+ _cx_node *tx; int c = (i_cmp((&raw), rkey));
+ if (c != 0)
+ tn->link[c < 0] = _cx_memb(_erase_r_)(tn->link[c < 0], rkey, erased);
+ else {
+ if (!*erased)
+ { _cx_memb(_value_drop)(&tn->value); *erased = 1; }
+ if (tn->link[0]->level && tn->link[1]->level) {
+ tx = tn->link[0];
+ while (tx->link[1]->level)
+ tx = tx->link[1];
+ tn->value = tx->value;
+ raw = i_keyto(_i_keyref(&tn->value));
+ tn->link[0] = _cx_memb(_erase_r_)(tn->link[0], &raw, erased);
+ } else { /* unlink node */
+ tx = tn;
+ tn = tn->link[tn->link[0]->level == 0];
+ c_free(tx);
+ }
+ }
+ if (tn->link[0]->level < tn->level - 1 || tn->link[1]->level < tn->level - 1) {
+ if (tn->link[1]->level > --tn->level)
+ tn->link[1]->level = tn->level;
+ tn = _cx_memb(_skew_)(tn);
+ tx = tn->link[0] = _cx_memb(_skew_)(tn->link[0]);
+ tx->link[0] = _cx_memb(_skew_)(tx->link[0]);
+ tn = _cx_memb(_split_)(tn);
+ tn->link[0] = _cx_memb(_split_)(tn->link[0]);
+ }
+ return tn;
+}
+
+STC_DEF int
+_cx_memb(_erase)(_cx_self* self, i_keyraw rkey) {
+ int erased = 0;
+ self->root = _cx_memb(_erase_r_)(self->root, &rkey, &erased);
+ self->size -= erased;
+ return erased;
+}
+
+STC_DEF _cx_iter
+_cx_memb(_erase_at)(_cx_self* self, _cx_iter it) {
+ _cx_rawkey raw = i_keyto(_i_keyref(it.ref)), nxt;
+ _cx_memb(_next)(&it);
+ if (it.ref)
+ nxt = i_keyto(_i_keyref(it.ref));
+ _cx_memb(_erase)(self, raw);
+ if (it.ref)
+ _cx_memb(_find_it)(self, nxt, &it);
+ return it;
+}
+
+STC_DEF _cx_iter
+_cx_memb(_erase_range)(_cx_self* self, _cx_iter it1, _cx_iter it2) {
+ if (!it2.ref) {
+ while (it1.ref)
+ it1 = _cx_memb(_erase_at)(self, it1);
+ return it1;
+ }
+ _cx_key k1 = *_i_keyref(it1.ref), k2 = *_i_keyref(it2.ref);
+ _cx_rawkey r1 = i_keyto((&k1));
+ for (;;) {
+ if (memcmp(&k1, &k2, sizeof k1) == 0)
+ return it1;
+ _cx_memb(_next)(&it1);
+ k1 = *_i_keyref(it1.ref);
+ _cx_memb(_erase)(self, r1);
+ r1 = i_keyto((&k1));
+ _cx_memb(_find_it)(self, r1, &it1);
+ }
+}
+
+#if !defined i_no_clone
+static _cx_node*
+_cx_memb(_clone_r_)(_cx_node *tn) {
+ if (! tn->level)
+ return tn;
+ _cx_node *cn = c_alloc(_cx_node);
+ cn->level = tn->level;
+ cn->value = _cx_memb(_value_clone)(tn->value);
+ cn->link[0] = _cx_memb(_clone_r_)(tn->link[0]);
+ cn->link[1] = _cx_memb(_clone_r_)(tn->link[1]);
+ return cn;
+}
+
+STC_DEF _cx_self
+_cx_memb(_clone)(_cx_self cx) {
+ return c_INIT(_cx_self){_cx_memb(_clone_r_)(cx.root), cx.size};
+}
+#endif // !i_no_clone
+
+#if !defined i_no_emplace
+STC_DEF _cx_result
+_cx_memb(_emplace)(_cx_self* self, i_keyraw rkey _i_MAP_ONLY(, i_valraw rmapped)) {
+ _cx_result res = _cx_memb(_insert_entry_)(self, rkey);
+ if (res.inserted) {
+ *_i_keyref(res.ref) = i_keyfrom(rkey);
+ _i_MAP_ONLY(res.ref->second = i_valfrom(rmapped);)
+ }
+ return res;
+}
+#endif // i_no_emplace
+
+static void
+_cx_memb(_drop_r_)(_cx_node* tn) {
+ if (tn->level != 0) {
+ _cx_memb(_drop_r_)(tn->link[0]);
+ _cx_memb(_drop_r_)(tn->link[1]);
+ _cx_memb(_value_drop)(&tn->value);
+ c_free(tn);
+ }
+}
+
+STC_DEF void
+_cx_memb(_drop)(_cx_self* self) {
+ _cx_memb(_drop_r_)(self->root);
+}
+
+#endif // i_implement
+#undef _i_isset
+#undef _i_ismap
+#undef _i_keyref
+#undef _i_MAP_ONLY
+#undef _i_SET_ONLY
+#define CSMAP_H_INCLUDED
+#include <stc/priv/template.h>
diff --git a/misc/archived/cstr.h b/misc/archived/cstr.h
new file mode 100644
index 00000000..8de6c4b0
--- /dev/null
+++ b/misc/archived/cstr.h
@@ -0,0 +1,384 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef CSTR_H_INCLUDED
+#define CSTR_H_INCLUDED
+
+#include <stc/ccommon.h>
+#include <stc/forward.h>
+#include <stdlib.h> /* malloc */
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h> /* vsnprintf */
+#include <ctype.h>
+
+#define c_unchecked_container_of(ptr, type, member) \
+ ((type*)((char*)(ptr) - offsetof(type, member)))
+
+typedef char cstr_value;
+typedef struct { cstr_value* str; } cstr;
+typedef struct { size_t size, cap; char chr[1]; } cstr_priv;
+#define _cstr_p(self) c_unchecked_container_of((self)->str, cstr_priv, chr)
+#ifdef i_static
+ static cstr_priv _cstr_nullrep = {0, 0, {0}};
+ static const cstr cstr_NULL = {_cstr_nullrep.chr};
+#else
+ extern const cstr cstr_NULL;
+#endif
+/* optimal memory: based on malloc_usable_size() sequence: 24, 40, 56, ... */
+#define _cstr_opt_mem(cap) ((((offsetof(cstr_priv, chr) + (cap) + 8)>>4)<<4) + 8)
+/* optimal string capacity: 7, 23, 39, ... */
+#define _cstr_opt_cap(cap) (_cstr_opt_mem(cap) - offsetof(cstr_priv, chr) - 1)
+
+STC_API cstr cstr_from_n(const char* str, size_t n);
+STC_API cstr cstr_from_fmt(const char* fmt, ...);
+STC_API char* cstr_reserve(cstr* self, size_t cap);
+STC_API void cstr_resize(cstr* self, size_t len, char fill);
+STC_API cstr* cstr_assign_n(cstr* self, const char* str, size_t n);
+STC_API int cstr_printf(cstr* self, const char* fmt, ...);
+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(cstr* self, size_t pos, size_t n);
+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; }
+STC_INLINE const char* cstr_str(const cstr* self) { return self->str; }
+#define cstr_toraw(self) (self)->str
+STC_INLINE csview cstr_sv(const cstr* self)
+ { return c_INIT(csview){self->str, _cstr_p(self)->size}; }
+#define cstr_lit(literal) \
+ cstr_from_n(literal, c_strlen_lit(literal))
+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(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)
+ { if (_cstr_p(self)->cap) c_free(_cstr_p(self)); }
+STC_INLINE cstr cstr_clone(cstr s)
+ { return cstr_from_n(s.str, _cstr_p(&s)->size); }
+STC_INLINE void cstr_clear(cstr* self)
+ { self->str[_cstr_p(self)->size = 0] = '\0'; }
+STC_INLINE cstr* cstr_assign(cstr* self, const char* str)
+ { return cstr_assign_n(self, str, strlen(str)); }
+STC_INLINE cstr* cstr_copy(cstr* self, cstr s)
+ { return cstr_assign_n(self, s.str, _cstr_p(&s)->size); }
+STC_INLINE cstr* cstr_append(cstr* self, const char* str)
+ { return cstr_append_n(self, str, strlen(str)); }
+STC_INLINE cstr* cstr_append_s(cstr* self, cstr s)
+ { return cstr_append_n(self, s.str, _cstr_p(&s)->size); }
+STC_INLINE void cstr_push_back(cstr* self, char value)
+ { cstr_append_n(self, &value, 1); }
+STC_INLINE void cstr_pop_back(cstr* self)
+ { self->str[ --_cstr_p(self)->size ] = '\0'; }
+STC_INLINE void cstr_insert_n(cstr* self, const size_t pos, const char* str, const size_t n)
+ { cstr_replace_at_sv(self, pos, 0, c_SV(str, n)); }
+STC_INLINE void cstr_insert(cstr* self, const size_t pos, const char* str)
+ { cstr_replace_at_sv(self, pos, 0, c_SV(str, strlen(str))); }
+STC_INLINE void cstr_insert_s(cstr* self, const size_t pos, cstr s)
+ { cstr_replace_at_sv(self, pos, 0, c_SV(s.str, _cstr_p(&s)->size)); }
+STC_INLINE void cstr_replace_at(cstr* self, const size_t pos, const size_t len, const char* str)
+ { cstr_replace_at_sv(self, pos, len, c_SV(str, strlen(str))); }
+STC_INLINE void cstr_replace_s(cstr* self, const size_t pos, const size_t len, cstr s)
+ { cstr_replace_at_sv(self, pos, len, c_SV(s.str, _cstr_p(&s)->size)); }
+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(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); }
+
+STC_INLINE cstr_buf cstr_buffer(cstr* s) {
+ cstr_priv* p = _cstr_p(s);
+ return c_INIT(cstr_buf){s->str, p->size, p->cap};
+}
+
+STC_INLINE cstr cstr_with_capacity(const size_t cap) {
+ cstr s = cstr_NULL;
+ cstr_reserve(&s, cap);
+ return s;
+}
+
+STC_INLINE cstr cstr_with_size(const size_t len, const char fill) {
+ cstr s = cstr_NULL;
+ cstr_resize(&s, len, fill);
+ return s;
+}
+
+STC_INLINE char* cstr_append_uninit(cstr *self, size_t n) {
+ 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;
+}
+
+STC_INLINE cstr* cstr_take(cstr* self, cstr s) {
+ if (self->str != s.str && _cstr_p(self)->cap)
+ c_free(_cstr_p(self));
+ self->str = s.str;
+ return self;
+}
+
+STC_INLINE cstr cstr_move(cstr* self) {
+ cstr tmp = *self;
+ *self = cstr_NULL;
+ return tmp;
+}
+
+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(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) {
+ int ret = 0;
+ while (nmax-- && (ret = tolower(*s1++) - tolower(*s2)) == 0 && *s2++)
+ ;
+ return ret;
+}
+
+/* container adaptor functions: */
+#define cstr_cmp(xp, yp) strcmp((xp)->str, (yp)->str)
+
+STC_INLINE bool cstr_eq(const cstr* x, const cstr* y) {
+ size_t xs = _cstr_p(x)->size, ys = _cstr_p(y)->size;
+ return xs == ys && !memcmp(x->str, y->str, xs);
+}
+STC_INLINE uint64_t cstr_hash(const cstr *self) {
+ return cfasthash(self->str, _cstr_p(self)->size);
+}
+
+STC_INLINE void cstr_replace_ex(cstr* self, const char* find, const char* repl, unsigned count) {
+ cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(find, strlen(find)),
+ c_SV(repl, strlen(repl)), count));
+}
+STC_INLINE void cstr_replace(cstr* self, const char* search, const char* repl)
+ { cstr_replace_ex(self, search, repl, ~0U); }
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+#if defined(i_implement)
+
+#ifndef i_static
+static cstr_priv _cstr_nullrep = {0, 0, {0}};
+const cstr cstr_NULL = {_cstr_nullrep.chr};
+#endif
+
+STC_DEF char*
+cstr_reserve(cstr* self, const size_t cap) {
+ cstr_priv *p = _cstr_p(self);
+ const size_t oldcap = p->cap;
+ if (cap > oldcap) {
+ p = (cstr_priv*) c_realloc(((oldcap != 0) & (p != &_cstr_nullrep)) ? p : NULL, _cstr_opt_mem(cap));
+ if (!p) return NULL;
+ self->str = p->chr;
+ if (oldcap == 0) self->str[p->size = 0] = '\0';
+ p->cap = _cstr_opt_cap(cap);
+ }
+ return self->str;
+}
+
+STC_DEF void
+cstr_resize(cstr* self, const size_t len, const char fill) {
+ const size_t n = _cstr_p(self)->size;
+ cstr_reserve(self, len);
+ if (len > n) memset(self->str + n, fill, len - n);
+ if (len | n) self->str[_cstr_p(self)->size = len] = '\0';
+}
+
+STC_DEF cstr
+cstr_from_n(const char* str, const size_t n) {
+ if (n == 0) return cstr_NULL;
+ cstr_priv* prv = (cstr_priv*) c_malloc(_cstr_opt_mem(n));
+ cstr s = {(char *) memcpy(prv->chr, str, n)};
+ s.str[prv->size = n] = '\0';
+ prv->cap = _cstr_opt_cap(n);
+ return s;
+}
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif
+
+STC_DEF int
+cstr_vfmt(cstr* self, const char* fmt, va_list args) {
+ va_list args2;
+ va_copy(args2, args);
+ int len = vsnprintf(NULL, (size_t)0, fmt, args);
+ cstr_reserve(self, len);
+ vsprintf(self->str, fmt, args2);
+ va_end(args2);
+ return _cstr_p(self)->size = len;
+}
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(_MSC_VER)
+# pragma warning(pop)
+#endif
+
+STC_DEF cstr
+cstr_from_fmt(const char* fmt, ...) {
+ cstr ret = cstr_NULL;
+ va_list args; va_start(args, fmt);
+ cstr_vfmt(&ret, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+STC_DEF int
+cstr_printf(cstr* self, const char* fmt, ...) {
+ cstr ret = cstr_NULL;
+ va_list args;
+ va_start(args, fmt);
+ int n = cstr_vfmt(&ret, fmt, args);
+ va_end(args);
+ cstr_drop(self);
+ *self = ret;
+ return n;
+}
+
+STC_DEF cstr*
+cstr_assign_n(cstr* self, const char* str, const size_t n) {
+ if (n || _cstr_p(self)->cap) {
+ cstr_reserve(self, n);
+ memmove(self->str, str, n);
+ self->str[_cstr_p(self)->size = n] = '\0';
+ }
+ return self;
+}
+
+STC_DEF cstr*
+cstr_append_n(cstr* self, const char* str, const size_t n) {
+ if (n == 0) return self;
+ const size_t oldlen = _cstr_p(self)->size, newlen = oldlen + n;
+ if (newlen > _cstr_p(self)->cap) {
+ const size_t off = (size_t) (str - self->str); /* handle self append */
+ cstr_reserve(self, (oldlen*3 >> 1) + n);
+ if (off <= oldlen) str = self->str + off;
+ }
+ memcpy(&self->str[oldlen], str, n);
+ self->str[_cstr_p(self)->size = newlen] = '\0';
+ return self;
+}
+
+STC_INLINE void _cstr_internal_move(cstr* self, const size_t pos1, const size_t pos2) {
+ if (pos1 == pos2)
+ return;
+ const size_t len = _cstr_p(self)->size, newlen = len + pos2 - pos1;
+ if (newlen > _cstr_p(self)->cap)
+ cstr_reserve(self, (len*3 >> 1) + pos2 - pos1);
+ memmove(&self->str[pos2], &self->str[pos1], len - pos1);
+ self->str[_cstr_p(self)->size = newlen] = '\0';
+}
+
+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);
+ if (len > sz - pos) len = sz - pos;
+ char buf[256], *xstr = repl.size > 256 ? c_malloc(repl.size) : buf;
+ memcpy(xstr, repl.str, repl.size);
+ _cstr_internal_move(self, pos + len, pos + repl.size);
+ memcpy(&self->str[pos], xstr, repl.size);
+ if (repl.size > 256) c_free(xstr);
+}
+
+STC_DEF cstr
+cstr_replace_sv(csview str, csview find, csview repl, unsigned count) {
+ cstr out = cstr_NULL;
+ size_t from = 0; char* res;
+ if (find.size)
+ while (count-- && (res = cstrnstrn(str.str + from, find.str, str.size - from, find.size))) {
+ const size_t pos = res - str.str;
+ cstr_append_n(&out, str.str + from, pos - from);
+ cstr_append_n(&out, repl.str, repl.size);
+ from = pos + find.size;
+ }
+ cstr_append_n(&out, str.str + from, str.size - from);
+ return out;
+}
+
+STC_DEF void
+cstr_erase(cstr* self, const size_t pos, size_t n) {
+ const size_t len = _cstr_p(self)->size;
+ if (n > len - pos) n = len - pos;
+ if (len) {
+ memmove(&self->str[pos], &self->str[pos + n], len - (pos + n));
+ self->str[_cstr_p(self)->size -= n] = '\0';
+ }
+}
+
+STC_DEF bool
+cstr_getdelim(cstr *self, const int delim, FILE *fp) {
+ size_t pos = 0, cap = _cstr_p(self)->cap;
+ char* d = self->str;
+ int c = fgetc(fp);
+ if (c == EOF)
+ return false;
+ for (;;) {
+ if (c == delim || c == EOF) {
+ if (cap) d[_cstr_p(self)->size = pos] = '\0';
+ return true;
+ }
+ if (pos == cap) {
+ d = cstr_reserve(self, (cap*3 >> 1) + 16);
+ cap = cstr_capacity(*self);
+ }
+ d[pos++] = (char) c;
+ c = fgetc(fp);
+ }
+}
+
+STC_DEF size_t
+cstr_find(const cstr* self, const char* needle) {
+ char* res = strstr(self->str, needle);
+ return res ? res - self->str : c_NPOS;
+}
+
+STC_DEF size_t
+cstr_find_at(const cstr* self, const size_t pos, const char* needle) {
+ if (pos > _cstr_p(self)->size) return c_NPOS;
+ char* res = strstr(self->str + pos, needle);
+ return res ? res - self->str : c_NPOS;
+}
+
+#endif
+#endif // CSTR_H_INCLUDED
+#undef i_opt
diff --git a/misc/archived/new_arr.c b/misc/archived/new_arr.c
new file mode 100644
index 00000000..1006439d
--- /dev/null
+++ b/misc/archived/new_arr.c
@@ -0,0 +1,57 @@
+#include <stc/cstr.h>
+
+#define i_val int
+#include "carr2.h"
+
+#define i_val int
+#include "carr3.h"
+
+#define i_val_str
+#include "carr2.h"
+
+int main()
+{
+ int w = 7, h = 5, d = 3;
+
+ c_WITH (carr2_int volume = carr2_int_new_uninit(w, h), carr2_int_drop(&volume))
+ {
+ int *dat = carr2_int_data(&volume);
+ for (size_t i = 0; i < carr2_int_size(&volume); ++i)
+ dat[i] = i;
+
+ for (size_t x = 0; x < volume.xdim; ++x)
+ for (size_t y = 0; y < volume.ydim; ++y)
+ printf(" %d", volume.data[x][y]);
+ puts("");
+
+ c_FOREACH (i, carr2_int, volume)
+ printf(" %d", *i.ref);
+ puts("\n");
+ }
+
+ c_WITH (carr3_int volume = carr3_int_new_uninit(w, h, d), carr3_int_drop(&volume))
+ {
+ int *dat = carr3_int_data(&volume);
+ for (size_t i = 0; i < carr3_int_size(&volume); ++i)
+ dat[i] = i;
+
+ for (size_t x = 0; x < volume.xdim; ++x)
+ for (size_t y = 0; y < volume.ydim; ++y)
+ for (size_t z = 0; z < volume.zdim; ++z)
+ printf(" %d", volume.data[x][y][z]);
+ puts("");
+
+ c_FOREACH (i, carr3_int, volume)
+ printf(" %d", *i.ref);
+ puts("");
+ }
+
+ c_WITH (carr2_str text2d = carr2_str_with_size(h, d, cstr_NULL), carr2_str_drop(&text2d))
+ {
+ cstr_assign(&text2d.data[2][1], "hello");
+ cstr_assign(&text2d.data[4][0], "world");
+
+ c_FOREACH (i, carr2_str, text2d)
+ printf("line: %s\n", cstr_str(i.ref));
+ }
+}