Symmetri
Loading...
Searching...
No Matches
colors.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <string.h>
6
7#include <algorithm>
8#include <array> // std::array
9#include <cassert>
10#include <functional>
11#include <string_view>
12#include <type_traits>
13#include <utility> // std::index_sequence
14#include <vector> // hash
15#include <cstdio>
16
17#ifndef DOXYGEN_SHOULD_SKIP_THIS
18namespace sym_impl
19{
20 // https://rodusek.com/posts/2021/03/09/getting-an-unmangled-type-name-at-compile-time/
21
22 template <std::size_t... Idxs>
23 constexpr auto substring_as_array(std::string_view str,
24 std::index_sequence<Idxs...>)
25 {
26 return std::array{str[Idxs]..., '\0'};
27 }
28
29 template <typename T>
30 constexpr auto type_name_array()
31 {
32#if defined(__clang__)
33 constexpr auto prefix = std::string_view{"[T = symmetri::"};
34 constexpr auto suffix = std::string_view{"]"};
35 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
36#elif defined(__GNUC__)
37 constexpr auto prefix = std::string_view{"with T = symmetri::"};
38 constexpr auto suffix = std::string_view{"]"};
39 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
40#elif defined(_MSC_VER)
41 constexpr auto prefix = std::string_view{"type_name_array<symmetri::"};
42 constexpr auto suffix = std::string_view{">(void)"};
43 constexpr auto function = std::string_view{__FUNCSIG__};
44#else
45#error Unsupported compiler
46#endif
47
48 constexpr auto start = function.find(prefix) + prefix.size();
49 constexpr auto end = function.rfind(suffix);
50
51 static_assert(start < end);
52
53 constexpr auto name = function.substr(start, (end - start));
54 return substring_as_array(name, std::make_index_sequence<name.size()>{});
55 }
56
57 template <typename T>
58 struct type_name_holder
59 {
60 static inline constexpr auto value = type_name_array<T>();
61 };
62
63 template <typename T>
64 constexpr auto type_name() -> std::string_view
65 {
66 constexpr auto &value = type_name_holder<T>::value;
67 return std::string_view{value.data(), value.size()};
68 }
69
70#endif /* DOXYGEN_SHOULD_SKIP_THIS */
71}
72namespace symmetri
73{
74
83 class Token
84 {
85 public:
91 static std::vector<const char *> getColors()
92 {
93 std::vector<const char *> _colors;
94 _colors.reserve(colors.size());
95 std::copy_if(colors.begin(), colors.end(), std::back_inserter(_colors),
96 [](const auto &color)
97 { return color != nullptr; });
98 return _colors;
99 }
100
101 constexpr const auto &toString() const { return colors[id]; }
102
103 template <class T>
104 constexpr bool operator==(const T &t) const
105 {
106 return id == t.id;
107 }
108
109 constexpr bool operator<(const Token &rhs) const
110 {
111 return id < rhs.toIndex();
112 }
113
114 constexpr bool operator>(const Token &rhs) const
115 {
116 return id > rhs.toIndex();
117 }
118
119 constexpr size_t toIndex() const { return id; }
120
121 static constexpr bool equals(const char *a, const char *b)
122 {
123 return *a == *b && (*a == '\0' || equals(a + 1, b + 1));
124 }
125
126 template <class X, class V>
127 static constexpr auto find(X &x, V key)
128 {
129 std::size_t i = 0;
130 while (i < x.size())
131 {
132 if (x[i] != nullptr && equals(x[i], key))
133 return i;
134 ++i;
135 }
136
137 return i;
138 }
139
140 template <class X>
141 static constexpr auto findSlot(X &x)
142 {
143 std::size_t i = 0;
144 while (i < x.size())
145 {
146 if (x[i] == nullptr)
147 return i;
148 ++i;
149 }
150
151 return i;
152 }
153
154 constexpr Token(const char *_id)
155 : id(find(colors, _id) < kMaxTokenColors ? find(colors, _id) : findSlot(colors))
156 {
157 assert(id < colors.size() &&
158 "There can only be kMaxTokenColors different token-colors.");
159 colors[id] = _id;
160 }
161
162 protected:
163 const static size_t kMaxTokenColors =
164 100;
165 inline static std::array<const char *, kMaxTokenColors> colors = {nullptr};
166 size_t id;
167 };
168
169} // namespace symmetri
170
171// Custom specialization of std::hash can be injected in namespace std.
172template <>
173struct std::hash<symmetri::Token>
174{
175 constexpr std::size_t operator()(const symmetri::Token &s) const noexcept
176 {
177 return s.toIndex();
178 }
179};
180
186#define CREATE_CUSTOM_TOKEN(name) \
187 namespace symmetri \
188 { \
189 struct name : public Token \
190 { \
191 constexpr name() \
192 : Token(sym_impl::type_name<name>().data()) {} \
193 }; \
194 static inline name name; \
195 }
196
Tokens are elements that can reside in places. Tokens can have a color which makes them distinguishab...
Definition colors.hpp:84
static std::vector< const char * > getColors()
Get a list of all the colors.
Definition colors.hpp:91
static const size_t kMaxTokenColors
Maximum amount of different colors.
Definition colors.hpp:163
#define CREATE_CUSTOM_TOKEN(name)
A macro from which we can create token-colors. Colors ceated this way end up in the symmetri namespac...
Definition colors.hpp:186