SeqAn3 3.1.0
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>
19
22
23//-----------------------------------------------------------------------------
24// Implementation of single pass input view.
25//-----------------------------------------------------------------------------
26
27namespace seqan3::detail
28{
29
31template <typename view_t>
32class basic_iterator;
33
40template <std::ranges::view urng_t>
41class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
42{
44private:
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
74public:
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
144template <std::ranges::viewable_range urng_t>
145single_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
154namespace seqan3::detail
155{
163template <typename view_type>
164class 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
181public:
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
295protected:
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
312namespace seqan3::views
313{
361inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
362
363} // 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)
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:361
Provides various transformation traits for use on iterators.
The <iterator> header from C++20's standard library.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
The <ranges> header from C++20's standard library.
The <type_traits> header from C++20's standard library.