SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
single_pass_input.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 
16 #include <seqan3/std/concepts>
17 #include <seqan3/std/iterator>
18 #include <seqan3/std/ranges>
19 
20 //-----------------------------------------------------------------------------
21 // Implementation of single pass input view.
22 //-----------------------------------------------------------------------------
23 
24 namespace seqan3::detail
25 {
26 
28 template <typename view_t>
29 class basic_iterator;
30 
36 template <std::ranges::view urng_t>
38 class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
39 {
41 private:
42 
44  using urng_iterator_type = std::ranges::iterator_t<urng_t>;
45 
47  template <typename view_t>
48  friend class basic_iterator;
49 
51  struct state
52  {
54  urng_t urng;
56  urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
57  };
58 
60  std::shared_ptr<state> state_ptr{};
61 
65  using iterator = basic_iterator<single_pass_input_view>;
68  using sentinel = std::ranges::sentinel_t<urng_t>;
69  //\}
70 
71 public:
76  constexpr single_pass_input_view() = default;
79  constexpr single_pass_input_view(single_pass_input_view const &) = default;
81  constexpr single_pass_input_view(single_pass_input_view &&) = default;
83  constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
85  constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
87  ~single_pass_input_view() = default;
88 
90  explicit single_pass_input_view(urng_t _urng) :
91  state_ptr{new state{std::move(_urng)}}
92  {}
93 
95  template <typename other_urng_t>
97  requires (!std::same_as<std::remove_cvref_t<other_urng_t>, single_pass_input_view> &&
98  std::ranges::viewable_range<other_urng_t> && // Must come after self type check to avoid conflicts with the move constructor.
99  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<other_urng_t>>>)
101  explicit single_pass_input_view(other_urng_t && _urng) :
102  single_pass_input_view{std::views::all(_urng)}
103  {}
105 
116  iterator begin()
117  {
118  return {*this};
119  }
120 
122  iterator begin() const = delete;
123 
125  sentinel end()
126  {
127  return {std::ranges::end(state_ptr->urng)};
128  }
129 
131  sentinel end() const = delete;
133 };
134 
140 template <std::ranges::viewable_range urng_t>
142 single_pass_input_view(urng_t &&) ->
143  single_pass_input_view<std::views::all_t<urng_t>>;
145 } // seqan3::detail
146 
147 //-----------------------------------------------------------------------------
148 // Iterator for single pass input view.
149 //-----------------------------------------------------------------------------
150 
151 namespace seqan3::detail
152 {
160 template <typename view_type>
161 class basic_iterator<single_pass_input_view<view_type>>
162 {
164  using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
166  using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
167 
169  single_pass_input_view<view_type> * view_ptr{};
170 
172  template <typename input_view_type>
173  friend class basic_iterator;
174 
176  static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
177 
178 public:
179 
183  using difference_type = std::iter_difference_t<base_iterator_type>;
186  using value_type = std::iter_value_t<base_iterator_type>;
188  using pointer = detail::iter_pointer_t<base_iterator_type>;
192  using iterator_category = std::input_iterator_tag;
194 
198  basic_iterator() = default;
201  constexpr basic_iterator(basic_iterator const & rhs) = default;
203  constexpr basic_iterator(basic_iterator && rhs) = default;
205  constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
207  constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
209  ~basic_iterator() = default;
210 
212  basic_iterator(single_pass_input_view<view_type> & view) noexcept : view_ptr{&view}
213  {}
215 
219  reference operator*() const noexcept
221  {
222  return *cached();
223  }
224 
226  pointer operator->() const noexcept
228  requires (!std::is_void_v<pointer>)
230  {
231  return std::addressof(*cached());
232  }
234 
238  basic_iterator & operator++() noexcept
240  {
241  ++cached();
242  return *this;
243  }
244 
246  auto operator++(int) noexcept
247  {
248  if constexpr (std::output_iterator<base_iterator_type, reference> &&
249  std::copy_constructible<base_iterator_type>)
250  {
251  basic_iterator tmp{*this};
252  ++(*this);
253  return tmp;
254  }
255  else
256  {
257  ++(*this);
258  }
259  }
261 
265  constexpr bool operator==(sentinel_type const & s) const noexcept
267  {
268  return cached() == s;
269  }
270 
272  friend constexpr bool
273  operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
274  {
275  return rhs == s;
276  }
277 
279  constexpr bool operator!=(sentinel_type const & rhs) const noexcept
280  {
281  return !(*this == rhs);
282  }
283 
285  friend constexpr bool
286  operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
287  {
288  return rhs != s;
289  }
291 
292 protected:
295  base_iterator_type & cached() const noexcept
296  {
297  assert(view_ptr != nullptr);
298  assert(view_ptr->state_ptr != nullptr);
299  return view_ptr->state_ptr->cached_urng_iter;
300  }
301 };
302 } // seqan3::detail
303 
304 //-----------------------------------------------------------------------------
305 // View shortcut for functor.
306 //-----------------------------------------------------------------------------
307 
309 namespace seqan3::views
310 {
362 inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
363 
365 } // namespace seqan3::views
seqan3::views
The SeqAn namespace for views.
Definition: view_iota_simd.hpp:218
std::shared_ptr
std::rel_ops::operator!=
T operator!=(T... args)
iterator
Provides C++20 additions to the <iterator> header.
std::input_iterator_tag
concepts
The Concepts library.
std::addressof
T addressof(T... args)
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
std::iter_difference_t
ranges
Adaptations of concepts from the Ranges TS.
std::remove_reference_t
std::ranges::begin
T begin(T... args)
std
SeqAn specific customisations in the standard namespace.
std::remove_cvref_t
std::end
T end(T... args)
detail.hpp
Auxiliary header for the views submodule .
seqan3::views::single_pass_input
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:362