SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
single_pass_input.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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/concepts>
16 #include <seqan3/std/iterator>
17 #include <seqan3/std/ranges>
18 #include <seqan3/std/type_traits>
19 
22 
23 //-----------------------------------------------------------------------------
24 // Implementation of single pass input view.
25 //-----------------------------------------------------------------------------
26 
27 namespace seqan3::detail
28 {
29 
31 template <typename view_t>
32 class basic_iterator;
33 
40 template <std::ranges::view urng_t>
41 class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
42 {
44 private:
45 
47  using urng_iterator_type = std::ranges::iterator_t<urng_t>;
48 
50  template <typename view_t>
51  friend class basic_iterator;
52 
54  struct state
55  {
57  urng_t urng;
59  urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
60  };
61 
63  std::shared_ptr<state> state_ptr{};
64 
69  using iterator = basic_iterator<single_pass_input_view>;
71  using sentinel = std::ranges::sentinel_t<urng_t>;
72  //\}
73 
74 public:
80  constexpr single_pass_input_view() = default;
82  constexpr single_pass_input_view(single_pass_input_view const &) = default;
84  constexpr single_pass_input_view(single_pass_input_view &&) = default;
86  constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
88  constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
90  ~single_pass_input_view() = default;
91 
93  explicit single_pass_input_view(urng_t _urng) :
94  state_ptr{new state{std::move(_urng)}}
95  {}
96 
98  template <typename other_urng_t>
100  requires (!std::same_as<std::remove_cvref_t<other_urng_t>, single_pass_input_view> &&
101  std::ranges::viewable_range<other_urng_t> && // Must come after self type check to avoid conflicts with the move constructor.
102  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<other_urng_t>>>)
104  explicit single_pass_input_view(other_urng_t && _urng) :
105  single_pass_input_view{std::views::all(_urng)}
106  {}
108 
119  iterator begin()
120  {
121  return {*this};
122  }
123 
125  iterator begin() const = delete;
126 
128  sentinel end()
129  {
130  return {std::ranges::end(state_ptr->urng)};
131  }
132 
134  sentinel end() const = delete;
136 };
137 
144 template <std::ranges::viewable_range urng_t>
145 single_pass_input_view(urng_t &&) ->
146  single_pass_input_view<std::views::all_t<urng_t>>;
148 } // seqan3::detail
149 
150 //-----------------------------------------------------------------------------
151 // Iterator for single pass input view.
152 //-----------------------------------------------------------------------------
153 
154 namespace seqan3::detail
155 {
163 template <typename view_type>
164 class basic_iterator<single_pass_input_view<view_type>>
165 {
167  using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
169  using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
170 
172  single_pass_input_view<view_type> * view_ptr{};
173 
175  template <typename input_view_type>
176  friend class basic_iterator;
177 
179  static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
180 
181 public:
182 
187  using difference_type = std::iter_difference_t<base_iterator_type>;
189  using value_type = std::iter_value_t<base_iterator_type>;
191  using pointer = detail::iter_pointer_t<base_iterator_type>;
195  using iterator_category = std::input_iterator_tag;
197 
202  basic_iterator() = default;
204  constexpr basic_iterator(basic_iterator const & rhs) = default;
206  constexpr basic_iterator(basic_iterator && rhs) = default;
208  constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
210  constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
212  ~basic_iterator() = default;
213 
215  basic_iterator(single_pass_input_view<view_type> & view) noexcept : view_ptr{&view}
216  {}
218 
223  reference operator*() const noexcept
224  {
225  return *cached();
226  }
227 
229  pointer operator->() const noexcept
231  requires (!std::is_void_v<pointer>)
233  {
234  return std::addressof(*cached());
235  }
237 
242  basic_iterator & operator++() noexcept
243  {
244  ++cached();
245  return *this;
246  }
247 
249  auto operator++(int) noexcept
250  {
251  if constexpr (std::output_iterator<base_iterator_type, reference> &&
252  std::copy_constructible<base_iterator_type>)
253  {
254  basic_iterator tmp{*this};
255  ++(*this);
256  return tmp;
257  }
258  else
259  {
260  ++(*this);
261  }
262  }
264 
269  constexpr bool operator==(sentinel_type const & s) const noexcept
270  {
271  return cached() == s;
272  }
273 
275  friend constexpr bool
276  operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
277  {
278  return rhs == s;
279  }
280 
282  constexpr bool operator!=(sentinel_type const & rhs) const noexcept
283  {
284  return !(*this == rhs);
285  }
286 
288  friend constexpr bool
289  operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
290  {
291  return rhs != s;
292  }
294 
295 protected:
298  base_iterator_type & cached() const noexcept
299  {
300  assert(view_ptr != nullptr);
301  assert(view_ptr->state_ptr != nullptr);
302  return view_ptr->state_ptr->cached_urng_iter;
303  }
304 };
305 } // seqan3::detail
306 
307 //-----------------------------------------------------------------------------
308 // View shortcut for functor.
309 //-----------------------------------------------------------------------------
310 
312 namespace seqan3::views
313 {
365 inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
366 
368 } // namespace seqan3::views
Provides seqan3::detail::adaptor_for_view_without_args.
T addressof(T... args)
T begin(T... args)
The Concepts library.
T end(T... args)
constexpr auto single_pass_input
A view adapter that decays most of the range properties and adds single pass behavior.
Definition: single_pass_input.hpp:365
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
Provides various transformation traits for use on iterators.
Provides C++20 additions to the <iterator> header.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Adaptations of concepts from the Ranges TS.
Provides C++20 additions to the type_traits header.