SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
single_pass_input.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <cassert>
13#include <concepts>
14#include <iterator>
15#include <memory>
16#include <ranges>
17#include <type_traits>
18
21
22//-----------------------------------------------------------------------------
23// Implementation of single pass input view.
24//-----------------------------------------------------------------------------
25
26namespace seqan3::detail
27{
28
30template <typename view_t>
31class basic_iterator;
32
39template <std::ranges::view urng_t>
40class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
41{
43
44private:
46 using urng_iterator_type = std::ranges::iterator_t<urng_t>;
47
49 template <typename view_t>
50 friend class basic_iterator;
51
53 struct state
54 {
56 urng_t urng;
58 urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
59 };
60
62 std::shared_ptr<state> state_ptr{};
63
68 using iterator = basic_iterator<single_pass_input_view>;
70 using sentinel = std::ranges::sentinel_t<urng_t>;
71 //\}
72
73public:
79 constexpr single_pass_input_view() = default;
81 constexpr single_pass_input_view(single_pass_input_view const &) = default;
83 constexpr single_pass_input_view(single_pass_input_view &&) = default;
85 constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
87 constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
89 ~single_pass_input_view() = default;
90
92 explicit constexpr single_pass_input_view(urng_t _urng) : state_ptr{new state{std::move(_urng)}}
93 {}
94
96 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>
99 && // Must come after self type check to avoid conflicts with the move constructor.
100 std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<other_urng_t>>>)
101 explicit constexpr single_pass_input_view(other_urng_t && _urng) : single_pass_input_view{std::views::all(_urng)}
102 {}
104
115 iterator begin()
116 {
117 return {*this};
118 }
119
121 iterator begin() const = delete;
122
124 sentinel end()
125 {
126 return {std::ranges::end(state_ptr->urng)};
127 }
128
130 sentinel end() const = delete;
132};
133
140template <std::ranges::viewable_range urng_t>
141single_pass_input_view(urng_t &&) -> single_pass_input_view<std::views::all_t<urng_t>>;
143} // namespace seqan3::detail
144
145//-----------------------------------------------------------------------------
146// Iterator for single pass input view.
147//-----------------------------------------------------------------------------
148
149namespace seqan3::detail
150{
158template <typename view_type>
159class basic_iterator<single_pass_input_view<view_type>>
160{
162 using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
164 using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
165
167 single_pass_input_view<view_type> * view_ptr{};
168
170 template <typename input_view_type>
171 friend class basic_iterator;
172
174 static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
175
176public:
181 using difference_type = std::iter_difference_t<base_iterator_type>;
183 using value_type = std::iter_value_t<base_iterator_type>;
185 using pointer = detail::iter_pointer_t<base_iterator_type>;
189 using iterator_category = std::input_iterator_tag;
191
196 basic_iterator() = default;
198 constexpr basic_iterator(basic_iterator const & rhs) = default;
200 constexpr basic_iterator(basic_iterator && rhs) = default;
202 constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
204 constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
206 ~basic_iterator() = default;
207
209 basic_iterator(single_pass_input_view<view_type> & view) noexcept : view_ptr{&view}
210 {}
212
217 reference operator*() const noexcept
218 {
219 return *cached();
220 }
221
223 pointer operator->() const noexcept
224 requires (!std::is_void_v<pointer>)
225 {
226 return std::addressof(*cached());
227 }
229
234 basic_iterator & operator++() noexcept
235 {
236 ++cached();
237 return *this;
238 }
239
241 void operator++(int) noexcept
242 {
243 // this post-increment can't be an std::output_iterator, because it would require that `*it++ = value` must have
244 // the same semantic as `*i = value; ++i`, but it actually has the following `++i; *i = value` semantic, due to
245 // the centralised storage of the underlying_iterator in the view where each copy of a basic_iterator points to
246 // the same centralised state.
247 ++(*this);
248 }
250
255 constexpr bool operator==(sentinel_type const & s) const noexcept
256 {
257 return cached() == s;
258 }
259
261 friend constexpr bool operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
262 {
263 return rhs == s;
264 }
265
267 constexpr bool operator!=(sentinel_type const & rhs) const noexcept
268 {
269 return !(*this == rhs);
270 }
271
273 friend constexpr bool operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
274 {
275 return rhs != s;
276 }
278
279protected:
282 base_iterator_type & cached() const noexcept
283 {
284 assert(view_ptr != nullptr);
285 assert(view_ptr->state_ptr != nullptr);
286 return view_ptr->state_ptr->cached_urng_iter;
287 }
288};
289} // namespace seqan3::detail
290
291//-----------------------------------------------------------------------------
292// View shortcut for functor.
293//-----------------------------------------------------------------------------
294
296namespace seqan3::views
297{
345inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
346
347} // namespace seqan3::views
Provides seqan3::detail::adaptor_for_view_without_args.
T addressof(T... args)
T begin(T... args)
T end(T... args)
Provides various transformation traits for use on iterators.
T move(T... args)
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Hide me