Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Span.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/InitializerList.h" // IWYU pragma: keep
5#include "../Foundation/LibC.h" // IWYU pragma: keep
6#include "../Foundation/TypeTraits.h" // SameConstnessAs
7
8namespace SC
9{
10template <typename Type>
11struct Span;
12
13namespace detail
14{
15// clang-format off
16template<typename U> struct SpanSizeOfType { static constexpr auto size = sizeof(U); };
17template<> struct SpanSizeOfType<void> { static constexpr auto size = 1; };
18template<> struct SpanSizeOfType<const void> { static constexpr auto size = 1; };
19// clang-format on
20} // namespace detail
21
24
27template <typename Type>
28struct Span
29{
30 private:
31 // clang-format off
32 using SizeType = size_t;
33 using VoidType = typename TypeTraits::SameConstnessAs<Type, void>::type;
34 template <typename U> using TypeIfNotVoid = typename TypeTraits::EnableIf<not TypeTraits::IsSame<U, VoidType>::value, Type>::type;
35 template <typename U> using SameType = TypeTraits::IsSame<typename TypeTraits::RemoveConst<U>::type, typename TypeTraits::RemoveConst<Type>::type>;
36 template <typename U> using EnableNotVoid = typename TypeTraits::EnableIf<SameType<U>::value and not TypeTraits::IsSame<U, VoidType>::value, bool>::type;
37 // clang-format on
38 Type* items;
39 SizeType sizeElements;
40
41 public:
42 template <size_t N, typename U = Type, EnableNotVoid<U> = true>
43 constexpr Span(U (&itemsArray)[N]) : items(itemsArray), sizeElements(N)
44 {}
45
47 constexpr Span() : items(nullptr), sizeElements(0) {}
48
52 constexpr Span(Type* items, SizeType sizeInElements) : items(items), sizeElements(sizeInElements) {}
53
56 template <typename U = Type>
57 constexpr Span(TypeIfNotVoid<U>& type) : items(&type), sizeElements(1)
58 {}
59
62 template <typename U = Type>
63 constexpr Span(std::initializer_list<TypeIfNotVoid<U>> list) : items(nullptr), sizeElements(0)
64 {
65 // We need this two step initialization to avoid warnings on all compilers
66 items = list.begin();
67 sizeElements = list.size();
68 }
69
70 // clang-format off
71 template <typename U = Type> operator Span<const TypeIfNotVoid<U>>() const { return {items, sizeElements}; }
72 template <typename U = Type> operator Span< TypeIfNotVoid<U>>() { return {items, sizeElements}; }
73 operator Span<const void>() const { return Span<const void>(items, sizeElements * detail::SpanSizeOfType<Type>::size); }
74 operator Span<void>() { return Span<void>(items, sizeElements * detail::SpanSizeOfType<Type>::size); }
75
77 template <typename T> [[nodiscard]] static Span<Type> reinterpret_object(T& value) { return {reinterpret_cast<Type*>(&value), sizeof(T) / detail::SpanSizeOfType<Type>::size}; }
78
80 [[nodiscard]] static Span<Type> reinterpret_bytes(VoidType* rawMemory, SizeType sizeInBytes) { return Span(reinterpret_cast<Type*>(rawMemory), sizeInBytes / detail::SpanSizeOfType<Type>::size); }
81
83 template <typename T> [[nodiscard]] Span<const T> reinterpret_as_span_of() const { return Span<const T>(reinterpret_cast<const T*>(items), sizeInBytes() / sizeof(T)); }
84
86 template <typename T> [[nodiscard]] Span<T> reinterpret_as_span_of() { return Span<T>(reinterpret_cast<T*>(items), sizeInBytes() / sizeof(T)); }
87
88 [[nodiscard]] constexpr const Type* begin() const { return items; }
89 [[nodiscard]] constexpr const Type* end() const { return items + sizeElements; }
90 [[nodiscard]] constexpr const Type* data() const { return items; }
91 [[nodiscard]] constexpr Type* begin() { return items; }
92 [[nodiscard]] constexpr Type* end() { return items + sizeElements; }
93 [[nodiscard]] constexpr Type* data() { return items; }
94
95 [[nodiscard]] constexpr SizeType sizeInElements() const { return sizeElements; }
96 [[nodiscard]] constexpr SizeType sizeInBytes() const { return sizeElements * detail::SpanSizeOfType<Type>::size; }
97
98 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
99
100 template <typename U = Type> TypeIfNotVoid<U>& operator[](SizeType idx) { return items[idx]; }
101 template <typename U = Type> const TypeIfNotVoid<U>& operator[](SizeType idx) const { return items[idx]; }
102 // clang-format on
103
108 [[nodiscard]] constexpr bool sliceStart(SizeType offsetInElements, Span& destination) const
109 {
110 bool valid = offsetInElements <= sizeElements;
111 destination = valid ? Span(items + offsetInElements, sizeElements - offsetInElements) : Span(nullptr, 0);
112 return valid;
113 }
114
120 [[nodiscard]] constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements,
121 Span& destination) const
122 {
123 bool valid = offsetInElements + lengthInElements <= sizeElements;
124 destination = valid ? Span(items + offsetInElements, lengthInElements) : Span(nullptr, 0);
125 return valid;
126 }
127};
129
130} // namespace SC
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:29
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:77
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:80
Span< T > reinterpret_as_span_of()
Reinterprets the current span as an array of the specified type.
Definition Span.h:86
Span< const T > reinterpret_as_span_of() const
Reinterprets the current span as an array of the specified type.
Definition Span.h:83
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:108
constexpr Span()
Builds an empty Span.
Definition Span.h:47
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:120
constexpr Span(Type *items, SizeType sizeInElements)
Builds a Span from an array.
Definition Span.h:52
constexpr Span(std::initializer_list< TypeIfNotVoid< U > > list)
Span specialized constructor (mainly used for converting const char* to StringView)
Definition Span.h:63
constexpr Span(TypeIfNotVoid< U > &type)
Builds a Span from a single object.
Definition Span.h:57
EnableIf conditionally defines a type if a boolean template parameter is true.
Definition TypeTraits.h:25
IsSame evaluates to true if the provided types T and U are the same, false otherwise.
Definition TypeTraits.h:29