32 namespace seqan3::detail
52 template <std::ranges::view urng_t,
typename fun_t,
bool or_throw,
bool and_consume>
53 class view_take_until :
public std::ranges::view_interface<view_take_until<urng_t, fun_t, or_throw, and_consume>>
58 "The functor type for views::take_until must model std::invocable<fun_t, reference_t<urng_t>>.");
60 "The functor type for views::take_until must return std::boolean.");
66 ranges::semiregular_t<fun_t> fun;
74 template <
typename rng_t>
75 class iterator_type :
public inherited_iterator_base<iterator_type<rng_t>, std::ranges::iterator_t<rng_t>>
79 using base_base_t = std::ranges::iterator_t<rng_t>;
81 using base_t = inherited_iterator_base<iterator_type, std::ranges::iterator_t<rng_t>>;
84 using sentinel_type = std::ranges::sentinel_t<rng_t>;
91 ranges::semiregular_t<fun_ref_t> fun;
98 constexpr iterator_type() =
default;
99 constexpr iterator_type(iterator_type
const & rhs) =
default;
100 constexpr iterator_type(iterator_type && rhs) =
default;
101 constexpr iterator_type & operator=(iterator_type
const & rhs) =
default;
102 constexpr iterator_type & operator=(iterator_type && rhs) =
default;
103 ~iterator_type() =
default;
106 iterator_type(base_base_t it) noexcept(noexcept(base_t{it})) :
111 iterator_type(base_base_t it,
113 sentinel_type ) noexcept(noexcept(base_t{it})) :
132 using iterator_category = iterator_tag_t<base_base_t>;
139 bool operator==(iterator_type
const & rhs)
const
141 noexcept(noexcept(std::declval<base_base_t &>() == std::declval<base_base_t &>()))
143 requires
std::forward_iterator<base_base_t>
146 return *this->this_to_base() == *rhs.this_to_base();
150 bool operator==(sentinel_type
const & rhs)
const
151 noexcept(!or_throw &&
152 noexcept(std::declval<base_base_t &>() == std::declval<sentinel_type &>()) &&
153 noexcept(fun(std::declval<reference>())))
155 if (*this->this_to_base() == rhs)
157 if constexpr (or_throw)
158 throw unexpected_end_of_input{
"Reached end of input before functor evaluated to true."};
167 friend bool operator==(sentinel_type
const & lhs, iterator_type
const & rhs)
168 noexcept(noexcept(rhs == lhs))
174 bool operator!=(sentinel_type
const & rhs)
const
175 noexcept(noexcept(std::declval<iterator_type &>() == rhs))
177 return !(*
this == rhs);
181 bool operator!=(iterator_type
const & rhs)
const
182 noexcept(noexcept(std::declval<iterator_type &>() == rhs))
184 requires std::forward_iterator<base_base_t>
187 return !(*
this == rhs);
191 friend bool operator!=(sentinel_type
const & lhs, iterator_type
const & rhs)
192 noexcept(noexcept(rhs != lhs))
201 template <
typename rng_t>
202 class iterator_type_consume_input :
public inherited_iterator_base<iterator_type_consume_input<rng_t>, std::ranges::iterator_t<rng_t>>
206 using base_base_t = std::ranges::iterator_t<rng_t>;
208 using base_t = inherited_iterator_base<iterator_type_consume_input, std::ranges::iterator_t<rng_t>>;
215 ranges::semiregular_t<fun_ref_t> fun;
218 using sentinel_type = std::ranges::sentinel_t<rng_t>;
221 sentinel_type stored_end;
224 bool at_end_gracefully =
false;
231 constexpr iterator_type_consume_input() =
default;
234 constexpr iterator_type_consume_input(iterator_type_consume_input
const & rhs) =
default;
236 constexpr iterator_type_consume_input(iterator_type_consume_input && rhs) =
default;
238 constexpr iterator_type_consume_input & operator=(iterator_type_consume_input
const & rhs) =
default;
240 constexpr iterator_type_consume_input & operator=(iterator_type_consume_input && rhs) =
default;
242 ~iterator_type_consume_input() =
default;
245 iterator_type_consume_input(base_base_t it,
247 sentinel_type sen) noexcept(noexcept(base_t{it})) :
250 if ((*this->this_to_base() != stored_end) && fun(**
this))
252 at_end_gracefully =
true;
273 iterator_type_consume_input & operator++()
275 noexcept(noexcept(++
std::declval<base_t &>()) &&
276 noexcept(
std::declval<base_base_t &>() !=
std::declval<sentinel_type &>()) &&
277 noexcept(fun(
std::declval<reference>())))
279 base_t::operator++();
281 while ((*this->this_to_base() != stored_end) && fun(**
this))
283 at_end_gracefully =
true;
284 base_t::operator++();
291 iterator_type_consume_input operator++(
int)
292 noexcept(noexcept(++std::declval<iterator_type_consume_input &>()) &&
293 std::is_nothrow_copy_constructible_v<iterator_type_consume_input>)
295 iterator_type_consume_input cpy{*
this};
305 bool operator==(sentinel_type
const & rhs)
const
307 noexcept(!or_throw &&
308 noexcept(std::declval<base_base_t &>() != std::declval<sentinel_type &>()) &&
309 noexcept(fun(std::declval<reference>())))
311 if (at_end_gracefully)
314 if (*this->this_to_base() == rhs)
316 if constexpr (or_throw)
317 throw unexpected_end_of_input{
"Reached end of input before functor evaluated to true."};
326 friend bool operator==(sentinel_type
const & lhs, iterator_type_consume_input
const & rhs)
327 noexcept(noexcept(rhs == lhs))
333 bool operator!=(sentinel_type
const & rhs)
const
334 noexcept(noexcept(std::declval<iterator_type_consume_input &>() == rhs))
336 return !(*
this == rhs);
340 friend bool operator!=(sentinel_type
const & lhs, iterator_type_consume_input
const & rhs)
341 noexcept(noexcept(rhs != lhs))
352 using reference = reference_t<urng_t>;
355 using const_reference = detail::transformation_trait_or_t<seqan3::reference<urng_t const>,
void>;
357 using value_type = value_type_t<urng_t>;
359 using size_type = void;
361 using difference_type = difference_type_t<urng_t>;
364 iterator_type_consume_input<urng_t>,
365 iterator_type<urng_t>>;
370 detail::transformation_trait_or_t<
377 view_take_until() =
default;
378 constexpr view_take_until(view_take_until
const & rhs) =
default;
379 constexpr view_take_until(view_take_until && rhs) =
default;
380 constexpr view_take_until & operator=(view_take_until
const & rhs) =
default;
381 constexpr view_take_until & operator=(view_take_until && rhs) =
default;
382 ~view_take_until() =
default;
388 view_take_until(urng_t _urange, fun_t _fun)
389 : urange{
std::move(_urange)}, fun{std::forward<fun_t>(_fun)}
397 template <std::ranges::viewable_range rng_t>
401 view_take_until(rng_t && _urange, fun_t _fun)
422 iterator
begin() noexcept
424 return {
std::ranges::begin(urange), static_cast<fun_t &>(fun), std::ranges::end(urange)};
428 const_iterator
begin() const noexcept
429 requires const_iterable
431 return {
std::ranges::begin(urange), static_cast<fun_t const &>(fun), std::ranges::end(urange)};
435 const_iterator
cbegin() const noexcept
436 requires const_iterable
438 return {
std::ranges::begin(urange), static_cast<fun_t const &>(fun), std::ranges::end(urange)};
456 return std::ranges::end(urange);
460 auto end() const noexcept
461 requires const_iterable
463 return std::ranges::cend(urange);
467 auto cend() const noexcept
468 requires const_iterable
470 return std::ranges::cend(urange);
477 template <
typename urng_t,
typename fun_t,
bool or_throw = false,
bool and_consume = false>
478 view_take_until(urng_t &&, fun_t) -> view_take_until<std::ranges::all_view<urng_t>, fun_t, or_throw, and_consume>;
487 template <
bool or_throw,
bool and_consume>
491 template <
typename fun_t>
492 constexpr
auto operator()(fun_t && fun)
const
494 return adaptor_from_functor{*
this, std::forward<fun_t>(fun)};
504 template <std::ranges::viewable_range urng_t,
typename fun_t>
505 constexpr
auto operator()(urng_t && urange, fun_t && fun)
const
507 return view_take_until<std::ranges::all_view<urng_t>, fun_t, or_throw, and_consume>
510 std::forward<fun_t>(fun)
585 inline auto constexpr
take_until = detail::take_until_fn<false, false>{};