Sane C++ Libraries
C++ Platform Abstraction Libraries
Span.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/InitializerList.h"
5#include "../Foundation/LibC.h" // memcmp
6#include "../Foundation/TypeTraits.h" // SameConstnessAs
7
8namespace SC
9{
10template <typename Type>
11struct Span;
12
13struct SpanStringView;
14struct SpanString;
15} // namespace SC
16
19
22template <typename Type>
24{
25 using SizeType = size_t;
26 using VoidType = typename TypeTraits::SameConstnessAs<Type, void>::type;
27
28 template <size_t N>
29 constexpr Span(Type (&_items)[N]) : items(_items), sizeElements(N)
30 {}
31
33 constexpr Span() : items(nullptr), sizeElements(0) {}
34
38 constexpr Span(Type* items, SizeType sizeInElements) : items(items), sizeElements(sizeInElements) {}
39
42 constexpr Span(Type& type) : items(&type), sizeElements(1) {}
43
46 constexpr Span(std::initializer_list<Type> list) : items(nullptr), sizeElements(0)
47 {
48 // We need this two step initialization to avoid warnings on all compilers
49 items = list.begin();
50 sizeElements = list.size();
51 }
52
54 operator Span<const Type>() const { return {items, sizeElements}; }
55
60 template <typename T>
61 [[nodiscard]] static Span<Type> reinterpret_object(T& value)
62 {
63 return {reinterpret_cast<Type*>(&value), sizeof(T) / sizeof(Type)};
64 }
65
70 [[nodiscard]] static Span<Type> reinterpret_bytes(VoidType* rawMemory, SizeType sizeInBytes)
71 {
72 return Span(reinterpret_cast<Type*>(rawMemory), sizeInBytes / sizeof(Type));
73 }
74
76 template <typename T>
78 {
79 return Span<const T>(reinterpret_cast<const T*>(items), sizeInBytes() / sizeof(T));
80 }
81
83 template <typename T>
85 {
86 return Span<T>(reinterpret_cast<T*>(items), sizeInBytes() / sizeof(T));
87 }
88
91 [[nodiscard]] constexpr const Type* begin() const { return items; }
92
95 [[nodiscard]] constexpr const Type* end() const { return items + sizeElements; }
96
99 [[nodiscard]] constexpr const Type* data() const { return items; }
100
103 [[nodiscard]] constexpr Type* begin() { return items; }
104
107 [[nodiscard]] constexpr Type* end() { return items + sizeElements; }
108
111 [[nodiscard]] constexpr Type* data() { return items; }
112
115 [[nodiscard]] constexpr SizeType sizeInElements() const { return sizeElements; }
116
119 [[nodiscard]] constexpr SizeType sizeInBytes() const { return sizeElements * sizeof(Type); }
120
127 [[nodiscard]] constexpr bool sliceStart(SizeType offsetInElements, Span& destination) const
128 {
129 if (offsetInElements <= sizeInElements())
130 {
131 destination = Span(items + offsetInElements, (sizeInElements() - offsetInElements));
132 return true;
133 }
134 return false;
135 }
136
144 [[nodiscard]] constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements,
145 Span& destination) const
146 {
147 if (offsetInElements + lengthInElements <= sizeInElements())
148 {
149 destination = Span(items + offsetInElements, lengthInElements);
150 return true;
151 }
152 return false;
153 }
154
158 [[nodiscard]] const bool sliceFromStartUntil(Span other, Span& output) const
159 {
160 const auto diff = other.items - items;
161 if (diff < 0 or static_cast<SizeType>(diff) > sizeInBytes())
162 {
163 return false;
164 }
165 else
166 {
167 output = Span(items, static_cast<SizeType>(diff) / sizeof(Type));
168 return true;
169 }
170 }
171
174 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
175
176 [[nodiscard]] constexpr bool contains(const Type& type, SizeType* index = nullptr) const
177 {
178 for (SizeType idx = 0; idx < sizeElements; ++idx)
179 {
180 if (items[idx] == type)
181 {
182 if (index)
183 {
184 *index = idx;
185 }
186 return true;
187 }
188 }
189 return false;
190 }
191
192 Type& operator[](SizeType idx) { return items[idx]; }
193
194 const Type& operator[](SizeType idx) const { return items[idx]; }
195
197 template <typename IntType>
198 Type* get(IntType idx)
199 {
200 if (idx >= 0 and idx < static_cast<IntType>(sizeElements))
201 return items + idx;
202 return nullptr;
203 }
204
206 template <typename IntType>
207 const Type* get(IntType idx) const
208 {
209 if (idx >= 0 and idx < static_cast<IntType>(sizeElements))
210 return items + idx;
211 return nullptr;
212 }
213
215 template <typename U>
216 [[nodiscard]] bool memcmpWith(const Span<U> other) const
217 {
218 if (sizeInBytes() != other.sizeInBytes())
219 return false;
220 if (sizeInBytes() == 0)
221 return true;
222 return ::memcmp(items, other.data(), sizeInBytes()) == 0;
223 }
224
226 template <typename U>
227 [[nodiscard]] bool memcpyTo(Span<U>& other) const
228 {
229 if (other.sizeInBytes() < sizeInBytes())
230 return false;
231 ::memcpy(other.data(), items, sizeInBytes());
232 other = {other.data(), sizeInBytes() / sizeof(U)};
233 return true;
234 }
235
236 private:
237 Type* items;
238 SizeType sizeElements;
239};
240
241#if SC_PLATFORM_WINDOWS
242#define SC_NATIVE_STR(str) L##str
243#else
244#define SC_NATIVE_STR(str) str
245#endif
246
249{
250 constexpr SpanStringView() = default;
251 constexpr SpanStringView(const char* string, size_t stringLength) : text(string, stringLength) {}
252 template <size_t N>
253 constexpr SpanStringView(const char (&charLiteral)[N]) : text(charLiteral)
254 {}
255
257 template <int N>
258 [[nodiscard]] bool writeNullTerminated(char (&buffer)[N]) const
259 {
260 if (N < text.sizeInElements() + 1)
261 return false;
262 ::memcpy(&buffer[0], text.data(), text.sizeInElements());
263 buffer[N - 1] = 0;
264 return true;
265 }
266
267 Span<const char> text;
268};
269
272{
273 template <size_t N>
274 constexpr SpanString(char (&buffer)[N]) : text(buffer)
275 {}
276
277 operator SpanStringView() const
278 {
280 sv.text = text;
281 return sv;
282 }
283
284 SC::Span<char> text;
285};
unsigned long size_t
Platform independent unsigned size type.
Definition: PrimitiveTypes.h:56
View over a contiguous sequence of items (pointer + size in elements).
Definition: Span.h:24
static Span< Type > reinterpret_object(T &value)
Constructs a Span reinterpreting memory pointed by object of type T as a type Type
Definition: Span.h:61
constexpr const Type * data() const
Returns pointer to first element of the span.
Definition: Span.h:99
static Span< Type > reinterpret_bytes(VoidType *rawMemory, SizeType sizeInBytes)
Construct a span reinterpreting raw memory (void* or const void*) to Type or const Type
Definition: Span.h:70
const Type * get(IntType idx) const
Gets the item at given index or nullptr if index is negative or bigger than size.
Definition: Span.h:207
constexpr SizeType sizeInBytes() const
Size of Span in bytes.
Definition: Span.h:119
bool memcmpWith(const Span< U > other) const
Compares this span with another one byte by byte.
Definition: Span.h:216
constexpr Span(std::initializer_list< Type > list)
Span specialized constructor (mainly used for converting const char* to StringView)
Definition: Span.h:46
Span< T > reinterpret_as_array_of()
Reinterprets the current span as an array of the specified type.
Definition: Span.h:84
constexpr bool sliceStart(SizeType offsetInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span, until end.
Definition: Span.h:127
constexpr Span()
Builds an empty Span.
Definition: Span.h:33
constexpr Type * begin()
Returns pointer to first element of the span.
Definition: Span.h:103
constexpr Type * end()
Returns pointer to one after the last element of the span.
Definition: Span.h:107
constexpr const Type * begin() const
Returns pointer to first element of the span.
Definition: Span.h:91
Type * get(IntType idx)
Gets the item at given index or nullptr if index is negative or bigger than size.
Definition: Span.h:198
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition: Span.h:144
bool memcpyTo(Span< U > &other) const
Bitwise copies contents of this Span over another (non-overlapping)
Definition: Span.h:227
constexpr Span(Type *items, SizeType sizeInElements)
Builds a Span from an array.
Definition: Span.h:38
Span< const T > reinterpret_as_array_of() const
Reinterprets the current span as an array of the specified type.
Definition: Span.h:77
constexpr Type * data()
Returns pointer to first element of the span.
Definition: Span.h:111
constexpr bool empty() const
Check if Span is empty.
Definition: Span.h:174
constexpr SizeType sizeInElements() const
Size of Span in elements.
Definition: Span.h:115
constexpr const Type * end() const
Returns pointer to one after the last element of the span.
Definition: Span.h:95
constexpr Span(Type &type)
Builds a Span from a single object.
Definition: Span.h:42
const bool sliceFromStartUntil(Span other, Span &output) const
Creates another Span shorter or equal than the current one such that its end equals other....
Definition: Span.h:158
An writable view over an ASCII string (to avoid including Strings library)
Definition: Span.h:272
An read-only view over an ASCII string (to avoid including Strings library)
Definition: Span.h:249
bool writeNullTerminated(char(&buffer)[N]) const
Writes current string view over a sized char array buffer, adding a null terminator.
Definition: Span.h:258