summaryrefslogtreecommitdiffhomepage
path: root/include/stc/algo/filter.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/stc/algo/filter.h')
-rw-r--r--include/stc/algo/filter.h95
1 files changed, 71 insertions, 24 deletions
diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h
index 48a36d9b..e133577c 100644
--- a/include/stc/algo/filter.h
+++ b/include/stc/algo/filter.h
@@ -24,24 +24,24 @@
#include <stdio.h>
#define i_val int
#include <stc/cstack.h>
-#include <stc/algo/filter.h>
+#include <stc/calgo.h>
int main()
{
- c_with (cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7, 8, 9}),
- cstack_int_drop(&stk))
- {
- 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("");
- }
+ cstack_int stk = c_make(cstack_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("");
+
+ cstack_int_drop(&stk);
}
*/
#ifndef STC_FILTER_H_INCLUDED
@@ -49,24 +49,71 @@ int main()
#include <stc/ccommon.h>
-#ifndef c_NFILTERS
-#define c_NFILTERS 32
-#endif
+// c_forfilter:
-#define c_flt_take(i, n) _flt_take(&(i).b, n)
-#define c_flt_skip(i, n) (c_flt_count(i) > (n))
+#define c_flt_skip(i, n) (c_flt_counter(i) > (n))
#define c_flt_skipwhile(i, pred) ((i).b.s2[(i).b.s2top++] |= !(pred))
+#define c_flt_take(i, n) _flt_take(&(i).b, n)
#define c_flt_takewhile(i, pred) _flt_takewhile(&(i).b, pred)
-#define c_flt_last(i) (i).b.s1[(i).b.s1top-1]
-#define c_flt_count(i) ++(i).b.s1[(i).b.s1top++]
+#define c_flt_counter(i) ++(i).b.s1[(i).b.s1top++]
+#define c_flt_getcount(i) (i).b.s1[(i).b.s1top - 1]
#define c_forfilter(i, C, cnt, filter) \
+ c_forfilter_it(i, C, C##_begin(&cnt), filter)
+
+#define c_forfilter_it(i, C, start, filter) \
for (struct {struct _flt_base b; C##_iter it; C##_value *ref;} \
- i = {.it=C##_begin(&cnt), .ref=i.it.ref} ; !i.b.done & (i.ref != NULL) ; \
+ i = {.it=start, .ref=i.it.ref} ; !i.b.done & (i.it.ref != NULL) ; \
C##_next(&i.it), i.ref = i.it.ref, i.b.s1top=0, i.b.s2top=0) \
if (!(filter)) ; else
-// -----
+
+// c_find_if, c_erase_if, c_eraseremove_if:
+
+#define c_find_if(...) c_MACRO_OVERLOAD(c_find_if, __VA_ARGS__)
+#define c_find_if_4(it, C, cnt, pred) do { \
+ intptr_t _index = 0; \
+ for (it = C##_begin(&cnt); it.ref && !(pred); C##_next(&it)) \
+ ++_index; \
+} while (0)
+
+#define c_find_if_5(it, C, start, end, pred) do { \
+ intptr_t _index = 0; \
+ const C##_value* _endref = (end).ref; \
+ for (it = start; it.ref != _endref && !(pred); C##_next(&it)) \
+ ++_index; \
+ if (it.ref == _endref) it.ref = NULL; \
+} while (0)
+
+
+// Use with: clist, cmap, cset, csmap, csset:
+#define c_erase_if(it, C, cnt, pred) do { \
+ C* _cnt = &cnt; \
+ intptr_t _index = 0; \
+ for (C##_iter it = C##_begin(_cnt); it.ref; ++_index) { \
+ if (pred) it = C##_erase_at(_cnt, it); \
+ else C##_next(&it); \
+ } \
+} while (0)
+
+
+// Use with: cstack, cvec, cdeq, cqueue:
+#define c_eraseremove_if(it, C, cnt, pred) do { \
+ C* _cnt = &cnt; \
+ intptr_t _n = 0, _index = 0; \
+ C##_iter it = C##_begin(_cnt), _i; \
+ while (it.ref && !(pred)) \
+ C##_next(&it), ++_index; \
+ for (_i = it; it.ref; C##_next(&it), ++_index) \
+ if (pred) C##_value_drop(it.ref), ++_n; \
+ else *_i.ref = *it.ref, C##_next(&_i); \
+ _cnt->_len -= _n; \
+} while (0)
+
+// ------------------------ private -------------------------
+#ifndef c_NFILTERS
+#define c_NFILTERS 32
+#endif
struct _flt_base {
uint32_t s1[c_NFILTERS];