[set] Add an edge detection iterator

set_while checks the iterator's current element membership and skips to
the first element with different membership. ie, if the current element
is in the set, then set_while returns the next element *not* in the set,
but if the current is not in the set, then set_while returns the next
element that *is* in the set. Rather handy for dealing with clusters of
set elements.
This commit is contained in:
Bill Currie 2023-05-26 21:46:34 +09:00
parent 89e60bd521
commit d5156a2320
2 changed files with 33 additions and 0 deletions

View file

@ -428,6 +428,9 @@ set_iter_t *set_first_r (set_pool_t *set_pool, const set_t *set);
set_iter_t *set_next (set_iter_t *set_iter);
set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter);
set_iter_t *set_while (set_iter_t *set_iter);
set_iter_t *set_while_r (set_pool_t *set_pool, set_iter_t *set_iter);
struct dstring_s;
/** Return a human-readable string representing the set.

View file

@ -734,6 +734,36 @@ set_next (set_iter_t *set_iter)
return set_next_r (&static_set_pool, set_iter);
}
set_iter_t *
set_while_r (set_pool_t *set_pool, set_iter_t *set_iter)
{
unsigned x;
if (_set_is_member (set_iter->set, set_iter->element)) {
for (x = set_iter->element + 1; x < set_iter->set->size; x++) {
if (!_set_is_member (set_iter->set, x)) {
set_iter->element = x;
return set_iter;
}
}
} else {
for (x = set_iter->element + 1; x < set_iter->set->size; x++) {
if (_set_is_member (set_iter->set, x)) {
set_iter->element = x;
return set_iter;
}
}
}
delete_setiter (set_pool, set_iter);
return 0;
}
set_iter_t *
set_while (set_iter_t *set_iter)
{
return set_while_r (&static_set_pool, set_iter);
}
const char *
set_to_dstring_r (set_pool_t *set_pool, dstring_t *str, const set_t *set)
{