30namespace seqan3::detail
50template <std::ranges::view urng_t,
typename fun_t,
bool or_throw,
bool and_consume>
51class view_take_until :
public std::ranges::view_interface<view_take_until<urng_t, fun_t, or_throw, and_consume>>
54 static_assert(std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>,
55 "The functor type for detail::take_until must model"
56 "std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>.");
57 static_assert(std::convertible_to<
std::result_of_t<fun_t && (std::ranges::range_reference_t<urng_t>)>,
bool>,
58 "The result type of the functor for detail::take_until must be a boolean.");
64 copyable_wrapper_t<fun_t> fun;
67 static constexpr bool const_iterable =
72 template <
bool const_range>
73 using basic_iterator = seqan3::detail::maybe_const_iterator_t<const_range, urng_t>;
77 template <
bool const_range>
82 template <
bool const_range>
83 class basic_consume_iterator;
87 template <
bool const_range>
88 using basic_consume_sentinel = std::default_sentinel_t;
94 view_take_until() =
default;
95 constexpr view_take_until(view_take_until
const & rhs) =
default;
96 constexpr view_take_until(view_take_until && rhs) =
default;
97 constexpr view_take_until & operator=(view_take_until
const & rhs) =
default;
98 constexpr view_take_until & operator=(view_take_until && rhs) =
default;
99 ~view_take_until() =
default;
105 view_take_until(urng_t && _urange, fun_t && _fun) :
115 template <std::ranges::viewable_range rng_t>
116 requires std::constructible_from<urng_t, std::views::all_t<rng_t>>
117 view_take_until(rng_t && _urange, fun_t && _fun) :
138 auto begin() noexcept
140 if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
141 return basic_consume_iterator<false>{
std::ranges::begin(urange), fun, std::ranges::end(urange)};
147 auto begin() const noexcept
148 requires const_iterable
150 if constexpr (and_consume && !std::ranges::forward_range<urng_t const>)
151 return basic_consume_iterator<true>{
std::ranges::cbegin(urange), fun, std::ranges::cend(urange)};
171 if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
172 return basic_consume_sentinel<false>{};
174 return basic_sentinel<false>{std::ranges::end(urange), fun};
178 auto end() const noexcept
179 requires const_iterable
181 if constexpr (and_consume && !std::ranges::forward_range<urng_t const>)
182 return basic_consume_sentinel<true>{};
184 return basic_sentinel<true>{std::ranges::end(urange), fun};
191template <
typename urng_t,
typename fun_t,
bool or_throw = false,
bool and_consume = false>
192view_take_until(urng_t &&, fun_t &&) -> view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>;
194template <std::ranges::view urng_t,
typename fun_t,
bool or_throw,
bool and_consume>
195template <
bool const_range>
196class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_consume_iterator :
197 public inherited_iterator_base<basic_consume_iterator<const_range>,
198 seqan3::detail::maybe_const_iterator_t<const_range, urng_t>>
202 using underlying_iterator_t = seqan3::detail::maybe_const_iterator_t<const_range, urng_t>;
204 using base_t = inherited_iterator_base<basic_consume_iterator, underlying_iterator_t>;
207 copyable_wrapper_t<fun_t>
const * fun{
nullptr};
210 using underlying_sentinel_t = seqan3::detail::maybe_const_sentinel_t<const_range, urng_t>;
213 underlying_sentinel_t underlying_sentinel;
216 bool at_end_gracefully =
false;
223 constexpr basic_consume_iterator() =
default;
224 constexpr basic_consume_iterator(basic_consume_iterator
const & rhs) =
default;
225 constexpr basic_consume_iterator(basic_consume_iterator && rhs) =
default;
226 constexpr basic_consume_iterator & operator=(basic_consume_iterator
const & rhs) =
default;
227 constexpr basic_consume_iterator & operator=(basic_consume_iterator && rhs) =
default;
228 ~basic_consume_iterator() =
default;
231 basic_consume_iterator(underlying_iterator_t it,
232 copyable_wrapper_t<fun_t>
const & _fun,
233 underlying_sentinel_t sen)
noexcept(
noexcept(base_t{it})) :
234 base_t{std::move(it)},
236 underlying_sentinel{std::move(sen)}
238 if ((this->base() != underlying_sentinel) && fun->operator()(**
this))
240 at_end_gracefully =
true;
253 using pointer = detail::iter_pointer_t<underlying_iterator_t>;
262 basic_consume_iterator & operator++() noexcept(noexcept(++
std::declval<base_t &>()) && noexcept(
263 std::declval<underlying_iterator_t &>()
264 !=
std::declval<underlying_sentinel_t &>()) && noexcept(fun->operator()(
std::declval<reference>())))
266 base_t::operator++();
268 while ((this->base() != underlying_sentinel) && fun->operator()(**
this))
270 at_end_gracefully =
true;
271 base_t::operator++();
278 decltype(
auto)
operator++(
int)
noexcept(
noexcept(++std::declval<basic_consume_iterator &>())
279 && (std::same_as<
decltype(std::declval<underlying_iterator_t &>()++),
void>
280 || std::is_nothrow_copy_constructible_v<basic_consume_iterator>))
283 if constexpr (std::same_as<decltype(std::declval<underlying_iterator_t &>()++),
void>)
289 basic_consume_iterator cpy{*
this};
300 bool operator==(basic_consume_sentinel<const_range>
const &)
const noexcept(!or_throw &&
noexcept(
301 std::declval<underlying_iterator_t &>()
302 != std::declval<underlying_sentinel_t &>()) &&
noexcept(fun->operator()(std::declval<reference>())))
304 if (at_end_gracefully)
307 if (this->base() == underlying_sentinel)
309 if constexpr (or_throw)
310 throw unexpected_end_of_input{
"Reached end of input before functor evaluated to true."};
315 return fun->operator()(**this);
319 friend bool operator==(basic_consume_sentinel<const_range>
const & lhs,
320 basic_consume_iterator
const & rhs)
noexcept(
noexcept(rhs == lhs))
326 bool operator!=(basic_consume_sentinel<const_range>
const & rhs)
const
327 noexcept(
noexcept(std::declval<basic_consume_iterator &>() == rhs))
329 return !(*
this == rhs);
333 friend bool operator!=(basic_consume_sentinel<const_range>
const & lhs,
334 basic_consume_iterator
const & rhs)
noexcept(
noexcept(rhs != lhs))
341template <std::ranges::view urng_t,
typename fun_t,
bool or_throw,
bool and_consume>
342template <
bool const_range>
343class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_sentinel
347 using underlying_sentinel_t = seqan3::detail::maybe_const_sentinel_t<const_range, urng_t>;
350 underlying_sentinel_t underlying_sentinel{};
353 copyable_wrapper_t<fun_t>
const * fun{
nullptr};
359 basic_sentinel() =
default;
360 basic_sentinel(basic_sentinel
const &) =
default;
361 basic_sentinel(basic_sentinel &&) =
default;
362 basic_sentinel & operator=(basic_sentinel
const &) =
default;
363 basic_sentinel & operator=(basic_sentinel &&) =
default;
364 ~basic_sentinel() =
default;
370 explicit basic_sentinel(underlying_sentinel_t underlying_sentinel, copyable_wrapper_t<fun_t>
const & _fun) :
371 underlying_sentinel{
std::
move(underlying_sentinel)},
376 basic_sentinel(basic_sentinel<!const_range> other)
377 requires const_range && std::convertible_to<std::ranges::sentinel_t<urng_t>, underlying_sentinel_t>
378 : underlying_sentinel{std::move(other.underlying_sentinel)}, fun{other.fun}
387 friend bool operator==(basic_iterator<const_range>
const & lhs, basic_sentinel
const & rhs)
390 if (lhs == rhs.underlying_sentinel)
392 if constexpr (or_throw)
393 throw unexpected_end_of_input{
"Reached end of input before functor evaluated to true."};
398 return rhs.fun->operator()(*lhs);
402 friend bool operator==(basic_sentinel
const & lhs, basic_iterator<const_range>
const & rhs)
408 friend bool operator!=(basic_iterator<const_range>
const & lhs, basic_sentinel
const & rhs)
410 return !(lhs == rhs);
414 friend bool operator!=(basic_sentinel
const & lhs, basic_iterator<const_range>
const & rhs)
420 template <
bool other_const_range = !const_range>
421 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
422 friend bool operator==(basic_iterator<other_const_range>
const & lhs, basic_sentinel
const & rhs)
425 if (lhs == rhs.underlying_sentinel)
427 if constexpr (or_throw)
428 throw unexpected_end_of_input{
"Reached end of input before functor evaluated to true."};
433 return rhs.fun->operator()(*lhs);
437 template <
bool other_const_range = !const_range>
438 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
439 friend bool operator==(basic_sentinel
const & lhs, basic_iterator<other_const_range>
const & rhs)
445 template <
bool other_const_range = !const_range>
446 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
447 friend bool operator!=(basic_iterator<other_const_range>
const & lhs, basic_sentinel
const & rhs)
449 return !(lhs == rhs);
453 template <
bool other_const_range = !const_range>
454 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
455 friend bool operator!=(basic_sentinel
const & lhs, basic_iterator<other_const_range>
const & rhs)
469template <
bool or_throw,
bool and_consume>
473 template <
typename fun_t>
474 constexpr auto operator()(fun_t && fun)
const
476 return adaptor_from_functor{*
this, std::forward<fun_t>(fun)};
486 template <std::ranges::viewable_range urng_t,
typename fun_t>
487 constexpr auto operator()(urng_t && urange, fun_t && fun)
const
489 return view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>{
490 std::views::all(std::forward<urng_t>(urange)),
491 std::forward<fun_t>(fun)};
501namespace seqan3::detail
560inline constexpr auto take_until = take_until_fn<false, false>{};
574inline constexpr auto take_until_or_throw = take_until_fn<true, false>{};
588inline constexpr auto take_until_and_consume = take_until_fn<false, true>{};
602inline constexpr auto take_until_or_throw_and_consume = take_until_fn<true, true>{};
Provides seqan3::detail::adaptor_from_functor.
Provides seqan3::detail::copyable_wrapper.
Provides various transformation traits used by the range module.
Provides the seqan3::detail::inherited_iterator_base template.
Specifies requirements of an input range type for which the const version of that type satisfies the ...
Provides exceptions used in the I/O module.
Provides various transformation traits for use on iterators.
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.