sandbox
Loading...
Searching...
No Matches
storage_iterator.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_ECS_DETAIL_STORAGE_ITERATOR_HPP_
3#define LIBSBX_ECS_DETAIL_STORAGE_ITERATOR_HPP_
4
5#include <iterator>
6#include <type_traits>
7#include <memory>
8
9#include <libsbx/utility/fast_mod.hpp>
10
11#include <libsbx/memory/iterable_adaptor.hpp>
12
13namespace sbx::ecs::detail {
14
15template<typename Container, std::size_t Page>
16class storage_iterator final {
17
19
20 using container_type = std::remove_const_t<Container>;
21 using allocator_traits = std::allocator_traits<typename container_type::allocator_type>;
22
23 using iterator_traits = std::iterator_traits<std::conditional_t<
24 std::is_const_v<Container>,
25 typename allocator_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
26 typename allocator_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>
27 >;
28
29public:
30
31 using value_type = typename iterator_traits::value_type;
32 using pointer = typename iterator_traits::pointer;
33 using reference = typename iterator_traits::reference;
34 using difference_type = typename iterator_traits::difference_type;
35 using iterator_category = std::random_access_iterator_tag;
36
37 constexpr storage_iterator() noexcept = default;
38
39 constexpr storage_iterator(Container* container, const difference_type offset) noexcept
40 : _container{container},
41 _offset{offset} { }
42
43 template<bool IsConst = std::is_const_v<Container>>
44 requires (!IsConst)
45 constexpr storage_iterator(const storage_iterator<std::remove_const_t<Container>, Page>& other) noexcept
46 : storage_iterator{other._payload, other._offset} { }
47
48 constexpr auto operator++() noexcept -> storage_iterator& {
49 --_offset;
50 return *this;
51 }
52
53 constexpr auto operator++(int) noexcept -> storage_iterator {
54 const auto original = *this;
55 ++(*this);
56 return original;
57 }
58
59 constexpr auto operator--() noexcept -> storage_iterator& {
60 ++_offset;
61 return *this;
62 }
63
64 constexpr auto operator--(int) noexcept -> storage_iterator {
65 const auto original = *this;
66 --(*this);
67 return original;
68 }
69
70 constexpr auto operator+=(const difference_type value) noexcept -> storage_iterator& {
71 _offset -= value;
72 return *this;
73 }
74
75 constexpr auto operator+(const difference_type value) const noexcept -> storage_iterator {
76 auto copy = *this;
77 return (copy += value);
78 }
79
80 constexpr auto operator-=(const difference_type value) noexcept -> storage_iterator& {
81 return (*this += -value);
82 }
83
84 constexpr auto operator-(const difference_type value) const noexcept -> storage_iterator {
85 return (*this + -value);
86 }
87
88 [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
89 const auto position = static_cast<typename Container::size_type>(index() - value);
90 return (*_container)[position / Page][utility::fast_mod(static_cast<std::size_t>(position), Page)];
91 }
92
93 [[nodiscard]] constexpr pointer operator->() const noexcept {
94 return std::addressof(operator[](0));
95 }
96
97 [[nodiscard]] constexpr reference operator*() const noexcept {
98 return operator[](0);
99 }
100
101 [[nodiscard]] constexpr difference_type index() const noexcept {
102 return _offset - 1;
103 }
104
105private:
106
107 Container* _container;
108 difference_type _offset;
109
110}; // class storage_iterator
111
112template<typename Lhs, typename Rhs, std::size_t Page>
113[[nodiscard]] constexpr bool operator==(const storage_iterator<Lhs, Page>& lhs, const storage_iterator<Rhs, Page>& rhs) noexcept {
114 return lhs.index() == rhs.index();
115}
116
117template<typename Iterator, typename... Other>
119
120 template<typename It, typename... Args>
121 friend class extended_storage_iterator;
122
123 template<typename... Lhs, typename... Rhs>
124 friend constexpr bool operator==(const extended_storage_iterator<Lhs...>&, const extended_storage_iterator<Rhs...>&) noexcept;
125
126public:
127
128 using iterator = Iterator;
129 using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<Iterator>()), std::forward_as_tuple(*std::declval<Other>()...)));
131 using reference = value_type;
132 using difference_type = std::ptrdiff_t;
133 using iterator_category = std::input_iterator_tag;
134 using iterator_concept = std::forward_iterator_tag;
135
136 constexpr extended_storage_iterator()
137 : _values{} { }
138
139 constexpr extended_storage_iterator(iterator base, Other... other)
140 : _values{base, other...} { }
141
142 template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
144 : _values{other._values} {}
145
146 constexpr auto operator++() noexcept -> extended_storage_iterator& {
147 return ++std::get<iterator>(_values), (++std::get<Other>(_values), ...), *this;
148 }
149
150 constexpr auto operator++(int) noexcept -> extended_storage_iterator {
151 const auto original = *this;
152 ++(*this);
153 return original;
154 }
155
156 [[nodiscard]] constexpr auto operator->() const noexcept -> pointer {
157 return operator*();
158 }
159
160 [[nodiscard]] constexpr auto operator*() const noexcept -> reference {
161 return {*std::get<iterator>(_values), *std::get<Other>(_values)...};
162 }
163
164 [[nodiscard]] constexpr auto base() const noexcept -> iterator {
165 return std::get<iterator>(_values);
166 }
167
168private:
169
170 std::tuple<iterator, Other...> _values;
171
172}; // class extended_storage_iterator
173
174template<typename... Lhs, typename... Rhs>
175[[nodiscard]] constexpr bool operator==(const extended_storage_iterator<Lhs...>& lhs, const extended_storage_iterator<Rhs...>& rhs) noexcept {
176 return std::get<0>(lhs._values) == std::get<0>(rhs._values);
177}
178
179} // namespace sbx::ecs::detail
180
181#endif // LIBSBX_ECS_DETAIL_STORAGE_ITERATOR_HPP_
Definition: storage_iterator.hpp:118
Definition: storage_iterator.hpp:16
Definition: iterable_adaptor.hpp:51