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} // namespace SC
13
16
19template <typename Type>
21{
22 using SizeType = size_t;
23 using VoidType = typename TypeTraits::SameConstnessAs<Type, void>::type;
24
25 template <size_t N>
26 constexpr Span(Type (&_items)[N]) : items(_items), sizeElements(N)
27 {}
28
30 constexpr Span() : items(nullptr), sizeElements(0) {}
31
35 constexpr Span(Type* items, SizeType sizeInElements) : items(items), sizeElements(sizeInElements) {}
36
39 constexpr Span(Type& type) : items(&type), sizeElements(1) {}
40
43 constexpr Span(std::initializer_list<Type> list) : items(nullptr), sizeElements(0)
44 {
45 // We need this two step initialization to avoid warnings on all compilers
46 items = list.begin();
47 sizeElements = list.size();
48 }
49
51 operator Span<const Type>() const { return {items, sizeElements}; }
52
57 template <typename T>
58 [[nodiscard]] static Span<Type> reinterpret_object(T& value)
59 {
60 return {reinterpret_cast<Type*>(&value), sizeof(T) / sizeof(Type)};
61 }
62
67 [[nodiscard]] static Span<Type> reinterpret_bytes(VoidType* rawMemory, SizeType sizeInBytes)
68 {
69 return Span(reinterpret_cast<Type*>(rawMemory), sizeInBytes / sizeof(Type));
70 }
71
73 template <typename T>
74 [[nodiscard]] Span<T> reinterpret_as_array_of() const
75 {
76 return Span<T>(reinterpret_cast<T*>(items), sizeInBytes() / sizeof(T));
77 }
78
81 [[nodiscard]] constexpr const Type* begin() const { return items; }
82
85 [[nodiscard]] constexpr const Type* end() const { return items + sizeElements; }
86
89 [[nodiscard]] constexpr const Type* data() const { return items; }
90
93 [[nodiscard]] constexpr Type* begin() { return items; }
94
97 [[nodiscard]] constexpr Type* end() { return items + sizeElements; }
98
101 [[nodiscard]] constexpr Type* data() { return items; }
102
105 [[nodiscard]] constexpr SizeType sizeInElements() const { return sizeElements; }
106
109 [[nodiscard]] constexpr SizeType sizeInBytes() const { return sizeElements * sizeof(Type); }
110
117 [[nodiscard]] constexpr bool sliceStart(SizeType offsetInElements, Span& destination) const
118 {
119 if (offsetInElements <= sizeInElements())
120 {
121 destination = Span(items + offsetInElements, (sizeInElements() - offsetInElements));
122 return true;
123 }
124 return false;
125 }
126
134 [[nodiscard]] constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements,
135 Span& destination) const
136 {
137 if (offsetInElements + lengthInElements <= sizeInElements())
138 {
139 destination = Span(items + offsetInElements, lengthInElements);
140 return true;
141 }
142 return false;
143 }
144
148 [[nodiscard]] const bool sliceFromStartUntil(Span other, Span& output) const
149 {
150 const auto diff = other.items - items;
151 if (diff < 0 or static_cast<SizeType>(diff) > sizeInBytes())
152 {
153 return false;
154 }
155 else
156 {
157 output = Span(items, static_cast<SizeType>(diff) / sizeof(Type));
158 return true;
159 }
160 }
161
164 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
165
166 [[nodiscard]] constexpr bool contains(const Type& type, SizeType* index = nullptr) const
167 {
168 for (SizeType idx = 0; idx < sizeElements; ++idx)
169 {
170 if (items[idx] == type)
171 {
172 if (index)
173 {
174 *index = idx;
175 }
176 return true;
177 }
178 }
179 return false;
180 }
181
182 Type& operator[](SizeType idx) { return items[idx]; }
183
184 const Type& operator[](SizeType idx) const { return items[idx]; }
185
187 template <typename IntType>
188 Type* get(IntType idx)
189 {
190 if (idx >= 0 and idx < static_cast<IntType>(sizeElements))
191 return items + idx;
192 return nullptr;
193 }
194
196 template <typename IntType>
197 const Type* get(IntType idx) const
198 {
199 if (idx >= 0 and idx < static_cast<IntType>(sizeElements))
200 return items + idx;
201 return nullptr;
202 }
203
204 template <typename U>
205 [[nodiscard]] bool equals(const Span<U> other) const
206 {
207 if (sizeInBytes() != other.sizeInBytes())
208 return false;
209 if (sizeInBytes() == 0)
210 return true;
211 return ::memcmp(items, other.data(), sizeInBytes()) == 0;
212 }
213
214 private:
215 Type* items;
216 SizeType sizeElements;
217};
218
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:21
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:58
constexpr const Type * data() const
Returns pointer to first element of the span.
Definition: Span.h:89
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:67
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:197
constexpr SizeType sizeInBytes() const
Size of Span in bytes.
Definition: Span.h:109
constexpr Span(std::initializer_list< Type > list)
Span specialized constructor (mainly used for converting const char* to StringView)
Definition: Span.h:43
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:117
Span< T > reinterpret_as_array_of() const
Reinterprets the current span as an array of the specified type.
Definition: Span.h:74
constexpr Span()
Builds an empty Span.
Definition: Span.h:30
constexpr Type * begin()
Returns pointer to first element of the span.
Definition: Span.h:93
constexpr Type * end()
Returns pointer to one after the last element of the span.
Definition: Span.h:97
constexpr const Type * begin() const
Returns pointer to first element of the span.
Definition: Span.h:81
Type * get(IntType idx)
Gets the item at given index or nullptr if index is negative or bigger than size.
Definition: Span.h:188
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:134
constexpr Span(Type *items, SizeType sizeInElements)
Builds a Span from an array.
Definition: Span.h:35
constexpr Type * data()
Returns pointer to first element of the span.
Definition: Span.h:101
constexpr bool empty() const
Check if Span is empty.
Definition: Span.h:164
constexpr SizeType sizeInElements() const
Size of Span in elements.
Definition: Span.h:105
constexpr const Type * end() const
Returns pointer to one after the last element of the span.
Definition: Span.h:85
constexpr Span(Type &type)
Builds a Span from a single object.
Definition: Span.h:39
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:148