|
| 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 | + |
| 8 | +/*!\file |
| 9 | + * \brief Provides the seqan3::detail::in_file_iterator class template. |
| 10 | + * \author Hannes Hauswedell <hannes.hauswedell AT fu-berlin.de> |
| 11 | + */ |
| 12 | + |
| 13 | +#pragma once |
| 14 | + |
| 15 | +#include <cassert> |
| 16 | +#include <ranges> |
| 17 | + |
| 18 | +#include <bio/platform.hpp> |
| 19 | + |
| 20 | +namespace bio::detail |
| 21 | +{ |
| 22 | + |
| 23 | +/*!\brief Input iterator that provides a range-like interface for readers. |
| 24 | + * \tparam file_type The data structure on which the iterator operates. |
| 25 | + * \implements std::input_Iterator |
| 26 | + * \ingroup bio |
| 27 | + * |
| 28 | + * This iterator is a single-pass input iterator for input files. All member types are resolved |
| 29 | + * via `file_type`'s member types, dereference is implemented via file's `front()` member |
| 30 | + * function, and increment calls the `buffer_next_record()` member of file. |
| 31 | + * |
| 32 | + * Note that since this is a single-pass input iterator, post-increment returns void because |
| 33 | + * previous iterators are always invalid (all iterators point to the current position in single-pass |
| 34 | + * ranges). |
| 35 | + * |
| 36 | + * This iterator may be compared against std::default_sentinel_t, this check delegates to |
| 37 | + * calling the `eof()` member function on the file's stream. |
| 38 | + */ |
| 39 | +template <typename file_type> |
| 40 | +class in_file_iterator |
| 41 | +{ |
| 42 | + static_assert(!std::is_const_v<file_type>, |
| 43 | + "You cannot iterate over const files, because the iterator changes the file."); |
| 44 | + |
| 45 | +public: |
| 46 | + /*!\name Member types |
| 47 | + * \brief The associated types are derived from the `file_type`. |
| 48 | + * \{ |
| 49 | + */ |
| 50 | + |
| 51 | + //!\brief The value type. |
| 52 | + using value_type = typename file_type::record_type; |
| 53 | + //!\brief The reference type. |
| 54 | + using reference = typename file_type::record_type &; |
| 55 | + //!\brief The const reference type. |
| 56 | + using const_reference = typename file_type::record_type &; |
| 57 | + //!\brief The size type. |
| 58 | + using size_type = size_t; |
| 59 | + //!\brief The difference type. A signed integer type, usually std::ptrdiff_t. |
| 60 | + using difference_type = ptrdiff_t; |
| 61 | + //!\brief The pointer type. |
| 62 | + using pointer = typename file_type::record_type *; |
| 63 | + //!\brief Tag this class as an input iterator. |
| 64 | + using iterator_category = std::input_iterator_tag; |
| 65 | + //!\} |
| 66 | + |
| 67 | + /*!\name Constructors, destructor and assignment. |
| 68 | + * \{ |
| 69 | + */ |
| 70 | + in_file_iterator() = default; //!< Defaulted. |
| 71 | + in_file_iterator(in_file_iterator const &) = default; //!< Defaulted. |
| 72 | + in_file_iterator(in_file_iterator &&) = default; //!< Defaulted. |
| 73 | + ~in_file_iterator() = default; //!< Defaulted. |
| 74 | + in_file_iterator & operator=(in_file_iterator const &) = default; //!< Defaulted. |
| 75 | + in_file_iterator & operator=(in_file_iterator &&) = default; //!< Defaulted. |
| 76 | + |
| 77 | + //!\brief Construct with reference to host. |
| 78 | + in_file_iterator(file_type & _host) noexcept : host{&_host} {} |
| 79 | + //!\} |
| 80 | + |
| 81 | + /*!\name Iterator operations |
| 82 | + * \{ |
| 83 | + */ |
| 84 | + //!\brief Move to the next record in the file and return a reference to it. |
| 85 | + in_file_iterator & operator++() |
| 86 | + { |
| 87 | + assert(host != nullptr); |
| 88 | + host->read_next_record(); |
| 89 | + return *this; |
| 90 | + } |
| 91 | + |
| 92 | + //!\brief Post-increment is the same as pre-increment, but returns void. |
| 93 | + void operator++(int) |
| 94 | + { |
| 95 | + assert(host != nullptr); |
| 96 | + ++(*this); |
| 97 | + } |
| 98 | + |
| 99 | + //!\brief Dereference returns the currently buffered record. |
| 100 | + reference operator*() noexcept |
| 101 | + { |
| 102 | + assert(host != nullptr); |
| 103 | + return host->record_buffer; |
| 104 | + } |
| 105 | + |
| 106 | + //!\brief Dereference returns the currently buffered record. |
| 107 | + reference operator*() const noexcept |
| 108 | + { |
| 109 | + assert(host != nullptr); |
| 110 | + return host->record_buffer; |
| 111 | + } |
| 112 | + |
| 113 | + //!\brief Dereference returns the currently buffered record. |
| 114 | + value_type * operator->() noexcept |
| 115 | + { |
| 116 | + assert(host != nullptr); |
| 117 | + return &host->record_buffer; |
| 118 | + } |
| 119 | + |
| 120 | + //!\brief Dereference returns the currently buffered record. |
| 121 | + value_type const * operator->() const noexcept |
| 122 | + { |
| 123 | + assert(host != nullptr); |
| 124 | + return &host->record_buffer; |
| 125 | + } |
| 126 | + |
| 127 | + //!\} |
| 128 | + |
| 129 | + /*!\name Comparison operators |
| 130 | + * \brief Only (in-)equality comparison of iterator with end() is supported. |
| 131 | + * \{ |
| 132 | + */ |
| 133 | + |
| 134 | + //!\brief Checks whether `*this` is equal to the sentinel. |
| 135 | + constexpr bool operator==(std::default_sentinel_t const &) const noexcept |
| 136 | + { |
| 137 | + assert(host != nullptr); |
| 138 | + return host->at_end; |
| 139 | + } |
| 140 | + |
| 141 | + //!\brief Checks whether `*this` is not equal to the sentinel. |
| 142 | + constexpr bool operator!=(std::default_sentinel_t const &) const noexcept |
| 143 | + { |
| 144 | + assert(host != nullptr); |
| 145 | + return !host->at_end; |
| 146 | + } |
| 147 | + |
| 148 | + //!\brief Checks whether `it` is equal to the sentinel. |
| 149 | + constexpr friend bool operator==(std::default_sentinel_t const &, in_file_iterator const & it) noexcept |
| 150 | + { |
| 151 | + return (it == std::default_sentinel); |
| 152 | + } |
| 153 | + |
| 154 | + //!\brief Checks whether `it` is not equal to the sentinel. |
| 155 | + constexpr friend bool operator!=(std::default_sentinel_t const &, in_file_iterator const & it) noexcept |
| 156 | + { |
| 157 | + return (it != std::default_sentinel); |
| 158 | + } |
| 159 | + //!\} |
| 160 | + |
| 161 | +private: |
| 162 | + //!\brief Pointer to file host. |
| 163 | + file_type * host{}; |
| 164 | +}; |
| 165 | + |
| 166 | +} // namespace bio::detail |
0 commit comments