SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
take_until.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <seqan3/std/algorithm>
16 #include <seqan3/std/concepts>
17 #include <seqan3/std/iterator>
18 #include <seqan3/std/ranges>
19 #include <seqan3/std/type_traits>
20 
24 #include <seqan3/io/exception.hpp>
25 #include <seqan3/range/concept.hpp>
30 
31 namespace seqan3::detail
32 {
33 
34 // ============================================================================
35 // view_take_until
36 // ============================================================================
37 
51 template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
52 class view_take_until : public std::ranges::view_interface<view_take_until<urng_t, fun_t, or_throw, and_consume>>
53 {
54 private:
55 
56  static_assert(std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>,
57  "The functor type for views::take_until must model"
58  "std::invocable<fun_t, std::ranges::range_reference_t<urng_t>>.");
59  static_assert(std::convertible_to<std::result_of_t<fun_t&&(std::ranges::range_reference_t<urng_t>)>, bool>,
60  "The result type of the functor for views::take_until must be a boolean.");
61 
63  urng_t urange;
64 
66  ranges::semiregular_t<fun_t> fun;
67 
69  static constexpr bool const_iterable = const_iterable_range<urng_t> &&
70  std::regular_invocable<fun_t, std::ranges::range_reference_t<urng_t>>;
71 
72  template <typename rng_t>
73  class basic_iterator;
74 
75  template <bool is_const_range>
76  class basic_sentinel;
77 
78  template <typename rng_t>
80 
81 private:
89 
93 
94 public:
98  view_take_until() = default;
99  constexpr view_take_until(view_take_until const & rhs) = default;
100  constexpr view_take_until(view_take_until && rhs) = default;
101  constexpr view_take_until & operator=(view_take_until const & rhs) = default;
102  constexpr view_take_until & operator=(view_take_until && rhs) = default;
103  ~view_take_until() = default;
104 
109  view_take_until(urng_t _urange, fun_t _fun)
110  : urange{std::move(_urange)}, fun{std::forward<fun_t>(_fun)}
111  {}
112 
118  template <std::ranges::viewable_range rng_t>
120  requires std::constructible_from<rng_t, std::views::all_t<rng_t>>
122  view_take_until(rng_t && _urange, fun_t _fun)
123  : view_take_until{std::views::all(std::forward<rng_t>(_urange)), std::move(_fun)}
124  {}
126 
143  iterator begin() noexcept
144  {
145  return {std::ranges::begin(urange), static_cast<fun_t &>(fun), std::ranges::end(urange)};
146  }
147 
149  const_iterator begin() const noexcept
150  requires const_iterable
151  {
152  return {std::ranges::cbegin(urange), static_cast<fun_t const &>(fun), std::ranges::cend(urange)};
153  }
154 
168  auto end() noexcept
169  {
170  if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
171  return std::ranges::end(urange);
172  else
173  return basic_sentinel<false>{std::ranges::end(urange), fun};
174  }
175 
177  auto end() const noexcept
178  requires const_iterable
179  {
180  if constexpr (and_consume && !std::ranges::forward_range<urng_t>)
181  return std::ranges::cend(urange);
182  else
183  return basic_sentinel<true>{std::ranges::cend(urange), static_cast<fun_t const &>(fun)};
184  }
186 };
187 
190 template <typename urng_t, typename fun_t, bool or_throw = false, bool and_consume = false>
191 view_take_until(urng_t &&, fun_t) -> view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>;
192 
195 template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
196 template <typename rng_t>
197 class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_iterator :
198  public inherited_iterator_base<basic_iterator<rng_t>, std::ranges::iterator_t<rng_t>>
199 {
200 private:
202  using base_base_t = std::ranges::iterator_t<rng_t>;
206  using sentinel_type = std::ranges::sentinel_t<rng_t>;
213 
214 public:
219  constexpr basic_iterator() = default;
220  constexpr basic_iterator(basic_iterator const & rhs) = default;
221  constexpr basic_iterator(basic_iterator && rhs) = default;
222  constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
223  constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
224  ~basic_iterator() = default;
225 
227  basic_iterator(base_base_t it) noexcept(noexcept(base_t{it})) :
228  base_t{std::move(it)}
229  {}
230 
233  fun_ref_t _fun,
234  sentinel_type /*only used by the consuming iterator*/) noexcept(noexcept(base_t{it})) :
235  base_t{std::move(it)}, fun{_fun}
236  {}
238 
257 };
258 
261 template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
262 template <typename rng_t>
263 class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_consume_iterator :
264  public inherited_iterator_base<basic_consume_iterator<rng_t>, std::ranges::iterator_t<rng_t>>
265 {
266 private:
268  using base_base_t = std::ranges::iterator_t<rng_t>;
271 
278 
280  using sentinel_type = std::ranges::sentinel_t<rng_t>;
281 
284 
286  bool at_end_gracefully = false;
287 
288 public:
293  constexpr basic_consume_iterator() = default;
294  constexpr basic_consume_iterator(basic_consume_iterator const & rhs) = default;
295  constexpr basic_consume_iterator(basic_consume_iterator && rhs) = default;
296  constexpr basic_consume_iterator & operator=(basic_consume_iterator const & rhs) = default;
299 
302  fun_ref_t _fun,
303  sentinel_type sen) noexcept(noexcept(base_t{it})) :
304  base_t{std::move(it)}, fun{_fun}, stored_end{std::move(sen)}
305  {
306  if ((this->base() != stored_end) && fun(**this))
307  {
308  at_end_gracefully = true;
309  ++(*this);
310  }
311  }
313 
324 
331  noexcept(noexcept(++std::declval<base_t &>()) &&
332  noexcept(std::declval<base_base_t &>() != std::declval<sentinel_type &>()) &&
333  noexcept(fun(std::declval<reference>())))
334  {
335  base_t::operator++();
336 
337  while ((this->base() != stored_end) && fun(**this))
338  {
339  at_end_gracefully = true;
340  base_t::operator++();
341  }
342 
343  return *this;
344  }
345 
348  noexcept(noexcept(++std::declval<basic_consume_iterator &>()) &&
349  std::is_nothrow_copy_constructible_v<basic_consume_iterator>)
350  {
351  basic_consume_iterator cpy{*this};
352  ++(*this);
353  return cpy;
354  }
356 
361  bool operator==(sentinel_type const & rhs) const
362  noexcept(!or_throw &&
363  noexcept(std::declval<base_base_t &>() != std::declval<sentinel_type &>()) &&
364  noexcept(fun(std::declval<reference>())))
365  {
366  if (at_end_gracefully)
367  return true;
368 
369  if (this->base() == rhs)
370  {
371  if constexpr (or_throw)
372  throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
373  else
374  return true;
375  }
376 
377  return fun(**this);
378  }
379 
381  friend bool operator==(sentinel_type const & lhs, basic_consume_iterator const & rhs)
382  noexcept(noexcept(rhs == lhs))
383  {
384  return rhs == lhs;
385  }
386 
388  bool operator!=(sentinel_type const & rhs) const
389  noexcept(noexcept(std::declval<basic_consume_iterator &>() == rhs))
390  {
391  return !(*this == rhs);
392  }
393 
395  friend bool operator!=(sentinel_type const & lhs, basic_consume_iterator const & rhs)
396  noexcept(noexcept(rhs != lhs))
397  {
398  return rhs != lhs;
399  }
401 };
402 
404 template <std::ranges::view urng_t, typename fun_t, bool or_throw, bool and_consume>
405 template <bool is_const_range>
406 class view_take_until<urng_t, fun_t, or_throw, and_consume>::basic_sentinel
407 {
408 private:
412  using urng_sentinel_type = std::ranges::sentinel_t<urng_base_type>;
414  using predicate_ref_t = std::conditional_t<is_const_range,
417 
419  urng_sentinel_type urng_sentinel{};
420 
423 
424 public:
428  basic_sentinel() = default;
429  basic_sentinel(basic_sentinel const &) = default;
431  basic_sentinel & operator=(basic_sentinel const &) = default;
433  ~basic_sentinel() = default;
434 
439  explicit basic_sentinel(urng_sentinel_type urng_sentinel, predicate_ref_t predicate) :
440  urng_sentinel{std::move(urng_sentinel)},
441  predicate{predicate}
442  {}
443 
446  requires is_const_range && std::convertible_to<std::ranges::sentinel_t<urng_t>, urng_sentinel_type>
447  : urng_sentinel{std::move(other.urng_sentinel)},
448  predicate{other.predicate}
449  {}
451 
457  template <typename rng_t>
458  friend bool operator==(basic_iterator<rng_t> const & lhs, basic_sentinel const & rhs)
459  {
460  // Actual comparison delegated to lhs base
461  if (lhs.base() == rhs.urng_sentinel)
462  {
463  if constexpr (or_throw)
464  throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
465  else
466  return true;
467  }
468 
469  return rhs.predicate(*lhs);
470  }
471 
473  template <typename rng_t>
474  friend bool operator==(basic_sentinel const & lhs, basic_iterator<rng_t> const & rhs)
475  {
476  return rhs == lhs;
477  }
478 
480  template <typename rng_t>
481  friend bool operator!=(basic_iterator<rng_t> const & lhs, basic_sentinel const & rhs)
482  {
483  return !(lhs == rhs);
484  }
485 
487  template <typename rng_t>
488  friend bool operator!=(basic_sentinel const & lhs, basic_iterator<rng_t> const & rhs)
489  {
490  return rhs != lhs;
491  }
493 };
494 
495 // ============================================================================
496 // take_until_fn (adaptor definition)
497 // ============================================================================
498 
502 template <bool or_throw, bool and_consume>
504 {
506  template <typename fun_t>
507  constexpr auto operator()(fun_t && fun) const
508  {
509  return adaptor_from_functor{*this, std::forward<fun_t>(fun)};
510  }
511 
519  template <std::ranges::viewable_range urng_t, typename fun_t>
520  constexpr auto operator()(urng_t && urange, fun_t && fun) const
521  {
522  return view_take_until<std::views::all_t<urng_t>, fun_t, or_throw, and_consume>
523  {
524  std::views::all(std::forward<urng_t>(urange)),
525  std::forward<fun_t>(fun)
526  };
527  }
528 };
529 
530 } // namespace seqan3::detail
531 
532 // ============================================================================
533 // views::take_until (adaptor instance definition)
534 // ============================================================================
535 
536 namespace seqan3::views
537 {
538 
601 
602 // ============================================================================
603 // views::take_until_or_throw (adaptor instance definition)
604 // ============================================================================
605 
615 
616 // ============================================================================
617 // views::take_until_and_consume (adaptor instance definition)
618 // ============================================================================
619 
629 
630 // ============================================================================
631 // views::take_until_or_throw_and_consume (adaptor instance definition)
632 // ============================================================================
633 
643 
645 
646 } // namespace seqan3::views
Adaptations of algorithms from the Ranges TS.
Template for range adaptor closure objects that store arguments and wrap a proto-adaptor.
Definition: detail.hpp:371
A CRTP base template for creating iterators that inherit from other iterators.
Definition: inherited_iterator_base.hpp:52
constexpr base_t base() const &
Get a copy of the base.
Definition: inherited_iterator_base.hpp:111
Special iterator type used when consuming behaviour is selected.
Definition: take_until.hpp:265
seqan3::semiregular_box_t< fun_ref_t > fun
Reference to the functor stored in the view.
Definition: take_until.hpp:277
std::ranges::sentinel_t< rng_t > sentinel_type
The sentinel type is identical to that of the underlying range.
Definition: take_until.hpp:280
constexpr basic_consume_iterator & operator=(basic_consume_iterator &&rhs)=default
Defaulted.
constexpr basic_consume_iterator & operator=(basic_consume_iterator const &rhs)=default
Defaulted.
bool operator!=(sentinel_type const &rhs) const noexcept(noexcept(std::declval< basic_consume_iterator & >()==rhs))
Return the saved at_end state.
Definition: take_until.hpp:388
constexpr basic_consume_iterator(basic_consume_iterator const &rhs)=default
Defaulted.
friend bool operator==(sentinel_type const &lhs, basic_consume_iterator const &rhs) noexcept(noexcept(rhs==lhs))
Return the saved at_end state.
Definition: take_until.hpp:381
basic_consume_iterator operator++(int) noexcept(noexcept(++std::declval< basic_consume_iterator & >()) &&std::is_nothrow_copy_constructible_v< basic_consume_iterator >)
Post-increment implemented via pre-increment.
Definition: take_until.hpp:347
basic_consume_iterator & operator++() noexcept(noexcept(++std::declval< base_t & >()) &&noexcept(std::declval< base_base_t & >() !=std::declval< sentinel_type & >()) &&noexcept(fun(std::declval< reference >())))
Override pre-increment to implement consuming behaviour.
Definition: take_until.hpp:330
std::ranges::iterator_t< rng_t > base_base_t
The iterator type of the underlying range.
Definition: take_until.hpp:268
basic_consume_iterator(base_base_t it, fun_ref_t _fun, sentinel_type sen) noexcept(noexcept(base_t{it}))
Constructor that delegates to the CRTP layer and initialises the callable.
Definition: take_until.hpp:301
bool operator==(sentinel_type const &rhs) const noexcept(!or_throw &&noexcept(std::declval< base_base_t & >() !=std::declval< sentinel_type & >()) &&noexcept(fun(std::declval< reference >())))
Return the saved at_end state.
Definition: take_until.hpp:361
detail::iter_pointer_t< base_base_t > pointer
From base.
Definition: take_until.hpp:321
sentinel_type stored_end
Whether this iterator has reached the end (cache is only used on pure input ranges).
Definition: take_until.hpp:283
constexpr basic_consume_iterator(basic_consume_iterator &&rhs)=default
Defaulted.
friend bool operator!=(sentinel_type const &lhs, basic_consume_iterator const &rhs) noexcept(noexcept(rhs !=lhs))
Return the saved at_end state.
Definition: take_until.hpp:395
The iterator type inherits from the underlying type, but overwrites several operators.
Definition: take_until.hpp:199
std::ranges::sentinel_t< rng_t > sentinel_type
The sentinel type is identical to that of the underlying range.
Definition: take_until.hpp:206
detail::iterator_category_tag_t< base_base_t > iterator_category
The iterator category tag.
Definition: take_until.hpp:253
constexpr basic_iterator & operator=(basic_iterator const &rhs)=default
Defaulted.
constexpr basic_iterator(basic_iterator const &rhs)=default
Defaulted.
constexpr basic_iterator & operator=(basic_iterator &&rhs)=default
Defaulted.
constexpr basic_iterator()=default
Defaulted.
seqan3::semiregular_box_t< fun_ref_t > fun
Reference to the functor stored in the view.
Definition: take_until.hpp:212
std::ranges::iterator_t< rng_t > base_base_t
The iterator type of the underlying range.
Definition: take_until.hpp:202
basic_iterator(base_base_t it, fun_ref_t _fun, sentinel_type) noexcept(noexcept(base_t{it}))
Constructor that delegates to the CRTP layer and initialises the callable.
Definition: take_until.hpp:232
basic_iterator(base_base_t it) noexcept(noexcept(base_t{it}))
Constructor that delegates to the CRTP layer.
Definition: take_until.hpp:227
constexpr basic_iterator(basic_iterator &&rhs)=default
Defaulted.
detail::iter_pointer_t< base_base_t > pointer
The pointer type.
Definition: take_until.hpp:251
The sentinel type of take_until, provides the comparison operators.
Definition: take_until.hpp:407
basic_sentinel(basic_sentinel<!is_const_range > other) requires is_const_range &&std
Construct from a not const range a const range.
Definition: take_until.hpp:445
basic_sentinel(basic_sentinel const &)=default
Defaulted.
urng_sentinel_type urng_sentinel
The actual end of the underlying range.
Definition: take_until.hpp:419
friend bool operator==(basic_iterator< rng_t > const &lhs, basic_sentinel const &rhs)
Compares lhs with rhs for equality.
Definition: take_until.hpp:458
seqan3::semiregular_box_t< predicate_ref_t > predicate
Reference to the predicate stored in the view.
Definition: take_until.hpp:422
basic_sentinel & operator=(basic_sentinel const &)=default
Defaulted.
basic_sentinel & operator=(basic_sentinel &&)=default
Defaulted.
basic_sentinel(urng_sentinel_type urng_sentinel, predicate_ref_t predicate)
Construct from a sentinel and a predicate.
Definition: take_until.hpp:439
basic_sentinel(basic_sentinel &&)=default
Defaulted.
friend bool operator!=(basic_sentinel const &lhs, basic_iterator< rng_t > const &rhs)
Compares lhs with rhs for inequality.
Definition: take_until.hpp:488
friend bool operator!=(basic_iterator< rng_t > const &lhs, basic_sentinel const &rhs)
Compares lhs with rhs for inequality.
Definition: take_until.hpp:481
friend bool operator==(basic_sentinel const &lhs, basic_iterator< rng_t > const &rhs)
Compares lhs with rhs for equality.
Definition: take_until.hpp:474
std::ranges::sentinel_t< urng_base_type > urng_sentinel_type
The sentinel type of the underlying range.
Definition: take_until.hpp:412
The type returned by seqan3::views::take_until and seqan3::views::take_until_or_throw.
Definition: take_until.hpp:53
constexpr view_take_until(view_take_until &&rhs)=default
Defaulted.
iterator begin() noexcept
Returns an iterator to the first element of the container.
Definition: take_until.hpp:143
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.
constexpr view_take_until & operator=(view_take_until const &rhs)=default
Defaulted.
view_take_until(rng_t &&_urange, fun_t _fun)
Construct from another viewable_range.
Definition: take_until.hpp:122
view_take_until()=default
Defaulted.
const_iterator begin() const noexcept requires const _iterable
Returns an iterator to the first element of the container.
Definition: take_until.hpp:149
view_take_until(urng_t _urange, fun_t _fun)
Construct from another range.
Definition: take_until.hpp:109
urng_t urange
The underlying range.
Definition: take_until.hpp:58
constexpr view_take_until & operator=(view_take_until &&rhs)=default
Defaulted.
static constexpr bool const_iterable
Whether this view is const_iterable or not.
Definition: take_until.hpp:69
constexpr view_take_until(view_take_until const &rhs)=default
Defaulted.
auto end() const noexcept requires const _iterable
Returns an iterator to the element following the last element of the range.
Definition: take_until.hpp:177
ranges::semiregular_t< fun_t > fun
The functor.
Definition: take_until.hpp:66
~view_take_until()=default
Defaulted.
auto end() noexcept
Returns an iterator to the element following the last element of the range.
Definition: take_until.hpp:168
The Concepts library.
Provides various transformation traits used by the range module.
::ranges::semiregular_box_t semiregular_box_t
Utility transformation trait to get a wrapper type that models std::semiregular. Imported from ranges...
Definition: semiregular_box.hpp:35
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.hpp:614
constexpr auto take_until
A view adaptor that returns elements from the underlying range until the functor evaluates to true (o...
Definition: take_until.hpp:600
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.hpp:642
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
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.hpp:628
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.
Provides C++20 additions to the <iterator> header.
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
typename iter_pointer< it_t >::type iter_pointer_t
Return the pointer type of the input type (transformation_trait shortcut).
Definition: iterator_traits.hpp:270
typename std::iterator_traits< it_t >::iterator_category iterator_category_tag_t
Exposes the iterator_category from the modelled concept.
Definition: iterator_traits.hpp:200
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.
Adaptations of concepts from the standard library.
Auxiliary header for the views submodule .
Adaptations of concepts from the Ranges TS.
Provides seqan3::semiregular_box.
View adaptor definition for views::take_until and views::take_until_or_throw.
Definition: take_until.hpp:504
constexpr auto operator()(fun_t &&fun) const
Store the arguments and return a range adaptor closure object.
Definition: take_until.hpp:507
constexpr auto operator()(urng_t &&urange, fun_t &&fun) const
Call the view's constructor with the given parameters.
Definition: take_until.hpp:520
Thrown if I/O was expecting more input (e.g. a delimiter or a new line), but the end of input was rea...
Definition: exception.hpp:76
Provides C++20 additions to the type_traits header.
Provides seqan3::detail::transformation_trait_or.