diff options
| author | Tyge Løvset <[email protected]> | 2023-02-04 23:35:56 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-02-04 23:35:56 +0100 |
| commit | adc47cefc2976768c3f0b773bd26bfd1062e8a53 (patch) | |
| tree | 4923f88afb0d091d5d39ae03d65a4998a0517652 /misc | |
| parent | 0c4c4f8bba17562735b67b2923cd23c773aa53a7 (diff) | |
| parent | d2ff84c53aa9bd3857fdf22dcf7cd9398a4780be (diff) | |
| download | STC-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')
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"); +} |
