Sane C++ Libraries
C++ Platform Abstraction Libraries
ReflectionFoundation.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/Compiler.h"
5#include "../Foundation/Span.h"
6namespace SC
7{
8namespace Reflection
9{
12
16template <typename T, uint32_t N>
18{
19 T values[N] = {};
20 uint32_t size = 0;
21
22 operator Span<const T>() const { return {values, size}; }
27 [[nodiscard]] constexpr bool contains(T value, uint32_t* outIndex = nullptr) const
28 {
29 for (uint32_t i = 0; i < size; ++i)
30 {
31 if (values[i] == value)
32 {
33 if (outIndex)
34 *outIndex = i;
35 return true;
36 }
37 }
38 return false;
39 }
40
45 template <uint32_t N2>
46 [[nodiscard]] constexpr bool append(const ArrayWithSize<T, N2>& other)
47 {
48 if (size + other.size >= N)
49 return false;
50 for (uint32_t i = 0; i < other.size; ++i)
51 {
52 values[size++] = other.values[i];
53 }
54 return true;
55 }
56
60 [[nodiscard]] constexpr bool push_back(const T& value)
61 {
62 if (size < N)
63 {
64 values[size++] = value;
65 return true;
66 }
67 return false;
68 }
69
70 bool equals(Span<const T> other) const
71 {
72 return size == other.sizeInElements() and ::memcmp(values, other.data(), other.sizeInBytes()) == 0;
73 }
74};
75
77template <typename Type>
79{
80 Type* iterator;
81 Type* iteratorEnd;
82
83 constexpr WritableRange(Type* iteratorStart, const uint32_t capacity)
84 : iterator(iteratorStart), iteratorEnd(iteratorStart + capacity)
85 {}
86
87 [[nodiscard]] constexpr bool writeAndAdvance(const Type& value)
88 {
89 if (iterator < iteratorEnd)
90 {
91 *iterator = value;
92 iterator++;
93 return true;
94 }
95 return false;
96 }
97};
98
100struct Sv
101{
102 const char* data;
104
106 constexpr Sv() : data(nullptr), length(0) {}
107
111 constexpr Sv(const char* data, uint32_t length) : data(data), length(length) {}
112
116 template <uint32_t N>
117 constexpr Sv(const char (&data)[N]) : data(data), length(N - 1)
118 {}
119
120 constexpr bool operator==(const Sv other) const
121 {
122 if (length != other.length)
123 return false;
124 for (uint32_t idx = 0; idx < length; ++idx)
125 {
126 if (data[idx] != other.data[idx])
127 return false;
128 }
129 return true;
130 }
131};
132
136template <typename T>
137static constexpr Sv ClNm()
138{
139 // clang-format off
140#if SC_COMPILER_CLANG || SC_COMPILER_GCC
141 const char* name = __PRETTY_FUNCTION__;
142 constexpr char separating_char = '=';
143 constexpr uint32_t skip_chars = 2;
144 constexpr uint32_t trim_chars = 1;
145 uint32_t length = 0;
146 const char* it = name;
147 while (*it != separating_char)
148 it++;
149 it += skip_chars;
150 while (it[length] != 0)
151 length++;
152 return Sv(it, length - trim_chars);
153#else
154 const char* name = __FUNCSIG__;
155 constexpr char separating_char = '<';
156 constexpr char ending_char = '>';
157 const char* it = name;
158 while (*it != separating_char)
159 it++;
160 auto itStart = it + 1;
161 while (*it != ending_char)
162 {
163 if (*it == ' ')
164 itStart = it + 1;
165 it++;
166 }
167 return Sv(itStart, static_cast<int>(it - itStart));
168#endif
169 // clang-format on
170}
171
172using TypeStringView = Sv;
173
176template <typename T>
178{
179#if SC_LANGUAGE_CPP_AT_LEAST_17
180 private:
181 // In C++ 17 we trim the long string producted by ClassName<T> to reduce executable size
182 [[nodiscard]] static constexpr auto TrimClassName()
183 {
184 constexpr auto className = ClNm<T>();
185
186 ArrayWithSize<char, className.length> trimmedName;
187 for (uint32_t i = 0; i < className.length; ++i)
188 {
189 trimmedName.values[i] = className.data[i];
190 }
191 trimmedName.size = className.length;
192 return trimmedName;
193 }
194
195 // Inline static constexpr requires C++17
196 static inline constexpr auto value = TrimClassName();
197
198 public:
199 [[nodiscard]] static constexpr TypeStringView get() { return TypeStringView(value.values, value.size); }
200#else
201 [[nodiscard]] static constexpr TypeStringView get()
202 {
203 auto className = ClNm<T>();
204 return TypeStringView(className.data, className.length);
205 }
206#endif
207};
208
210
211} // namespace Reflection
212} // namespace SC
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition: PrimitiveTypes.h:38
A constexpr array.
Definition: ReflectionFoundation.h:18
constexpr bool push_back(const T &value)
Append a single item to this array.
Definition: ReflectionFoundation.h:60
constexpr bool append(const ArrayWithSize< T, N2 > &other)
Appends another sized array to this one (assuming enough space)
Definition: ReflectionFoundation.h:46
constexpr bool contains(T value, uint32_t *outIndex=nullptr) const
Check if array contains given value, and retrieve index where such item exists.
Definition: ReflectionFoundation.h:27
A minimal ASCII StringView with shortened name to be used in TypeToString.
Definition: ReflectionFoundation.h:101
constexpr Sv()
Construct empty Sv.
Definition: ReflectionFoundation.h:106
uint32_t length
Number of bytes of the ASCII string.
Definition: ReflectionFoundation.h:103
constexpr Sv(const char *data, uint32_t length)
Construct Sv from a pointer to a char* and a length.
Definition: ReflectionFoundation.h:111
constexpr Sv(const char(&data)[N])
Construct Sv from a string literal.
Definition: ReflectionFoundation.h:117
const char * data
Pointer to the start of ASCII string.
Definition: ReflectionFoundation.h:102
Strips down class name produced by ClNm to reduce binary size (from C++17 going forward)
Definition: ReflectionFoundation.h:178
A writable span of objects.
Definition: ReflectionFoundation.h:79
View over a contiguous sequence of items (pointer + size in elements).
Definition: Span.h:21
constexpr const Type * data() const
Returns pointer to first element of the span.
Definition: Span.h:89
constexpr SizeType sizeInBytes() const
Size of Span in bytes.
Definition: Span.h:109
constexpr SizeType sizeInElements() const
Size of Span in elements.
Definition: Span.h:105