HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
lookahead_iterator.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2023.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "../utility/module.hpp"
11#include <iterator>
12#include <bit>
13#include <optional>
14#include <string>
15
16namespace hi {
17inline namespace v1 {
18
25template<size_t LookaheadCount, typename It, std::sentinel_for<It> ItEnd = std::default_sentinel_t>
27public:
28 static_assert(std::has_single_bit(LookaheadCount), "LookaheadCount must be a power of two.");
29
30 constexpr static size_t max_size = LookaheadCount;
31
32 using value_type = std::iterator_traits<It>::value_type;
33 using reference = value_type const &;
34 using pointer = value_type const *;
35 using difference_type = std::ptrdiff_t;
36 using iterator_category = std::forward_iterator_tag;
37
38 constexpr lookahead_iterator() noexcept = default;
39 constexpr lookahead_iterator(lookahead_iterator const &) noexcept = delete;
40 constexpr lookahead_iterator(lookahead_iterator &&) noexcept = default;
41 constexpr lookahead_iterator&operator=(lookahead_iterator const &) noexcept = delete;
42 constexpr lookahead_iterator&operator=(lookahead_iterator &&) noexcept = default;
43
44 constexpr explicit lookahead_iterator(It first, ItEnd last) noexcept : _it(first), _last(last), _size(0)
45 {
46 while (_size != max_size and first != last) {
47 add_one_to_lookahead();
48 }
49 }
50
55 [[nodiscard]] constexpr size_t size() const noexcept
56 {
57 return _size;
58 }
59
64 [[nodiscard]] constexpr bool empty() const noexcept
65 {
66 return _size == 0;
67 }
68
69 constexpr explicit operator bool() const noexcept
70 {
71 return not empty();
72 }
73
74 [[nodiscard]] constexpr bool operator==(std::default_sentinel_t) const noexcept
75 {
76 return empty();
77 }
78
84 [[nodiscard]] constexpr reference operator[](size_t i) const noexcept
85 {
86 hi_axiom(i < _size);
87 return _lookahead[(_tail + i) % max_size];
88 }
89
96 [[nodiscard]] constexpr reference at(size_t i) const
97 {
98 if (i < _size) {
99 return (*this)[i];
100 } else {
101 throw std::out_of_range("lookahead_iterator::at()");
102 }
103 }
104
111 [[nodiscard]] constexpr std::optional<value_type> next(size_t i = 1) const noexcept
112 {
113 if (i < _size) {
114 return (*this)[i];
115 } else {
116 return std::nullopt;
117 }
118 }
119
122 constexpr reference operator*() const noexcept
123 {
124 hi_axiom(_size != 0);
125 return (*this)[0];
126 }
127
130 constexpr pointer operator->() const noexcept
131 {
132 hi_axiom(_size != 0);
133 return std::addressof((*this)[0]);
134 }
135
138 constexpr lookahead_iterator &operator++() noexcept
139 {
140 hi_axiom(_size != 0);
141 --_size;
142 ++_tail;
143 add_one_to_lookahead();
144
145 return *this;
146 }
147
148 constexpr lookahead_iterator &operator+=(size_t n) noexcept
149 {
150 for (auto i = 0_uz; i != n; ++i) {
151 ++(*this);
152 }
153 return *this;
154 }
155
156 constexpr void operator++(int) noexcept
157 {
158 ++(*this);
159 }
160
161private:
162 It _it;
163 ItEnd _last;
164 size_t _size = 0;
165 size_t _tail = 0;
166
167 std::array<value_type, max_size> _lookahead = {};
168
169 constexpr void add_one_to_lookahead() noexcept
170 {
171 hi_axiom(_size < max_size);
172
173 if (_it != _last) {
174 _lookahead[(_tail + _size) % max_size] = *_it;
175 ++_it;
176 ++_size;
177 }
178 }
179};
180
181static_assert(std::movable<lookahead_iterator<2, std::string::iterator, std::string::iterator>>);
182static_assert(std::is_same_v<std::iterator_traits<lookahead_iterator<2, std::string::iterator, std::string::iterator>>::value_type, char>);
183static_assert(std::input_or_output_iterator<lookahead_iterator<2, std::string::iterator, std::string::iterator>>);
184static_assert(std::weakly_incrementable<lookahead_iterator<2, std::string::iterator, std::string::iterator>>);
185
193template<size_t LookaheadCount, typename It, std::sentinel_for<It> ItEnd = std::default_sentinel_t>
194auto make_lookahead_iterator(It first, ItEnd last = std::default_sentinel) noexcept
195{
197}
198
206template<size_t LookaheadCount, std::ranges::range Range>
207auto make_lookahead_iterator(Range const &range) noexcept
208{
209 return make_lookahead_iterator<LookaheadCount>(std::ranges::begin(range), std::ranges::end(range));
210}
211
212}}
213
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
auto make_lookahead_iterator(It first, ItEnd last=std::default_sentinel) noexcept
Create a lookahead_iterator from a forward iterator.
Definition lookahead_iterator.hpp:194
Lookahead iterator.
Definition lookahead_iterator.hpp:26
constexpr lookahead_iterator & operator++() noexcept
Increment the iterator.
Definition lookahead_iterator.hpp:138
constexpr size_t size() const noexcept
The number of entries can be looked ahead.
Definition lookahead_iterator.hpp:55
constexpr pointer operator->() const noexcept
Get a pointer to the value at the iterator.
Definition lookahead_iterator.hpp:130
constexpr reference at(size_t i) const
Get a reference to an item at or beyond the iterator.
Definition lookahead_iterator.hpp:96
constexpr std::optional< value_type > next(size_t i=1) const noexcept
Get a reference to an item at or beyond the iterator.
Definition lookahead_iterator.hpp:111
constexpr reference operator[](size_t i) const noexcept
Get a reference to an item at or beyond the iterator.
Definition lookahead_iterator.hpp:84
constexpr reference operator*() const noexcept
Get a reference to the value at the iterator.
Definition lookahead_iterator.hpp:122
constexpr bool empty() const noexcept
Check if the iterator is at end.
Definition lookahead_iterator.hpp:64
T addressof(T... args)