SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
single_pass_input.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 <cassert>
16 #include <concepts>
17 #include <iterator>
18 #include <memory>
19 #include <ranges>
20 #include <type_traits>
21 
24 
25 //-----------------------------------------------------------------------------
26 // Implementation of single pass input view.
27 //-----------------------------------------------------------------------------
28 
29 namespace seqan3::detail
30 {
31 
33 template <typename view_t>
34 class basic_iterator;
35 
42 template <std::ranges::view urng_t>
43 class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
44 {
46 
47 private:
49  using urng_iterator_type = std::ranges::iterator_t<urng_t>;
50 
52  template <typename view_t>
53  friend class basic_iterator;
54 
56  struct state
57  {
59  urng_t urng;
61  urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
62  };
63 
65  std::shared_ptr<state> state_ptr{};
66 
71  using iterator = basic_iterator<single_pass_input_view>;
73  using sentinel = std::ranges::sentinel_t<urng_t>;
74  //\}
75 
76 public:
82  constexpr single_pass_input_view() = default;
84  constexpr single_pass_input_view(single_pass_input_view const &) = default;
86  constexpr single_pass_input_view(single_pass_input_view &&) = default;
88  constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
90  constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
92  ~single_pass_input_view() = default;
93 
95  explicit single_pass_input_view(urng_t _urng) : state_ptr{new state{std::move(_urng)}}
96  {}
97 
99  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>
102  && // Must come after self type check to avoid conflicts with the move constructor.
103  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) : single_pass_input_view{std::views::all(_urng)}
105  {}
107 
118  iterator begin()
119  {
120  return {*this};
121  }
122 
124  iterator begin() const = delete;
125 
127  sentinel end()
128  {
129  return {std::ranges::end(state_ptr->urng)};
130  }
131 
133  sentinel end() const = delete;
135 };
136 
143 template <std::ranges::viewable_range urng_t>
144 single_pass_input_view(urng_t &&) -> single_pass_input_view<std::views::all_t<urng_t>>;
146 } // namespace seqan3::detail
147 
148 //-----------------------------------------------------------------------------
149 // Iterator for single pass input view.
150 //-----------------------------------------------------------------------------
151 
152 namespace seqan3::detail
153 {
161 template <typename view_type>
162 class basic_iterator<single_pass_input_view<view_type>>
163 {
165  using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
167  using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
168 
170  single_pass_input_view<view_type> * view_ptr{};
171 
173  template <typename input_view_type>
174  friend class basic_iterator;
175 
177  static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
178 
179 public:
184  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>;
190  using reference = std::iter_reference_t<base_iterator_type>;
192  using iterator_category = std::input_iterator_tag;
194 
199  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 
220  reference operator*() const noexcept
221  {
222  return *cached();
223  }
224 
226  pointer operator->() const noexcept
227  requires (!std::is_void_v<pointer>)
228  {
229  return std::addressof(*cached());
230  }
232 
237  basic_iterator & operator++() noexcept
238  {
239  ++cached();
240  return *this;
241  }
242 
244  void operator++(int) noexcept
245  {
246  // this post-increment can't be an std::output_iterator, because it would require that `*it++ = value` must have
247  // the same semantic as `*i = value; ++i`, but it actually has the following `++i; *i = value` semantic, due to
248  // the centralised storage of the underlying_iterator in the view where each copy of a basic_iterator points to
249  // the same centralised state.
250  ++(*this);
251  }
253 
258  constexpr bool operator==(sentinel_type const & s) const noexcept
259  {
260  return cached() == s;
261  }
262 
264  friend constexpr bool operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
265  {
266  return rhs == s;
267  }
268 
270  constexpr bool operator!=(sentinel_type const & rhs) const noexcept
271  {
272  return !(*this == rhs);
273  }
274 
276  friend constexpr bool operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
277  {
278  return rhs != s;
279  }
281 
282 protected:
285  base_iterator_type & cached() const noexcept
286  {
287  assert(view_ptr != nullptr);
288  assert(view_ptr->state_ptr != nullptr);
289  return view_ptr->state_ptr->cached_urng_iter;
290  }
291 };
292 } // namespace seqan3::detail
293 
294 //-----------------------------------------------------------------------------
295 // View shortcut for functor.
296 //-----------------------------------------------------------------------------
297 
299 namespace seqan3::views
300 {
348 inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
349 
350 } // namespace seqan3::views
Provides seqan3::detail::adaptor_for_view_without_args.
T addressof(T... args)
T begin(T... args)
The <concepts> header from C++20's standard library.
T end(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
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:348
Provides various transformation traits for use on iterators.
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
The <ranges> header from C++20's standard library.