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 TypeInitializerList = typename TypeTraits::EnableIf<TypeTraits::IsConst<U>::value and not TypeTraits::IsSame<U, VoidType>::value, Type>::type;
36 template <typename U> using SameType = TypeTraits::IsSame<typename TypeTraits::RemoveConst<U>::type, typename TypeTraits::RemoveConst<Type>::type>;
37 template <typename U> using EnableNotVoid = typename TypeTraits::EnableIf<SameType<U>::value and not TypeTraits::IsSame<U, VoidType>::value, bool>::type;
38 // clang-format on
39 Type* items;
40 SizeType sizeElements;
41
42 public:
43 template <size_t N, typename U = Type, EnableNotVoid<U> = true>
44 constexpr Span(U (&itemsArray)[N]) : items(itemsArray), sizeElements(N)
45 {}
46
48 constexpr Span() : items(nullptr), sizeElements(0) {}
49
53 constexpr Span(Type* items, SizeType sizeInElements) : items(items), sizeElements(sizeInElements) {}
54
57 template <typename U = Type>
58 constexpr Span(TypeIfNotVoid<U>& type) : items(&type), sizeElements(1)
59 {}
60
63 template <typename U = Type>
64 constexpr Span(std::initializer_list<TypeInitializerList<U>> list) : items(nullptr), sizeElements(0)
65 {
66 // We need this two step initialization to avoid warnings on all compilers
67 items = list.begin();
68 sizeElements = list.size();
69 }
70
71 // clang-format off
72 template <typename U = Type> operator Span<const TypeIfNotVoid<U>>() const { return {items, sizeElements}; }
73 template <typename U = Type> operator Span< TypeIfNotVoid<U>>() { return {items, sizeElements}; }
74 operator Span<const void>() const { return Span<const void>(items, sizeElements * detail::SpanSizeOfType<Type>::size); }
75 operator Span<void>() { return Span<void>(items, sizeElements * detail::SpanSizeOfType<Type>::size); }
76
78 template <typename T> [[nodiscard]] static Span<Type> reinterpret_object(T& value) { return {reinterpret_cast<Type*>(&value), sizeof(T) / detail::SpanSizeOfType<Type>::size}; }
79
81 [[nodiscard]] static Span<Type> reinterpret_bytes(VoidType* rawMemory, SizeType sizeInBytes) { return Span(reinterpret_cast<Type*>(rawMemory), sizeInBytes / detail::SpanSizeOfType<Type>::size); }
82
84 template <typename T> [[nodiscard]] Span<const T> reinterpret_as_span_of() const { return Span<const T>(reinterpret_cast<const T*>(items), sizeInBytes() / sizeof(T)); }
85
87 template <typename T> [[nodiscard]] Span<T> reinterpret_as_span_of() { return Span<T>(reinterpret_cast<T*>(items), sizeInBytes() / sizeof(T)); }
88
89 [[nodiscard]] constexpr const Type* begin() const { return items; }
90 [[nodiscard]] constexpr const Type* end() const { return items + sizeElements; }
91 [[nodiscard]] constexpr const Type* data() const { return items; }
92 [[nodiscard]] constexpr Type* begin() { return items; }
93 [[nodiscard]] constexpr Type* end() { return items + sizeElements; }
94 [[nodiscard]] constexpr Type* data() { return items; }
95
96 [[nodiscard]] constexpr SizeType sizeInElements() const { return sizeElements; }
97 [[nodiscard]] constexpr SizeType sizeInBytes() const { return sizeElements * detail::SpanSizeOfType<Type>::size; }
98
99 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
100
101 template <typename U = Type> TypeIfNotVoid<U>& operator[](SizeType idx) { return items[idx]; }
102 template <typename U = Type> const TypeIfNotVoid<U>& operator[](SizeType idx) const { return items[idx]; }
103 // clang-format on
104
109 [[nodiscard]] constexpr bool sliceStart(SizeType offsetInElements, Span& destination) const
110 {
111 bool valid = offsetInElements <= sizeElements;
112 destination = valid ? Span(items + offsetInElements, sizeElements - offsetInElements) : Span(nullptr, 0);
113 return valid;
114 }
115
121 [[nodiscard]] constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements,
122 Span& destination) const
123 {
124 bool valid = offsetInElements + lengthInElements <= sizeElements;
125 destination = valid ? Span(items + offsetInElements, lengthInElements) : Span(nullptr, 0);
126 return valid;
127 }
128};
130
131// Allows using this type across Plugin boundaries
132SC_COMPILER_EXTERN template struct SC_COMPILER_EXPORT Span<char>;
133} // namespace SC
#define SC_COMPILER_EXTERN
Define compiler-specific export macros for DLL visibility.
Definition Compiler.h:74
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:78
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:81
Span< T > reinterpret_as_span_of()
Reinterprets the current span as an array of the specified type.
Definition Span.h:87
Span< const T > reinterpret_as_span_of() const
Reinterprets the current span as an array of the specified type.
Definition Span.h:84
constexpr Span(std::initializer_list< TypeInitializerList< U > > list)
Span specialized constructor (mainly used for converting const char* to StringView)
Definition Span.h:64
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:109
constexpr Span()
Builds an empty Span.
Definition Span.h:48
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:121
constexpr Span(Type *items, SizeType sizeInElements)
Builds a Span from an array.
Definition Span.h:53
constexpr Span(TypeIfNotVoid< U > &type)
Builds a Span from a single object.
Definition Span.h:58
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