|
15 | 15 | #include <iris/requirements.hpp> |
16 | 16 | #include <iris/type_traits.hpp> |
17 | 17 |
|
| 18 | +#include <functional> |
18 | 19 | #include <algorithm> |
19 | 20 | #include <vector> |
20 | 21 | #include <ranges> |
@@ -145,6 +146,23 @@ class run_length_sequence |
145 | 146 | return {index(), *value_it_}; |
146 | 147 | } |
147 | 148 |
|
| 149 | + [[nodiscard]] constexpr T const& run_value() const noexcept |
| 150 | + { |
| 151 | + return *value_it_; |
| 152 | + } |
| 153 | + |
| 154 | + constexpr void advance_run() noexcept |
| 155 | + { |
| 156 | + ++ofs_it_; |
| 157 | + ++value_it_; |
| 158 | + rel_pos_ = static_cast<IndexT>(0u); |
| 159 | + } |
| 160 | + [[nodiscard]] friend constexpr iterator_impl next_run(iterator_impl it) noexcept |
| 161 | + { |
| 162 | + it.advance_run(); |
| 163 | + return it; |
| 164 | + } |
| 165 | + |
148 | 166 | constexpr iterator_impl& operator++() noexcept |
149 | 167 | { |
150 | 168 | auto ofs_next = std::next(ofs_it_); |
@@ -469,6 +487,88 @@ class run_length_sequence |
469 | 487 | ); |
470 | 488 | } |
471 | 489 |
|
| 490 | + template<class Pred> |
| 491 | + requires std::predicate<Pred&, T const&> |
| 492 | + [[nodiscard]] constexpr const_iterator find_run_if(const_iterator from, Pred&& pred) const |
| 493 | + noexcept(std::is_nothrow_invocable_v<Pred&, T const&>) |
| 494 | + { |
| 495 | + auto const last = this->end(); |
| 496 | + for (; from != last; from.advance_run()) { |
| 497 | + if (std::invoke(pred, from.run_value())) { |
| 498 | + return from; |
| 499 | + } |
| 500 | + } |
| 501 | + return last; |
| 502 | + } |
| 503 | + |
| 504 | + template<class Pred> |
| 505 | + requires std::predicate<Pred&, T const&> |
| 506 | + [[nodiscard]] constexpr const_iterator find_run_if_not(const_iterator from, Pred&& pred) const |
| 507 | + noexcept(std::is_nothrow_invocable_v<Pred&, T const&>) |
| 508 | + { |
| 509 | + auto const last = this->end(); |
| 510 | + for (; from != last; from.advance_run()) { |
| 511 | + if (!std::invoke(pred, from.run_value())) { |
| 512 | + return from; |
| 513 | + } |
| 514 | + } |
| 515 | + return last; |
| 516 | + } |
| 517 | + |
| 518 | + template<class U> |
| 519 | + requires req::half_equality_comparable<T, U> |
| 520 | + [[nodiscard]] constexpr const_iterator find_run(const_iterator from, U const& value) const |
| 521 | + noexcept(noexcept(std::declval<T const&>() == value)) |
| 522 | + { |
| 523 | + return this->find_run_if(std::move(from), [&](T const& e) noexcept(noexcept(e == value)) { |
| 524 | + return e == value; |
| 525 | + }); |
| 526 | + } |
| 527 | + |
| 528 | + template<class U> |
| 529 | + requires req::half_equality_comparable<T, U> |
| 530 | + [[nodiscard]] constexpr const_iterator find_run_not(const_iterator from, U const& value) const |
| 531 | + noexcept(noexcept(std::declval<T const&>() != value)) |
| 532 | + { |
| 533 | + return this->find_run_if(std::move(from), [&](T const& e) noexcept(noexcept(e != value)) { |
| 534 | + return e != value; |
| 535 | + }); |
| 536 | + } |
| 537 | + |
| 538 | + // --------------------------------------------------------------------- |
| 539 | + |
| 540 | + template<class Pred> |
| 541 | + requires std::predicate<Pred&, T const&> |
| 542 | + [[nodiscard]] constexpr const_iterator find_run_if(Pred&& pred) const |
| 543 | + noexcept(noexcept(this->find_run_if(begin(), std::forward<Pred>(pred)))) |
| 544 | + { |
| 545 | + return this->find_run_if(begin(), std::forward<Pred>(pred)); |
| 546 | + } |
| 547 | + |
| 548 | + template<class Pred> |
| 549 | + requires std::predicate<Pred&, T const&> |
| 550 | + [[nodiscard]] constexpr const_iterator find_run_if_not(Pred&& pred) const |
| 551 | + noexcept(noexcept(this->find_run_if_not(begin(), std::forward<Pred>(pred)))) |
| 552 | + { |
| 553 | + return this->find_run_if_not(begin(), std::forward<Pred>(pred)); |
| 554 | + } |
| 555 | + |
| 556 | + template<class U> |
| 557 | + requires req::half_equality_comparable<T, U> |
| 558 | + [[nodiscard]] constexpr const_iterator find_run(U const& value) const |
| 559 | + noexcept(noexcept(this->find_run(begin(), value))) |
| 560 | + { |
| 561 | + return this->find_run(begin(), value); |
| 562 | + } |
| 563 | + |
| 564 | + template<class U> |
| 565 | + requires req::half_equality_comparable<T, U> |
| 566 | + [[nodiscard]] constexpr const_iterator find_run_not(U const& value) const |
| 567 | + noexcept(noexcept(this->find_run_not(begin(), value))) |
| 568 | + { |
| 569 | + return this->find_run_not(begin(), value); |
| 570 | + } |
| 571 | + |
472 | 572 | // --------------------------------------------------------------------- |
473 | 573 |
|
474 | 574 | // Returns an iterator to the element at logical position `pos`, or `end()` |
|
0 commit comments