SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
take_until_view.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <algorithm>
13#include <concepts>
14#include <iterator>
15#include <ranges>
16#include <type_traits>
17
26
27namespace seqan3::detail
28{
29
30// ============================================================================
31// view_take_until
32// ============================================================================
33
47template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
48class view_take_until : public std::ranges::view_interface<view_take_until<urng_t, fun_t, or_throw, and_consume>>
49{
50private:
51 static_assert(std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>,
52 "The functor type for detail::take_until must model"
53 "std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>.");
54 static_assert(std::convertible_to<std::invoke_result_t<fun_t &&, std::ranges::range_reference_t<urng_t>>, bool>,
55 "The result type of the functor for detail::take_until must be a boolean.");
56
58 urng_t urange;
59
62
64 static constexpr bool const_iterable =
65 const_iterable_range<urng_t> && indirect_unary_predicate_on_range<fun_t const, urng_t const>;
66
69 template <bool const_range>
71
74 template <bool const_range>
75 class basic_sentinel;
76
79 template <bool const_range>
81
84 template <bool const_range>
85 using basic_consume_sentinel = std::default_sentinel_t;
86
87public:
91 view_take_until() = default;
92 constexpr view_take_until(view_take_until const & rhs) = default;
93 constexpr view_take_until(view_take_until && rhs) = default;
94 constexpr view_take_until & operator=(view_take_until const & rhs) = default;
95 constexpr view_take_until & operator=(view_take_until && rhs) = default;
96 ~view_take_until() = default;
97
102 view_take_until(urng_t && _urange, fun_t && _fun) :
103 urange{std::forward<urng_t>(_urange)},
104 fun{std::forward<fun_t>(_fun)}
105 {}
106
112 template <std::ranges::viewable_range rng_t>
113 requires std::constructible_from<urng_t, std::views::all_t<rng_t>>
114 view_take_until(rng_t && _urange, fun_t && _fun) :
115 view_take_until{std::views::all(std::forward<rng_t>(_urange)), std::forward<fun_t>(_fun)}
116 {}
118
135 auto begin() noexcept
136 {
137 if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
139 else
141 }
142
144 auto begin() const noexcept
145 requires const_iterable
146 {
147 if constexpr (and_consume && !std::ranges::forward_range<urng_t const>)
149 else
151 }
152
166 auto end() noexcept
167 {
168 if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
170 else
171 return basic_sentinel<false>{std::ranges::end(urange), fun};
172 }
173
175 auto end() const noexcept
176 requires const_iterable
177 {
178 if constexpr (and_consume && !std::ranges::forward_range<urng_t const>)
180 else
181 return basic_sentinel<true>{std::ranges::end(urange), fun};
182 }
184};
185
188template <typename urng_t, typename fun_t, bool or_throw = false, bool and_consume = false>
189view_take_until(urng_t &&, fun_t &&) -> view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>;
190
191template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
192template <bool const_range>
193class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_consume_iterator :
194 public inherited_iterator_base<basic_consume_iterator<const_range>,
195 seqan3::detail::maybe_const_iterator_t<const_range, urng_t>>
196{
197private:
202
205
208
211
213 bool at_end_gracefully = false;
214
215public:
220 constexpr basic_consume_iterator() = default;
221 constexpr basic_consume_iterator(basic_consume_iterator const & rhs) = default;
222 constexpr basic_consume_iterator(basic_consume_iterator && rhs) = default;
223 constexpr basic_consume_iterator & operator=(basic_consume_iterator const & rhs) = default;
226
229 copyable_wrapper_t<fun_t> const & _fun,
230 underlying_sentinel_t sen) noexcept(noexcept(base_t{it})) :
231 base_t{std::move(it)},
232 fun{std::addressof(_fun)},
233 underlying_sentinel{std::move(sen)}
234 {
235 if ((this->base() != underlying_sentinel) && fun->operator()(**this))
236 {
237 at_end_gracefully = true;
238 ++(*this);
239 }
240 }
242
253
259 basic_consume_iterator & operator++() noexcept(noexcept(++std::declval<base_t &>()) && noexcept(
260 std::declval<underlying_iterator_t &>()
261 != std::declval<underlying_sentinel_t &>()) && noexcept(fun->operator()(std::declval<reference>())))
262 {
263 base_t::operator++();
264
265 while ((this->base() != underlying_sentinel) && fun->operator()(**this))
266 {
267 at_end_gracefully = true;
268 base_t::operator++();
269 }
270
271 return *this;
272 }
273
275 decltype(auto) operator++(int) noexcept(noexcept(++std::declval<basic_consume_iterator &>())
276 && (std::same_as<decltype(std::declval<underlying_iterator_t &>()++), void>
277 || std::is_nothrow_copy_constructible_v<basic_consume_iterator>))
278 {
279 // if underlying iterator is a C++20 input iterator (i.e. returns void), return void too.
280 if constexpr (std::same_as<decltype(std::declval<underlying_iterator_t &>()++), void>)
281 {
282 ++(*this);
283 }
284 else
285 {
286 basic_consume_iterator cpy{*this};
287 ++(*this);
288 return cpy;
289 }
290 }
292
297 bool operator==(basic_consume_sentinel<const_range> const &) const noexcept(!or_throw && noexcept(
298 std::declval<underlying_iterator_t &>()
299 != std::declval<underlying_sentinel_t &>()) && noexcept(fun->operator()(std::declval<reference>())))
300 {
301 if (at_end_gracefully)
302 return true;
303
304 if (this->base() == underlying_sentinel)
305 {
306 if constexpr (or_throw)
307 throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
308 else
309 return true;
310 }
311
312 return fun->operator()(**this);
313 }
314
317 basic_consume_iterator const & rhs) noexcept(noexcept(rhs == lhs))
318 {
319 return rhs == lhs;
320 }
321
324 noexcept(noexcept(std::declval<basic_consume_iterator &>() == rhs))
325 {
326 return !(*this == rhs);
327 }
328
331 basic_consume_iterator const & rhs) noexcept(noexcept(rhs != lhs))
332 {
333 return rhs != lhs;
334 }
336};
337
338template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
339template <bool const_range>
340class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_sentinel
341{
342private:
345
347 underlying_sentinel_t underlying_sentinel{};
348
351
352public:
356 basic_sentinel() = default;
357 basic_sentinel(basic_sentinel const &) = default;
361 ~basic_sentinel() = default;
362
367 explicit basic_sentinel(underlying_sentinel_t underlying_sentinel, copyable_wrapper_t<fun_t> const & _fun) :
368 underlying_sentinel{std::move(underlying_sentinel)},
369 fun{std::addressof(_fun)}
370 {}
371
374 requires const_range && std::convertible_to<std::ranges::sentinel_t<urng_t>, underlying_sentinel_t>
375 : underlying_sentinel{std::move(other.underlying_sentinel)}, fun{other.fun}
376 {}
378
384 friend bool operator==(basic_iterator<const_range> const & lhs, basic_sentinel const & rhs)
385 {
386 // Actual comparison delegated to lhs base
387 if (lhs == rhs.underlying_sentinel)
388 {
389 if constexpr (or_throw)
390 throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
391 else
392 return true;
393 }
394
395 return rhs.fun->operator()(*lhs);
396 }
397
399 friend bool operator==(basic_sentinel const & lhs, basic_iterator<const_range> const & rhs)
400 {
401 return rhs == lhs;
402 }
403
405 friend bool operator!=(basic_iterator<const_range> const & lhs, basic_sentinel const & rhs)
406 {
407 return !(lhs == rhs);
408 }
409
411 friend bool operator!=(basic_sentinel const & lhs, basic_iterator<const_range> const & rhs)
412 {
413 return rhs != lhs;
414 }
415
417 template <bool other_const_range = !const_range>
418 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
419 friend bool operator==(basic_iterator<other_const_range> const & lhs, basic_sentinel const & rhs)
420 {
421 // Actual comparison delegated to lhs base
422 if (lhs == rhs.underlying_sentinel)
423 {
424 if constexpr (or_throw)
425 throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
426 else
427 return true;
428 }
429
430 return rhs.fun->operator()(*lhs);
431 }
432
434 template <bool other_const_range = !const_range>
435 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
436 friend bool operator==(basic_sentinel const & lhs, basic_iterator<other_const_range> const & rhs)
437 {
438 return rhs == lhs;
439 }
440
442 template <bool other_const_range = !const_range>
443 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
444 friend bool operator!=(basic_iterator<other_const_range> const & lhs, basic_sentinel const & rhs)
445 {
446 return !(lhs == rhs);
447 }
448
450 template <bool other_const_range = !const_range>
451 requires (std::sentinel_for<underlying_sentinel_t, basic_iterator<other_const_range>>)
452 friend bool operator!=(basic_sentinel const & lhs, basic_iterator<other_const_range> const & rhs)
453 {
454 return rhs != lhs;
455 }
457};
458
459// ============================================================================
460// take_until_fn (adaptor definition)
461// ============================================================================
462
466template <bool or_throw, bool and_consume>
468{
470 template <typename fun_t>
471 constexpr auto operator()(fun_t && fun) const
472 {
473 return adaptor_from_functor{*this, std::forward<fun_t>(fun)};
474 }
475
483 template <std::ranges::viewable_range urng_t, typename fun_t>
484 constexpr auto operator()(urng_t && urange, fun_t && fun) const
485 {
486 return view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>{
487 std::views::all(std::forward<urng_t>(urange)),
488 std::forward<fun_t>(fun)};
489 }
490};
491
492} // namespace seqan3::detail
493
494// ============================================================================
495// detail::take_until (adaptor instance definition)
496// ============================================================================
497
498namespace seqan3::detail
499{
557inline constexpr auto take_until = take_until_fn<false, false>{};
558
559// ============================================================================
560// detail::take_until_or_throw (adaptor instance definition)
561// ============================================================================
562
572
573// ============================================================================
574// detail::take_until_and_consume (adaptor instance definition)
575// ============================================================================
576
586
587// ============================================================================
588// detail::take_until_or_throw_and_consume (adaptor instance definition)
589// ============================================================================
590
600
601} // namespace seqan3::detail
Provides seqan3::detail::adaptor_from_functor.
T addressof(T... args)
T begin(T... args)
Template for range adaptor closure objects that store arguments and wrap a proto-adaptor.
Definition adaptor_from_functor.hpp:54
Utility wrapper that behaves like std::optional but makes the type conform with the std::copyable con...
Definition copyable_wrapper.hpp:34
A CRTP base template for creating iterators that inherit from other iterators.
Definition inherited_iterator_base.hpp:49
Special iterator type used when consuming behaviour is selected.
Definition take_until_view.hpp:196
seqan3::detail::maybe_const_sentinel_t< const_range, urng_t > underlying_sentinel_t
The sentinel type is identical to that of the underlying range.
Definition take_until_view.hpp:207
seqan3::detail::maybe_const_iterator_t< const_range, urng_t > underlying_iterator_t
The iterator type of the underlying range.
Definition take_until_view.hpp:199
detail::iter_pointer_t< underlying_iterator_t > pointer
From base.
Definition take_until_view.hpp:250
constexpr basic_consume_iterator & operator=(basic_consume_iterator const &rhs)=default
Defaulted.
constexpr basic_consume_iterator(basic_consume_iterator const &rhs)=default
Defaulted.
constexpr basic_consume_iterator & operator=(basic_consume_iterator &&rhs)=default
Defaulted.
basic_consume_iterator(underlying_iterator_t it, copyable_wrapper_t< fun_t > const &_fun, underlying_sentinel_t sen) noexcept(noexcept(base_t{it}))
Constructor that delegates to the CRTP layer and initialises the callable.
Definition take_until_view.hpp:228
constexpr basic_consume_iterator(basic_consume_iterator &&rhs)=default
Defaulted.
bool operator==(basic_consume_sentinel< const_range > const &) const noexcept(!or_throw &&noexcept(std::declval< underlying_iterator_t & >() !=std::declval< underlying_sentinel_t & >()) &&noexcept(fun->operator()(std::declval< reference >())))
Return the saved at_end state.
Definition take_until_view.hpp:297
friend bool operator!=(basic_consume_sentinel< const_range > const &lhs, basic_consume_iterator const &rhs) noexcept(noexcept(rhs !=lhs))
Return the saved at_end state.
Definition take_until_view.hpp:330
friend bool operator==(basic_consume_sentinel< const_range > const &lhs, basic_consume_iterator const &rhs) noexcept(noexcept(rhs==lhs))
Return the saved at_end state.
Definition take_until_view.hpp:316
bool operator!=(basic_consume_sentinel< const_range > const &rhs) const noexcept(noexcept(std::declval< basic_consume_iterator & >()==rhs))
Return the saved at_end state.
Definition take_until_view.hpp:323
underlying_sentinel_t underlying_sentinel
Whether this iterator has reached the end (cache is only used on pure input ranges).
Definition take_until_view.hpp:210
basic_consume_iterator & operator++() noexcept(noexcept(++std::declval< base_t & >()) &&noexcept(std::declval< underlying_iterator_t & >() !=std::declval< underlying_sentinel_t & >()) &&noexcept(fun->operator()(std::declval< reference >())))
Override pre-increment to implement consuming behaviour.
Definition take_until_view.hpp:259
The sentinel type of take_until, provides the comparison operators.
Definition take_until_view.hpp:341
friend bool operator!=(basic_sentinel const &lhs, basic_iterator< const_range > const &rhs)
Compares lhs with rhs for inequality.
Definition take_until_view.hpp:411
basic_sentinel(basic_sentinel<!const_range > other) &&std
Construct from a not const range a const range.
Definition take_until_view.hpp:373
copyable_wrapper_t< fun_t > const * fun
Pointer to the functor stored in the view.
Definition take_until_view.hpp:350
basic_sentinel(basic_sentinel &&)=default
Defaulted.
underlying_sentinel_t underlying_sentinel
The actual end of the underlying range.
Definition take_until_view.hpp:347
seqan3::detail::maybe_const_sentinel_t< const_range, urng_t > underlying_sentinel_t
The sentinel type of the underlying range.
Definition take_until_view.hpp:344
friend bool operator==(basic_sentinel const &lhs, basic_iterator< const_range > const &rhs)
Compares lhs with rhs for equality.
Definition take_until_view.hpp:399
friend bool operator==(basic_iterator< const_range > const &lhs, basic_sentinel const &rhs)
Compares lhs with rhs for equality.
Definition take_until_view.hpp:384
basic_sentinel(underlying_sentinel_t underlying_sentinel, copyable_wrapper_t< fun_t > const &_fun)
Construct from a sentinel and a functor.
Definition take_until_view.hpp:367
friend bool operator!=(basic_iterator< const_range > const &lhs, basic_sentinel const &rhs)
Compares lhs with rhs for inequality.
Definition take_until_view.hpp:405
basic_sentinel & operator=(basic_sentinel const &)=default
Defaulted.
basic_sentinel & operator=(basic_sentinel &&)=default
Defaulted.
basic_sentinel(basic_sentinel const &)=default
Defaulted.
The type returned by seqan3::detail::take_until and seqan3::detail::take_until_or_throw.
Definition take_until_view.hpp:49
constexpr view_take_until(view_take_until &&rhs)=default
Defaulted.
view_take_until(rng_t &&_urange, fun_t &&_fun)
Construct from another viewable_range.
Definition take_until_view.hpp:114
std::default_sentinel_t basic_consume_sentinel
The sentinel type of take_until when consuming behaviour is selected.
Definition take_until_view.hpp:85
constexpr view_take_until & operator=(view_take_until &&rhs)=default
Defaulted.
auto begin() noexcept
Returns an iterator to the first element of the container.
Definition take_until_view.hpp:135
view_take_until()=default
Defaulted.
auto end() const noexcept
Returns an iterator to the element following the last element of the range.
Definition take_until_view.hpp:175
view_take_until(urng_t &&_urange, fun_t &&_fun)
Construct from another range.
Definition take_until_view.hpp:102
copyable_wrapper_t< fun_t > fun
The functor.
Definition take_until_view.hpp:61
constexpr view_take_until & operator=(view_take_until const &rhs)=default
Defaulted.
auto begin() const noexcept
Returns an iterator to the first element of the container.
Definition take_until_view.hpp:144
urng_t urange
The underlying range.
Definition take_until_view.hpp:58
static constexpr bool const_iterable
Whether this view is const_iterable or not.
Definition take_until_view.hpp:64
constexpr view_take_until(view_take_until const &rhs)=default
Defaulted.
~view_take_until()=default
Defaulted.
seqan3::detail::maybe_const_iterator_t< const_range, urng_t > basic_iterator
Iterator of the underlying range (urng_t).
Definition take_until_view.hpp:70
view_take_until(urng_t &&, fun_t &&) -> view_take_until< std::views::all_t< urng_t >, fun_t, or_throw, and_consume >
Type deduction guide that strips references.
auto end() noexcept
Returns an iterator to the element following the last element of the range.
Definition take_until_view.hpp:166
Provides seqan3::detail::copyable_wrapper.
Provides various transformation traits used by the range module.
std::ranges::sentinel_t< maybe_const_range_t< const_v, range_t > > maybe_const_sentinel_t
Returns the const sentinel of range_t if const_range is true; otherwise the non-const sentinel.
Definition core/range/type_traits.hpp:46
std::ranges::iterator_t< maybe_const_range_t< const_range, range_t > > maybe_const_iterator_t
Returns the const iterator of range_t if const_range is true; otherwise the non-const iterator.
Definition core/range/type_traits.hpp:41
typename iter_pointer< it_t >::type iter_pointer_t
Return the pointer type of the input type (transformation_trait shortcut).
Definition iterator_traits.hpp:151
seqan::stl::views::all all
Returns a view that includes all elements of the range argument.
Definition all_view.hpp:35
constexpr auto take_until
A view adaptor that returns elements from the underlying range until the functor evaluates to true (o...
Definition take_until_view.hpp:557
constexpr auto take_until_or_throw_and_consume
A view adaptor that returns elements from the underlying range until the functor evaluates to true (t...
Definition take_until_view.hpp:599
constexpr auto take_until_and_consume
A view adaptor that returns elements from the underlying range until the functor evaluates to true (o...
Definition take_until_view.hpp:585
constexpr auto take_until_or_throw
A view adaptor that returns elements from the underlying range until the functor evaluates to true (t...
Definition take_until_view.hpp:571
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.
The internal SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
SeqAn specific customisations in the standard namespace.
View adaptor definition for detail::take_until and detail::take_until_or_throw.
Definition take_until_view.hpp:468
constexpr auto operator()(fun_t &&fun) const
Store the arguments and return a range adaptor closure object.
Definition take_until_view.hpp:471
constexpr auto operator()(urng_t &&urange, fun_t &&fun) const
Call the view's constructor with the given parameters.
Definition take_until_view.hpp:484
Thrown if I/O was expecting more input (e.g. a delimiter or a new line), but the end of input was rea...
Definition io/exception.hpp:75
Provides seqan3::detail::transformation_trait_or.
Additional non-standard concepts for ranges.
Hide me