Loading...
Searching...
No Matches
single_pass_input.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <cassert>
#include <concepts>
#include <iterator>
#include <memory>
#include <ranges>
#include <type_traits>
#include <seqan3/core/detail/iterator_traits.hpp>
#include <seqan3/core/range/detail/adaptor_for_view_without_args.hpp>
//-----------------------------------------------------------------------------
// Implementation of single pass input view.
//-----------------------------------------------------------------------------
namespace seqan3::detail
{
template <typename view_t>
class basic_iterator;
template <std::ranges::view urng_t>
class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
{
private:
using urng_iterator_type = std::ranges::iterator_t<urng_t>;
template <typename view_t>
friend class basic_iterator;
struct state
{
urng_t urng;
urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
};
std::shared_ptr<state> state_ptr{};
using iterator = basic_iterator<single_pass_input_view>;
using sentinel = std::ranges::sentinel_t<urng_t>;
//\}
public:
constexpr single_pass_input_view() = default;
constexpr single_pass_input_view(single_pass_input_view const &) = default;
constexpr single_pass_input_view(single_pass_input_view &&) = default;
constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
~single_pass_input_view() = default;
explicit constexpr single_pass_input_view(urng_t _urng) : state_ptr{new state{std::move(_urng)}}
{}
template <typename other_urng_t>
requires (!std::same_as<std::remove_cvref_t<other_urng_t>, single_pass_input_view>
&& std::ranges::viewable_range<other_urng_t>
&& // Must come after self type check to avoid conflicts with the move constructor.
std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<other_urng_t>>>)
explicit constexpr single_pass_input_view(other_urng_t && _urng) : single_pass_input_view{std::views::all(_urng)}
{}
iterator begin()
{
return {*this};
}
iterator begin() const = delete;
sentinel end()
{
return {std::ranges::end(state_ptr->urng)};
}
sentinel end() const = delete;
};
template <std::ranges::viewable_range urng_t>
single_pass_input_view(urng_t &&) -> single_pass_input_view<std::views::all_t<urng_t>>;
} // namespace seqan3::detail
//-----------------------------------------------------------------------------
// Iterator for single pass input view.
//-----------------------------------------------------------------------------
namespace seqan3::detail
{
template <typename view_type>
class basic_iterator<single_pass_input_view<view_type>>
{
using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
single_pass_input_view<view_type> * view_ptr{};
template <typename input_view_type>
friend class basic_iterator;
static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
public:
using difference_type = std::iter_difference_t<base_iterator_type>;
using value_type = std::iter_value_t<base_iterator_type>;
using pointer = detail::iter_pointer_t<base_iterator_type>;
using reference = std::iter_reference_t<base_iterator_type>;
using iterator_category = std::input_iterator_tag;
basic_iterator() = default;
constexpr basic_iterator(basic_iterator const & rhs) = default;
constexpr basic_iterator(basic_iterator && rhs) = default;
constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
~basic_iterator() = default;
basic_iterator(single_pass_input_view<view_type> & view) noexcept : view_ptr{&view}
{}
reference operator*() const noexcept
{
return *cached();
}
pointer operator->() const noexcept
requires (!std::is_void_v<pointer>)
{
return std::addressof(*cached());
}
basic_iterator & operator++() noexcept
{
++cached();
return *this;
}
void operator++(int) noexcept
{
// this post-increment can't be an std::output_iterator, because it would require that `*it++ = value` must have
// the same semantic as `*i = value; ++i`, but it actually has the following `++i; *i = value` semantic, due to
// the centralised storage of the underlying_iterator in the view where each copy of a basic_iterator points to
// the same centralised state.
++(*this);
}
constexpr bool operator==(sentinel_type const & s) const noexcept
{
return cached() == s;
}
friend constexpr bool operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
{
return rhs == s;
}
constexpr bool operator!=(sentinel_type const & rhs) const noexcept
{
return !(*this == rhs);
}
friend constexpr bool operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
{
return rhs != s;
}
protected:
base_iterator_type & cached() const noexcept
{
assert(view_ptr != nullptr);
assert(view_ptr->state_ptr != nullptr);
return view_ptr->state_ptr->cached_urng_iter;
}
};
} // namespace seqan3::detail
//-----------------------------------------------------------------------------
// View shortcut for functor.
//-----------------------------------------------------------------------------
namespace seqan3::views
{
inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
} // namespace seqan3::views
namespace std::ranges
{
template <std::ranges::view urng_t>
inline constexpr bool enable_borrowed_range<seqan3::detail::single_pass_input_view<urng_t>> =
enable_borrowed_range<urng_t>;
} // namespace std::ranges
adaptor_for_view_without_args.hpp
Provides seqan3::detail::adaptor_for_view_without_args.
std::addressof
T addressof(T... args)
cassert
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:346
iterator_traits.hpp
Provides various transformation traits for use on iterators.
iterator
memory
seqan3::views
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
std::ranges
[adaptor_def]
Definition take_exactly_view.hpp:592
std::rel_ops::operator!=
T operator!=(T... args)
type_traits
Hide me