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
16#ifndef DOXYGEN_SHOULD_SKIP_THIS
17namespace sym_impl {
18// https://rodusek.com/posts/2021/03/09/getting-an-unmangled-type-name-at-compile-time/
19
20template <std::size_t... Idxs>
21constexpr auto substring_as_array(std::string_view str,
22 std::index_sequence<Idxs...>) {
23 return std::array{str[Idxs]..., '\0'};
24}
25
26template <typename T>
27constexpr auto type_name_array() {
28#if defined(__clang__)
29 constexpr auto prefix = std::string_view{"[T = symmetri::"};
30 constexpr auto suffix = std::string_view{"]"};
31 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
32#elif defined(__GNUC__)
33 constexpr auto prefix = std::string_view{"with T = symmetri::"};
34 constexpr auto suffix = std::string_view{"]"};
35 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
36#elif defined(_MSC_VER)
37 constexpr auto prefix = std::string_view{"type_name_array<symmetri::"};
38 constexpr auto suffix = std::string_view{">(void)"};
39 constexpr auto function = std::string_view{__FUNCSIG__};
40#else
41#error Unsupported compiler
42#endif
43
44 constexpr auto start = function.find(prefix) + prefix.size();
45 constexpr auto end = function.rfind(suffix);
46
47 static_assert(start < end);
48
49 constexpr auto name = function.substr(start, (end - start));
50 return substring_as_array(name, std::make_index_sequence<name.size()>{});
51}
52
53template <typename T>
54struct type_name_holder {
55 static inline constexpr auto value = type_name_array<T>();
56};
57
58template <typename T>
59constexpr auto type_name() -> std::string_view {
60 constexpr auto& value = type_name_holder<T>::value;
61 return std::string_view{value.data(), value.size()};
62}
63
64template <auto Id>
65struct counter {
66 using tag = counter;
67
68 struct generator {
69 template <typename...>
70 friend constexpr auto is_defined(tag) {
71 return true;
72 }
73 };
74
75 template <typename...>
76 friend constexpr auto is_defined(tag);
77
78 template <typename Tag = tag, auto I = (int)is_defined(Tag{})>
79 static constexpr auto exists(decltype(I)) {
80 return true;
81 }
82
83 static constexpr auto exists(...) { return generator(), false; }
84};
85
86template <typename T, auto Id = int{}>
87constexpr auto unique_id() {
88 if constexpr (counter<Id>::exists(Id)) {
89 return unique_id<T, Id + 1>();
90 } else {
91 return Id;
92 }
93}
94
95#endif /* DOXYGEN_SHOULD_SKIP_THIS */
96}
97namespace symmetri {
98
107class Token {
108 public:
114 static std::vector<const char*> getColors() {
115 std::vector<const char*> _colors;
116 _colors.reserve(colors.size());
117 std::copy_if(colors.begin(), colors.end(), std::back_inserter(_colors),
118 [](const auto& color) { return color != nullptr; });
119 return _colors;
120 }
121
122 constexpr const auto& toString() const { return colors[id]; }
123
124 template <class T>
125 constexpr bool operator==(const T& t) const {
126 return id == t.id;
127 }
128
129 constexpr bool operator<(const Token& rhs) const {
130 return id < rhs.toIndex();
131 }
132
133 constexpr bool operator>(const Token& rhs) const {
134 return id > rhs.toIndex();
135 }
141 constexpr int toIndex() const { return id; }
142
143 Token(const char* _id)
144 : id([_id]() -> int {
145 const auto it =
146 std::find_if(colors.cbegin(), colors.cend(), [=](const char* s) {
147 return s != nullptr && 0 == strcmp(_id, s);
148 });
149 if (it == colors.cend()) {
150 const auto nullptr_it =
151 std::find(colors.cbegin(), colors.cend(), nullptr);
152 assert(nullptr_it != colors.cend() &&
153 "There can only be kMaxTokenColors different token-colors.");
154 const auto idx = std::distance(colors.cbegin(), nullptr_it);
155 colors[idx] = strdup(_id);
156 return idx;
157 } else {
158 return std::distance(colors.cbegin(), it);
159 }
160 }()) {}
161
162 protected:
163 const static size_t kMaxTokenColors =
164 100;
165 constexpr Token(const char* id, const int idx) : id(idx) { colors[idx] = id; }
166 inline static std::array<const char*, kMaxTokenColors> colors = {nullptr};
167 int id;
168};
169
170} // namespace symmetri
171
172// Custom specialization of std::hash can be injected in namespace std.
173template <>
174struct std::hash<symmetri::Token> {
175 constexpr std::size_t operator()(const symmetri::Token& s) const noexcept {
176 return s.toIndex();
177 }
178};
179
185#define CREATE_CUSTOM_TOKEN(name) \
186 namespace symmetri { \
187 struct name : public Token { \
188 constexpr name() \
189 : Token(sym_impl::type_name<name>().data(), \
190 sym_impl::unique_id<name>()) { \
191 static_assert( \
192 sym_impl::unique_id<name>() < kMaxTokenColors, \
193 "There can only be kMaxTokenColors different token-colors."); \
194 } \
195 }; \
196 static inline name name; \
197 }
198
Tokens are elements that can reside in places. Tokens can have a color which makes them distinguishab...
Definition colors.hpp:107
static std::vector< const char * > getColors()
Get a list of all the colors.
Definition colors.hpp:114
constexpr int toIndex() const
returns the unique index for this color.
Definition colors.hpp:141
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:185