summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2022-12-29 00:28:50 +0100
committerTyge Løvset <[email protected]>2022-12-29 00:28:50 +0100
commit0761c13f316cc98ae7756f3527931aa86bed5016 (patch)
treee90777558956fcf91d6b1c958e0c3a6fb0ab007f
parentd623c6c85071b9af5d607bb5d9aceceaea05220a (diff)
downloadSTC-modified-0761c13f316cc98ae7756f3527931aa86bed5016.tar.gz
STC-modified-0761c13f316cc98ae7756f3527931aa86bed5016.zip
Restructuring of some headers into include/algo folder. Some API changes *_replace*() functions have been renamed, and a few minor API changes.
-rw-r--r--README.md11
-rw-r--r--docs/ccommon_api.md4
-rw-r--r--docs/cregex_api.md4
-rw-r--r--docs/cstr_api.md7
-rw-r--r--docs/csview_api.md2
-rw-r--r--include/stc/algo/crange.h72
-rw-r--r--include/stc/algo/csort.h127
-rw-r--r--include/stc/algo/cspan.h77
-rw-r--r--include/stc/algo/filter.h76
-rw-r--r--include/stc/carc.h7
-rw-r--r--include/stc/cbox.h8
-rw-r--r--include/stc/cregex.h8
-rw-r--r--include/stc/cstack.h3
-rw-r--r--include/stc/cstr.h16
-rw-r--r--include/stc/views.h142
-rw-r--r--misc/examples/cpque.c2
-rw-r--r--misc/examples/demos.c2
-rw-r--r--misc/examples/forfilter.c8
-rw-r--r--misc/examples/forloops.c2
-rw-r--r--misc/examples/prime.c6
-rw-r--r--misc/examples/regex_replace.c4
-rw-r--r--misc/examples/utf8replace_c.c4
-rw-r--r--misc/include/alt/cstr.h11
-rw-r--r--src/cregex.c4
24 files changed, 411 insertions, 196 deletions
diff --git a/README.md b/README.md
index 012e3406..848da4bb 100644
--- a/README.md
+++ b/README.md
@@ -26,26 +26,25 @@ in the future, and do minor modifications.
Containers
----------
-- [***ccommon*** - Generic algorithms and macros](docs/ccommon_api.md)
- [***carc*** - **std::shared_ptr** alike type](docs/carc_api.md)
-- [***carr2***, ***carr3*** - 2D and 3D **array** types](docs/carray_api.md)
-- [***cbits*** - **std::bitset** alike type](docs/cbits_api.md)
- [***cbox*** - **std::unique_ptr** alike type](docs/cbox_api.md)
-- [***cdeq*** - **std::deque** alike type](docs/cdeq_api.md)
+- [***cbits*** - **std::bitset** alike type](docs/cbits_api.md)
- [***clist*** - **std::forward_list** alike type](docs/clist_api.md)
-- [***cmap*** - **std::unordered_map** alike type](docs/cmap_api.md)
-- [***cpque*** - **std::priority_queue** alike type](docs/cpque_api.md)
- [***cqueue*** - **std::queue** alike type](docs/cqueue_api.md)
+- [***cpque*** - **std::priority_queue** alike type](docs/cpque_api.md)
+- [***cmap*** - **std::unordered_map** alike type](docs/cmap_api.md)
- [***cset*** - **std::unordered_set** alike type](docs/cset_api.md)
- [***csmap*** - **std::map** sorted map alike type](docs/csmap_api.md)
- [***csset*** - **std::set** sorted set alike type](docs/csset_api.md)
- [***cstack*** - **std::stack** alike type](docs/cstack_api.md)
- [***cstr*** - **std::string** alike type](docs/cstr_api.md)
- [***csview*** - **std::string_view** alike type](docs/csview_api.md)
+- [***cdeq*** - **std::deque** alike type](docs/cdeq_api.md)
- [***cvec*** - **std::vector** alike type](docs/cvec_api.md)
Others
------
+- [***ccommon*** - Generic algorithms and macros](docs/ccommon_api.md)
- [***cregex*** - Regular expression parser (extended from Rob Pike's regexp9)](docs/cregex_api.md)
- [***crandom*** - A novel very fast *PRNG* named **stc64**](docs/crandom_api.md)
- [***coption*** - getopt() alike command line args parser](docs/coption_api.md)
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index a9961002..474c80ac 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -288,13 +288,13 @@ c_FORFILTER (i, crange, r1
// 2. The 11 first primes:
printf("2");
-c_FORFILTER (i, crange, crange_literal(3, crange_MAX, 2)
+c_FORFILTER (i, crange, crange_LITERAL(3, INT64_MAX, 2)
, isPrime(*i.ref)
, c_FLT_TAKE(10))
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
```
-### c_FIND_IF, c_find_in, c_ERASE_IF
+### c_FIND_IF, c_ERASE_IF
Find or erase linearily in containers using a predicate
```c
// Search vec for first value > 2:
diff --git a/docs/cregex_api.md b/docs/cregex_api.md
index 1b3c03d6..3197a59e 100644
--- a/docs/cregex_api.md
+++ b/docs/cregex_api.md
@@ -48,8 +48,8 @@ cstr cregex_replace_sv(const cregex* re, csview input, const char* replac
/* All-in-one replacement (compile + find/replace + drop) */
cstr cregex_replace_pattern(const char* pattern, const char* input, const char* replace);
-cstr cregex_replace_pattern_n(const char* pattern, const char* input, const char* replace, unsigned count,
- bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags);
+cstr cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count,
+ bool(*mfun)(int capgrp, csview match, cstr* mstr), int rflags);
void cregex_drop(cregex* self); /* destroy */
```
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 3857633a..0ee8b2cb 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -68,7 +68,8 @@ void cstr_insert_s(cstr* self, size_t pos, cstr ins);
void cstr_erase(cstr* self, size_t pos, size_t len); // erase len bytes from pos
-void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count); // count==0: replace all.
+void cstr_replace(cstr* self, const char* search, const char* repl);
+void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count);
cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count);
void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl); // replace at a position
void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl);
@@ -101,7 +102,7 @@ size_t cstr_u8_size_n(const cstr self, size_t nbytes); // utf8 si
size_t cstr_u8_to_pos(const cstr* self, size_t u8idx); // byte pos offset at utf8 codepoint index
const char* cstr_u8_at(const cstr* self, size_t u8idx); // char* position at utf8 codepoint index
csview cstr_u8_chr(const cstr* self, size_t u8idx); // get utf8 character as a csview
-void cstr_u8_replace(cstr* self, size_t bytepos, size_t u8len, csview repl); // replace u8len utf8 chars
+void cstr_u8_replace_at(cstr* self, size_t bytepos, size_t u8len, csview repl); // replace u8len utf8 chars
void cstr_u8_erase(cstr* self, size_t bytepos, size_t u8len); // erase u8len codepoints from pos
// iterate utf8 codepoints
@@ -173,7 +174,7 @@ int main() {
cstr_erase(&s1, 7, 5); // -nine
printf("%s\n", cstr_str(&s1));
- cstr_replace(&s1, "seven", "four", 1);
+ cstr_replace_ex(&s1, "seven", "four", 1);
printf("%s\n", cstr_str(&s1));
// reassign:
diff --git a/docs/csview_api.md b/docs/csview_api.md
index 05348745..b5508ace 100644
--- a/docs/csview_api.md
+++ b/docs/csview_api.md
@@ -153,7 +153,7 @@ int main()
{
c_AUTO (cstr, s1) {
s1 = cstr_lit("hell😀 w😀rld");
- cstr_u8_replace(&s1, cstr_find(&s1, "😀rld"), 1, c_SV("ø"));
+ cstr_u8_replace_at(&s1, cstr_find(&s1, "😀rld"), 1, c_SV("ø"));
printf("%s\n", cstr_str(&s1));
c_FOREACH (i, cstr, s1)
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..486568f2
--- /dev/null
+++ b/include/stc/algo/filter.h
@@ -0,0 +1,76 @@
+/* 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
+#define i_capacity 10
+#include <stc/cstack.h>
+#include <stc/algo/filter.h>
+
+int main()
+{
+ cstack_int stk = cstack_INITIALIZER(int, {1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ 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..7f7789ab 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);
}
diff --git a/include/stc/cbox.h b/include/stc/cbox.h
index bcb1b275..a0966fcc 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;
}
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..e4b64848 100644
--- a/include/stc/cstack.h
+++ b/include/stc/cstack.h
@@ -52,6 +52,9 @@ STC_INLINE _cx_self _cx_memb(_init)(void) {
}
#ifdef i_capacity
+#define cstack_INITIALIZER(T, ...) \
+ {.data=__VA_ARGS__, ._len=sizeof((T[])__VA_ARGS__)/sizeof(T)}
+
STC_INLINE void _cx_memb(_create)(_cx_self* self)
{ self->_len = 0; }
#else
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/views.h b/include/stc/views.h
deleted file mode 100644
index ea5f4536..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_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_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_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
-
-
-// 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
diff --git a/misc/examples/cpque.c b/misc/examples/cpque.c
index 47080038..2ec841ae 100644
--- a/misc/examples/cpque.c
+++ b/misc/examples/cpque.c
@@ -8,7 +8,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <stc/forward.h>
-#include <stc/views.h>
+#include <stc/algo/crange.h>
#include <stc/cstr.h>
// predeclare
diff --git a/misc/examples/demos.c b/misc/examples/demos.c
index b077aa73..4a9fac89 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(&cs, "seven", "four", 1);
+ cstr_replace_ex(&cs, "seven", "four", 1);
printf("%s.\n", cstr_str(&cs));
cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c
index 32154904..c0a4ccad 100644
--- a/misc/examples/forfilter.c
+++ b/misc/examples/forfilter.c
@@ -2,7 +2,8 @@
#define i_extern
#include <stc/cstr.h>
#include <stc/csview.h>
-#include <stc/views.h>
+#include <stc/algo/filter.h>
+#include <stc/algo/crange.h>
#define i_type IVec
#define i_val int
@@ -63,12 +64,13 @@ void demo2(void)
c_AUTO (IVec, vector) {
puts("demo2:");
- c_FORFILTER (x, crange, crange_literal(INT64_MAX)
+ c_FORFILTER (x, crange, crange_LITERAL(INT64_MAX)
, c_FLT_SKIPWHILE(x, *x.ref != 11)
&& *x.ref % 2 != 0
, c_FLT_TAKE(x, 5))
IVec_push(&vector, *x.ref * *x.ref);
- c_FOREACH (x, IVec, vector) printf(" %d", *x.ref);
+ c_FOREACH (x, IVec, vector)
+ printf(" %d", *x.ref);
puts("");
}
}
diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c
index 95a955a3..69c1c193 100644
--- a/misc/examples/forloops.c
+++ b/misc/examples/forloops.c
@@ -1,5 +1,5 @@
#include <stdio.h>
-#include <stc/views.h>
+#include <stc/algo/filter.h>
#define i_type IVec
#define i_val int
diff --git a/misc/examples/prime.c b/misc/examples/prime.c
index 41d637b8..f6e89e09 100644
--- a/misc/examples/prime.c
+++ b/misc/examples/prime.c
@@ -2,7 +2,9 @@
#include <math.h>
#include <time.h>
#include <stc/cbits.h>
-#include <stc/views.h>
+#include <stc/algo/filter.h>
+#include <stc/algo/crange.h>
+
cbits sieveOfEratosthenes(size_t n)
{
@@ -41,7 +43,7 @@ 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)
+ c_FORFILTER (i, crange, crange_LITERAL(n - 1, 0, -2)
, cbits_test(&primes, *i.ref>>1)
, c_FLT_TAKE(i, 50)) {
printf("%lld ", *i.ref);
diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c
index d621c0db..a170856b 100644
--- a/misc/examples/regex_replace.c
+++ b/misc/examples/regex_replace.c
@@ -26,11 +26,11 @@ int main()
printf("fixed: %s\n", cstr_str(&str));
/* US date format, and add 10 years to dates: */
- cstr_take(&str, cregex_replace_pattern_n(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT));
+ cstr_take(&str, cregex_replace_pattern_ex(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_n(pattern, input, "[$0]", 1, NULL, CREG_DEFAULT));
+ cstr_take(&str, cregex_replace_pattern_ex(pattern, input, "[$0]", 1, NULL, CREG_DEFAULT));
printf("brack: %s\n", cstr_str(&str));
/* Shows how to compile RE separately */
diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c
index 74b765dc..3645bd0a 100644
--- a/misc/examples/utf8replace_c.c
+++ b/misc/examples/utf8replace_c.c
@@ -8,10 +8,10 @@ int main() {
printf("%s\n", cstr_str(&hello));
/* replace second smiley at utf8 codepoint pos 7 */
- cstr_u8_replace(&hello, cstr_u8_to_pos(&hello, 7), 1, c_SV("🐨"));
+ cstr_u8_replace_at(&hello, cstr_u8_to_pos(&hello, 7), 1, c_SV("🐨"));
printf("%s\n", cstr_str(&hello));
- cstr_replace(&hello, "🐨", "ø", 1);
+ cstr_replace_ex(&hello, "🐨", "ø", 1);
printf("%s\n", cstr_str(&hello));
upper = cstr_toupper_sv(cstr_sv(&hello));
diff --git a/misc/include/alt/cstr.h b/misc/include/alt/cstr.h
index ecb9c9fb..8de6c4b0 100644
--- a/misc/include/alt/cstr.h
+++ b/misc/include/alt/cstr.h
@@ -182,12 +182,12 @@ STC_INLINE uint64_t cstr_hash(const cstr *self) {
return cfasthash(self->str, _cstr_p(self)->size);
}
-STC_INLINE void
-cstr_replace(cstr* self, const char* find, const char* repl, unsigned count) {
- csview in = cstr_sv(self);
- cstr_take(self, cstr_replace_sv(in, c_SV(find, strlen(find)),
- c_SV(repl, strlen(repl)), count));
+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)
@@ -324,7 +324,6 @@ 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 (count == 0) count = ~0;
if (find.size)
while (count-- && (res = cstrnstrn(str.str + from, find.str, str.size - from, find.size))) {
const size_t pos = res - str.str;
diff --git a/src/cregex.c b/src/cregex.c
index c30ff967..d19b063f 100644
--- a/src/cregex.c
+++ b/src/cregex.c
@@ -1268,8 +1268,8 @@ cregex_replace_sv(const cregex* re, csview input, const char* replace, unsigned
}
cstr
-cregex_replace_pattern_n(const char* pattern, const char* input, const char* replace, unsigned count,
- bool (*mfun)(int, csview, cstr*), int crflags) {
+cregex_replace_pattern_ex(const char* pattern, const char* input, const char* replace, unsigned count,
+ bool (*mfun)(int, csview, cstr*), int crflags) {
cregex re = cregex_init();
if (cregex_compile(&re, pattern, crflags) != CREG_OK)
assert(0);