xtd 0.2.0
Loading...
Searching...
No Matches
__enum_introspection.hpp
1#pragma once
3#if !defined(__XTD_CORE_INTERNAL__)
4#error "Do not include this file: Internal use only"
5#endif
7
8#include "../typeof.hpp"
9#include "../types.hpp"
10#include "../string.hpp"
11
13#if defined(__XTD_DO_NOT_USE_ENUMERATION_INTROSPECTION__)
14#define __enum_introspection__(namespace_name, enum_t, base_t, ...)
15#else
16#include <string_view>
18
20namespace __enumeration_introspection {
21 constexpr std::string_view trim(std::string_view view) {
22 size_t start = view.find_first_not_of(' ');
23 if (start == std::string_view::npos) return "";
24 size_t end = view.find_first_of(" =", start);
25 if (end == std::string_view::npos) return view.substr(start);
26 return view.substr(start, end - start);
27 }
28
29 template <size_t count, size_t str_size, class function_t>
30 constexpr void split_trim_apply(char const(&str)[str_size], function_t func) {
31 std::string_view view(str, str_size - 1);
32
33 for (size_t i = 0; i < count; i++) {
34 auto new_pos = view.find(',');
35 func(trim(view.substr(0, new_pos)));
36 if (new_pos != std::string_view::npos) view = view.substr(new_pos + 1);
37 else break;
38 }
39 }
40
41 template <size_t count, size_t str_size>
42 constexpr size_t compute_name_block_size(char const(&str)[str_size]) {
43 size_t total = 0;
44 split_trim_apply<count>(str, [&](std::string_view sv) {total += sv.size();});
45 return total;
46 }
47
48 template <size_t count, size_t str_size>
49 constexpr void write_names_and_sizes(char const(&str)[str_size], char* destination, unsigned* offsets) {
50 size_t current_offset = 0;
51 split_trim_apply<count>(str, [&](std::string_view sv) {
52 char const* source = sv.data();
53 size_t size = sv.size();
54 for (size_t i = 0; i < size; i++)
55 destination[i] = source[i];
56 *offsets++ = static_cast<unsigned>(current_offset);
57 destination += size; // Known errors with assignment pointer parameter.
58 current_offset += size;
59 });
60 *offsets = static_cast<unsigned>(current_offset);
61 }
62
63 constexpr auto get_top_name(std::string_view view) {
64 auto pos = view.find_last_of(':');
65 if (pos == view.npos) return view;
66 return view.substr(pos + 1);
67 }
68
69 template <size_t count>
70 constexpr auto get_top_name(char const(&str)[count]) {return get_top_name(std::string_view(str, count - 1));}
71
72 template <typename base_t>
73 struct enumeration_maker {
74 base_t value {};
75 bool is_set = false;
76 enumeration_maker() = default;
77 enumeration_maker(enumeration_maker const&) = default;
78 constexpr enumeration_maker(base_t) : enumeration_maker() {} // Can't be explicit by design.
79 enumeration_maker& operator =(enumeration_maker const&) = default;
80
81 template <typename type_t>
82 constexpr enumeration_maker& operator =(type_t const& v) {
83 value = base_t(v);
84 is_set = true;
85 return *this;
86 }
87
88 constexpr operator base_t() const {return value;}
89 template <typename type_t>
90 constexpr explicit operator type_t() const {return type_t(value);}
91 };
92
93 template <typename base_t>
94 struct value_assigner {
95 base_t value {};
96
97 constexpr value_assigner& operator, (enumeration_maker<base_t>& other) {
98 if (other.is_set) value = other.value;
99 else other = value;
100 ++value;
101 return *this;
102 }
103 };
104
105 class string_block_iterator {
106 char const* data {};
107 unsigned const* indices {};
108
109 public:
110 string_block_iterator() = default;
111 string_block_iterator(string_block_iterator const&) = default;
112 constexpr string_block_iterator(char const* data, unsigned const* indices) noexcept : data(data), indices(indices) {}
113
114 constexpr string_block_iterator& operator ++() noexcept {
115 indices++;
116 return *this;
117 }
118 constexpr string_block_iterator operator ++(int) noexcept {
119 string_block_iterator previous_state = *this;
120 indices++;
121 return previous_state;
122 }
123 constexpr xtd::intptr operator -(string_block_iterator const& other) const noexcept {return indices - other.indices;}
124 constexpr bool operator ==(string_block_iterator const& other) const noexcept {return indices == other.indices;}
125 constexpr bool operator !=(string_block_iterator const& other) const noexcept {return indices != other.indices;}
126 constexpr auto operator *() const noexcept -> std::string_view {
127 int off0 = indices[0];
128 int off1 = indices[1];
129 return std::string_view(data + off0, off1 - off0);
130 }
131 };
132
133 template <size_t count, size_t blk_size>
134 struct string_block {
135 char data[blk_size] {};
136 unsigned offsets[count + 1] {};
137 string_block() = default;
138 string_block(string_block const&) = default;
139
140 template <typename function_t>
141 explicit constexpr string_block(function_t&& func) : string_block() {func(*this);}
142
143 template <typename function_t>
144 constexpr string_block(string_block const& source, function_t&& func) : string_block() {func(source, *this);}
145
146 using iterator = string_block_iterator;
147 using const_iterator = iterator;
148 constexpr iterator begin() const noexcept {return iterator(data, offsets);}
149 constexpr iterator end() const noexcept {return iterator(data, offsets + count);}
150 constexpr static size_t size() noexcept {return count;}
151 constexpr static size_t block_size() noexcept {return blk_size;}
152 constexpr std::string_view operator [](size_t i) const noexcept {
153 auto off1 = offsets[i];
154 auto off2 = offsets[i + 1];
155 return std::string_view(data + off1, off2 - off1);
156 }
157 };
158
159 template <typename type_t>
160 constexpr std::string_view name_of_type = typeof_<type_t>().name();
161
162 template <typename enum_t>
163 struct enum_type_info_base {
164 constexpr static std::string_view qualified_type_name {name_of_type<enum_t>};
165 constexpr static std::string_view type_name {get_top_name(name_of_type<enum_t>)};
166 constexpr static size_t num_states = 0;
167 constexpr static size_t size() noexcept {return 0;}
168 };
169
170 template <typename enum_t>
171 struct enum_value_list_base : enum_type_info_base<enum_t> {};
172
173 template <typename enum_t>
174 struct enum_name_list_base : enum_type_info_base<enum_t> {
175 using enum_type_info_base<enum_t>::num_states;
176 constexpr static size_t name_block_size = 0;
177 using block_type = string_block<num_states, name_block_size>;
178 block_type name_block;
179 };
180
181 template <typename enum_t>
182 struct enum_type_info : public enum_type_info_base<enum_t> {
183 private:
184 using super = enum_type_info_base<enum_t>;
185
186 public:
187 using super::num_states;
188 using super::qualified_type_name;
189 using super::size;
190 using super::type_name;
191 };
192
193 template <typename enum_t>
194 struct enum_value_list : enum_type_info<enum_t> {
195 private:
196 constexpr static enum_value_list_base<enum_t> values {};
197 using super = enum_type_info<enum_t>;
198
199 public:
200 using iterator = enum_t const*;
201 using const_iterator = enum_t const*;
202 constexpr enum_t const* begin() const noexcept {return values.__enumeration_internal_values__;}
203 constexpr enum_t const* end() const noexcept {return values.__enumeration_internal_values__ + super::num_states;}
204 constexpr enum_t const& operator [](size_t i) const noexcept {return values.__enumeration_internal_values__[i];}
205 };
206
207 template <typename enum_t>
208 struct enum_name_list : enum_type_info<enum_t> {
209 private:
210 constexpr static enum_name_list_base<enum_t> name_info {};
211 using super = enum_type_info<enum_t>;
212
213 public:
214 using block_type = typename enum_name_list_base<enum_t>::block_type;
215 using iterator = string_block_iterator;
216 using const_iterator = iterator;
217 constexpr static block_type const& get_name_block() noexcept {return name_info.name_block;}
218 constexpr iterator begin() const noexcept {return name_info.name_block.begin();}
219 constexpr iterator end() const noexcept {return name_info.name_block.end();}
220 constexpr std::string_view operator [](size_t i) const noexcept {return name_info.name_block[i];}
221 };
222
223 template <typename enum_t>
224 constexpr size_t num_states = enum_type_info<enum_t>::num_states;
225
226 template <typename enum_t>
227 constexpr enum_value_list<enum_t> enum_values {};
228
229 template <typename enum_t>
230 constexpr enum_name_list<enum_t> enum_names {};
231}
232
233#define __enum_introspection_concat__(str1, str2) (#str1 "::" #str2)
234
235#define __enum_introspection__(namespace_name, enum_t, base_t, ...) \
236 namespace __enumeration_introspection { \
237 template <> struct enum_type_info_base<enum_t> { \
238 using base_type = base_t; \
239 [[maybe_unused]] constexpr static std::string_view qualified_type_name = __enum_introspection_concat__(namespace_name, enum_t); \
240 [[maybe_unused]] constexpr static std::string_view type_name = get_top_name(__enum_introspection_concat__(namespace_name, enum_t)); \
241 constexpr static size_t num_states = []() -> size_t { \
242 enumeration_maker<base_t> __VA_ARGS__; \
243 enumeration_maker<base_t> __enum_introspection_vals[] {__VA_ARGS__}; \
244 return sizeof(__enum_introspection_vals) / sizeof(enumeration_maker<base_t>); \
245 }(); \
246 constexpr static size_t size() noexcept {return num_states;} \
247 }; \
248 template <> struct enum_value_list_base<enum_t> : enum_type_info_base<enum_t> { \
249 enum_t __enumeration_internal_values__[enum_type_info_base<enum_t>::num_states]; \
250 constexpr enum_value_list_base() : __enumeration_internal_values__() { \
251 enumeration_maker<base_t> __VA_ARGS__; \
252 value_assigner<base_t> {}, __VA_ARGS__; \
253 enumeration_maker<base_t> __enum_introspection_vals[] {__VA_ARGS__}; \
254 for (size_t i = 0; i < enum_type_info_base<enum_t>::num_states; i++) \
255 this->__enumeration_internal_values__[i] = enum_t(__enum_introspection_vals[i]); \
256 } \
257 }; \
258 template <> struct enum_name_list_base<enum_t> : enum_type_info_base<enum_t> { \
259 using enum_type_info_base<enum_t>::num_states; \
260 constexpr static size_t name_block_size = compute_name_block_size<num_states>(#__VA_ARGS__); \
261 using block_type = string_block<num_states, name_block_size>; \
262 block_type name_block; \
263 constexpr enum_name_list_base() : name_block([](auto& block) { \
264 write_names_and_sizes<num_states>(#__VA_ARGS__, block.data, block.offsets); \
265 }) {} \
266 }; \
267 }
268
269#endif
size_t size
Represents a size of any object in bytes.
Definition size.hpp:23
intmax_t intptr
Represent a pointer or a handle.
Definition intptr.hpp:23
delegate< result_t(arguments_t...)> func
Represents a delegate that has variables parameters and returns a value of the type specified by the ...
Definition func.hpp:16
@ start
Starting of a logical operation.
@ other
The operating system is other.
@ end
The END key.
@ i
The I key.