diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/stc/algo/crange.h | 72 | ||||
| -rw-r--r-- | include/stc/algo/csort.h | 127 | ||||
| -rw-r--r-- | include/stc/algo/cspan.h | 77 | ||||
| -rw-r--r-- | include/stc/algo/filter.h | 78 | ||||
| -rw-r--r-- | include/stc/carc.h | 15 | ||||
| -rw-r--r-- | include/stc/carr2.h | 152 | ||||
| -rw-r--r-- | include/stc/carr3.h | 157 | ||||
| -rw-r--r-- | include/stc/cbox.h | 22 | ||||
| -rw-r--r-- | include/stc/ccommon.h | 1 | ||||
| -rw-r--r-- | include/stc/cregex.h | 8 | ||||
| -rw-r--r-- | include/stc/cstack.h | 2 | ||||
| -rw-r--r-- | include/stc/cstr.h | 16 | ||||
| -rw-r--r-- | include/stc/priv/allcaps.h | 56 | ||||
| -rw-r--r-- | include/stc/views.h | 142 |
14 files changed, 446 insertions, 479 deletions
diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h new file mode 100644 index 00000000..ccdd13ae --- /dev/null +++ b/include/stc/algo/crange.h @@ -0,0 +1,72 @@ +/* MIT License + * + * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ +/* +#include <stdio.h> +#include <stc/algo/filter.h> +#include <stc/algo/crange.h> + +int main() +{ + crange r1 = crange_make(80, 90); + c_foreach (i, crange, r1) + printf(" %lld", *i.ref); + puts(""); + + // use a temporary crange object. + int a = 100, b = INT32_MAX; + c_forfilter (i, crange, crange_LITERAL(a, b, 8) + , i.index > 10 + , c_flt_take(i, 3)) + printf(" %lld", *i.ref); + puts(""); +} +*/ +#ifndef STC_CRANGE_H_INCLUDED +#define STC_CRANGE_H_INCLUDED + +#include <stc/ccommon.h> + +#define crange_LITERAL(...) \ + (*(crange[]){crange_make(__VA_ARGS__)}) + +typedef long long crange_value; +typedef struct { crange_value start, end, step, value; } crange; +typedef struct { crange_value *ref, end, step; } crange_iter; + +#define crange_make(...) c_MACRO_OVERLOAD(crange_make, __VA_ARGS__) +#define crange_make1(stop) crange_make3(0, stop, 1) +#define crange_make2(start, stop) crange_make3(start, stop, 1) + +STC_INLINE crange crange_make3(crange_value start, crange_value stop, crange_value step) + { crange r = {start, stop - (step > 0), step}; return r; } + +STC_INLINE crange_iter crange_begin(crange* self) + { self->value = self->start; crange_iter it = {&self->value, self->end, self->step}; return it; } + +STC_INLINE crange_iter crange_end(crange* self) + { crange_iter it = {NULL}; return it; } + +STC_INLINE void crange_next(crange_iter* it) + { *it->ref += it->step; if ((it->step > 0) == (*it->ref > it->end)) it->ref = NULL; } + +#endif diff --git a/include/stc/algo/csort.h b/include/stc/algo/csort.h new file mode 100644 index 00000000..9b115398 --- /dev/null +++ b/include/stc/algo/csort.h @@ -0,0 +1,127 @@ +/* MIT License + * + * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef STC_CSORT_H_INCLUDED +#define STC_CSORT_H_INCLUDED +#include <stdint.h> +#define c_CONCAT(a, b) a ## b +#define c_PASTE(a, b) c_CONCAT(a, b) +#endif + +/* Generic Quicksort in C +template params: +#define i_val - value type [required] +#define i_less - less function. default: *x < *y +#define i_tag NAME - define csort_NAME(). default {i_val} + +// test: +#include <stdio.h> +#include <time.h> +#include <stdlib.h> +#define i_val int +#include <stc/crandom.h> +#include <stc/algo/csort.h> +#ifdef __cplusplus +#include <algorithm> +#endif + +int testsort(csortval_int *a, size_t size, const char *desc) { + clock_t t = clock(); +#ifdef __cplusplus + puts("std::sort"); + std::sort(a, a + size); +#else + puts("csort"); + csort_int(a, size); +#endif + t = clock() - t; + + printf("%s: %zu elements sorted in %.3fms\n", + desc, size, t * 1000.0 / CLOCKS_PER_SEC); + return 0; +} + +int main(int argc, char *argv[]) { + size_t i, size = argc > 1 ? strtoull(argv[1], NULL, 0) : 10000000; + csortval_int *a = (csortval_int*)malloc(sizeof(*a) * size); + if (a != NULL) { + for (i = 0; i < size; i++) + a[i] = crandom() & (1U << 28) - 1; + testsort(a, size, "random"); + for (i = 0; i < 20; i++) printf(" %d", a[i]); + puts(""); + testsort(a, size, "sorted"); + for (i = 0; i < size; i++) a[i] = size - i; + testsort(a, size, "reverse sorted"); + for (i = 0; i < size; i++) a[i] = 126735; + testsort(a, size, "constant"); + free(a); + } + return 0; +}*/ +#ifndef i_tag +#define i_tag i_val +#endif +#ifndef i_less +#define i_less(x, y) *x < *y +#endif + +typedef i_val c_PASTE(csortval_, i_tag); + +static inline void c_PASTE(cisort_, i_tag)(i_val arr[], intptr_t low, intptr_t high) { + for (intptr_t j = low, i = low+1; i <= high; j = i, ++i) { + i_val key = arr[i]; + while (j >= 0 && (i_less((&key), (&arr[j])))) { + arr[j + 1] = arr[j]; + --j; + } + arr[j + 1] = key; + } +} + +static inline void c_PASTE(cqsort_, i_tag)(i_val arr[], intptr_t low, intptr_t high) +{ + intptr_t i = low, j = high; + i_val pivot = arr[(i + j)/2]; + + while (i <= j) { + while (i_less((&arr[i]), (&pivot))) ++i; + while (i_less((&pivot), (&arr[j]))) --j; + if (i <= j) { + i_val t = arr[i]; arr[i] = arr[j]; arr[j] = t; + ++i; --j; + } + } + if (j > low) j - low < 65 ? c_PASTE(cisort_, i_tag)(arr, low, j) + : c_PASTE(cqsort_, i_tag)(arr, low, j); + if (i < high) high - i < 65 ? c_PASTE(cisort_, i_tag)(arr, i, high) + : c_PASTE(cqsort_, i_tag)(arr, i, high); +} + +static inline void c_PASTE(csort_, i_tag)(i_val arr[], size_t elements) +{ + elements < 65 ? c_PASTE(cisort_, i_tag)(arr, 0, (intptr_t)elements - 1) + : c_PASTE(cqsort_, i_tag)(arr, 0, (intptr_t)elements - 1); +} +#undef i_tag +#undef i_val +#undef i_less diff --git a/include/stc/algo/cspan.h b/include/stc/algo/cspan.h new file mode 100644 index 00000000..d6d6dd56 --- /dev/null +++ b/include/stc/algo/cspan.h @@ -0,0 +1,77 @@ +/* MIT License + * + * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ +/* +#include <stdio.h> +#include <stc/algo/cspan.h> +using_cspan(IntSpan, int); + +int main() +{ + int array[] = {1, 2, 3, 4, 5}; + IntSpan iv = {array, c_arraylen(array)}; + + c_foreach (i, IntSpan, iv) + printf(" %d", *i.ref); + puts(""); + + // use a temporary IntSpan object. + c_forfilter (i, IntSpan, cspan_LITERAL(IntSpan, {10, 20, 30, 23, 22, 21}) + , c_flt_skipwhile(i, *i.ref < 25) + && (*i.ref & 1) == 0 // even only + , c_flt_take(i, 2)) // break after 2 + printf(" %d", *i.ref); + puts(""); +} +*/ +#ifndef STC_CSPAN_H_INCLUDED +#define STC_CSPAN_H_INCLUDED + +#include <stc/ccommon.h> + +#define cspan_LITERAL(C, ...) \ + ((C){.data = (C##_value[])__VA_ARGS__, \ + .size = sizeof((C##_value[])__VA_ARGS__)/sizeof(C##_value)}) + +#define using_cspan(Self, T) \ +typedef T Self##_raw; typedef const Self##_raw Self##_value; \ +typedef struct { Self##_value *data; size_t size; } Self; \ +typedef struct { Self##_value *ref, *end; } Self##_iter; \ + \ +STC_INLINE Self##_value* Self##_at(const Self* self, size_t idx) \ + { assert(idx < self->size); return self->data + idx; } \ + \ +STC_INLINE Self##_iter Self##_begin(const Self* self) { \ + Self##_iter it = {self->data, self->data + self->size}; \ + return it; \ +} \ + \ +STC_INLINE Self##_iter Self##_end(const Self* self) { \ + Self##_iter it = {NULL, self->data + self->size}; \ + return it; \ +} \ + \ +STC_INLINE void Self##_next(Self##_iter* it) \ + { if (++it->ref == it->end) it->ref = NULL; } \ +struct stc_nostruct + +#endif diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h new file mode 100644 index 00000000..10aeb7e7 --- /dev/null +++ b/include/stc/algo/filter.h @@ -0,0 +1,78 @@ +/* MIT License + * + * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. +*/ +/* +#include <stdio.h> +#define i_val int +#include <stc/cstack.h> +#include <stc/algo/filter.h> + +int main() +{ + c_WITH (cstack_int stk = {0}, cstack_int_drop(&stk)) { + c_FORLIST (i, int, {1, 2, 3, 4, 5, 6, 7, 8, 9}) + cstack_int_push(&stk, i); + + c_FOREACH (i, cstack_int, stk) + printf(" %d", *i.ref); + puts(""); + + c_FORFILTER (i, cstack_int, stk + , c_flt_skipwhile(i, *i.ref < 3) + && (*i.ref & 1) == 0 // even only + , c_flt_take(i, 2)) // break after 2 + printf(" %d", *i.ref); + puts(""); + } +} +*/ +#ifndef STC_FILTER_H_INCLUDED +#define STC_FILTER_H_INCLUDED + +#include <stc/ccommon.h> + +#ifndef c_NFILTERS + #define c_NFILTERS 14 /* 22, 30, .. */ +#endif + +#define c_flt_take(i, n) (++(i).s1[(i).s1top++] <= (n)) +#define c_flt_skip(i, n) (++(i).s1[(i).s1top++] > (n)) +#define c_flt_skipwhile(i, pred) ((i).s2[(i).s2top++] |= !(pred)) +#define c_flt_takewhile(i, pred) !c_flt_skipwhile(i, pred) + +#define c_forfilter(...) c_MACRO_OVERLOAD(c_forfilter, __VA_ARGS__) + +#define c_forfilter4(i, C, cnt, filter) \ + c_forfilter_b(i, C, C##_begin(&cnt), filter) + +#define c_forfilter5(i, C, cnt, filter, cond) \ + c_forfilter_b(i, C, C##_begin(&cnt), filter) if (!(cond)) break; else + +#define c_forfilter_b(i, C, start, filter) \ + for (struct {C##_iter it; C##_value *ref; \ + uint32_t s1[c_NFILTERS], index, count; \ + bool s2[c_NFILTERS]; uint8_t s1top, s2top;} \ + i = {.it=start, .ref=i.it.ref}; i.it.ref \ + ; C##_next(&i.it), i.ref = i.it.ref, ++i.index, i.s1top=0, i.s2top=0) \ + if (!((filter) && ++i.count)) ; else + +#endif diff --git a/include/stc/carc.h b/include/stc/carc.h index 22453f1d..f14fdd65 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -72,7 +72,6 @@ int main() { #endif #define carc_NULL {NULL, NULL} -#define _cx_carc_rep struct _cx_memb(_rep_) #endif // CARC_H_INCLUDED #ifndef _i_prefix @@ -91,7 +90,7 @@ typedef i_keyraw _cx_raw; #if !c_option(c_is_forward) _cx_deftypes(_c_carc_types, _cx_self, i_key); #endif -_cx_carc_rep { catomic_long counter; i_key value; }; +struct _cx_memb(_rep_) { catomic_long counter; i_key value; }; STC_INLINE _cx_self _cx_memb(_init)(void) { return c_INIT(_cx_self){NULL, NULL}; } @@ -109,7 +108,7 @@ STC_INLINE _cx_self _cx_memb(_from_ptr)(_cx_value* p) { // c++: std::make_shared<_cx_value>(val) STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { _cx_self ptr; - _cx_carc_rep *rep = c_alloc(_cx_carc_rep); + struct _cx_memb(_rep_)* rep = c_alloc(struct _cx_memb(_rep_)); *(ptr.use_count = &rep->counter) = 1; *(ptr.get = &rep->value) = val; return ptr; @@ -127,7 +126,7 @@ STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->use_count && _i_atomic_dec_and_test(self->use_count)) { i_keydrop(self->get); - if ((char *)self->get != (char *)self->use_count + offsetof(_cx_carc_rep, value)) + if ((char *)self->get != (char *)self->use_count + offsetof(struct _cx_memb(_rep_), value)) c_free(self->get); c_free((long*)self->use_count); } @@ -158,17 +157,17 @@ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) { return ptr; } -STC_INLINE void _cx_memb(_copy)(_cx_self* self, _cx_self ptr) { +STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) { if (ptr.use_count) _i_atomic_inc(ptr.use_count); _cx_memb(_drop)(self); *self = ptr; } -STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self ptr) { - if (self->get != ptr.get) +STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) { + if (self->get != unowned.get) _cx_memb(_drop)(self); - *self = ptr; + *self = unowned; } #ifndef i_no_cmp diff --git a/include/stc/carr2.h b/include/stc/carr2.h deleted file mode 100644 index 89ae9b77..00000000 --- a/include/stc/carr2.h +++ /dev/null @@ -1,152 +0,0 @@ -/* MIT License - * - * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "ccommon.h" - -#ifndef CARR2_H_INCLUDED -#define CARR2_H_INCLUDED -#include "forward.h" -#include <stdlib.h> -#endif -/* -// carr2- 2D dynamic array in one memory block with easy indexing. -#define i_key int -#include <stc/carr2.h> -#include <stdio.h> - -int main() { - int w = 7, h = 5; - c_with (carr2_int image = carr2_int_new_uninit(w, h), carr2_int_drop(&image)) - { - int *dat = carr2_int_data(&image); - for (int i = 0; i < carr2_int_size(&image); ++i) - dat[i] = i; - - for (int x = 0; x < image.xdim; ++x) - for (int y = 0; y < image.ydim; ++y) - printf(" %d", image.data[x][y]); - puts("\n"); - - c_foreach (i, carr2_int, image) - printf(" %d", *i.ref); - puts(""); - } -} -*/ - -#ifndef _i_prefix -#define _i_prefix carr2_ -#endif -#include "priv/template.h" -#if !c_option(c_is_forward) -_cx_deftypes(_c_carr2_types, _cx_self, i_key); -#endif - -STC_API _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, i_key null); -STC_API _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, _cx_value* storage); -STC_API _cx_value* _cx_memb(_release)(_cx_self* self); -STC_API void _cx_memb(_drop)(_cx_self* self); -#if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self src); -STC_API void _cx_memb(_copy)(_cx_self *self, const _cx_self* other); -#endif - -STC_INLINE _cx_self _cx_memb(_new_uninit)(size_t xdim, size_t ydim) { - return _cx_memb(_with_data)(xdim, ydim, c_alloc_n(_cx_value, xdim*ydim)); -} -STC_INLINE size_t _cx_memb(_size)(const _cx_self* self) - { return self->xdim*self->ydim; } - -STC_INLINE _cx_value *_cx_memb(_data)(_cx_self* self) - { return *self->data; } - -STC_INLINE const _cx_value *_cx_memb(_at)(const _cx_self* self, size_t x, size_t y) { - assert(x < self->xdim && y < self->ydim); - return *self->data + self->ydim*x + y; -} - -STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y) { - return self->ydim*x + y; -} - - -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - size_t n = self->xdim*self->ydim; - return c_INIT(_cx_iter){n ? *self->data : NULL, *self->data + n}; -} - -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL, *self->data + self->xdim*self->ydim}; } - -STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { if (++it->ref == it->end) it->ref = NULL; } - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) - -STC_DEF _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, _cx_value* block) { - _cx_self _arr = {c_alloc_n(_cx_value*, xdim), xdim, ydim}; - for (size_t x = 0; x < xdim; ++x, block += ydim) - _arr.data[x] = block; - return _arr; -} - -STC_DEF _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, i_key null) { - _cx_self _arr = _cx_memb(_new_uninit)(xdim, ydim); - for (_cx_value* p = _arr.data[0], *e = p + xdim*ydim; p != e; ++p) - *p = null; - return _arr; -} - -#if !defined i_no_clone - -STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { - _cx_self _arr = _cx_memb(_new_uninit)(src.xdim, src.ydim); - for (_cx_value* p = _arr.data[0], *q = src.data[0], *e = p + _cx_memb(_size)(&src); p != e; ++p, ++q) - *p = i_keyclone((*q)); - return _arr; -} - -STC_DEF void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { - if (self->data == other->data) return; - _cx_memb(_drop)(self); *self = _cx_memb(_clone)(*other); -} -#endif - -STC_DEF _cx_value *_cx_memb(_release)(_cx_self* self) { - _cx_value *values = self->data[0]; - c_free(self->data); - self->data = NULL; - return values; -} - -STC_DEF void _cx_memb(_drop)(_cx_self* self) { - if (!self->data) return; - for (_cx_value* p = self->data[0], *q = p + _cx_memb(_size)(self); p != q; ) { - --q; i_keydrop(q); - } - c_free(self->data[0]); /* values */ - c_free(self->data); /* pointers */ -} - -#endif -#include "priv/template.h" diff --git a/include/stc/carr3.h b/include/stc/carr3.h deleted file mode 100644 index d167dd69..00000000 --- a/include/stc/carr3.h +++ /dev/null @@ -1,157 +0,0 @@ -/* MIT License - * - * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "ccommon.h" - -#ifndef CARR3_H_INCLUDED -#define CARR3_H_INCLUDED -#include "forward.h" -#include <stdlib.h> -#endif -/* -// carr3 - 3D dynamic array in one memory block with easy indexing. -#define i_key int -#include <stc/carr3.h> -#include <stdio.h> - -int main() { - int w = 7, h = 5, d = 3; - c_with (carr3_int image = carr3_int_new_uninit(w, h, d), carr3_int_drop(&image)) - { - int *dat = carr3_int_data(&image); - for (int i = 0; i < carr3_int_size(&image); ++i) - dat[i] = i; - - for (int x = 0; x < image.xdim; ++x) - for (int y = 0; y < image.ydim; ++y) - for (int z = 0; z < image.zdim; ++z) - printf(" %d", image.data[x][y][z]); - puts("\n"); - - c_foreach (i, carr3_int, image) - printf(" %d", *i.ref); - puts(""); - } -} -*/ - -#ifndef _i_prefix -#define _i_prefix carr3_ -#endif -#include "priv/template.h" - -#if !c_option(c_is_forward) -_cx_deftypes(_c_carr3_types, _cx_self, i_key); -#endif - -STC_API _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, size_t zdim, i_key null); -STC_API _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, size_t zdim, _cx_value* storage); -STC_API _cx_value* _cx_memb(_release)(_cx_self* self); -STC_API void _cx_memb(_drop)(_cx_self* self); -#if !defined i_no_clone -STC_API _cx_self _cx_memb(_clone)(_cx_self src); -STC_API void _cx_memb(_copy)(_cx_self *self, const _cx_self* other); -#endif - -STC_INLINE _cx_self _cx_memb(_new_uninit)(size_t xdim, size_t ydim, size_t zdim) { - return _cx_memb(_with_data)(xdim, ydim, zdim, c_alloc_n(_cx_value, xdim*ydim*zdim)); -} - -STC_INLINE size_t _cx_memb(_size)(const _cx_self* self) - { return self->xdim*self->ydim*self->zdim; } - -STC_INLINE _cx_value* _cx_memb(_data)(_cx_self* self) - { return **self->data; } - -STC_INLINE const _cx_value* _cx_memb(_at)(const _cx_self* self, size_t x, size_t y, size_t z) { - assert(x < self->xdim && y < self->ydim && z < self->zdim); - return **self->data + self->zdim*(self->ydim*x + y) + z; -} - -STC_INLINE size_t _cx_memb(_idx)(const _cx_self* self, size_t x, size_t y, size_t z) { - return self->zdim*(self->ydim*x + y) + z; -} - - -STC_INLINE _cx_iter _cx_memb(_begin)(const _cx_self* self) { - size_t n = _cx_memb(_size)(self); - return c_INIT(_cx_iter){n ? **self->data : NULL, **self->data + n}; -} - -STC_INLINE _cx_iter _cx_memb(_end)(const _cx_self* self) - { return c_INIT(_cx_iter){NULL, **self->data + _cx_memb(_size)(self)}; } - -STC_INLINE void _cx_memb(_next)(_cx_iter* it) - { if (++it->ref == it->end) it->ref = NULL; } - -/* -------------------------- IMPLEMENTATION ------------------------- */ -#if defined(i_implement) - -STC_DEF _cx_self _cx_memb(_with_data)(size_t xdim, size_t ydim, size_t zdim, _cx_value* block) { - _cx_self _arr = {c_alloc_n(_cx_value**, xdim*(ydim + 1)), xdim, ydim, zdim}; - _cx_value** p = (_cx_value**) &_arr.data[xdim]; - for (size_t x = 0, y; x < xdim; ++x, p += ydim) - for (y = 0, _arr.data[x] = p; y < ydim; ++y, block += zdim) - p[y] = block; - return _arr; -} - -STC_DEF _cx_self _cx_memb(_with_size)(size_t xdim, size_t ydim, size_t zdim, i_key null) { - _cx_self _arr = _cx_memb(_new_uninit)(xdim, ydim, zdim); - for (_cx_value* p = **_arr.data, *e = p + xdim*ydim*zdim; p != e; ++p) - *p = null; - return _arr; -} - -#if !defined i_no_clone - -STC_DEF _cx_self _cx_memb(_clone)(_cx_self src) { - _cx_self _arr = _cx_memb(_new_uninit)(src.xdim, src.ydim, src.zdim); - for (_cx_value* p = **_arr.data, *q = **src.data, *e = p + _cx_memb(_size)(&src); p != e; ++p, ++q) - *p = i_keyclone((*q)); - return _arr; -} - -STC_DEF void _cx_memb(_copy)(_cx_self *self, const _cx_self* other) { - if (self->data == other->data) return; - _cx_memb(_drop)(self); *self = _cx_memb(_clone)(*other); -} -#endif - -STC_DEF _cx_value* _cx_memb(_release)(_cx_self* self) { - _cx_value *values = self->data[0][0]; - c_free(self->data); - self->data = NULL; - return values; -} - -STC_DEF void _cx_memb(_drop)(_cx_self* self) { - if (!self->data) return; - for (_cx_value* p = **self->data, *q = p + _cx_memb(_size)(self); p != q; ) { - --q; i_keydrop(q); - } - c_free(self->data[0][0]); /* data */ - c_free(self->data); /* pointers */ -} - -#endif -#include "priv/template.h" diff --git a/include/stc/cbox.h b/include/stc/cbox.h index bcb1b275..b8a61375 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -77,7 +77,7 @@ typedef i_keyraw _cx_raw; _cx_deftypes(_c_cbox_types, _cx_self, i_key); #endif -// constructors (takes ownsership) +// constructors (take ownership) STC_INLINE _cx_self _cx_memb(_init)(void) { return c_INIT(_cx_self){NULL}; } @@ -110,6 +110,9 @@ STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { return ptr; } +STC_INLINE _cx_value* _cx_memb(_release)(_cx_self* self) + { return _cx_memb(_move)(self).get; } + STC_INLINE void _cx_memb(_reset)(_cx_self* self) { _cx_memb(_drop)(self); self->get = NULL; @@ -117,8 +120,7 @@ STC_INLINE void _cx_memb(_reset)(_cx_self* self) { // take ownership of p STC_INLINE void _cx_memb(_reset_to)(_cx_self* self, _cx_value* p) { - if (self->get) - i_keydrop(self->get); + _cx_memb(_drop)(self); self->get = p; } @@ -140,10 +142,18 @@ STC_INLINE _cx_self _cx_memb(_from)(_cx_value val) } #endif // !i_no_clone -STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self other) { - if (other.get != self->get) +STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) { + if (unowned.get != self->get) _cx_memb(_drop)(self); - *self = other; + *self = unowned; +} +/* transfer ownership; set dying to NULL */ +STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* dying) { + if (dying->get == self->get) + return; + _cx_memb(_drop)(self); + *self = *dying; + dying->get = NULL; } #ifndef i_no_cmp diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index af6b52a5..95c35915 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -29,6 +29,7 @@ #include <stdbool.h> #include <string.h> #include <assert.h> +#include "priv/allcaps.h" #if SIZE_MAX == UINT32_MAX #define c_ZU PRIu32 diff --git a/include/stc/cregex.h b/include/stc/cregex.h index b6e33879..975bd675 100644 --- a/include/stc/cregex.h +++ b/include/stc/cregex.h @@ -127,15 +127,15 @@ cstr cregex_replace_sv(const cregex* re, csview input, const char* replace, unsi static inline cstr cregex_replace(const cregex* re, const char* input, const char* replace) { csview sv = {input, strlen(input)}; - return cregex_replace_sv(re, sv, replace, 0, NULL, CREG_DEFAULT); + return cregex_replace_sv(re, sv, replace, ~0U, NULL, CREG_DEFAULT); } /* replace + compile RE pattern, and extra arguments */ -cstr cregex_replace_pattern_n(const char* pattern, const char* input, const char* replace, unsigned count, - bool (*mfun)(int i, csview match, cstr* mstr), int crflags); +cstr cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count, + bool (*mfun)(int i, csview match, cstr* mstr), int crflags); static inline cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace) - { return cregex_replace_pattern_n(pattern, input, replace, 0, NULL, CREG_DEFAULT); } + { return cregex_replace_pattern_ex(pattern, input, replace, ~0U, NULL, CREG_DEFAULT); } /* destroy regex */ void cregex_drop(cregex* self); diff --git a/include/stc/cstack.h b/include/stc/cstack.h index 73d0e2e1..5e87cf9f 100644 --- a/include/stc/cstack.h +++ b/include/stc/cstack.h @@ -68,7 +68,7 @@ STC_INLINE _cx_self _cx_memb(_with_size)(size_t size, i_key null) { while (size) out.data[--size] = null; return out; } -#endif +#endif // i_capacity STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_value *p = self->data + self->_len; diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 6f774135..9748b72c 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -88,7 +88,6 @@ STC_API void cstr_u8_erase(cstr* self, size_t bytepos, size_t u8len); STC_API cstr cstr_from_fmt(const char* fmt, ...); STC_API size_t cstr_append_fmt(cstr* self, const char* fmt, ...); STC_API size_t cstr_printf(cstr* self, const char* fmt, ...); -STC_API void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count); STC_API cstr cstr_replace_sv(csview sv, csview search, csview repl, unsigned count); STC_INLINE cstr_buf cstr_buffer(cstr* s) { @@ -376,6 +375,12 @@ STC_INLINE char* cstr_append_s(cstr* self, cstr s) { return cstr_append_n(self, sv.str, sv.size); } +STC_INLINE void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count) { + cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(search, strlen(search)), + 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); } STC_INLINE void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl) { char* d = _cstr_internal_move(self, pos + len, pos + repl.size); @@ -388,7 +393,7 @@ STC_INLINE void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* STC_INLINE void cstr_replace_at_s(cstr* self, size_t pos, size_t len, cstr repl) { cstr_replace_at_sv(self, pos, len, cstr_sv(&repl)); } -STC_INLINE void cstr_u8_replace(cstr* self, size_t bytepos, size_t u8len, csview repl) +STC_INLINE void cstr_u8_replace_at(cstr* self, size_t bytepos, size_t u8len, csview repl) { cstr_replace_at_sv(self, bytepos, utf8_pos(cstr_str(self) + bytepos, u8len), repl); } @@ -583,13 +588,6 @@ cstr_replace_sv(csview in, csview search, csview repl, unsigned count) { return out; } -STC_DEF void -cstr_replace(cstr* self, const char* search, const char* repl, unsigned count) { - csview in = cstr_sv(self); - cstr_take(self, cstr_replace_sv(in, c_SV(search, strlen(search)), - c_SV(repl, strlen(repl)), count)); -} - STC_DEF void cstr_erase(cstr* self, const size_t pos, size_t len) { cstr_buf r = cstr_buffer(self); if (len > r.size - pos) len = r.size - pos; diff --git a/include/stc/priv/allcaps.h b/include/stc/priv/allcaps.h new file mode 100644 index 00000000..1e2460b5 --- /dev/null +++ b/include/stc/priv/allcaps.h @@ -0,0 +1,56 @@ +/* MIT License + * + * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define c_ALLOC c_alloc +#define c_ALLOC_N c_alloc_n +#define c_NEW c_new +#define c_MALLOC c_malloc +#define c_CALLOC c_calloc +#define c_REALLOC c_realloc +#define c_FREE c_free +#define c_DELETE c_delete +#define c_SWAP c_swap +#define c_CONTAINER_OF c_container_of +#define c_STATIC_ASSERT c_static_assert +#define c_ARRAYLEN c_arraylen +#define c_OPTION c_option +#define c_FORLIST c_forlist +#define c_FORRANGE c_forrange +#define c_FOREACH c_foreach +#define c_FORWHILE c_forwhile +#define c_FORPAIR c_forpair +#define c_FORFILTER c_forfilter +#define c_FORMATCH c_formatch +#define c_FORTOKEN c_fortoken +#define c_FORTOKEN_SV c_fortoken_sv +#define c_AUTO c_auto +#define c_AUTODROP c_autodrop +#define c_WITH c_with +#define c_SCOPE c_scope +#define c_DEFER c_defer +#define c_DROP c_drop +#define c_FIND_IF c_find_if +#define c_ERASE_IF c_erase_if +#define c_FLT_TAKE c_flt_take +#define c_FLT_SKIP c_flt_skip +#define c_FLT_SKIPWHILE c_flt_skipwhile +#define c_FLT_TAKEWHILE c_flt_takewhile diff --git a/include/stc/views.h b/include/stc/views.h deleted file mode 100644 index 8f7a0d78..00000000 --- a/include/stc/views.h +++ /dev/null @@ -1,142 +0,0 @@ -/* MIT License - * - * Copyright (c) 2022 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. -*/ -/* -#include <stdio.h> -#include <stc/views.h> -using_clview(IView, int); - -int main() -{ - int array[] = {1, 2, 3, 4, 5}; - IView iv = {array, c_arraylen(array)}; - - c_foreach (i, IView, iv) - printf(" %d", *i.ref); - puts(""); - - // use a temporary IView object. - c_forfilter (i, IView, clview_literal(IView, {10, 20, 30, 23, 22, 21}) - , c_flt_skipwhile(i, *i.ref < 25) - && (*i.ref & 1) == 0 // even only - , c_flt_take(i, 2)) // break after 2 - printf(" %d", *i.ref); - puts(""); - - // crange: - - crange r1 = crange_make(80, 90); - c_foreach (i, crange, r1) - printf(" %lld", *i.ref); - puts(""); - - // use a temporary crange object. - int a = 100, b = INT32_MAX; - c_forfilter (i, crange, crange_literal(a, b, 8) - , i.index > 10 - , c_flt_take(i, 3)) - printf(" %lld", *i.ref); - puts(""); -} -*/ -#ifndef STC_VIEWS_H_INCLUDED -#define STC_VIEWS_H_INCLUDED - -#include <stc/ccommon.h> - -#ifndef c_FLT_STACK - #define c_FLT_STACK 14 /* 22, 30, .. */ -#endif -#define c_flt_take(i, n) (++(i).s1[(i).s1top++] <= (n)) -#define c_flt_skip(i, n) (++(i).s1[(i).s1top++] > (n)) -#define c_flt_skipwhile(i, pred) ((i).s2[(i).s2top++] |= !(pred)) -#define c_flt_takewhile(i, pred) !c_flt_skipwhile(i, pred) - -#define c_forfilter(...) c_MACRO_OVERLOAD(c_forfilter, __VA_ARGS__) -#define c_forfilter4(i, C, cnt, filter) \ - c_forfilter_s(i, C, C##_begin(&cnt), filter) -#define c_forfilter5(i, C, cnt, filter, cond) \ - c_forfilter_s(i, C, C##_begin(&cnt), filter) if (!(cond)) break; else -#define c_forfilter_s(i, C, start, filter) \ - for (struct {C##_iter it; C##_value *ref; \ - uint32_t s1[c_FLT_STACK], index, count; \ - bool s2[c_FLT_STACK]; uint8_t s1top, s2top;} \ - i = {.it=start, .ref=i.it.ref}; i.it.ref \ - ; C##_next(&i.it), i.ref = i.it.ref, ++i.index, i.s1top=0, i.s2top=0) \ - if (!((filter) && ++i.count)) ; else - - -// clview type - -#define clview_literal(C, ...) \ - ((C){.data = (C##_value[])__VA_ARGS__, \ - .size = sizeof((C##_value[])__VA_ARGS__)/sizeof(C##_value)}) - -#define using_clview(Self, T) \ -typedef T Self##_raw; typedef const Self##_raw Self##_value; \ -typedef struct { Self##_value *data; size_t size; } Self; \ -typedef struct { Self##_value *ref, *end; } Self##_iter; \ - \ -STC_INLINE Self##_value* Self##_at(const Self* self, size_t idx) \ - { assert(idx < self->size); return self->data + idx; } \ - \ -STC_INLINE Self##_iter Self##_begin(const Self* self) { \ - Self##_iter it = {self->data, self->data + self->size}; \ - return it; \ -} \ - \ -STC_INLINE Self##_iter Self##_end(const Self* self) { \ - Self##_iter it = {NULL, self->data + self->size}; \ - return it; \ -} \ - \ -STC_INLINE void Self##_next(Self##_iter* it) \ - { if (++it->ref == it->end) it->ref = NULL; } \ -struct stc_nostruct - - -// crange type - -#define crange_literal(...) \ - (*(crange[]){crange_make(__VA_ARGS__)}) - -typedef long long crange_value; -typedef struct { crange_value start, end, step, value; } crange; -typedef struct { crange_value *ref, end, step; } crange_iter; - -#define crange_make(...) c_MACRO_OVERLOAD(crange_make, __VA_ARGS__) -#define crange_make1(stop) crange_make3(0, stop, 1) -#define crange_make2(start, stop) crange_make3(start, stop, 1) - -STC_INLINE crange crange_make3(crange_value start, crange_value stop, crange_value step) - { crange r = {start, stop - (step > 0), step}; return r; } - -STC_INLINE crange_iter crange_begin(crange* self) - { self->value = self->start; crange_iter it = {&self->value, self->end, self->step}; return it; } - -STC_INLINE crange_iter crange_end(crange* self) - { crange_iter it = {NULL}; return it; } - -STC_INLINE void crange_next(crange_iter* it) - { *it->ref += it->step; if ((it->step > 0) == (*it->ref > it->end)) it->ref = NULL; } - -#endif |
