Grindstone Game Engine v0.2.0
An open source game engine and toolkit.
Loading...
Searching...
No Matches
Span.hpp
1#pragma once
2
3#include <type_traits>
4
5#include <Common/Assert.hpp>
6#include <Common/IntTypes.hpp>
7
8#include "Iterators.hpp"
9
10namespace Grindstone::Containers {
11 template<typename T>
12 class Span {
13 public:
14 using Iterator = ArrayIterator<T>;
15 using ConstIterator = ConstArrayIterator<T>;
16 using ReverseIterator = ReverseArrayIterator<T>;
17 using ConstReverseIterator = ConstArrayIterator<T>;
18
19 Span() = default;
20
21 Span(T* ptr, size_t size) : size(size), contents(ptr) {}
22
23 Span(const Span& other) : size(other.size), contents(other.contents) {}
24
25 Span(Span&& other) noexcept : size(other.size), contents(other.contents) {
26 other.size = 0;
27 other.contents = nullptr;
28 }
29
30 template <typename U,
31 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
32 Span(const Span<U>& other)
33 : size(other.GetSize()), contents(std::move(other.contents)) {}
34
35 template <typename U,
36 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
37 Span(Span<U>&& other) noexcept
38 : size(other.GetSize()), contents(std::move(other.contents)) {
39 other.size = 0;
40 other.contents = nullptr;
41 }
42
43 template <typename U,
44 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
45 Span& operator=(const Span<U>& other) {
46 size = other.size;
47 contents = other.contents;
48
49 return *this;
50 }
51
52 template <typename U,
53 std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
54 Span& operator=(Span<U>&& other) noexcept {
55 if (this != reinterpret_cast<Span<T>*>(&other)) {
56 size = other.size;
57 contents = other.contents;
58 other.size = 0;
59 other.contents = nullptr;
60 }
61 return *this;
62 }
63
64 Span& operator=(const Span& other) {
65 size = other.size;
66 contents = other.contents;
67 }
68
69 Span& operator=(Span&& other) noexcept {
70 size = other.size;
71 contents = other.contents;
72
73 other.size = 0;
74 other.contents = nullptr;
75
76 return *this;
77 }
78
79 ~Span() {
80 contents = nullptr;
81 size = 0;
82 }
83
84 [[nodiscard]] const T& GetBegin() const {
85 return contents[0];
86 }
87
88 [[nodiscard]] T& GetBegin() {
89 return contents[0];
90 }
91
92 [[nodiscard]] const T& GetEnd() const {
93 return contents[size];
94 }
95
96 [[nodiscard]] T& GetEnd() {
97 return contents[size];
98 }
99
100 bool TryGet(T& outValue, size_t index) {
101 if (index < size) {
102 outValue = contents[index];
103 return true;
104 }
105
106 return false;
107 }
108
109 size_t GetSize() const {
110 return size;
111 }
112
113 Span<T> GetSubspan(size_t firstIndex, size_t count) {
114 GS_ASSERT_ENGINE_WITH_MESSAGE(count == 0 || firstIndex + count <= size, "Array index is invalid.");
115 return Span<T>{ &contents[firstIndex], count };
116 }
117
118 T& operator[](size_t index) {
119 GS_ASSERT_ENGINE_WITH_MESSAGE(index < size, "Array index is invalid.");
120 return contents[index];
121 }
122
123 const T& operator[](size_t index) const {
124 GS_ASSERT_ENGINE_WITH_MESSAGE(index < size, "Array index is invalid.");
125 return contents[index];
126 }
127
128 [[nodiscard]] constexpr Iterator begin() noexcept {
129 return Iterator(contents);
130 }
131
132 [[nodiscard]] constexpr ConstIterator begin() const noexcept {
133 return ConstIterator(contents);
134 }
135
136 [[nodiscard]] constexpr Iterator end() noexcept {
137 return Iterator(&contents[size]);
138 }
139
140 [[nodiscard]] constexpr ConstIterator end() const noexcept {
141 return ConstIterator(&contents[size]);
142 }
143
144 [[nodiscard]] constexpr ReverseIterator rbegin() noexcept {
145 return ReverseIterator(end());
146 }
147
148 [[nodiscard]] constexpr ConstReverseIterator rbegin() const noexcept {
149 return ConstReverseIterator(end());
150 }
151
152 [[nodiscard]] constexpr ReverseIterator rend() noexcept {
153 return ReverseIterator(begin());
154 }
155
156 [[nodiscard]] constexpr ConstReverseIterator rend() const noexcept {
157 return ConstReverseIterator(begin());
158 }
159
160 [[nodiscard]] constexpr ConstIterator cbegin() const noexcept {
161 return ConstIterator(contents);
162 }
163
164 [[nodiscard]] constexpr ConstIterator cend() const noexcept {
165 return ConstIterator(&contents[size]);
166 }
167
168 [[nodiscard]] constexpr ConstReverseIterator crbegin() const noexcept {
169 return ConstReverseIterator(end());
170 }
171
172 [[nodiscard]] constexpr ConstReverseIterator crend() const noexcept {
173 return ConstReverseIterator(begin());
174 }
175 protected:
176 size_t size = 0;
177 T* contents = nullptr;
178 };
179
180 using BufferSpan = Span<Grindstone::Byte>;
181
182 template<typename T>
183 class ReverseRange {
184 public:
185 explicit ReverseRange(T& iterable) : iterable{ iterable } {}
186 auto begin() const { return std::rbegin(iterable); }
187 auto end() const { return std::rend(iterable); }
188 private:
189 T& iterable;
190 };
191
192 template<typename T>
193 class ReverseRangeTemp {
194 public:
195 explicit ReverseRangeTemp(T&& iterable) : iterable{ std::move(iterable) } {}
196 auto begin() const { return std::rbegin(iterable); }
197 auto end() const { return std::rend(iterable); }
198 private:
199 T iterable;
200 };
201}
Definition Span.hpp:12
Definition Bitset.hpp:8
Definition Iterators.hpp:29