summaryrefslogtreecommitdiffhomepage
path: root/misc
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-02-04 23:35:56 +0100
committerGitHub <[email protected]>2023-02-04 23:35:56 +0100
commitadc47cefc2976768c3f0b773bd26bfd1062e8a53 (patch)
tree4923f88afb0d091d5d39ae03d65a4998a0517652 /misc
parent0c4c4f8bba17562735b67b2923cd23c773aa53a7 (diff)
parentd2ff84c53aa9bd3857fdf22dcf7cd9398a4780be (diff)
downloadSTC-modified-adc47cefc2976768c3f0b773bd26bfd1062e8a53.tar.gz
STC-modified-adc47cefc2976768c3f0b773bd26bfd1062e8a53.zip
Merge pull request #46 from tylov/newinit
Version 4.1 RC2: signed sizes and indices, cspan with numpy slicing.
Diffstat (limited to 'misc')
-rw-r--r--misc/archived/csmap.h511
-rw-r--r--misc/archived/cstr.h384
-rw-r--r--misc/archived/new_arr.c57
-rw-r--r--misc/benchmarks/build_all.sh2
-rw-r--r--misc/examples/astar.c4
-rw-r--r--misc/examples/birthday.c6
-rw-r--r--misc/examples/bits.c12
-rw-r--r--misc/examples/bits2.c4
-rw-r--r--misc/examples/books.c2
-rw-r--r--misc/examples/box.c2
-rw-r--r--misc/examples/city.c2
-rw-r--r--misc/examples/complex.c2
-rw-r--r--misc/examples/csmap_erase.c6
-rw-r--r--misc/examples/csmap_find.c2
-rw-r--r--misc/examples/cstr_match.c6
-rw-r--r--misc/examples/demos.c12
-rw-r--r--misc/examples/forfilter.c30
-rw-r--r--misc/examples/forloops.c10
-rw-r--r--misc/examples/functor.c2
-rw-r--r--misc/examples/gauss1.c4
-rw-r--r--misc/examples/gauss2.c4
-rwxr-xr-xmisc/examples/make.sh12
-rw-r--r--misc/examples/multidim.c103
-rw-r--r--misc/examples/music_arc.c2
-rw-r--r--misc/examples/new_map.c17
-rw-r--r--misc/examples/new_pque.c2
-rw-r--r--misc/examples/new_queue.c10
-rw-r--r--misc/examples/new_sptr.c2
-rw-r--r--misc/examples/person_arc.c2
-rw-r--r--misc/examples/prime.c23
-rw-r--r--misc/examples/printspan.c47
-rw-r--r--misc/examples/priority.c6
-rw-r--r--misc/examples/queue.c6
-rw-r--r--misc/examples/random.c18
-rw-r--r--misc/examples/rawptr_elements.c2
-rw-r--r--misc/examples/regex1.c2
-rw-r--r--misc/examples/regex2.c2
-rw-r--r--misc/examples/regex_match.c5
-rw-r--r--misc/examples/regex_replace.c6
-rw-r--r--misc/examples/shape.c14
-rw-r--r--misc/examples/sort.c8
-rw-r--r--misc/examples/splitstr.c2
-rw-r--r--misc/examples/sso_map.c2
-rw-r--r--misc/examples/sso_substr.c4
-rw-r--r--misc/examples/stack.c2
-rw-r--r--misc/examples/sview_split.c2
-rw-r--r--misc/examples/utf8replace_c.c7
-rw-r--r--misc/examples/vikings.c4
-rw-r--r--misc/tests/cregex_test.c336
-rw-r--r--misc/tests/cspan_test.c125
-rw-r--r--misc/tests/ctest.h575
-rw-r--r--misc/tests/main.c31
-rw-r--r--misc/tests/mytests.c.txt233
53 files changed, 1369 insertions, 1307 deletions
diff --git a/misc/archived/csmap.h b/misc/archived/csmap.h
deleted file mode 100644
index 5c9fba6b..00000000
--- a/misc/archived/csmap.h
+++ /dev/null
@@ -1,511 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2023 Tyge Løvset
- *
- * 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 _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
deleted file mode 100644
index e074b6e4..00000000
--- a/misc/archived/cstr.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2023 Tyge Løvset
- *
- * 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, crawstr_len(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
deleted file mode 100644
index 1006439d..00000000
--- a/misc/archived/new_arr.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#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));
- }
-}
diff --git a/misc/benchmarks/build_all.sh b/misc/benchmarks/build_all.sh
index 54340998..869559ba 100644
--- a/misc/benchmarks/build_all.sh
+++ b/misc/benchmarks/build_all.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-cc='g++ -I../../include -s -O3 -Wall -pedantic -x c++ -std=c++20'
+cc='g++ -I../../include -s -O3 -Wall -pedantic -x c++ -std=c++2a'
#cc='clang++ -I../include -s -O3 -Wall -pedantic -x c++ -std=c++20'
#cc='cl -nologo -I../include -O2 -TP -EHsc -std:c++20'
run=0
diff --git a/misc/examples/astar.c b/misc/examples/astar.c
index 828de8ce..ddc9de3a 100644
--- a/misc/examples/astar.c
+++ b/misc/examples/astar.c
@@ -37,7 +37,7 @@ point_equal(const point* a, const point* b)
point
point_from(const cstr* maze, const char* c, int width)
{
- int index = cstr_find(maze, c);
+ int index = (int)cstr_find(maze, c);
return point_init(index % width, index / width, width);
}
@@ -156,7 +156,7 @@ main(void)
"# # # # # # #\n"
"#########################################################################\n"), cstr_drop(&maze))
{
- int width = cstr_find(&maze, "\n") + 1;
+ int width = (int)cstr_find(&maze, "\n") + 1;
c_WITH (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path))
{
c_FOREACH (it, cdeq_point, path)
diff --git a/misc/examples/birthday.c b/misc/examples/birthday.c
index be7f0457..fb887cd7 100644
--- a/misc/examples/birthday.c
+++ b/misc/examples/birthday.c
@@ -50,19 +50,19 @@ void test_distribution(void)
uint64_t sum = 0;
c_FOREACH (i, cmap_x, map) sum += i.ref->second;
- sum /= map.size;
+ sum /= (uint64_t)map.size;
c_FOREACH (i, cmap_x, map) {
printf("%4" PRIu32 ": %" PRIu64 " - %" PRIu64 ": %11.8f\n",
i.ref->first, i.ref->second, sum,
- (1 - (double)i.ref->second / sum));
+ (1.0 - (double)i.ref->second / (double)sum));
}
}
}
int main()
{
- seed = time(NULL);
+ seed = (uint64_t)time(NULL);
test_distribution();
test_repeats();
}
diff --git a/misc/examples/bits.c b/misc/examples/bits.c
index c50eac6e..03b74881 100644
--- a/misc/examples/bits.c
+++ b/misc/examples/bits.c
@@ -4,18 +4,18 @@
int main()
{
c_WITH (cbits set = cbits_with_size(23, true), cbits_drop(&set)) {
- printf("count %" c_ZU ", %" c_ZU "\n", cbits_count(&set), cbits_size(&set));
+ printf("count %" c_ZI ", %" c_ZI "\n", cbits_count(&set), cbits_size(&set));
cbits s1 = cbits_from("1110100110111");
char buf[256];
cbits_to_str(&s1, buf, 0, 255);
- printf("buf: %s: %" c_ZU "\n", buf, cbits_count(&s1));
+ printf("buf: %s: %" c_ZI "\n", buf, cbits_count(&s1));
cbits_drop(&s1);
cbits_reset(&set, 9);
cbits_resize(&set, 43, false);
printf(" str: %s\n", cbits_to_str(&set, buf, 0, 255));
- printf("%4" c_ZU ": ", cbits_size(&set));
+ printf("%4" c_ZI ": ", cbits_size(&set));
c_FORRANGE (i, cbits_size(&set))
printf("%d", cbits_test(&set, i));
puts("");
@@ -25,12 +25,12 @@ int main()
cbits_resize(&set, 93, false);
cbits_resize(&set, 102, true);
cbits_set_value(&set, 99, false);
- printf("%4" c_ZU ": ", cbits_size(&set));
+ printf("%4" c_ZI ": ", cbits_size(&set));
c_FORRANGE (i, cbits_size(&set))
printf("%d", cbits_test(&set, i));
puts("\nIterate:");
- printf("%4" c_ZU ": ", cbits_size(&set));
+ printf("%4" c_ZI ": ", cbits_size(&set));
c_FORRANGE (i, cbits_size(&set))
printf("%d", cbits_test(&set, i));
puts("");
@@ -52,7 +52,7 @@ int main()
puts("");
cbits_set_all(&set, false);
- printf("%4" c_ZU ": ", cbits_size(&set));
+ printf("%4" c_ZI ": ", cbits_size(&set));
c_FORRANGE (i, cbits_size(&set))
printf("%d", cbits_test(&set, i));
puts("");
diff --git a/misc/examples/bits2.c b/misc/examples/bits2.c
index 502e7268..9b1d1af7 100644
--- a/misc/examples/bits2.c
+++ b/misc/examples/bits2.c
@@ -9,10 +9,10 @@ int main()
{
Bits s1 = Bits_from("1110100110111");
- printf("size %" c_ZU "\n", Bits_size(&s1));
+ printf("size %" c_ZI "\n", Bits_size(&s1));
char buf[256];
Bits_to_str(&s1, buf, 0, 256);
- printf("buf: %s: count=%" c_ZU "\n", buf, Bits_count(&s1));
+ printf("buf: %s: count=%" c_ZI "\n", buf, Bits_count(&s1));
Bits_reset(&s1, 8);
printf(" s1: %s\n", Bits_to_str(&s1, buf, 0, 256));
diff --git a/misc/examples/books.c b/misc/examples/books.c
index 96c7ff6e..4695941a 100644
--- a/misc/examples/books.c
+++ b/misc/examples/books.c
@@ -32,7 +32,7 @@ int main()
// When collections store owned values (String), they can still be
// queried using references (&str).
if (cmap_str_contains(&book_reviews, "Les Misérables")) {
- printf("We've got %" c_ZU " reviews, but Les Misérables ain't one.",
+ printf("We've got %" c_ZI " reviews, but Les Misérables ain't one.",
cmap_str_size(&book_reviews));
}
diff --git a/misc/examples/box.c b/misc/examples/box.c
index 446a7603..3a7a8139 100644
--- a/misc/examples/box.c
+++ b/misc/examples/box.c
@@ -24,7 +24,7 @@ Person Person_clone(Person p) {
void Person_drop(Person* p) {
printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last));
- c_DROP(cstr, &p->name, &p->last);
+ c_drop(cstr, &p->name, &p->last);
}
#define i_type PBox
diff --git a/misc/examples/city.c b/misc/examples/city.c
index 7f355bdf..e24c90de 100644
--- a/misc/examples/city.c
+++ b/misc/examples/city.c
@@ -44,7 +44,7 @@ City City_clone(City c) {
void City_drop(City* c) {
printf("drop %s\n", cstr_str(&c->name));
- c_DROP(cstr, &c->name, &c->country);
+ c_drop(cstr, &c->name, &c->country);
}
diff --git a/misc/examples/complex.c b/misc/examples/complex.c
index 6fed1d4d..5c212554 100644
--- a/misc/examples/complex.c
+++ b/misc/examples/complex.c
@@ -37,7 +37,7 @@ int main()
// Put in some data in the structures
stack.data[3] = 3.1415927f;
- printf("stack size: %" c_ZU "\n", FloatStack_size(&stack));
+ printf("stack size: %" c_ZI "\n", FloatStack_size(&stack));
StackList list = StackList_init();
StackList_push_back(&list, stack);
diff --git a/misc/examples/csmap_erase.c b/misc/examples/csmap_erase.c
index bef00a17..a41a1ad1 100644
--- a/misc/examples/csmap_erase.c
+++ b/misc/examples/csmap_erase.c
@@ -12,7 +12,7 @@ void printmap(mymap m)
{
c_FOREACH (elem, mymap, m)
printf(" [%d, %s]", elem.ref->first, cstr_str(&elem.ref->second));
- printf("\nsize() == %" c_ZU "\n\n", mymap_size(&m));
+ printf("\nsize() == %" c_ZI "\n\n", mymap_size(&m));
}
int main()
@@ -75,9 +75,9 @@ int main()
puts("Starting data of map m3 is:");
printmap(m3);
// The 3rd member function removes elements with a given Key
- size_t count = mymap_erase(&m3, 2);
+ int count = mymap_erase(&m3, 2);
// The 3rd member function also returns the number of elements removed
- printf("The number of elements removed from m3 is: %" c_ZU "\n", count);
+ printf("The number of elements removed from m3 is: %d\n", count);
puts("After the element with a key of 2 is deleted, the map m3 is:");
printmap(m3);
}
diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c
index a61a47be..201c94e9 100644
--- a/misc/examples/csmap_find.c
+++ b/misc/examples/csmap_find.c
@@ -18,7 +18,7 @@ void print_elem(csmap_istr_raw p) {
#define using_print_collection(CX) \
void print_collection_##CX(const CX* t) { \
- printf("%" c_ZU " elements: ", CX##_size(t)); \
+ printf("%" c_ZI " elements: ", CX##_size(t)); \
\
c_FOREACH (p, CX, *t) { \
print_elem(CX##_value_toraw(p.ref)); \
diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c
index 116e5dd4..bfb0df6b 100644
--- a/misc/examples/cstr_match.c
+++ b/misc/examples/cstr_match.c
@@ -5,8 +5,8 @@
int main()
{
c_WITH (cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) {
- size_t pos = cstr_find_at(&ss, 0, "brown");
- printf("%" c_ZU " [%s]\n", pos, pos == c_NPOS ? "<NULL>" : cstr_str(&ss) + pos);
+ intptr_t pos = cstr_find_at(&ss, 0, "brown");
+ printf("%" c_ZI " [%s]\n", pos, pos == c_NPOS ? "<NULL>" : cstr_str(&ss) + pos);
printf("equals: %d\n", cstr_equals(&ss, "The quick brown fox jumps over the lazy dog.JPG"));
printf("contains: %d\n", cstr_contains(&ss, "umps ove"));
printf("starts_with: %d\n", cstr_starts_with(&ss, "The quick brown"));
@@ -16,7 +16,7 @@ int main()
cstr s1 = cstr_lit("hell😀 w😀rl🐨");
csview ch1 = cstr_u8_chr(&s1, 7);
csview ch2 = cstr_u8_chr(&s1, 10);
- printf("%s\nsize: %" c_ZU ", %" c_ZU "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1));
+ printf("%s\nsize: %" c_ZI ", %" c_ZI "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1));
printf("ch1: %.*s\n", c_ARGSV(ch1));
printf("ch2: %.*s\n", c_ARGSV(ch2));
}
diff --git a/misc/examples/demos.c b/misc/examples/demos.c
index 4455b840..7070d860 100644
--- a/misc/examples/demos.c
+++ b/misc/examples/demos.c
@@ -13,7 +13,7 @@ void stringdemo1()
cstr_erase(&cs, 7, 5); // -nine
printf("%s.\n", cstr_str(&cs));
- cstr_replace_ex(&cs, "seven", "four", 1);
+ cstr_replace(&cs, "seven", "four", 1);
printf("%s.\n", cstr_str(&cs));
cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
@@ -38,7 +38,7 @@ void vectordemo1()
c_WITH (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_drop(&bignums))
{
cvec_ix_reserve(&bignums, 100);
- for (size_t i = 10; i <= 100; i += 10)
+ for (int i = 10; i <= 100; i += 10)
cvec_ix_push(&bignums, i * i);
printf("erase - %d: %" PRIu64 "\n", 3, bignums.data[3]);
@@ -47,8 +47,8 @@ void vectordemo1()
cvec_ix_pop(&bignums); // erase the last
cvec_ix_erase_n(&bignums, 0, 1); // erase the first
- for (size_t i = 0; i < cvec_ix_size(&bignums); ++i) {
- printf("%" c_ZU ": %" PRIu64 "\n", i, bignums.data[i]);
+ for (int i = 0; i < cvec_ix_size(&bignums); ++i) {
+ printf("%d: %" PRIu64 "\n", i, bignums.data[i]);
}
}
}
@@ -175,11 +175,11 @@ void mapdemo3()
cmap_str_iter it = cmap_str_find(&table, "Make");
c_FOREACH (i, cmap_str, table)
printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second));
- printf("size %" c_ZU ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second));
+ printf("size %" c_ZI ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second));
//cmap_str_erase(&table, "Make");
cmap_str_erase_at(&table, it);
- printf("size %" c_ZU "\n", cmap_str_size(&table));
+ printf("size %" c_ZI "\n", cmap_str_size(&table));
c_FOREACH (i, cmap_str, table)
printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second));
cmap_str_drop(&table); // frees key and value cstrs, and hash table.
diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c
index 05d0bc28..1c64c9e0 100644
--- a/misc/examples/forfilter.c
+++ b/misc/examples/forfilter.c
@@ -33,12 +33,12 @@ void demo1(void)
int res, sum = 0;
c_FORFILTER (i, IVec, vec
- , c_FLT_SKIPWHILE(i, *i.ref != 80)
- && c_FLT_SKIP(i, 1)
- && c_FLT_SKIPWHILE(i, *i.ref != 80)
+ , c_flt_skipwhile(i, *i.ref != 80)
+ && c_flt_skip(i, 1)
+ && c_flt_skipwhile(i, *i.ref != 80)
&& flt_isEven(i)
&& flt_skipValue(i, 80)
- , c_FLT_TAKE(i, 5) // short-circuit
+ , c_flt_take(i, 5) // short-circuit
){
sum += res = flt_square(i);
printf(" %d", res);
@@ -64,12 +64,12 @@ void demo2(void)
{
c_AUTO (IVec, vector) {
puts("demo2:");
-
- c_FORFILTER (x, crange, crange_literal(INT64_MAX)
- , c_FLT_SKIPWHILE(x, *x.ref != 11)
+ crange R = crange_make(INT64_MAX);
+ c_FORFILTER (x, crange, R
+ , c_flt_skipwhile(x, *x.ref != 11)
&& *x.ref % 2 != 0
- , c_FLT_TAKE(x, 5))
- IVec_push(&vector, *x.ref * *x.ref);
+ , c_flt_take(x, 5))
+ IVec_push(&vector, (int)(*x.ref * *x.ref));
c_FOREACH (x, IVec, vector)
printf(" %d", *x.ref);
puts("");
@@ -126,13 +126,13 @@ void demo5(void)
#define flt_even(i) ((*i.ref & 1) == 0)
#define flt_mid_decade(i) ((*i.ref % 10) != 0)
puts("demo5:");
- crange r1 = crange_make(1963, INT32_MAX);
- c_FORFILTER (i, crange, r1
- , c_FLT_SKIP(i,15)
- && c_FLT_SKIPWHILE(i, flt_mid_decade(i))
- && c_FLT_SKIP(i,30)
+ crange R = crange_make(1963, INT32_MAX);
+ c_FORFILTER (i, crange, R
+ , c_flt_skip(i,15)
+ && c_flt_skipwhile(i, flt_mid_decade(i))
+ && c_flt_skip(i,30)
&& flt_even(i)
- , c_FLT_TAKE(i,10))
+ , c_flt_take(i,10))
printf(" %lld", *i.ref);
puts("");
}
diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c
index 69c1c193..cd3c4d9e 100644
--- a/misc/examples/forloops.c
+++ b/misc/examples/forloops.c
@@ -68,12 +68,12 @@ int main()
puts("\n\nc_forfilter:");
c_FORFILTER (i, IVec, vec
- , c_FLT_SKIPWHILE(i, *i.ref != 65)
- && c_FLT_TAKEWHILE(i, *i.ref != 280)
- && c_FLT_SKIPWHILE(i, isOdd(i))
+ , c_flt_skipwhile(i, *i.ref != 65)
+ && c_flt_takewhile(i, *i.ref != 280)
+ && c_flt_skipwhile(i, isOdd(i))
&& isOdd(i)
- && c_FLT_SKIP(i, 2)
- , c_FLT_TAKE(i, 1))
+ && c_flt_skip(i, 2)
+ , c_flt_take(i, 1))
printf(" %d", *i.ref);
puts("");
// 189
diff --git a/misc/examples/functor.c b/misc/examples/functor.c
index 54e2702d..f1db3644 100644
--- a/misc/examples/functor.c
+++ b/misc/examples/functor.c
@@ -23,7 +23,7 @@ struct {
#define i_type ipque
#define i_val int
#define i_opt c_is_forward // needed to avoid re-type-define container type
-#define i_less_functor(self, x, y) c_CONTAINER_OF(self, IPQueue, Q)->less(x, y)
+#define i_less_functor(self, x, y) c_container_of(self, IPQueue, Q)->less(x, y)
#include <stc/cpque.h>
void print_queue(const char* name, IPQueue q) {
diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c
index 519a7895..6b06b4e8 100644
--- a/misc/examples/gauss1.c
+++ b/misc/examples/gauss1.c
@@ -24,7 +24,7 @@ int main()
printf("Demo of gaussian / normal distribution of %d random samples\n", N);
// Setup random engine with normal distribution.
- uint64_t seed = time(NULL);
+ uint64_t seed = (uint64_t)time(NULL);
stc64_t rng = stc64_new(seed);
stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev);
@@ -45,7 +45,7 @@ int main()
// Print the gaussian bar chart
c_FOREACH (i, cvec_ii, histvec) {
- int n = (int)(i.ref->second * StdDev * Scale * 2.5 / N);
+ int n = (int)(i.ref->second * StdDev * Scale * 2.5 / (double)N);
if (n > 0) {
printf("%4d ", i.ref->first);
c_FORRANGE (n) printf("*");
diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c
index c2ed2e00..c627fc91 100644
--- a/misc/examples/gauss2.c
+++ b/misc/examples/gauss2.c
@@ -18,7 +18,7 @@ int main()
printf("Demo of gaussian / normal distribution of %d random samples\n", N);
// Setup random engine with normal distribution.
- uint64_t seed = time(NULL);
+ uint64_t seed = (uint64_t)time(NULL);
stc64_t rng = stc64_new(seed);
stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev);
@@ -33,7 +33,7 @@ int main()
// Print the gaussian bar chart
c_AUTO (cstr, bar)
c_FORPAIR (index, count, csmap_int, mhist) {
- size_t n = (size_t) (*_.count * StdDev * Scale * 2.5 / (float)N);
+ int n = (int)((float)*_.count * StdDev * Scale * 2.5f / (float)N);
if (n > 0) {
cstr_resize(&bar, n, '*');
printf("%4d %s\n", *_.index, cstr_str(&bar));
diff --git a/misc/examples/make.sh b/misc/examples/make.sh
index bd1392fc..19a53880 100755
--- a/misc/examples/make.sh
+++ b/misc/examples/make.sh
@@ -6,14 +6,14 @@ if [ "$(uname)" = 'Linux' ]; then
oflag='-o '
fi
+cc=gcc; cflags="-s -O2 -std=c99 -Wconversion -Wpedantic -Wall -Wsign-compare -Wwrite-strings"
#cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall $sanitize"
-cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings" # -Wconversion
#cc=tcc; cflags="-Wall -std=c99"
#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings"
#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -DSTC_CSTR_V1 -DSTC_CSMAP_V1"
#cc=gcc; cflags="-x c++ -s -O2 -Wall -std=c++20"
#cc=g++; cflags="-x c++ -s -O2 -Wall"
-#cc=cl; cflags="-O2 -nologo -W2 -MD"
+#cc=cl; cflags="-O2 -nologo -W3 -MD"
#cc=cl; cflags="-nologo -TP"
#cc=cl; cflags="-nologo -std:c11"
@@ -40,13 +40,13 @@ fi
if [ $run = 0 ] ; then
for i in *.c ; do
- echo $comp -I../include $i $clibs $oflag$(basename $i .c).exe
- $comp -I../include $i $clibs $oflag$(basename $i .c).exe
+ echo $comp -I../../include $i $clibs $oflag$(basename $i .c).exe
+ $comp -I../../include $i $clibs $oflag$(basename $i .c).exe
done
else
for i in *.c ; do
- echo $comp -I../include $i $clibs
- $comp -I../include $i $clibs
+ echo $comp -I../../include $i $clibs
+ $comp -I../../include $i $clibs
if [ -f $(basename -s .c $i).exe ]; then ./$(basename -s .c $i).exe; fi
if [ -f ./a.exe ]; then ./a.exe; fi
if [ -f ./a.out ]; then ./a.out; fi
diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c
index 945741b1..e61959ca 100644
--- a/misc/examples/multidim.c
+++ b/misc/examples/multidim.c
@@ -5,53 +5,66 @@
#include <stdio.h>
using_cspan3(ispan, int);
-/*
-using_cspan(ispan, int, 1);
-using_cspan(ispan2, int, 2);
-using_cspan(ispan3, int, 3);
-*/
int main()
{
- cstack_int v = {0};
- c_FORLIST (i, unsigned, {1,2,3,4,5,6,7,8,9,10,11,12})
- cstack_int_push(&v, *i.ref);
-
- // View data as contiguous memory representing 12 ints
- ispan ms1 = cspan_from(&v);
- // View data as contiguous memory representing 2 rows of 6 ints each
- ispan2 ms2 = cspan_make(v.data, 2, 6);
- // View the same data as a 3D array 2 x 3 x 2
- ispan3 ms3 = cspan_make(v.data, 2, 3, 2);
-
- // write data using 2D view
- for (unsigned i=0; i != ms2.dim[0]; i++)
- for (unsigned j=0; j != ms2.dim[1]; j++)
- *cspan_at(&ms2, i, j) = i*1000 + j;
-
- // print all items using 1D view
- printf("all: ");
- for (unsigned i=0; i != cspan_size(&ms1); i++)
- printf(" %d", *cspan_at(&ms1, i));
- puts("");
-
- // or iterate a subspan...
- ispan2 sub = cspan_at3(&ms3, 1);
- printf("sub: ");
- c_FOREACH (i, ispan2, sub)
- printf(" %d", *i.ref);
- puts("");
-
- // read back using 3D view
- for (unsigned i=0; i != ms3.dim[0]; i++)
- {
- printf("slice @ i = %u\n", i);
- for (unsigned j=0; j != ms3.dim[1]; j++)
- {
- for (unsigned k=0; k != ms3.dim[2]; k++)
- printf("%d ", *cspan_at(&ms3, i, j, k));
- puts("");
+ cstack_int v = {0};
+ c_FORLIST (i, int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24})
+ cstack_int_push(&v, *i.ref);
+
+ // View data as contiguous memory representing 24 ints
+ ispan ms1 = cspan_from(&v);
+
+ // View the same data as a 3D array 2 x 3 x 4
+ ispan3 ms3 = cspan_md(v.data, 2, 3, 4);
+
+ puts("ms3:");
+ for (int i=0; i != ms3.shape[0]; i++) {
+ for (int j=0; j != ms3.shape[1]; j++) {
+ for (int k=0; k != ms3.shape[2]; k++) {
+ printf(" %2d", *cspan_at(&ms3, i, j, k));
+ }
+ puts("");
+ }
+ puts("");
}
- }
- cstack_int_drop(&v);
+ puts("ss3 = ms3[:, 1:3, 1:3]");
+ ispan3 ss3 = ms3;
+ //cspan_slice(&ss3, {c_ALL}, {1,3}, {1,3});
+ ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3});
+
+ for (int i=0; i != ss3.shape[0]; i++) {
+ for (int j=0; j != ss3.shape[1]; j++) {
+ for (int k=0; k != ss3.shape[2]; k++) {
+ printf(" %2d", *cspan_at(&ss3, i, j, k));
+ }
+ puts("");
+ }
+ puts("");
+ }
+
+ puts("Iterate ss3 flat:");
+ c_FOREACH (i, ispan3, ss3)
+ printf(" %d", *i.ref);
+ puts("");
+
+ ispan2 ms2 = cspan_submd3(&ms3, 0);
+
+ // write data using 2D view
+ for (int i=0; i != ms2.shape[0]; i++)
+ for (int j=0; j != ms2.shape[1]; j++)
+ *cspan_at(&ms2, i, j) = i*1000 + j;
+
+ puts("\nview data as 1D view:");
+ for (int i=0; i != cspan_size(&ms1); i++)
+ printf(" %d", *cspan_at(&ms1, i));
+ puts("");
+
+ puts("iterate subspan ms3[1]:");
+ ispan2 sub = cspan_submd3(&ms3, 1);
+ c_FOREACH (i, ispan2, sub)
+ printf(" %d", *i.ref);
+ puts("");
+
+ cstack_int_drop(&v);
}
diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c
index 9896c591..fad7ddcf 100644
--- a/misc/examples/music_arc.c
+++ b/misc/examples/music_arc.c
@@ -16,7 +16,7 @@ Song Song_make(const char* artist, const char* title)
void Song_drop(Song* s) {
printf("drop: %s\n", cstr_str(&s->title));
- c_DROP(cstr, &s->artist, &s->title);
+ c_drop(cstr, &s->artist, &s->title);
}
// Define the reference counted type
diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c
index 72705eb2..9cee987d 100644
--- a/misc/examples/new_map.c
+++ b/misc/examples/new_map.c
@@ -48,24 +48,25 @@ int main()
c_AUTO (cset_str, sset)
{
cmap_int_insert(&map, 123, 321);
+ cmap_int_insert(&map, 456, 654);
+ cmap_int_insert(&map, 789, 987);
- c_FORLIST (i, cmap_pnt_raw, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}})
- cmap_pnt_insert(&pmap, c_PAIR(i.ref));
+ pmap = c_make(cmap_pnt, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}});
c_FOREACH (i, cmap_pnt, pmap)
printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second);
puts("");
- c_FORLIST (i, cmap_str_raw, {
+ smap = c_make(cmap_str, {
{"Hello, friend", "long time no see"},
- {"So long, friend", "see you around"},
- }) cmap_str_emplace(&smap, c_PAIR(i.ref));
+ {"So long", "see you around"},
+ });
- c_FORLIST (i, const char*, {
+ sset = c_make(cset_str, {
"Hello, friend",
"Nice to see you again",
- "So long, friend",
- }) cset_str_emplace(&sset, *i.ref);
+ "So long",
+ });
c_FOREACH (i, cset_str, sset)
printf(" %s\n", cstr_str(i.ref));
diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c
index d127b592..b3d94c2f 100644
--- a/misc/examples/new_pque.c
+++ b/misc/examples/new_pque.c
@@ -48,7 +48,7 @@ int main()
cpque_int_push(&ique, 123);
cpque_int_push(&ique, 321);
// print
- for (size_t i=0; i<cpque_int_size(&ique); ++i)
+ for (int i=0; i<cpque_int_size(&ique); ++i)
printf(" %d", ique.data[i]);
puts("");
}
diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c
index 828387b5..5c25a229 100644
--- a/misc/examples/new_queue.c
+++ b/misc/examples/new_queue.c
@@ -22,25 +22,25 @@ int point_cmp(const Point* a, const Point* b) {
int main() {
int n = 50000000;
- stc64_t rng = stc64_new(time(NULL));
+ stc64_t rng = stc64_new((uint64_t)time(NULL));
stc64_uniform_t dist = stc64_uniform_new(0, n);
c_AUTO (IQ, Q)
{
// Push 50'000'000 random numbers onto the queue.
c_FORRANGE (n)
- IQ_push(&Q, stc64_uniform(&rng, &dist));
+ IQ_push(&Q, (int)stc64_uniform(&rng, &dist));
// Push or pop on the queue 50 million times
- printf("befor: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q));
+ printf("befor: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
c_FORRANGE (n) {
- int r = stc64_uniform(&rng, &dist);
+ int r = (int)stc64_uniform(&rng, &dist);
if (r & 3)
IQ_push(&Q, r);
else
IQ_pop(&Q);
}
- printf("after: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q));
+ printf("after: size %" c_ZI ", capacity %" c_ZI "\n", IQ_size(&Q), IQ_capacity(&Q));
}
}
diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c
index 5441ae01..116827a4 100644
--- a/misc/examples/new_sptr.c
+++ b/misc/examples/new_sptr.c
@@ -43,7 +43,7 @@ Person Person_clone(Person p) {
}
void Person_drop(Person* p) {
printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last));
- c_DROP(cstr, &p->name, &p->last);
+ c_drop(cstr, &p->name, &p->last);
}
diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c
index f782c9da..4d9c2a51 100644
--- a/misc/examples/person_arc.c
+++ b/misc/examples/person_arc.c
@@ -24,7 +24,7 @@ Person Person_clone(Person p) {
void Person_drop(Person* p) {
printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last));
- c_DROP(cstr, &p->name, &p->last);
+ c_drop(cstr, &p->name, &p->last);
}
#define i_type PSPtr
diff --git a/misc/examples/prime.c b/misc/examples/prime.c
index 40ccc299..11c1f1c7 100644
--- a/misc/examples/prime.c
+++ b/misc/examples/prime.c
@@ -6,19 +6,19 @@
#include <stc/algo/crange.h>
-cbits sieveOfEratosthenes(size_t n)
+cbits sieveOfEratosthenes(intptr_t n)
{
cbits bits = cbits_with_size(n/2 + 1, true);
- size_t q = (size_t) sqrt((double) n) + 1;
- for (size_t i = 3; i < q; i += 2) {
- size_t j = i;
+ intptr_t q = (intptr_t)sqrt((double) n) + 1;
+ for (intptr_t i = 3; i < q; i += 2) {
+ intptr_t j = i;
for (; j < n; j += 2) {
if (cbits_test(&bits, j>>1)) {
i = j;
break;
}
}
- for (size_t j = i*i; j < n; j += i*2)
+ for (intptr_t j = i*i; j < n; j += i*2)
cbits_reset(&bits, j>>1);
}
return bits;
@@ -26,16 +26,16 @@ cbits sieveOfEratosthenes(size_t n)
int main(void)
{
- size_t n = 1000000000;
- printf("computing prime numbers up to %" c_ZU "\n", n);
+ intptr_t n = 1000000000;
+ printf("computing prime numbers up to %" c_ZI "\n", n);
clock_t t1 = clock();
c_WITH (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) {
puts("done");
- size_t np = cbits_count(&primes);
+ intptr_t np = cbits_count(&primes);
clock_t t2 = clock();
- printf("number of primes: %" c_ZU ", time: %f\n", np, (t2 - t1) / (float)CLOCKS_PER_SEC);
+ printf("number of primes: %" c_ZI ", time: %f\n", np, (float)(t2 - t1) / (float)CLOCKS_PER_SEC);
puts("Show all the primes in the range [2, 1000):");
printf("2");
c_FORRANGE (i, 3, 1000, 2)
@@ -43,9 +43,10 @@ int main(void)
puts("");
puts("Show the last 50 primes using a temporary crange generator:");
- c_FORFILTER (i, crange, crange_literal(n - 1, 0, -2)
+ crange R = crange_make(n - 1, 0, -2);
+ c_FORFILTER (i, crange, R
, cbits_test(&primes, *i.ref>>1)
- , c_FLT_TAKE(i, 50)) {
+ , c_flt_take(i, 50)) {
printf("%lld ", *i.ref);
if (i.count % 10 == 0) puts("");
}
diff --git a/misc/examples/printspan.c b/misc/examples/printspan.c
index a897e669..82b54367 100644
--- a/misc/examples/printspan.c
+++ b/misc/examples/printspan.c
@@ -1,42 +1,57 @@
// printspan.c
#include <stdio.h>
+#include <stc/cstr.h>
#define i_val int
#include <stc/cvec.h>
#define i_val int
#include <stc/cstack.h>
#define i_val int
#include <stc/cdeq.h>
+#define i_val_str
+#include <stc/cset.h>
#include <stc/cspan.h>
-using_cspan(ispan, int, 1);
+using_cspan(intspan, int, 1);
-void printMe(ispan container) {
- printf("%d\n", (int)cspan_size(&container));
- c_FOREACH (e, ispan, container) printf("%d ", *e.ref);
+void printMe(intspan container) {
+ printf("%d:", (int)cspan_size(&container));
+ c_FOREACH (e, intspan, container) printf(" %d", *e.ref);
puts("");
}
-int main() {
+int main()
+{
c_AUTO (cvec_int, vec)
c_AUTO (cstack_int, stk)
c_AUTO (cdeq_int, deq)
+ c_AUTO (cset_str, set)
{
- int arr[] = {1, 2, 3, 4, 5};
- ispan sp = cspan_from_array(arr);
- printMe((ispan)cspan_subspan(&sp, 1, 3));
+ intspan sp1 = cspan_make(intspan, {1, 2});
+ printMe( sp1 );
+
+ printMe( c_make(intspan, {1, 2, 3}) );
- printMe((ispan)cspan_from_list(int, {1, 2, 3, 4}));
+ int arr[] = {1, 2, 3, 4, 5, 6};
+ intspan sp2 = cspan_from_array(arr);
+ printMe( (intspan)cspan_subspan(&sp2, 1, 4) );
- printMe((ispan)cspan_from_array(arr));
+ c_FORLIST (i, int, {1, 2, 3, 4, 5})
+ cvec_int_push(&vec, *i.ref);
+ printMe( (intspan)cspan_from(&vec) );
- c_FORLIST (i, int, {1, 2, 3, 4, 5, 6}) cvec_int_push(&vec, *i.ref);
- printMe((ispan)cspan_from(&vec));
+ printMe( sp2 );
- c_FORLIST (i, int, {1, 2, 3, 4, 5, 6, 7}) cstack_int_push(&stk, *i.ref);
- printMe((ispan)cspan_from(&stk));
+ stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7});
+ printMe( (intspan)cspan_from(&stk) );
- c_FORLIST (i, int, {1, 2, 3, 4, 5, 6, 7, 8}) cdeq_int_push_front(&deq, *i.ref);
- printMe((ispan)cspan_from(&deq));
+ deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8});
+ printMe( (intspan)cspan_from(&deq) );
+
+ set = c_make(cset_str, {"1", "2", "3", "4", "5", "6", "7", "8", "9"});
+ printf("%d:", (int)cset_str_size(&set));
+ c_FOREACH (e, cset_str, set)
+ printf(" %s", cstr_str(e.ref));
+ puts("");
}
}
diff --git a/misc/examples/priority.c b/misc/examples/priority.c
index 22da6f60..f39c0634 100644
--- a/misc/examples/priority.c
+++ b/misc/examples/priority.c
@@ -9,13 +9,13 @@
#include <stc/cpque.h>
int main() {
- size_t N = 10000000;
- stc64_t rng = stc64_new(time(NULL));
+ intptr_t N = 10000000;
+ stc64_t rng = stc64_new((uint64_t)time(NULL));
stc64_uniform_t dist = stc64_uniform_new(0, N * 10);
c_AUTO (cpque_i, heap)
{
// Push ten million random numbers to priority queue
- printf("Push %" c_ZU " numbers\n", N);
+ printf("Push %" c_ZI " numbers\n", N);
c_FORRANGE (N)
cpque_i_push(&heap, stc64_uniform(&rng, &dist));
diff --git a/misc/examples/queue.c b/misc/examples/queue.c
index 1d325fc6..ee537b58 100644
--- a/misc/examples/queue.c
+++ b/misc/examples/queue.c
@@ -15,17 +15,17 @@ int main() {
{
// Push ten million random numbers onto the queue.
c_FORRANGE (n)
- cqueue_i_push(&queue, stc64_uniform(&rng, &dist));
+ cqueue_i_push(&queue, (int)stc64_uniform(&rng, &dist));
// Push or pop on the queue ten million times
printf("%d\n", n);
c_FORRANGE (n) { // forrange uses initial n only.
- int r = stc64_uniform(&rng, &dist);
+ int r = (int)stc64_uniform(&rng, &dist);
if (r & 1)
++n, cqueue_i_push(&queue, r);
else
--n, cqueue_i_pop(&queue);
}
- printf("%d, %" c_ZU "\n", n, cqueue_i_size(&queue));
+ printf("%d, %" c_ZI "\n", n, cqueue_i_size(&queue));
}
}
diff --git a/misc/examples/random.c b/misc/examples/random.c
index 82214924..fc4576dd 100644
--- a/misc/examples/random.c
+++ b/misc/examples/random.c
@@ -5,10 +5,10 @@
int main()
{
const size_t N = 1000000000;
- const uint64_t seed = time(NULL), range = 1000000;
+ const uint64_t seed = (uint64_t)time(NULL), range = 1000000;
stc64_t rng = stc64_new(seed);
- uint64_t sum;
+ int64_t sum;
clock_t diff, before;
printf("Compare speed of full and unbiased ranged random numbers...\n");
@@ -18,8 +18,8 @@ int main()
sum += (uint32_t)stc64_rand(&rng);
}
diff = clock() - before;
- printf("full range\t\t: %f secs, %" c_ZU ", avg: %f\n",
- (float)diff / CLOCKS_PER_SEC, N, (double)sum / N);
+ printf("full range\t\t: %f secs, %" c_ZI ", avg: %f\n",
+ (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N);
stc64_uniform_t dist1 = stc64_uniform_new(0, range);
rng = stc64_new(seed);
@@ -29,17 +29,17 @@ int main()
sum += stc64_uniform(&rng, &dist1); // unbiased
}
diff = clock() - before;
- printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZU ", avg: %f\n",
- range, (float)diff/CLOCKS_PER_SEC, N, (double)sum / N);
+ printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZI ", avg: %f\n",
+ range, (float)diff/CLOCKS_PER_SEC, N, (float)sum / (float)N);
sum = 0;
rng = stc64_new(seed);
before = clock();
c_FORRANGE (N) {
- sum += stc64_rand(&rng) % (range + 1); // biased
+ sum += (int64_t)(stc64_rand(&rng) % (range + 1)); // biased
}
diff = clock() - before;
- printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZU ", avg: %f\n",
- range, (float)diff / CLOCKS_PER_SEC, N, (double)sum / N);
+ printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZI ", avg: %f\n",
+ range, (float)diff / CLOCKS_PER_SEC, N, (float)sum / (float)N);
}
diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c
index 05910c77..96a9ba86 100644
--- a/misc/examples/rawptr_elements.c
+++ b/misc/examples/rawptr_elements.c
@@ -13,7 +13,7 @@ typedef int64_t inttype;
#define i_valfrom(raw) c_NEW(inttype, raw)
#define i_valto(x) **x
#define i_valclone(x) c_NEW(inttype, *x)
-#define i_valdrop(x) c_FREE(*x)
+#define i_valdrop(x) c_free(*x)
#include <stc/cmap.h>
// With cbox:
diff --git a/misc/examples/regex1.c b/misc/examples/regex1.c
index 9552db62..ae00b71c 100644
--- a/misc/examples/regex1.c
+++ b/misc/examples/regex1.c
@@ -10,7 +10,7 @@ int main(int argc, char* argv[])
c_AUTO (cstr, input)
c_AUTO (cregex, float_expr)
{
- int res = cregex_compile(&float_expr, "^[+-]?[0-9]+((\\.[0-9]*)?|\\.[0-9]+)$", CREG_DEFAULT);
+ int res = cregex_compile(&float_expr, "^[+-]?[0-9]+((\\.[0-9]*)?|\\.[0-9]+)$");
// Until "q" is given, ask for another number
if (res > 0) while (true)
{
diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c
index e24cce51..2b742529 100644
--- a/misc/examples/regex2.c
+++ b/misc/examples/regex2.c
@@ -18,7 +18,7 @@ int main()
c_AUTO (cregex, re)
c_FORRANGE (i, c_ARRAYLEN(s))
{
- int res = cregex_compile(&re, s[i].pattern, CREG_DEFAULT);
+ int res = cregex_compile(&re, s[i].pattern);
if (res < 0) {
printf("error in regex pattern: %d\n", res);
continue;
diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c
index b6bd6521..b7d6ed3a 100644
--- a/misc/examples/regex_match.c
+++ b/misc/examples/regex_match.c
@@ -1,6 +1,7 @@
#define i_extern
#include <stc/cregex.h>
#include <stc/csview.h>
+
#define i_val float
#include <stc/cstack.h>
@@ -17,12 +18,12 @@ int main()
c_AUTO (cstr, nums)
{
const char* pattern = "[+-]?([0-9]*\\.)?\\d+([Ee][+-]?\\d+)?";
- int res = cregex_compile(&re, pattern, CREG_DEFAULT);
+ int res = cregex_compile(&re, pattern);
printf("%d: %s\n", res, pattern);
// extract and convert all numbers in str to floats
c_FORMATCH (i, &re, str)
- cstack_float_push(&vec, atof(i.match[0].str));
+ cstack_float_push(&vec, (float)atof(i.match[0].str));
c_FOREACH (i, cstack_float, vec)
printf(" %g\n", *i.ref);
diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c
index a170856b..ec38ca56 100644
--- a/misc/examples/regex_replace.c
+++ b/misc/examples/regex_replace.c
@@ -26,15 +26,15 @@ int main()
printf("fixed: %s\n", cstr_str(&str));
/* US date format, and add 10 years to dates: */
- cstr_take(&str, cregex_replace_pattern_ex(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT));
+ cstr_take(&str, cregex_replace_pattern(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT));
printf("us+10: %s\n", cstr_str(&str));
/* Wrap first date inside []: */
- cstr_take(&str, cregex_replace_pattern_ex(pattern, input, "[$0]", 1, NULL, CREG_DEFAULT));
+ cstr_take(&str, cregex_replace_pattern(pattern, input, "[$0]"));
printf("brack: %s\n", cstr_str(&str));
/* Shows how to compile RE separately */
- c_WITH (cregex re = cregex_from(pattern, CREG_DEFAULT), cregex_drop(&re)) {
+ c_WITH (cregex re = cregex_from(pattern), cregex_drop(&re)) {
if (cregex_captures(&re) == 0)
continue; /* break c_WITH */
/* European date format. */
diff --git a/misc/examples/shape.c b/misc/examples/shape.c
index ed0c3fe1..9ce0b946 100644
--- a/misc/examples/shape.c
+++ b/misc/examples/shape.c
@@ -38,7 +38,7 @@ void Shape_delete(Shape* shape)
{
if (shape) {
shape->api->drop(shape);
- c_FREE(shape);
+ c_free(shape);
}
}
@@ -50,12 +50,12 @@ typedef struct {
Point p[3];
} Triangle;
-static struct ShapeAPI Triangle_api;
+extern struct ShapeAPI Triangle_api;
Triangle Triangle_from(Point a, Point b, Point c)
{
- Triangle t = {{.api=&Triangle_api}, .p={a, b, c}};
+ Triangle t = {.shape={.api=&Triangle_api}, .p={a, b, c}};
return t;
}
@@ -68,7 +68,7 @@ static void Triangle_draw(const Shape* shape)
self->p[2].x, self->p[2].y);
}
-static struct ShapeAPI Triangle_api = {
+struct ShapeAPI Triangle_api = {
.drop = Shape_drop,
.draw = Triangle_draw,
};
@@ -85,12 +85,12 @@ typedef struct {
PointVec points;
} Polygon;
-static struct ShapeAPI Polygon_api;
+extern struct ShapeAPI Polygon_api;
Polygon Polygon_init(void)
{
- Polygon p = {{.api=&Polygon_api}, .points=PointVec_init()};
+ Polygon p = {.shape={.api=&Polygon_api}, .points=PointVec_init()};
return p;
}
@@ -116,7 +116,7 @@ static void Polygon_draw(const Shape* shape)
puts("");
}
-static struct ShapeAPI Polygon_api = {
+struct ShapeAPI Polygon_api = {
.drop = Polygon_drop,
.draw = Polygon_draw,
};
diff --git a/misc/examples/sort.c b/misc/examples/sort.c
index de94cede..65077143 100644
--- a/misc/examples/sort.c
+++ b/misc/examples/sort.c
@@ -14,7 +14,7 @@
#define fmt_Elem "%lld"
-int testsort(csort_elm_value *a, size_t size, const char *desc) {
+int testsort(csort_elm_value *a, long size, const char *desc) {
clock_t t = clock();
#ifdef __cplusplus
printf("std::sort: ");
@@ -26,13 +26,13 @@ int testsort(csort_elm_value *a, size_t size, const char *desc) {
t = clock() - t;
printf("%s: %d elements sorted in %.2f ms\n",
- desc, (int)size, t*1000.0/CLOCKS_PER_SEC);
+ desc, (int)size, (float)t*1000.0f/CLOCKS_PER_SEC);
return 0;
}
int main(int argc, char *argv[]) {
- size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000;
- csort_elm_value *a = (csort_elm_value*)malloc(sizeof(*a) * size);
+ long i, size = argc > 1 ? strtol(argv[1], NULL, 0) : 10000000;
+ csort_elm_value *a = (csort_elm_value*)c_malloc(c_sizeof(*a) * size);
if (a == NULL) return -1;
for (i = 0; i < size; i++)
diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c
index 70d1935e..ba927412 100644
--- a/misc/examples/splitstr.c
+++ b/misc/examples/splitstr.c
@@ -13,7 +13,7 @@ int main()
puts("\nSplit with c_FORMATCH (regex):");
- c_WITH (cregex re = cregex_from("[^ ]+", CREG_DEFAULT), cregex_drop(&re))
+ c_WITH (cregex re = cregex_from("[^ ]+"), cregex_drop(&re))
c_FORMATCH (i, &re, " Hello World C99! ")
printf("'%.*s'\n", c_ARGSV(i.match[0]));
}
diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c
index f88e5f79..0841a316 100644
--- a/misc/examples/sso_map.c
+++ b/misc/examples/sso_map.c
@@ -10,7 +10,7 @@ int main()
cmap_str_emplace(&m, "Test long ", "This is a longer string");
c_FORPAIR (k, v, cmap_str, m)
- printf("%s: '%s' Len=%" c_ZU ", Is long: %s\n",
+ printf("%s: '%s' Len=%" c_ZI ", Is long: %s\n",
cstr_str(_.k), cstr_str(_.v), cstr_size(_.v),
cstr_is_long(_.v) ? "true" : "false");
}
diff --git a/misc/examples/sso_substr.c b/misc/examples/sso_substr.c
index 8e7450ba..7e858ec4 100644
--- a/misc/examples/sso_substr.c
+++ b/misc/examples/sso_substr.c
@@ -6,7 +6,7 @@ int main ()
{
cstr str = cstr_lit("We think in generalities, but we live in details.");
csview sv1 = cstr_substr_ex(&str, 3, 5); // "think"
- size_t pos = cstr_find(&str, "live"); // position of "live"
+ intptr_t pos = cstr_find(&str, "live"); // position of "live"
csview sv2 = cstr_substr_ex(&str, pos, 4); // "live"
csview sv3 = cstr_slice_ex(&str, -8, -1); // "details"
printf("%.*s, %.*s, %.*s\n", c_ARGSV(sv1), c_ARGSV(sv2), c_ARGSV(sv3));
@@ -16,5 +16,5 @@ int main ()
cstr s3 = cstr_from_sv(cstr_substr_ex(&str, 0, 6)); // "apples"
printf("%s %s: %d, %d\n", cstr_str(&s2), cstr_str(&s3),
cstr_is_long(&str), cstr_is_long(&s2));
- c_DROP (cstr, &str, &s2, &s3);
+ c_drop (cstr, &str, &s2, &s3);
}
diff --git a/misc/examples/stack.c b/misc/examples/stack.c
index 370577b9..86099607 100644
--- a/misc/examples/stack.c
+++ b/misc/examples/stack.c
@@ -15,7 +15,7 @@ int main() {
c_AUTO (cstack_c, chars)
{
c_FORRANGE (i, 101)
- cstack_i_push(&stack, i*i);
+ cstack_i_push(&stack, (int)(i*i));
printf("%d\n", *cstack_i_top(&stack));
diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c
index 5658924e..2d4b5324 100644
--- a/misc/examples/sview_split.c
+++ b/misc/examples/sview_split.c
@@ -6,7 +6,7 @@ int main()
{
// No memory allocations or string length calculations!
const csview date = c_SV("2021/03/12");
- size_t pos = 0;
+ intptr_t pos = 0;
const csview year = csview_token(date, "/", &pos);
const csview month = csview_token(date, "/", &pos);
const csview day = csview_token(date, "/", &pos);
diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c
index 2d8d1921..3f98a2a6 100644
--- a/misc/examples/utf8replace_c.c
+++ b/misc/examples/utf8replace_c.c
@@ -16,11 +16,8 @@ int main() {
c_FOREACH (c, cstr, hello)
printf("%.*s,", c_ARGSV(c.u8.chr));
- //csview sv = c_SV("If you find the time, you will find the winner");
- //str = cstr_replace_sv(sv, c_SV("find"), c_SV("match"), 0);
-
- str = cstr_lit("If you find the time, you will find the winner");
- cstr_replace(&str, "find", "match");
+ str = cstr_lit("scooby, dooby doo");
+ cstr_replace(&str, "oo", "00");
printf("\n%s\n", cstr_str(&str));
}
}
diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c
index c65a9caa..86d60519 100644
--- a/misc/examples/vikings.c
+++ b/misc/examples/vikings.c
@@ -23,11 +23,11 @@ static inline int RViking_cmp(const RViking* rx, const RViking* ry) {
}
static inline Viking Viking_from(RViking raw) { // note: parameter is by value
- return c_INIT(Viking){cstr_from(raw.name), cstr_from(raw.country)};
+ return c_LITERAL(Viking){cstr_from(raw.name), cstr_from(raw.country)};
}
static inline RViking Viking_toraw(const Viking* vp) {
- return c_INIT(RViking){cstr_str(&vp->name), cstr_str(&vp->country)};
+ return c_LITERAL(RViking){cstr_str(&vp->name), cstr_str(&vp->country)};
}
// With this in place, we define the Viking => int hash map type:
diff --git a/misc/tests/cregex_test.c b/misc/tests/cregex_test.c
index cd812aa2..24c39950 100644
--- a/misc/tests/cregex_test.c
+++ b/misc/tests/cregex_test.c
@@ -1,260 +1,282 @@
-#if 0
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <stc/csview.h>
-#include <stc/stctest.h>
+#define i_extern
#include <stc/cregex.h>
+#include <stc/csview.h>
+#include "ctest.h"
-#define START_TEST(f) void f(void)
-#define END_TEST
+#define M_START(m) ((m).str - inp)
+#define M_END(m) (M_START(m) + (m).size)
-#define M_START(re, m) ((m).str - (re).input)
-#define M_END(re, m) (M_START(re, m) + (m).size)
-START_TEST(compile_match_char)
+CTEST(cregex, compile_match_char)
{
- cregex re = cregex_from("äsdf", 0);
- EXPECT_EQ(re.error, 0);
+ const char* inp;
+ cregex re = cregex_from("äsdf");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_TRUE(cregex_find("äsdf", &re, &match, 0));
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 5); // ä is two bytes wide
+ ASSERT_EQ(cregex_find(&re, inp="äsdf", &match, CREG_M_FULLMATCH), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 5); // ä is two bytes wide
- EXPECT_EQ(cregex_find("zäsdf", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 1);
- EXPECT_EQ(M_END(re, match), 6);
+ ASSERT_EQ(cregex_find(&re, inp="zäsdf", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 1);
+ ASSERT_EQ(M_END(match), 6);
cregex_drop(&re);
}
-END_TEST
-START_TEST(compile_match_anchors)
+CTEST(cregex, compile_match_anchors)
{
- cregex re = cregex_from("^äs.f$", 0);
- EXPECT_EQ(re.error, 0);
+ const char* inp;
+ cregex re = cregex_from(inp="^äs.f$");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_TRUE(cregex_find("äsdf", &re, &match, 0));
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 5);
+ ASSERT_EQ(cregex_find(&re, inp="äsdf", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 5);
- EXPECT_TRUE(cregex_is_match("äs♥f", &re));
- EXPECT_TRUE(cregex_is_match("äsöf", &re));
+ ASSERT_TRUE(cregex_is_match(&re, "äs♥f"));
+ ASSERT_TRUE(cregex_is_match(&re, "äsöf"));
- cregex_drop(re);
+ cregex_drop(&re);
}
-END_TEST
-START_TEST(compile_match_quantifiers)
+CTEST(cregex, compile_match_quantifiers1)
{
+ const char* inp;
c_AUTO (cregex, re) {
- re = cregex_from("ä+", 0);
- EXPECT_EQ(re.error, 0);
+ re = cregex_from("ä+");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_EQ(cregex_find("ääb", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 4);
+ ASSERT_EQ(cregex_find(&re, inp="ääb", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 4);
- EXPECT_EQ(cregex_find("bäbb", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 1);
- EXPECT_EQ(M_END(re, match), 3);
+ ASSERT_EQ(cregex_find(&re, inp="bäbb", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 1);
+ ASSERT_EQ(M_END(match), 3);
- EXPECT_FALSE(cregex_find("bbb", &re, &match, 0));
+ ASSERT_EQ(cregex_find(&re, "bbb", &match), CREG_NOMATCH);
}
+}
+
+CTEST(cregex, compile_match_quantifiers2)
+{
+ const char* inp;
c_AUTO (cregex, re) {
- re = cregex_from("bä*", 0);
- EXPECT_EQ(re.error, 0);
+ re = cregex_from("bä*");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_EQ(cregex_find("bääb", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 5);
+ ASSERT_EQ(cregex_find(&re, inp="bääb", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 5);
- EXPECT_EQ(cregex_find("bäbb", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 3);
+ ASSERT_EQ(cregex_find(&re, inp="bäbb", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 3);
- EXPECT_EQ(cregex_find("bbb", &re, &match, 0), 1);
- EXPECT_EQ(M_START(re, match), 0);
- EXPECT_EQ(M_END(re, match), 1);
+ ASSERT_EQ(cregex_find(&re, inp="bbb", &match), CREG_OK);
+ ASSERT_EQ(M_START(match), 0);
+ ASSERT_EQ(M_END(match), 1);
}
}
-END_TEST
-START_TEST(compile_match_escaped_chars)
+CTEST(cregex, compile_match_escaped_chars)
{
- cregex re = cregex_from("\\n\\r\\t\\{", 0);
- EXPECT_EQ(re.error, 0);
+ cregex re = cregex_from("\\n\\r\\t\\{");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_EQ(cregex_find("\n\r\t{", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("\n\r\t", &re, &match, 0), 0);
+ ASSERT_EQ(cregex_find(&re, "\n\r\t{", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "\n\r\t", &match), CREG_NOMATCH);
cregex_drop(&re);
}
-END_TEST
-START_TEST(compile_match_class_simple)
+CTEST(cregex, compile_match_class_simple)
{
c_AUTO (cregex, re1, re2, re3)
{
- re1 = cregex_from("\\s", 0);
- EXPECT_EQ(re1.error, 0);
- re2 = cregex_from("\\w", 0);
- EXPECT_EQ(re2.error, 0);
- re3 = cregex_from("\\D", 0);
- EXPECT_EQ(re3.error, 0);
+ re1 = cregex_from("\\s");
+ ASSERT_EQ(re1.error, 0);
+ re2 = cregex_from("\\w");
+ ASSERT_EQ(re2.error, 0);
+ re3 = cregex_from("\\D");
+ ASSERT_EQ(re3.error, 0);
csview match;
- EXPECT_EQ(cregex_find(" ", &re1, &match, 0), 1);
- EXPECT_EQ(cregex_find("\r", &re1, &match, 0), 1);
- EXPECT_EQ(cregex_find("\n", &re1, &match, 0), 1);
+ ASSERT_EQ(cregex_find(&re1, " " , &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re1, "\r", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re1, "\n", &match), CREG_OK);
- EXPECT_EQ(cregex_find("a", &re2, &match, 0), 1);
- EXPECT_EQ(cregex_find("0", &re2, &match, 0), 1);
- EXPECT_EQ(cregex_find("_", &re2, &match, 0), 1);
+ ASSERT_EQ(cregex_find(&re2, "a", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re2, "0", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re2, "_", &match), CREG_OK);
- EXPECT_EQ( cregex_find("k", &re3, &match, 0), 1);
- EXPECT_EQ(cregex_find("0", &re3, &match, 0), 0);
+ ASSERT_EQ(cregex_find(&re3, "k", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re3, "0", &match), CREG_NOMATCH);
}
}
-END_TEST
-START_TEST(compile_match_or)
+CTEST(cregex, compile_match_or)
{
c_AUTO (cregex, re, re2)
{
- re = cregex_from("as|df", 0);
- EXPECT_EQ(re.error, 0);
+ re = cregex_from("as|df");
+ ASSERT_EQ(re.error, 0);
- csview match;
- EXPECT_EQ(cregex_find("as", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("df", &re, &match, 0), 1);
+ csview match[4];
+ ASSERT_EQ(cregex_find(&re, "as", match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "df", match), CREG_OK);
- re2 = cregex_from("(as|df)", 0);
- EXPECT_EQ(re2.error, 0);
+ re2 = cregex_from("(as|df)");
+ ASSERT_EQ(re2.error, 0);
- EXPECT_EQ(cregex_find(&re2, "as", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find(&re2, "df", &re, &match, 0), 1);
+ ASSERT_EQ(cregex_find(&re2, "as", match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re2, "df", match), CREG_OK);
}
}
-END_TEST
-START_TEST(compile_match_class_complex_0)
+CTEST(cregex, compile_match_class_complex_0)
{
- cregex re = cregex_from("[asdf]", 0);
- EXPECT_EQ(re.error, 0);
+ cregex re = cregex_from("[asdf]");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_EQ(cregex_find("a", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("s", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("d", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("f", &re, &match, 0), 1);
+ ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "s", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "d", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "f", &match), CREG_OK);
cregex_drop(&re);
}
-END_TEST
-START_TEST(compile_match_class_complex_1)
+CTEST(cregex, compile_match_class_complex_1)
{
- cregex re = cregex_from("[a-zä0-9öA-Z]", 0);
- EXPECT_EQ(re.error, 0);
+ cregex re = cregex_from("[a-zä0-9öA-Z]");
+ ASSERT_EQ(re.error, 0);
csview match;
- EXPECT_EQ(cregex_find("a", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("5", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("A", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("ä", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("ö", &re, &match, 0), 1);
+ ASSERT_EQ(cregex_find(&re, "a", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "5", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "A", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "ä", &match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "ö", &match), CREG_OK);
cregex_drop(&re);
}
-END_TEST
-START_TEST(compile_match_cap)
+CTEST(cregex, compile_match_cap)
{
- cregex re = cregex_from("(abc)d", 0);
- EXPECT_EQ(re.error, 0);
+ cregex re = cregex_from("(abc)d");
+ ASSERT_EQ(re.error, 0);
- csview match;
- EXPECT_EQ(cregex_find("abcd", &re, &match, 0)), 1;
- EXPECT_EQ(cregex_find("llljabcdkk", &re, &match, 0), 1);
- EXPECT_EQ(cregex_find("abc", &re, &match, 0), 0);
+ csview match[4];
+ ASSERT_EQ(cregex_find(&re, "abcd", match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "llljabcdkk", match), CREG_OK);
+ ASSERT_EQ(cregex_find(&re, "abc", match), CREG_NOMATCH);
cregex_drop(&re);
}
-END_TEST
-START_TEST(search_all)
+CTEST(cregex, search_all)
{
+ const char* inp;
c_AUTO (cregex, re)
{
- re = cregex_from("ab", 0);
+ re = cregex_from("ab");
csview m = {0};
int res;
-
- res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT);
- EXPECT_TRUE(res==1 && M_START(re, m) == 0);
- res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT);
- EXPECT_TRUE(res==1 && M_START(re, m) == 3);
- res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT);
- EXPECT_TRUE(res==1 && M_START(re, m) == 6);
- res = cregex_find("ab,ab,ab", &m, CREG_M_NEXT);
- EXPECT_NE(res, 1);
+ ASSERT_EQ(re.error, CREG_OK);
+ inp="ab,ab,ab";
+ res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ ASSERT_EQ(M_START(m), 0);
+ res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ ASSERT_EQ(res, CREG_OK);
+ ASSERT_EQ(M_START(m), 3);
+ res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ ASSERT_EQ(M_START(m), 6);
+ res = cregex_find(&re, inp, &m, CREG_M_NEXT);
+ ASSERT_NE(res, CREG_OK);
}
}
-END_TEST
-START_TEST(captures_len)
+CTEST(cregex, captures_len)
{
c_AUTO (cregex, re) {
- cregex re = cregex_from("(ab(cd))(ef)", 0);
- EXPECT_EQ(cregex_captures(&re), 3);
+ cregex re = cregex_from("(ab(cd))(ef)");
+ ASSERT_EQ(cregex_captures(&re), 4);
}
}
-END_TEST
-START_TEST(captures_cap)
+CTEST(cregex, captures_cap)
{
+ const char* inp;
c_AUTO (cregex, re) {
- re = cregex_from("(ab)((cd)+)", 0);
- EXPECT_EQ(cregex_captures(&re), 3);
+ re = cregex_from("(ab)((cd)+)");
+ ASSERT_EQ(cregex_captures(&re), 4);
csview cap[5];
- EXPECT_EQ(cregex_find("xxabcdcde", &re, cap, 0), 1);
- EXPECT_TRUE(csview_equals(cap.match[0], c_SV("abcdcd")));
- /*
- EXPECT_EQ(cap0.end, 8);
- EXPECT_EQ(cap1.start, 2);
- EXPECT_EQ(cap1.end, 4);
- EXPECT_EQ(cap2.start, 4);
- EXPECT_EQ(cap2.end, 8);
- */
- EXPECT_FALSE(cregex_is_match("abcdcde", &re));
- EXPECT_TRUE(cregex_is_match("abcdcdcd", &re));
+ ASSERT_EQ(cregex_find(&re, inp="xxabcdcde", cap), CREG_OK);
+ ASSERT_TRUE(csview_equals(cap[0], "abcdcd"));
+
+ ASSERT_EQ(M_END(cap[0]), 8);
+ ASSERT_EQ(M_START(cap[1]), 2);
+ ASSERT_EQ(M_END(cap[1]), 4);
+ ASSERT_EQ(M_START(cap[2]), 4);
+ ASSERT_EQ(M_END(cap[2]), 8);
+
+ ASSERT_TRUE(cregex_is_match(&re, "abcdcde"));
+ ASSERT_TRUE(cregex_is_match(&re, "abcdcdcd"));
}
}
-END_TEST
+static bool add_10_years(int i, csview match, cstr* out) {
+ if (i == 1) { // group 1 matches year
+ int year;
+ sscanf(match.str, "%4d", &year); // scan 4 chars only
+ cstr_printf(out, "%04d", year + 10);
+ return true;
+ }
+ return false;
+}
-int main()
+CTEST(cregex, replace)
{
- RUN_TEST(compile_match_char);
- RUN_TEST(compile_match_anchors);
- RUN_TEST(compile_match_quantifiers);
- RUN_TEST(compile_match_escaped_chars);
- RUN_TEST(compile_match_class_simple);
- RUN_TEST(compile_match_class_complex_0);
- RUN_TEST(compile_match_class_complex_1);
- RUN_TEST(compile_match_cap);
- RUN_TEST(search_all);
- RUN_TEST(captures_len);
- RUN_TEST(captures_cap);
- RUN_TEST(compile_match_or);
- return REPORT_TESTS();
+ const char* pattern = "\\b(\\d\\d\\d\\d)-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])\\b";
+ const char* input = "start date: 2015-12-31, end date: 2022-02-28";
+
+ c_AUTO (cstr, str) {
+ /* replace with a fixed string, extended all-in-one call: */
+ cstr_take(&str, cregex_replace_pattern(pattern, input, "YYYY-MM-DD"));
+ ASSERT_TRUE(cstr_equals(&str, "start date: YYYY-MM-DD, end date: YYYY-MM-DD"));
+
+ /* US date format, and add 10 years to dates: */
+ cstr_take(&str, cregex_replace_pattern(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT));
+ ASSERT_TRUE(cstr_equals(&str, "start date: 2025/31/12, end date: 2032/28/02"));
+
+ /* Wrap first date inside []: */
+ cstr_take(&str, cregex_replace_pattern(pattern, input, "[$0]", 1));
+ ASSERT_TRUE(cstr_equals(&str, "start date: [2015-12-31], end date: 2022-02-28"));
+
+ /* Wrap all words in ${} */
+ cstr_take(&str, cregex_replace_pattern("[a-z]+", "52 apples and 31 mangoes", "$${$0}"));
+ ASSERT_TRUE(cstr_equals(&str, "52 ${apples} ${and} 31 ${mangoes}"));
+
+ /* Compile RE separately */
+ c_WITH (cregex re = cregex_from(pattern), cregex_drop(&re)) {
+ ASSERT_EQ(cregex_captures(&re), 4);
+
+ /* European date format. */
+ cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1"));
+ ASSERT_TRUE(cstr_equals(&str, "start date: 31.12.2015, end date: 28.02.2022"));
+
+ /* Strip out everything but the matches */
+ cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP));
+ ASSERT_TRUE(cstr_equals(&str, "31.12.2015;28.02.2022;"));
+ }
+ }
}
-#endif
-
diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c
new file mode 100644
index 00000000..9e33467c
--- /dev/null
+++ b/misc/tests/cspan_test.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stc/cspan.h>
+#include "ctest.h"
+
+using_cspan3(intspan, int);
+
+
+CTEST(cspan, subdim) {
+ int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ intspan3 m = cspan_md(array, 2, 2, 3);
+
+ for (size_t i = 0; i < m.shape[0]; ++i) {
+ intspan2 sub_i = cspan_submd3(&m, i);
+ for (size_t j = 0; j < m.shape[1]; ++j) {
+ intspan sub_i_j = cspan_submd2(&sub_i, j);
+ for (size_t k = 0; k < m.shape[2]; ++k) {
+ ASSERT_EQ(*cspan_at(&sub_i_j, k), *cspan_at(&m, i, j, k));
+ }
+ }
+ }
+}
+
+CTEST(cspan, slice) {
+ int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+ intspan2 m1 = cspan_md(array, 3, 4);
+
+ size_t sum1 = 0;
+ for (size_t i = 0; i < m1.shape[0]; ++i) {
+ for (size_t j = 0; j < m1.shape[1]; ++j) {
+ sum1 += *cspan_at(&m1, i, j);
+ }
+ }
+
+ intspan2 m2 = cspan_slice(intspan2, &m1, {c_ALL}, {2,4});
+
+ size_t sum2 = 0;
+ for (size_t i = 0; i < m2.shape[0]; ++i) {
+ for (size_t j = 0; j < m2.shape[1]; ++j) {
+ sum2 += *cspan_at(&m2, i, j);
+ }
+ }
+ ASSERT_EQ(78, sum1);
+ ASSERT_EQ(45, sum2);
+}
+
+#define i_val int
+#include <stc/cstack.h>
+
+CTEST(cspan, slice2) {
+ c_AUTO (cstack_int, stack)
+ {
+ c_FORRANGE (i, 10*20*30)
+ cstack_int_push(&stack, i);
+
+ intspan3 ms3 = cspan_md(stack.data, 10, 20, 30);
+ ms3 = cspan_slice(intspan3, &ms3, {1,4}, {3,7}, {20,24});
+
+ size_t sum = 0;
+ for (size_t i = 0; i < ms3.shape[0]; ++i) {
+ for (size_t j = 0; j < ms3.shape[1]; ++j) {
+ for (size_t k = 0; k < ms3.shape[2]; ++k) {
+ sum += *cspan_at(&ms3, i, j, k);
+ }
+ }
+ }
+ ASSERT_EQ(65112, sum);
+
+ sum = 0;
+ c_FOREACH (i, intspan3, ms3)
+ sum += *i.ref;
+ ASSERT_EQ(65112, sum);
+ }
+}
+
+
+#define i_type Tiles
+#define i_val intspan3
+#include <stc/cstack.h>
+
+CTEST_FIXTURE(cspan_cube) {
+ cstack_int stack;
+ Tiles tiles;
+};
+
+CTEST_SETUP(cspan_cube) {
+ enum {TSIZE=4, CUBE=64, N=CUBE*CUBE*CUBE};
+
+ _self->stack = cstack_int_init();
+ _self->tiles = Tiles_init();
+
+ cstack_int_reserve(&_self->stack, N);
+ c_FORRANGE (i, N)
+ cstack_int_push(&_self->stack, i+1);
+
+ intspan3 ms3 = cspan_md(_self->stack.data, CUBE, CUBE, CUBE);
+
+ c_FORRANGE (i, 0, ms3.shape[0], TSIZE) {
+ c_FORRANGE (j, 0, ms3.shape[1], TSIZE) {
+ c_FORRANGE (k, 0, ms3.shape[2], TSIZE) {
+ intspan3 tile = cspan_slice(intspan3, &ms3, {i, i + TSIZE}, {j, j + TSIZE}, {k, k + TSIZE});
+ Tiles_push(&_self->tiles, tile);
+ }
+ }
+ }
+}
+
+// Optional teardown function for suite, called after every test in suite
+CTEST_TEARDOWN(cspan_cube) {
+ cstack_int_drop(&_self->stack);
+ Tiles_drop(&_self->tiles);
+}
+
+
+CTEST_F(cspan_cube, slice3) {
+ intptr_t n = cstack_int_size(&_self->stack);
+ //printf("\ntiles: %zi, cells: %zi\n", Tiles_size(&_self->tiles), n);
+
+ int64_t sum = 0;
+ // iterate each 3d tile in sequence
+ c_FOREACH (i, Tiles, _self->tiles)
+ c_FOREACH (t, intspan3, *i.ref)
+ sum += *t.ref;
+
+ ASSERT_EQ(n*(n + 1)/2, sum);
+}
diff --git a/misc/tests/ctest.h b/misc/tests/ctest.h
new file mode 100644
index 00000000..373cda0e
--- /dev/null
+++ b/misc/tests/ctest.h
@@ -0,0 +1,575 @@
+/* Copyright 2011-2023 Bas van den Berg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CTEST_H
+#define CTEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __GNUC__
+#define CTEST_IMPL_FORMAT_PRINTF(a, b) __attribute__ ((format(printf, a, b)))
+#else
+#define CTEST_IMPL_FORMAT_PRINTF(a, b)
+#endif
+
+#include <inttypes.h> /* intmax_t, uintmax_t, PRI* */
+#include <stdbool.h> /* bool, true, false */
+#include <stddef.h> /* size_t */
+
+typedef void (*ctest_nullary_run_func)(void);
+typedef void (*ctest_unary_run_func)(void*);
+typedef void (*ctest_setup_func)(void*);
+typedef void (*ctest_teardown_func)(void*);
+
+union ctest_run_func_union {
+ ctest_nullary_run_func nullary;
+ ctest_unary_run_func unary;
+};
+
+#define CTEST_IMPL_PRAGMA(x) _Pragma (#x)
+#define CTEST_CONTAINER_OF(p, T, m) \
+ ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m)))
+
+#if defined(__GNUC__)
+#if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+/* the GCC argument will work for both gcc and clang */
+#define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \
+ CTEST_IMPL_PRAGMA(GCC diagnostic push) \
+ CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w)
+#define CTEST_IMPL_DIAG_POP() \
+ CTEST_IMPL_PRAGMA(GCC diagnostic pop)
+#else
+/* the push/pop functionality wasn't in gcc until 4.6, fallback to "ignored" */
+#define CTEST_IMPL_DIAG_PUSH_IGNORED(w) \
+ CTEST_IMPL_PRAGMA(GCC diagnostic ignored "-W" #w)
+#define CTEST_IMPL_DIAG_POP()
+#endif
+#else
+/* leave them out entirely for non-GNUC compilers */
+#define CTEST_IMPL_DIAG_PUSH_IGNORED(w)
+#define CTEST_IMPL_DIAG_POP()
+#endif
+
+struct ctest {
+ uint32_t magic0, padding;
+
+ const char* ssname; // suite name
+ const char* ttname; // test name
+ union ctest_run_func_union run;
+
+ void* data;
+ ctest_setup_func* setup;
+ ctest_teardown_func* teardown;
+
+ int32_t skip;
+ uint32_t magic1;
+};
+
+#define CTEST_IMPL_NAME(name) ctest_##name
+#define CTEST_IMPL_FNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_run)
+#define CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname)
+#define CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_NAME(sname##_data)
+#define CTEST_IMPL_DATA_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_data)
+#define CTEST_IMPL_SETUP_FNAME(sname) CTEST_IMPL_NAME(sname##_setup)
+#define CTEST_IMPL_SETUP_FPNAME(sname) CTEST_IMPL_NAME(sname##_setup_ptr)
+#define CTEST_IMPL_SETUP_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_setup_ptr)
+#define CTEST_IMPL_TEARDOWN_FNAME(sname) CTEST_IMPL_NAME(sname##_teardown)
+#define CTEST_IMPL_TEARDOWN_FPNAME(sname) CTEST_IMPL_NAME(sname##_teardown_ptr)
+#define CTEST_IMPL_TEARDOWN_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_teardown_ptr)
+
+#ifdef __APPLE__
+#define CTEST_IMPL_SECTION __attribute__ ((used, section ("__DATA, .ctest"), aligned(1)))
+#elif !defined _MSC_VER
+#define CTEST_IMPL_SECTION __attribute__ ((used, section (".ctest"), aligned(1)))
+#else
+#define CTEST_IMPL_SECTION
+#endif
+
+#define CTEST_IMPL_STRUCT(sname, tname, tskip, tdata, tsetup, tteardown) \
+ static struct ctest CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_SECTION = { \
+ 0xBADCAFE0, 0, \
+ #sname, \
+ #tname, \
+ { (ctest_nullary_run_func) CTEST_IMPL_FNAME(sname, tname) }, \
+ tdata, \
+ (ctest_setup_func*) tsetup, \
+ (ctest_teardown_func*) tteardown, \
+ tskip, \
+ 0xBADCAFE1, \
+ }
+
+#ifdef __cplusplus
+
+#define CTEST_SETUP(sname) \
+ template <> void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#define CTEST_TEARDOWN(sname) \
+ template <> void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#define CTEST_FIXTURE(sname) \
+ template <typename T> void CTEST_IMPL_SETUP_FNAME(sname)(T* _self) { } \
+ template <typename T> void CTEST_IMPL_TEARDOWN_FNAME(sname)(T* _self) { } \
+ struct CTEST_IMPL_DATA_SNAME(sname)
+
+#define CTEST_IMPL_CTEST(sname, tname, tskip) \
+ static void CTEST_IMPL_FNAME(sname, tname)(void); \
+ CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \
+ static void CTEST_IMPL_FNAME(sname, tname)(void)
+
+#define CTEST_IMPL_CTEST_F(sname, tname, tskip) \
+ static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \
+ static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \
+ static void (*CTEST_IMPL_SETUP_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \
+ static void (*CTEST_IMPL_TEARDOWN_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \
+ CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_TPNAME(sname, tname), &CTEST_IMPL_TEARDOWN_TPNAME(sname, tname)); \
+ static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#else
+
+#define CTEST_SETUP(sname) \
+ static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \
+ static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname); \
+ static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#define CTEST_TEARDOWN(sname) \
+ static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \
+ static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname); \
+ static void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#define CTEST_FIXTURE(sname) \
+ struct CTEST_IMPL_DATA_SNAME(sname); \
+ static void (*CTEST_IMPL_SETUP_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \
+ static void (*CTEST_IMPL_TEARDOWN_FPNAME(sname))(struct CTEST_IMPL_DATA_SNAME(sname)*); \
+ struct CTEST_IMPL_DATA_SNAME(sname)
+
+#define CTEST_IMPL_CTEST(sname, tname, tskip) \
+ static void CTEST_IMPL_FNAME(sname, tname)(void); \
+ CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \
+ static void CTEST_IMPL_FNAME(sname, tname)(void)
+
+#define CTEST_IMPL_CTEST_F(sname, tname, tskip) \
+ static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \
+ static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self); \
+ CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_FPNAME(sname), &CTEST_IMPL_TEARDOWN_FPNAME(sname)); \
+ static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* _self)
+
+#endif
+
+void CTEST_LOG(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2);
+void CTEST_ERR(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); // doesn't return
+
+#define CTEST(sname, tname) CTEST_IMPL_CTEST(sname, tname, 0)
+#define CTEST_SKIP(sname, tname) CTEST_IMPL_CTEST(sname, tname, 1)
+
+#define CTEST_F(sname, tname) CTEST_IMPL_CTEST_F(sname, tname, 0)
+#define CTEST_F_SKIP(sname, tname) CTEST_IMPL_CTEST_F(sname, tname, 1)
+
+void assert_str(const char* cmp, const char* exp, const char* real, const char* caller, int line);
+#define ASSERT_STREQ(exp, real) assert_str("==", exp, real, __FILE__, __LINE__)
+#define ASSERT_STRNE(exp, real) assert_str("!=", exp, real, __FILE__, __LINE__)
+#define ASSERT_SUBSTR(substr, real) assert_str("=~", substr, real, __FILE__, __LINE__)
+#define ASSERT_NOT_SUBSTR(substr, real) assert_str("!~", substr, real, __FILE__, __LINE__)
+
+void assert_wstr(const char* cmp, const wchar_t *exp, const wchar_t *real, const char* caller, int line);
+#define ASSERT_WSTREQ(exp, real) assert_wstr("==", exp, real, __FILE__, __LINE__)
+#define ASSERT_WSTRNE(exp, real) assert_wstr("!=", exp, real, __FILE__, __LINE__)
+
+#define CTEST_FLT_EPSILON 1e-5
+#define CTEST_DBL_EPSILON 1e-12
+
+void assert_compare(const char* cmp, intmax_t exp, intmax_t real, const char* caller, int line);
+#define ASSERT_EQ(v1, v2) assert_compare("==", v1, v2, __FILE__, __LINE__)
+#define ASSERT_NE(v1, v2) assert_compare("!=", v1, v2, __FILE__, __LINE__)
+#define ASSERT_LT(v1, v2) assert_compare("<", v1, v2, __FILE__, __LINE__)
+#define ASSERT_LE(v1, v2) assert_compare("<=", v1, v2, __FILE__, __LINE__)
+#define ASSERT_GT(v1, v2) assert_compare(">", v1, v2, __FILE__, __LINE__)
+#define ASSERT_GE(v1, v2) assert_compare(">=", v1, v2, __FILE__, __LINE__)
+
+void assert_interval(intmax_t low, intmax_t high, intmax_t real, const char* caller, int line);
+#define ASSERT_INTERVAL(low, high, real) assert_interval(low, high, real, __FILE__, __LINE__)
+
+void assert_pointers(const char* cmp, const void* exp, const void* real, const char* caller, int line);
+#define ASSERT_PTR_EQ(exp, real) ((void)sizeof((exp) == (real)), assert_pointers("==", exp, real, __FILE__, __LINE__))
+#define ASSERT_PTR_NE(exp, real) ((void)sizeof((exp) != (real)), assert_pointers("!=", exp, real, __FILE__, __LINE__))
+#define ASSERT_NULL(real) ASSERT_PTR_EQ(NULL, real)
+#define ASSERT_NOT_NULL(real) ASSERT_PTR_NE(NULL, real)
+
+void assert_bool(bool exp, bool real, const char* caller, int line);
+#define ASSERT_TRUE(real) assert_bool(true, real, __FILE__, __LINE__)
+#define ASSERT_FALSE(real) assert_bool(false, real, __FILE__, __LINE__)
+
+void assert_fail(const char* caller, int line);
+#define ASSERT_FAIL() assert_fail(__FILE__, __LINE__)
+
+void assert_dbl_compare(const char* cmp, double exp, double real, double tol, const char* caller, int line);
+#define ASSERT_NEAR(exp, real, tol) assert_dbl_compare("==", exp, real, tol, __FILE__, __LINE__)
+#define ASSERT_NOT_NEAR(exp, real, tol) assert_dbl_compare("!=", exp, real, tol, __FILE__, __LINE__)
+#define ASSERT_DOUBLE_EQ(exp, real) assert_dbl_compare("==", exp, real, -CTEST_DBL_EPSILON, __FILE__, __LINE__)
+#define ASSERT_DOUBLE_NE(exp, real) assert_dbl_compare("!=", exp, real, -CTEST_DBL_EPSILON, __FILE__, __LINE__)
+#define ASSERT_DOUBLE_LT(v1, v2) assert_dbl_compare("<", v1, v2, 0.0, __FILE__, __LINE__)
+#define ASSERT_DOUBLE_GT(v1, v2) assert_dbl_compare(">", v1, v2, 0.0, __FILE__, __LINE__)
+
+#define ASSERT_FLOAT_EQ(v1, v2) assert_dbl_compare("==", v1, v2, -CTEST_FLT_EPSILON, __FILE__, __LINE__)
+#define ASSERT_FLOAT_NE(v1, v2) assert_dbl_compare("!=", v1, v2, -CTEST_FLT_EPSILON, __FILE__, __LINE__)
+#define ASSERT_FLOAT_LT(v1, v2) assert_dbl_compare("<", (float)(v1), (float)(v2), 0.0, __FILE__, __LINE__)
+#define ASSERT_FLOAT_GT(v1, v2) assert_dbl_compare(">", (float)(v1), (float)(v2), 0.0, __FILE__, __LINE__)
+
+#ifdef CTEST_MAIN
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#if !defined(_WIN32) || defined(__GNUC__)
+#include <unistd.h>
+#elif defined(_WIN32)
+#include <io.h>
+#endif
+#include <stdint.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+static size_t ctest_errorsize;
+static char* ctest_errormsg;
+#define MSG_SIZE 4096
+static char ctest_errorbuffer[MSG_SIZE];
+static jmp_buf ctest_err;
+static int color_output = 1;
+static const char* suite_name;
+
+typedef int (*ctest_filter_func)(struct ctest*);
+
+#define ANSI_BLACK "\033[0;30m"
+#define ANSI_RED "\033[0;31m"
+#define ANSI_GREEN "\033[0;32m"
+#define ANSI_YELLOW "\033[0;33m"
+#define ANSI_BLUE "\033[0;34m"
+#define ANSI_MAGENTA "\033[0;35m"
+#define ANSI_CYAN "\033[0;36m"
+#define ANSI_GREY "\033[0;37m"
+#define ANSI_DARKGREY "\033[01;30m"
+#define ANSI_BRED "\033[01;31m"
+#define ANSI_BGREEN "\033[01;32m"
+#define ANSI_BYELLOW "\033[01;33m"
+#define ANSI_BBLUE "\033[01;34m"
+#define ANSI_BMAGENTA "\033[01;35m"
+#define ANSI_BCYAN "\033[01;36m"
+#define ANSI_WHITE "\033[01;37m"
+#define ANSI_NORMAL "\033[0m"
+
+CTEST(suite, test) { }
+
+static void vprint_errormsg(const char* const fmt, va_list ap) CTEST_IMPL_FORMAT_PRINTF(1, 0);
+static void print_errormsg(const char* const fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2);
+
+static void vprint_errormsg(const char* const fmt, va_list ap) {
+ // (v)snprintf returns the number that would have been written
+ const int ret = vsnprintf(ctest_errormsg, ctest_errorsize, fmt, ap);
+ if (ret < 0) {
+ ctest_errormsg[0] = 0x00;
+ } else {
+ const size_t size = (size_t) ret;
+ const size_t s = (ctest_errorsize <= size ? size -ctest_errorsize : size);
+ // ctest_errorsize may overflow at this point
+ ctest_errorsize -= s;
+ ctest_errormsg += s;
+ }
+}
+
+static void print_errormsg(const char* const fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ vprint_errormsg(fmt, argp);
+ va_end(argp);
+}
+
+static void msg_start(const char* color, const char* title) {
+ if (color_output) {
+ print_errormsg("%s", color);
+ }
+ print_errormsg(" %s: ", title);
+}
+
+static void msg_end(void) {
+ if (color_output) {
+ print_errormsg(ANSI_NORMAL);
+ }
+ print_errormsg("\n");
+}
+
+void CTEST_LOG(const char* fmt, ...)
+{
+ va_list argp;
+ msg_start(ANSI_BLUE, "LOG");
+
+ va_start(argp, fmt);
+ vprint_errormsg(fmt, argp);
+ va_end(argp);
+
+ msg_end();
+}
+
+CTEST_IMPL_DIAG_PUSH_IGNORED(missing-noreturn)
+
+void CTEST_ERR(const char* fmt, ...)
+{
+ va_list argp;
+ msg_start(ANSI_YELLOW, "ERR");
+
+ va_start(argp, fmt);
+ vprint_errormsg(fmt, argp);
+ va_end(argp);
+
+ msg_end();
+ longjmp(ctest_err, 1);
+}
+
+CTEST_IMPL_DIAG_POP()
+
+void assert_str(const char* cmp, const char* exp, const char* real, const char* caller, int line) {
+ if ((!exp ^ !real) || (exp && (
+ (cmp[1] == '=' && ((cmp[0] == '=') ^ (strcmp(real, exp) == 0))) ||
+ (cmp[1] == '~' && ((cmp[0] == '=') ^ (strstr(real, exp) != NULL)))
+ ))) {
+ CTEST_ERR("%s:%d assertion failed, '%s' %s '%s'", caller, line, exp, cmp, real);
+ }
+}
+
+void assert_wstr(const char* cmp, const wchar_t *exp, const wchar_t *real, const char* caller, int line) {
+ if ((!exp ^ !real) || (exp && (
+ (cmp[1] == '=' && ((cmp[0] == '=') ^ (wcscmp(real, exp) == 0))) ||
+ (cmp[1] == '~' && ((cmp[0] == '=') ^ (wcsstr(real, exp) != NULL)))
+ ))) {
+ CTEST_ERR("%s:%d assertion failed, '%ls' %s '%ls'", caller, line, exp, cmp, real);
+ }
+}
+
+static bool get_compare_result(const char* cmp, int c3, bool eq) {
+ if (cmp[0] == '<')
+ return c3 < 0 || ((cmp[1] == '=') & eq);
+ if (cmp[0] == '>')
+ return c3 > 0 || ((cmp[1] == '=') & eq);
+ return (cmp[0] == '=') == eq;
+}
+
+void assert_compare(const char* cmp, intmax_t exp, intmax_t real, const char* caller, int line) {
+ int c3 = (real < exp) - (exp < real);
+
+ if (!get_compare_result(cmp, c3, c3 == 0)) {
+ CTEST_ERR("%s:%d assertion failed, %" PRIdMAX " %s %" PRIdMAX "", caller, line, exp, cmp, real);
+ }
+}
+
+void assert_interval(intmax_t low, intmax_t high, intmax_t real, const char* caller, int line) {
+ if (real < low || real > high) {
+ CTEST_ERR("%s:%d expected %" PRIdMAX "-%" PRIdMAX ", got %" PRIdMAX, caller, line, low, high, real);
+ }
+}
+
+static bool approximately_equal(double a, double b, double epsilon) {
+ double d = a - b;
+ if (d < 0) d = -d;
+ if (a < 0) a = -a;
+ if (b < 0) b = -b;
+ return d <= (a > b ? a : b)*epsilon; /* D.Knuth */
+}
+
+/* tol < 0 means it is an epsilon, else absolute error */
+void assert_dbl_compare(const char* cmp, double exp, double real, double tol, const char* caller, int line) {
+ double diff = exp - real;
+ double absdiff = diff < 0 ? -diff : diff;
+ int c3 = (real < exp) - (exp < real);
+ bool eq = tol < 0 ? approximately_equal(exp, real, -tol) : absdiff <= tol;
+
+ if (!get_compare_result(cmp, c3, eq)) {
+ const char* tolstr = "tol";
+ if (tol < 0) {
+ tolstr = "eps";
+ tol = -tol;
+ }
+ CTEST_ERR("%s:%d assertion failed, %.8g %s %.8g (diff %.4g, %s %.4g)", caller, line, exp, cmp, real, diff, tolstr, tol);
+ }
+}
+
+void assert_pointers(const char* cmp, const void* exp, const void* real, const char* caller, int line) {
+ if ((exp == real) != (cmp[0] == '=')) {
+ CTEST_ERR("%s:%d assertion failed (0x%02llx) %s (0x%02llx)", caller, line, (unsigned long long)exp , cmp, (unsigned long long)real);
+ }
+}
+
+void assert_bool(bool exp, bool real, const char* caller, int line) {
+ if (exp != real) {
+ CTEST_ERR("%s:%d should be %s", caller, line, exp ? "true" : "false");
+ }
+}
+
+void assert_fail(const char* caller, int line) {
+ CTEST_ERR("%s:%d shouldn't come here", caller, line);
+}
+
+
+static int suite_all(struct ctest* t) {
+ (void) t; // avoid unused parameter warning
+ return 1;
+}
+
+static int suite_filter(struct ctest* t) {
+ return strncmp(suite_name, t->ssname, strlen(suite_name)) == 0;
+}
+
+static void color_print(const char* color, const char* text) {
+ if (color_output)
+ printf("%s%s" ANSI_NORMAL "\n", color, text);
+ else
+ printf("%s\n", text);
+}
+
+#ifndef CTEST_NO_SEGFAULT
+#include <signal.h>
+static void sighandler(int signum)
+{
+ const char msg_color[] = ANSI_BRED "[SIGSEGV: Segmentation fault]" ANSI_NORMAL "\n";
+ const char msg_nocolor[] = "[SIGSEGV: Segmentation fault]\n";
+
+ const char* msg = color_output ? msg_color : msg_nocolor;
+ intptr_t n = write(1, msg, (unsigned int)strlen(msg));
+ (void)n;
+ /* "Unregister" the signal handler and send the signal back to the process
+ * so it can terminate as expected */
+ signal(signum, SIG_DFL);
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ kill(getpid(), signum);
+#endif
+}
+#endif
+
+int ctest_main(int argc, const char *argv[]);
+#ifdef __GNUC__
+__attribute__((no_sanitize_address))
+#endif
+int ctest_main(int argc, const char *argv[])
+{
+ static int total = 0;
+ static int num_ok = 0;
+ static int num_fail = 0;
+ static int num_skip = 0;
+ static int idx = 1;
+ static ctest_filter_func filter = suite_all;
+
+#ifndef CTEST_NO_SEGFAULT
+ signal(SIGSEGV, sighandler);
+#endif
+
+ if (argc == 2) {
+ suite_name = argv[1];
+ filter = suite_filter;
+ }
+#ifdef CTEST_NO_COLORS
+ color_output = 0;
+#else
+ color_output = isatty(1);
+#endif
+ clock_t t1 = clock();
+
+ uint32_t* magic_begin = &CTEST_IMPL_TNAME(suite, test).magic1;
+ uint32_t* magic_end = &CTEST_IMPL_TNAME(suite, test).magic0, *m;
+ size_t num_ints = sizeof(struct ctest)/sizeof *m;
+
+#if (defined __TINYC__ && defined __unix__)
+ #define CTEST_IMPL_MAGIC_SEEK 10 /* search 4*(1+10) bytes outside ctest entry bounds */
+#else
+ #define CTEST_IMPL_MAGIC_SEEK 0 /* access only 4 bytes outside outer ctest entry bounds */
+#endif
+ for (m = magic_begin; magic_begin - m <= num_ints + CTEST_IMPL_MAGIC_SEEK; --m) {
+ if (*m == 0xBADCAFE1) {
+ magic_begin = m;
+ m -= num_ints - 1;
+ }
+ }
+ for (m = magic_end; m - magic_end <= num_ints; ++m) {
+ if (*m == 0xBADCAFE0) {
+ magic_end = m;
+ m += num_ints - 1;
+ }
+ }
+ magic_begin = &CTEST_CONTAINER_OF(magic_begin, struct ctest, magic1)->magic0;
+
+ static struct ctest* test;
+ for (m = magic_begin; m <= magic_end; m += num_ints) {
+ while (*m != 0xBADCAFE0) ++m;
+ test = CTEST_CONTAINER_OF(m, struct ctest, magic0);
+ if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
+ if (filter(test)) total++;
+ }
+
+ for (m = magic_begin; m <= magic_end; m += num_ints) {
+ while (*m != 0xBADCAFE0) ++m;
+ test = CTEST_CONTAINER_OF(m, struct ctest, magic0);
+ if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
+ if (filter(test)) {
+ ctest_errorbuffer[0] = 0;
+ ctest_errorsize = MSG_SIZE-1;
+ ctest_errormsg = ctest_errorbuffer;
+ printf("TEST %d/%d %s:%s ", idx, total, test->ssname, test->ttname);
+ fflush(stdout);
+ if (test->skip) {
+ color_print(ANSI_BYELLOW, "[SKIPPED]");
+ num_skip++;
+ } else {
+ int result = setjmp(ctest_err);
+ if (result == 0) {
+ if (test->setup && *test->setup) (*test->setup)(test->data);
+ if (test->data)
+ test->run.unary(test->data);
+ else
+ test->run.nullary();
+ if (test->teardown && *test->teardown) (*test->teardown)(test->data);
+ // if we got here it's ok
+#ifdef CTEST_NO_COLOR_OK
+ printf("[OK]\n");
+#else
+ color_print(ANSI_BGREEN, "[OK]");
+#endif
+ num_ok++;
+ } else {
+ color_print(ANSI_BRED, "[FAIL]");
+ num_fail++;
+ }
+ if (ctest_errorsize != MSG_SIZE-1) printf("%s", ctest_errorbuffer);
+ }
+ idx++;
+ }
+ }
+ clock_t t2 = clock();
+
+ const char* color = (num_fail) ? ANSI_BRED : ANSI_GREEN;
+ char results[80];
+ snprintf(results, sizeof(results), "RESULTS: %d tests (%d ok, %d failed, %d skipped) ran in %.1f ms",
+ total, num_ok, num_fail, num_skip, (double)(t2 - t1)*1000.0/CLOCKS_PER_SEC);
+ color_print(color, results);
+ return num_fail;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/misc/tests/main.c b/misc/tests/main.c
new file mode 100644
index 00000000..2b8931c4
--- /dev/null
+++ b/misc/tests/main.c
@@ -0,0 +1,31 @@
+/* Copyright 2011-2023 Bas van den Berg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#define CTEST_MAIN
+
+// uncomment lines below to enable/disable features. See README.md for details
+//#define CTEST_NO_SEGFAULT
+//#define CTEST_NO_COLORS
+//#define CTEST_NO_COLOR_OK
+
+#include "ctest.h"
+
+int main(int argc, const char *argv[])
+{
+ return ctest_main(argc, argv);
+}
+
diff --git a/misc/tests/mytests.c.txt b/misc/tests/mytests.c.txt
new file mode 100644
index 00000000..54413e42
--- /dev/null
+++ b/misc/tests/mytests.c.txt
@@ -0,0 +1,233 @@
+/* Copyright 2011-2023 Bas van den Berg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "ctest.h"
+
+// basic test without setup/teardown
+CTEST(suite1, test1) {
+}
+
+// there are many different ASSERT macro's (see ctest.h)
+CTEST(suite1, test2) {
+ ASSERT_EQ(1,2);
+}
+
+CTEST(suite2, test1) {
+ ASSERT_STREQ("foo", "bar");
+}
+
+CTEST(suite3, test3) {
+}
+
+
+// A test suite with a setup/teardown function
+// This is converted into a struct that's automatically passed to all tests in the suite
+CTEST_FIXTURE(memtest) {
+ unsigned char* buffer;
+};
+
+// Optional setup function for suite, called before every test in suite
+CTEST_SETUP(memtest) {
+ CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer);
+ self->buffer = (unsigned char*)malloc(1024);
+}
+
+// Optional teardown function for suite, called after every test in suite
+CTEST_TEARDOWN(memtest) {
+ CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer);
+ if (self->buffer) free(self->buffer);
+}
+
+// These tests are called with the struct* (named self) as argument
+CTEST_F(memtest, test1) {
+ CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer);
+}
+
+CTEST_F_SKIP(memtest, test3) {
+ (void)self;
+ ASSERT_FAIL();
+}
+
+CTEST_F(memtest, test2) {
+ CTEST_LOG("%s() data=%p buffer=%p", __func__, (void*)self, (void*)self->buffer);
+ ASSERT_FAIL();
+}
+
+
+CTEST_FIXTURE(fail) {
+ int unused;
+};
+
+// Asserts can also be used in setup/teardown functions
+CTEST_SETUP(fail) {
+ (void)self;
+ ASSERT_FAIL();
+}
+
+CTEST_F(fail, test1) {
+ (void)self;
+}
+
+
+
+CTEST_FIXTURE(weaklinkage) {
+ int number;
+};
+
+// This suite has data, but no setup/teardown
+CTEST_F(weaklinkage, test1) {
+ (void)self;
+ CTEST_LOG("%s()", __func__);
+}
+
+CTEST_F(weaklinkage, test2) {
+ (void)self;
+ CTEST_LOG("%s()", __func__);
+}
+
+
+CTEST_FIXTURE(nosetup) {
+ int value;
+};
+
+CTEST_TEARDOWN(nosetup) {
+ (void)self;
+ CTEST_LOG("%s()", __func__);
+}
+
+CTEST_F(nosetup, test1) {
+ (void)self;
+ CTEST_LOG("%s()", __func__);
+}
+
+
+// more ASSERT examples
+CTEST(ctest, test_assert_str) {
+ ASSERT_STREQ("foo", "foo");
+ ASSERT_STREQ("foo", "bar");
+}
+
+CTEST(ctest, test_assert_equal) {
+ ASSERT_EQ(123, 123);
+ ASSERT_EQ(123, 456);
+}
+
+CTEST(ctest, test_assert_not_equal) {
+ ASSERT_NE(123, 456);
+ ASSERT_NE(123, 123);
+}
+
+CTEST(ctest, test_assert_interval) {
+ ASSERT_INTERVAL(10, 20, 15);
+ ASSERT_INTERVAL(1000, 2000, 3000);
+}
+
+CTEST(ctest, test_assert_null) {
+ ASSERT_NULL(NULL);
+ ASSERT_NULL((void*)0xdeadbeef);
+}
+
+CTEST(ctest, test_assert_not_null_const) {
+ char *p = NULL;
+ ASSERT_PTR_NE(p, (const char*)"hallo");
+}
+
+CTEST(ctest, test_assert_true) {
+ ASSERT_TRUE(1);
+ ASSERT_TRUE(0);
+}
+
+CTEST(ctest, test_assert_false) {
+ ASSERT_FALSE(0);
+ ASSERT_FALSE(1);
+}
+
+CTEST_SKIP(ctest, test_skip) {
+ ASSERT_FAIL();
+}
+
+CTEST(ctest, test_assert_fail) {
+ ASSERT_FAIL();
+}
+
+/* Test that NULL-strings won't result in segv */
+CTEST(ctest, test_null_null) {
+ ASSERT_STREQ(NULL, NULL);
+}
+
+CTEST(ctest, test_null_string) {
+ ASSERT_STREQ(NULL, "shouldfail");
+}
+
+CTEST(ctest, test_string_null) {
+ ASSERT_STREQ("shouldfail", NULL);
+}
+
+CTEST(ctest, test_string_diff_ptrs) {
+ const char *str = "abc\0abc";
+ ASSERT_STREQ(str, str+4);
+}
+
+CTEST(ctest, test_large_numbers) {
+ unsigned long exp = 4200000000u;
+ ASSERT_EQ(exp, 4200000000u);
+ ASSERT_NE(exp, 1200000000u);
+}
+
+CTEST(ctest, test_ctest_err) {
+ CTEST_ERR("error log");
+}
+
+CTEST(ctest, test_dbl_near) {
+ double a = 0.000111;
+ ASSERT_DOUBLE_EQ(0.0001, a);
+}
+
+CTEST(ctest, test_dbl_near_tol) {
+ double a = 0.000111;
+ ASSERT_NEAR(0.0001, a, 1e-5); /* will fail */
+}
+
+CTEST(ctest, test_dbl_far) {
+ double a = 1.1;
+ ASSERT_DOUBLE_NE(1., a);
+ ASSERT_NOT_NEAR(1., a, 0.01);
+}
+
+CTEST(ctest, test_assert_compare) {
+ ASSERT_LT(123, 456);
+ ASSERT_GE(123, 123);
+ ASSERT_GT(99, 100);
+}
+
+CTEST(ctest, test_dbl_near2) {
+ float a = 0.000001000003f;
+ ASSERT_FLOAT_EQ(0.000001f, a); /* ok, uses float epsilon -1e-5 */
+ ASSERT_NEAR(0.000001, a, -1e-5); /* ok, tol < 0 = relative err (epsilon) */
+ ASSERT_DOUBLE_EQ(0.000001, a); /* fail, tol = -1e-12 (epsilon) */
+}
+
+CTEST(ctest, test_dbl_compare) {
+ float a = 0.000001000003f;
+ ASSERT_DOUBLE_LT(0.000001, a);
+ ASSERT_DOUBLE_GT(0.000001, a); /* fail */
+}
+
+CTEST(ctest, test_str_contains) {
+ ASSERT_STRNE("Hello", "World");
+ ASSERT_SUBSTR("ello", "Hello");
+ ASSERT_NOT_SUBSTR("Hell", "Hello");
+}