SeqAn3
take_until.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <range/v3/view/take_while.hpp>
43 #include <range/v3/algorithm/copy.hpp>
44 
48 #include <seqan3/io/exception.hpp>
49 #include <seqan3/range/concept.hpp>
53 #include <seqan3/std/concepts>
54 #include <seqan3/std/ranges>
56 #include <seqan3/std/concepts>
57 #include <seqan3/std/iterator>
58 #include <seqan3/std/type_traits>
60 
61 namespace seqan3::detail
62 {
63 
64 // ============================================================================
65 // view_take_until
66 // ============================================================================
67 
81 template <std::ranges::View urng_t, typename fun_t, bool or_throw>
82 class view_take_until : public ranges::view_interface<view_take_until<urng_t, fun_t, or_throw>>
83 {
84 private:
85 
86  static_assert(std::Invocable<fun_t, reference_t<urng_t>>,
87  "The functor type for view::take_until must model std::Invocable<fun_t, reference_t<urng_t>>.");
88  static_assert(std::Boolean<std::result_of_t<fun_t&&(reference_t<urng_t>)>>,
89  "The functor type for view::take_until must return std::Boolean.");
90 
92  urng_t urange;
93 
95  ranges::semiregular_t<fun_t> fun;
96 
98  static constexpr bool const_iterable = const_iterable_concept<urng_t> &&
100 
102  using sentinel_type = std::ranges::sentinel_t<urng_t>;
103 
106  template <typename rng_t>
107  class iterator_type : public inherited_iterator_base<iterator_type<rng_t>, std::ranges::iterator_t<rng_t>>
108  {
109  private:
111  using base_base_t = std::ranges::iterator_t<rng_t>;
113  using base_t = inherited_iterator_base<iterator_type, std::ranges::iterator_t<rng_t>>;
114 
116  using fun_ref_t = std::conditional_t<std::is_const_v<rng_t>,
117  std::remove_reference_t<fun_t> const &,
118  std::remove_reference_t<fun_t> &>;
120  ranges::semiregular_t<fun_ref_t> fun;
121 
122  public:
126  iterator_type() = default;
127  constexpr iterator_type(iterator_type const & rhs) = default;
128  constexpr iterator_type(iterator_type && rhs) = default;
129  constexpr iterator_type & operator=(iterator_type const & rhs) = default;
130  constexpr iterator_type & operator=(iterator_type && rhs) = default;
131  ~iterator_type() = default;
132 
134  iterator_type(base_base_t const & it) :
135  base_t{it}
136  {}
137 
139  iterator_type(base_base_t it, fun_ref_t _fun) :
140  base_t{it}, fun{_fun} {}
142 
147  using difference_type = typename std::iterator_traits<base_base_t>::difference_type;
148  using value_type = typename std::iterator_traits<base_base_t>::value_type;
149  using reference = typename std::iterator_traits<base_base_t>::reference;
150  using pointer = typename std::iterator_traits<base_base_t>::pointer;
151  using iterator_category = typename std::iterator_traits<base_base_t>::iterator_category;
153 
158  bool operator==(iterator_type const & rhs) const noexcept(!or_throw)
159  {
160  return static_cast<base_base_t>(*this) == static_cast<base_base_t>(rhs);
161  }
162 
163  bool operator==(sentinel_type const & rhs) const noexcept(!or_throw)
164  {
165  if (static_cast<base_base_t>(*this) == rhs)
166  {
167  if constexpr (or_throw)
168  throw unexpected_end_of_input{"Reached end of input before functor evaluated to true."};
169  else
170  return true;
171  }
172 
173  return fun(**this);
174  }
175 
176  friend bool operator==(sentinel_type const & lhs, iterator_type const & rhs) noexcept(!or_throw)
177  {
178  return rhs == lhs;
179  }
180 
181  bool operator!=(sentinel_type const & rhs) const noexcept(!or_throw)
182  {
183  return !(*this == rhs);
184  }
185 
186  bool operator!=(iterator_type const & rhs) const noexcept(!or_throw)
187  {
188  return static_cast<base_base_t>(*this) != static_cast<base_base_t>(rhs);
189  }
190 
191  friend bool operator!=(sentinel_type const & lhs, iterator_type const & rhs) noexcept(!or_throw)
192  {
193  return rhs != lhs;
194  }
196  }; // class iterator_type
197 
198 public:
202  using reference = reference_t<urng_t>;
205  using const_reference = detail::transformation_trait_or_t<seqan3::reference<urng_t const>, void>;
207  using value_type = value_type_t<urng_t>;
209  using size_type = void;
211  using difference_type = difference_type_t<urng_t>;
213  using iterator = iterator_type<urng_t>;
215  using const_iterator = detail::transformation_trait_or_t<std::type_identity<iterator_type<urng_t const>>, void>;
217 
221  view_take_until() = default;
222  constexpr view_take_until(view_take_until const & rhs) = default;
223  constexpr view_take_until(view_take_until && rhs) = default;
224  constexpr view_take_until & operator=(view_take_until const & rhs) = default;
225  constexpr view_take_until & operator=(view_take_until && rhs) = default;
226  ~view_take_until() = default;
227 
232  view_take_until(urng_t _urange, fun_t _fun)
233  : urange{std::move(_urange)}, fun{std::forward<fun_t>(_fun)}
234  {}
236 
253  iterator begin() noexcept
254  {
255  return {seqan3::begin(urange), static_cast<fun_t &>(fun)};
256  }
257 
259  const_iterator begin() const noexcept
260  requires const_iterable
261  {
262  return {seqan3::cbegin(urange), static_cast<fun_t const &>(fun)};
263  }
264 
266  const_iterator cbegin() const noexcept
267  requires const_iterable
268  {
269  return {seqan3::cbegin(urange), static_cast<fun_t const &>(fun)};
270  }
271 
285  sentinel_type end() noexcept
286  {
287  return {seqan3::end(urange)};
288  }
289 
291  sentinel_type end() const noexcept
292  requires const_iterable
293  {
294  return {seqan3::cend(urange)};
295  }
296 
298  sentinel_type cend() const noexcept
299  requires const_iterable
300  {
301  return {seqan3::cend(urange)};
302  }
304 
310  template <sequence_container_concept container_t>
311  operator container_t()
313  requires std::CommonReference<reference_t<container_t>, reference>
315  {
316  container_t ret;
318  return ret;
319  }
320 
322  template <sequence_container_concept container_t>
323  operator container_t() const
325  requires std::CommonReference<reference_t<container_t>, reference> && const_iterable_concept<urng_t>
327  {
328  container_t ret;
330  return ret;
331  }
332 };
333 
336 template <typename urng_t, typename fun_t, bool or_throw = false>
337 view_take_until(urng_t, fun_t) -> view_take_until<std::remove_reference_t<urng_t>, fun_t, or_throw>;
338 
339 // ============================================================================
340 // take_until_fn (adaptor definition)
341 // ============================================================================
342 
346 template <bool or_throw>
347 class take_until_fn : public pipable_adaptor_base<take_until_fn<or_throw>>
348 {
349 private:
351  using base_t = pipable_adaptor_base<take_until_fn<or_throw>>;
352 
353 public:
355  using base_t::base_t;
356 
357 private:
359  friend base_t;
360 
368  template <std::ranges::View urng_t, typename fun_t>
369  static auto impl(urng_t urange, fun_t && fun)
370  {
371  return view_take_until<urng_t, fun_t, or_throw>{std::move(urange), std::forward<fun_t>(fun)};
372  }
373 
382  template <std::ranges::ViewableRange urng_t, typename fun_t>
383  static auto impl(urng_t && urange, fun_t && fun)
384  {
385  return impl(view::all(std::forward<urng_t>(urange)), std::forward<fun_t>(fun));
386  }
387 };
388 
389 } // namespace seqan3::detail
390 
391 // ============================================================================
392 // view::take_until (adaptor instance definition)
393 // ============================================================================
394 
395 namespace seqan3::view
396 {
397 
448 inline auto constexpr take_until = detail::take_until_fn<false>{};
449 
450 // ============================================================================
451 // view::take_until_or_throw (adaptor instance definition)
452 // ============================================================================
453 
462 inline auto constexpr take_until_or_throw = detail::take_until_fn<true>{};
463 
465 
466 } // namespace seqan3::view
::ranges::cbegin cbegin
Alias for ranges::cbegin. Returns an iterator to the beginning of a range.
Definition: ranges:245
auto constexpr take_until
A view adaptor that returns elements from the underlying range until the functor evaluates to true (o...
Definition: take_until.hpp:448
Provides exceptions used in the I/O module.
Provides C++20 additions to the <iterator> header.
Contains various shortcuts for common std::ranges functions.
Provides seqan3::detail::transformation_trait_or.
Provides the seqan3::detail::inherited_iterator_base template.
Specifies whether the given callable is invocable with the given arguments.
SeqAn specific customisations in the standard namespace.
Definition: align_result.hpp:221
::ranges::copy copy
Alias for ranges::copy. Copies a range of elements to a new location.
Definition: ranges:200
t & operator=(t1 const &rhs)
Assignment operator.
Additional non-standard concepts for ranges.
The Concepts library.
Auxiliary header for the view submodule .
::ranges::iterator_t iterator_t
Alias for ranges::iterator_t. Obtains the iterator type of a range.
Definition: ranges:225
Adaptations of concepts from the Ranges TS.
::ranges::sentinel_t sentinel_t
Alias for ranges::sentinel_t. Obtains the sentinel type of a range.
Definition: ranges:220
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:185
Provides seqan3::view::all.
The SeqAn3 namespace for views.
Specifies whether the given callable is invocable with the given arguments and equality preserving (i...
Definition: aligned_sequence_concept.hpp:288
auto constexpr 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:462
Provides C++20 additions to the type_traits header.
Specifies that a type can be used in Boolean contexts.
typename reference< t >::type reference_t
Type metafunction shortcut for seqan3::reference.
Definition: pre.hpp:98
constexpr auto all
A view that safely wraps a container (you will likely not need to use this unless defining a new view...
Definition: view_all.hpp:95
Provides various metafunctions used by the range module.
Provides various metafunctions for use on iterators.
::ranges::cend cend
Alias for ranges::cend. Returns an iterator to the end of a range.
Definition: ranges:250
Adaptations of concepts from the standard library.
constexpr auto back_inserter(container_t &container)
Create a std::back_insert_iterator for the argument.
Definition: iterator:79
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:190