HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
nested_vector_iterator.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include <type_traits>
7#include <vector>
8
9namespace tt
10{
11
12
15template<
16 typename ParentCIt,
17 typename ParentIt,
18 typename ChildIt=std::conditional_t<
19 std::is_const_v<std::remove_reference_t<typename std::iterator_traits<ParentIt>::reference>>,
20 typename ParentIt::value_type::const_iterator,
21 typename ParentIt::value_type::iterator
22 >
23>
25 using value_type = typename std::iterator_traits<ChildIt>::value_type;
26 using difference_type = typename std::iterator_traits<ChildIt>::difference_type;
27 using reference = typename std::iterator_traits<ChildIt>::reference;
28
29 ParentCIt parent_it_end;
30 ParentIt parent_it;
31 ChildIt child_it;
32
33public:
34 nested_vector_iterator() noexcept = delete;
35 nested_vector_iterator(nested_vector_iterator const &other) noexcept = default;
36 nested_vector_iterator(nested_vector_iterator &&other) noexcept = default;
37 nested_vector_iterator &operator=(nested_vector_iterator const &other) noexcept = default;
38 nested_vector_iterator &operator=(nested_vector_iterator &&other) noexcept = default;
39 ~nested_vector_iterator() = default;
40
41 nested_vector_iterator(ParentCIt parent_it_end, ParentIt parent_it, ChildIt child_it) noexcept :
42 parent_it_end(parent_it_end), parent_it(parent_it), child_it(child_it) {}
43
44 nested_vector_iterator(ParentCIt parent_it_end, ParentIt parent_it) noexcept :
45 parent_it_end(parent_it_end), parent_it(parent_it)
46 {
47 tt_assume(parent_it_end == parent_it);
48 }
49
52 ParentIt parent() const noexcept { return parent_it; }
53
56 [[nodiscard]] bool at_end() const noexcept { return parent_it == parent_it_end; }
57
58 template<typename X=std::remove_reference_t<reference>, std::enable_if_t<!std::is_const_v<X>, int> = 0>
59 [[nodiscard]] value_type &operator*() noexcept { return *child_it; }
60
61 [[nodiscard]] value_type const &operator*() const noexcept { return *child_it; }
62
63 template<typename X=std::remove_reference_t<reference>, std::enable_if_t<!std::is_const_v<X>, int> = 0>
64 [[nodiscard]] value_type *operator->() noexcept { return &(*child_it); }
65
66 [[nodiscard]] value_type const *operator->() const noexcept { return &(*child_it); }
67
68 template<typename X=std::remove_reference_t<reference>, std::enable_if_t<!std::is_const_v<X>, int> = 0>
69 [[nodiscard]] value_type &operator[](size_t i) noexcept { return *(*this + i); }
70
71 [[nodiscard]] value_type const &operator[](size_t i) const noexcept { return *(*this + i); }
72
73 nested_vector_iterator &operator++() noexcept {
74 ++child_it;
75 if (child_it == parent_it->cend()) {
76 ++parent_it;
77 if (!at_end()) {
78 child_it = parent_it->begin();
79 }
80 }
81 return *this;
82 }
83
84 nested_vector_iterator &operator--() noexcept {
85 if (child_it == parent_it->begin()) {
86 --parent_it;
87 child_it = parent_it->end();
88 }
89 --child_it;
90 return *this;
91 }
92
93 nested_vector_iterator operator++(int) noexcept { auto tmp = *this; ++(*this); return tmp; }
94 nested_vector_iterator operator--(int) noexcept { auto tmp = *this; --(*this); return tmp; }
95
96 nested_vector_iterator &operator+=(difference_type rhs) noexcept {
97 if (rhs < 0) {
98 return (*this) -= -rhs;
99 }
100
101 do {
102 ttlet line_left = std::distance(child_it, parent_it->end());
103
104 if (line_left < rhs) {
105 ++parent_it;
106 if (!at_end()) {
107 child_it = parent_it->begin();
108 }
109 rhs -= line_left;
110
111 } else {
112 child_it += rhs;
113 rhs -= rhs;
114 }
115
116 } while (rhs);
117
118 return *this;
119 }
120
121 nested_vector_iterator &operator-=(difference_type rhs) noexcept {
122 if (rhs < 0) {
123 return (*this) += -rhs;
124 }
125
126 do {
127 ttlet line_left = std::distance(parent_it->begin(), child_it) + 1;
128
129 if (line_left < rhs) {
130 --parent_it;
131 child_it = parent_it->end() - 1;
132 rhs -= line_left;
133
134 } else {
135 child_it -= rhs;
136 rhs -= rhs;
137 }
138
139 } while (rhs);
140
141 return *this;
142 }
143
144 [[nodiscard]] friend bool operator==(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept {
145 if (lhs.at_end() && rhs.at_end()) {
146 return true;
147 } else if (lhs.at_end() || rhs.at_end()) {
148 return false;
149 } else {
150 return (lhs.parent_it == rhs.parent_it) && (lhs.child_it == rhs.child_it);
151 }
152 }
153
154 [[nodiscard]] friend bool operator<(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept {
155 if (lhs.at_end() && rhs.at_end()) {
156 return false;
157 } else if (rhs.at_end()) {
158 return true;
159 } else if (lhs.at_end()) {
160 return false;
161 } else if (lhs.parent_it == rhs.parent_it) {
162 return lhs.child_it < rhs.child_it;
163 } else {
164 return lhs.parent_it < rhs.parent_it;
165 }
166 }
167
168 [[nodiscard]] friend bool operator!=(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept { return !(lhs == rhs); }
169 [[nodiscard]] friend bool operator>(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept { return rhs < lhs; }
170 [[nodiscard]] friend bool operator<=(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept { return !(lhs > rhs); }
171 [[nodiscard]] friend bool operator>=(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept { return !(lhs < rhs); }
172
173 [[nodiscard]] friend nested_vector_iterator operator+(nested_vector_iterator lhs, difference_type rhs) noexcept { return lhs += rhs; }
174 [[nodiscard]] friend nested_vector_iterator operator-(nested_vector_iterator lhs, difference_type rhs) noexcept { return lhs -= rhs; }
175 [[nodiscard]] friend nested_vector_iterator operator+(difference_type lhs, nested_vector_iterator rhs) noexcept { return rhs += lhs; }
176
177 [[nodiscard]] friend difference_type operator-(nested_vector_iterator const &lhs, nested_vector_iterator const &rhs) noexcept {
178 if (rhs < lhs) {
179 return -(rhs - lhs);
180 } else {
181 auto lhs_ = lhs;
182 ssize_t count = 0;
183 while (lhs_.parent_it < rhs.parent_it) {
184 count += std::distance(lhs_.child_it, lhs_.parent_it->end());
185 ++(lhs_.parent_it);
186 lhs_.child_it = lhs_.parent_it->begin();
187 }
188 return count + std::distance(lhs_.child_it, rhs.child_it);
189 }
190 }
191};
192
193template<typename NestedVector>
194[[nodiscard]] auto nested_vector_iterator_begin(NestedVector &rhs) noexcept {
195 return size(rhs) == 0 ?
196 nested_vector_iterator(rhs.cend(), rhs.begin()) :
197 nested_vector_iterator(rhs.cend(), rhs.begin(), rhs.front().begin());
198}
199
200template<typename NestedVector>
201[[nodiscard]] auto nested_vector_iterator_end(NestedVector &rhs) noexcept {
202 return size(rhs) == 0 ?
203 nested_vector_iterator(rhs.cend(), rhs.end()) :
204 nested_vector_iterator(rhs.cend(), rhs.end(), rhs.back().end());
205}
206
207template<typename NestedVector>
208[[nodiscard]] auto nested_vector_iterator_cbegin(NestedVector const &rhs) noexcept {
209 return size(rhs) == 0 ?
210 nested_vector_iterator(rhs.cend(), rhs.cbegin()) :
211 nested_vector_iterator(rhs.cend(), rhs.cbegin(), rhs.front().cbegin());
212}
213
214template<typename NestedVector>
215[[nodiscard]] auto nested_vector_iterator_cend(NestedVector const &rhs) noexcept {
216 return size(rhs) == 0 ?
217 nested_vector_iterator(rhs.cend(), rhs.cend()) :
218 nested_vector_iterator(rhs.cend(), rhs.cend(), rhs.back().cend());
219}
220
221}
An iterator for a vector inside another vector.
Definition nested_vector_iterator.hpp:24
bool at_end() const noexcept
Don't need to check the child_it at end.
Definition nested_vector_iterator.hpp:56
ParentIt parent() const noexcept
Get the current parent iterator.
Definition nested_vector_iterator.hpp:52
T begin(T... args)
T count(T... args)
T distance(T... args)
T end(T... args)