AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
iterators.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include <tuple>
15#include <variant>
16#include <cstdint>
17#include <iterator>
18#include <ostream>
19#include "parameter_pack.h"
20#include "macros.h"
21
22
23namespace aui {
24
33 template <typename T>
34 struct reverse_iterator_wrap {
35 private:
36 const T* mIterable;
37
38 public:
39 explicit reverse_iterator_wrap(const T& mIterable) : mIterable(&mIterable) {}
40
41 auto begin() {
42 return mIterable->rbegin();
43 }
44 auto end() {
45 return mIterable->rend();
46 }
47 };
48
49 template<typename Iterator>
50 struct range {
51 private:
52 Iterator mBegin;
53 Iterator mEnd;
54 public:
55 constexpr range(Iterator mBegin, Iterator mEnd) : mBegin(mBegin), mEnd(mEnd) {}
56
57 constexpr ~range() {
58 AUI_NO_OPTIMIZE_OUT(range::size)
59 }
60
61 template<typename Container>
62 constexpr range(Container& c): mBegin(c.begin()), mEnd(c.end()) {
63
64 }
65
66
67 template<typename Container>
68 constexpr range(const Container& c): mBegin(c.begin()), mEnd(c.end()) {
69
70 }
71
72 [[nodiscard]]
73 constexpr bool empty() const noexcept {
74 return mBegin == mEnd;
75 }
76
77 [[nodiscard]]
78 constexpr std::size_t size() const noexcept {
79 return std::distance(mBegin, mEnd);
80 }
81
82 [[nodiscard]]
83 constexpr Iterator& begin() noexcept {
84 return mBegin;
85 }
86
87 [[nodiscard]]
88 constexpr Iterator& end() noexcept {
89 return mEnd;
90 }
91
92 [[nodiscard]]
93 constexpr Iterator begin() const noexcept {
94 return mBegin;
95 }
96
97 [[nodiscard]]
98 constexpr Iterator end() const noexcept {
99 return mEnd;
100 }
101
102 [[nodiscard]]
103 constexpr const auto& first() const {
104 return *mBegin;
105 }
106
107 [[nodiscard]]
108 constexpr const auto& last() const {
109 return *std::prev(mEnd);
110 }
111
112 [[nodiscard]]
113 constexpr bool operator==(const range& rhs) const noexcept;
114
115 [[nodiscard]]
116 constexpr bool operator!=(const range& rhs) const noexcept {
117 return !(*this == rhs);
118 }
119 };
120
121 template<typename Container>
122 range(Container& c) -> range<decltype(c.begin())>;
123
124 template<typename Container>
125 range(const Container& c) -> range<decltype(c.begin())>;
126
130 template<typename Container>
131 using const_iterator_if_const = std::conditional_t<std::is_const_v<Container>,
132 typename Container::const_iterator,
133 typename Container::iterator>;
134
135
153 template<typename... Containers>
154 struct zip {
155 private:
156 using iterator_parallel = std::tuple<decltype(std::declval<Containers>().begin())...>;
157
158 iterator_parallel begins_;
159 iterator_parallel ends_;
160
161 public:
162 struct iterator {
163 iterator_parallel iterators_;
164
165 iterator(iterator_parallel iterators) : iterators_(std::move(iterators)) {}
166
167 iterator& operator++() noexcept {
168 std::apply([](auto&&... v) {
169 (++v, ...);
170 }, iterators_);
171 return *this;
172 }
173
174 std::tuple<decltype(*std::declval<Containers>().begin())&...> operator*() noexcept {
175 return std::apply([](auto&&... v) {
176 return std::tuple<decltype(*std::declval<Containers>().begin())&...>((*v)...);
177 }, iterators_);
178 }
179
180 bool operator==(const iterator& rhs) const noexcept {
181 return iterators_ == rhs.iterators_;
182 }
183
184 bool operator!=(const iterator& rhs) const noexcept {
185 return iterators_ != rhs.iterators_;
186 }
187 };
188
189 zip(Containers&... c): begins_(c.begin()...), ends_(c.end()...) {
190
191 }
192
193 iterator begin() noexcept {
194 return iterator(begins_);
195 }
196 iterator end() noexcept {
197 return iterator(ends_);
198 }
199 };
200
201 namespace impl {
202 template<typename Iterator, class = void>
203 static constexpr bool is_forward_iterator = true;
204
205 template<typename Iterator>
206 static constexpr bool is_forward_iterator<std::reverse_iterator<Iterator>> = false;
207 }
208
220 template<typename Iterator>
221 auto reverse_iterator_direction(Iterator iterator) noexcept ->
222 decltype((iterator + 1).base()) requires (!impl::is_forward_iterator<Iterator>) {
223 return (iterator + 1).base();
224 }
225
226 template<typename Iterator>
227 auto reverse_iterator_direction(Iterator iterator) noexcept ->
228 decltype(std::make_reverse_iterator(std::declval<Iterator>())) requires (impl::is_forward_iterator<Iterator>) {
229
230 return std::make_reverse_iterator(iterator + 1);
231 }
232}
233
234template<typename Iterator>
235inline constexpr bool aui::range<Iterator>::operator==(const range& rhs) const noexcept {
236 if (size() != rhs.size()) {
237 return false;
238 }
239 for (const auto&[l, r] : aui::zip(*this, rhs)) {
240 if (l != r) {
241 return false;
242 }
243 }
244 return true;
245}
246
247template<typename T>
248inline std::ostream& operator<<(std::ostream& os, aui::range<T> range) {
249 os << "[ ";
250 bool isFirst = true;
251 for (const auto& v : range) {
252 if (isFirst) {
253 isFirst = false;
254 } else {
255 os << ", ";
256 }
257 os << v;
258 }
259 return os << " ]";
260}
#define AUI_NO_OPTIMIZE_OUT(object)
Forbids object from being optimized out by compiler.
Definition macros.h:40
Definition iterators.h:50
Iterates multiple containers in parallel.
Definition iterators.h:154