libgig 4.4.1
typeinfo.cpp
1/***************************************************************************
2 * *
3 * Copyright (C) 2017 Christian Schoenebeck *
4 * <cuse@users.sourceforge.net> *
5 * *
6 * This library is part of libgig. *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24#include <typeinfo>
25#include <map>
26#include <string>
27#include <stdlib.h>
28#include <stdint.h>
29#include <string.h> // for strdup()
30
31#if defined _MSC_VER // Microsoft compiler ...
32# define RAW_CPP_TYPENAME(t) t.raw_name()
33#else // i.e. especially GCC and clang ...
34# define RAW_CPP_TYPENAME(t) t.name()
35#endif
36
37#define RAW_CPP_TYPENAME_OF(type) RAW_CPP_TYPENAME(typeid(type))
38
39#define GIG_DECLARE_ENUM(type, ...) \
40 enum type { __VA_ARGS__ }; \
41 \
42 struct type##InfoRegistrator { \
43 type##InfoRegistrator() { \
44 const char* typeName = RAW_CPP_TYPENAME_OF(type); \
45 g_enumsByRawTypeName[typeName] = _parseEnumBody( #__VA_ARGS__ ); \
46 } \
47 }; \
48 \
49 static type##InfoRegistrator g_##type##InfoRegistrator
50
51struct EnumDeclaration {
52 std::map<size_t, std::string> nameByValue;
53 std::map<std::string, size_t> valueByName;
54 char** allKeys;
55
56 EnumDeclaration() : allKeys(NULL) {}
57
58 const size_t countKeys() const { return valueByName.size(); }
59
60 void loadAllKeys() {
61 const size_t n = valueByName.size();
62 allKeys = new char*[n + 1];
63 size_t i = 0;
64 for (std::map<std::string, size_t>::const_iterator it = valueByName.begin();
65 it != valueByName.end(); ++it, ++i)
66 {
67 allKeys[i] = strdup(it->first.c_str());
68 }
69 allKeys[n] = NULL;
70 }
71};
72
73struct EnumKeyVal {
74 std::string name;
75 size_t value;
76 bool isValid() const { return !name.empty(); }
77};
78
79static std::map<std::string, EnumDeclaration> g_enumsByRawTypeName;
80static std::map<std::string, size_t> g_allEnumValuesByKey;
81
82
83
84// *************** Internal functions **************
85// *
86
87static inline bool isWhiteSpace(const char& c) {
88 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
89}
90
91static size_t decodeEnumValue(const std::string& encodedValue) {
92 return strtoll(encodedValue.c_str(), NULL, 0 /* auto detect base */);
93}
94
95static EnumKeyVal _parseEnumKeyVal(const char* start, const char* end, size_t value) {
96 EnumKeyVal keyval;
97
98 if (start >= end)
99 return keyval; // invalid
100 // ignore white space
101 for (; isWhiteSpace(*start); ++start)
102 if (start >= end)
103 return keyval; // invalid
104 if (start >= end)
105 return keyval; // invalid
106
107 // parse key
108 for (const char* p = start; true; ++p) {
109 if (p >= end || isWhiteSpace(*p) || *p == '=') {
110 const size_t sz = p - start;
111 keyval.name.resize(sz);
112 memcpy(&keyval.name[0], start, sz);
113 keyval.value = value;
114 start = p + 1;
115 break;
116 }
117 }
118
119 if (start >= end)
120 return keyval; // valid, no explicit value provided
121 // seek forward to start of value
122 for (; isWhiteSpace(*start) || *start == '='; ++start)
123 if (start >= end)
124 return keyval; // valid, no explicit value provided
125 if (start >= end)
126 return keyval; // valid, no explicit value provided
127
128 std::string encodedValue;
129 // parse value portion
130 for (const char* p = start; true; ++p) {
131 if (p >= end || isWhiteSpace(*p)) {
132 const size_t sz = p - start;
133 encodedValue.resize(sz);
134 memcpy(&encodedValue[0], start, sz);
135 break;
136 }
137 }
138
139 if (encodedValue.empty())
140 return keyval; // valid, no explicit value provided
141
142 keyval.value = decodeEnumValue(encodedValue);
143
144 return keyval;
145}
146
147static EnumDeclaration _parseEnumBody(const char* body) {
148 EnumDeclaration decl;
149 size_t value = 0;
150 for (const char* a = body, *b = body; true; ++b) {
151 if (*b == 0 || *b == ',') {
152 const EnumKeyVal keyval = _parseEnumKeyVal(a, b, value);
153 if (!keyval.isValid()) break;
154 decl.nameByValue[keyval.value] = keyval.name;
155 decl.valueByName[keyval.name] = keyval.value;
156 g_allEnumValuesByKey[keyval.name] = keyval.value;
157 value = keyval.value + 1;
158 if (*b == 0) break;
159 a = b + 1;
160 }
161 }
162 return decl;
163}
164
165#include "gig.h"
166
167// *************** gig API functions **************
168// *
169
170namespace gig {
171
172 // this has to be defined manually, since leverarge_ctrl_t::type_t is a
173 // class internal member type
174 static leverage_ctrl_t::type_tInfoRegistrator g_leverageCtrlTTypeT;
175
176
190 size_t enumCount(String typeName) {
191 if (!g_enumsByRawTypeName.count(typeName))
192 return 0;
193 return g_enumsByRawTypeName[typeName].countKeys();
194 }
195
206 size_t enumCount(const std::type_info& type) {
207 return enumCount(RAW_CPP_TYPENAME(type));
208 }
209
219 size_t enumValue(String key) {
220 if (!g_allEnumValuesByKey.count(key))
221 return 0;
222 return g_allEnumValuesByKey[key];
223 }
224
239 bool enumKey(String typeName, String key) {
240 if (!g_enumsByRawTypeName.count(typeName))
241 return false;
242 return g_enumsByRawTypeName[typeName].valueByName.count(key);
243 }
244
257 bool enumKey(const std::type_info& type, String key) {
258 return enumKey(RAW_CPP_TYPENAME(type), key);
259 }
260
280 const char* enumKey(String typeName, size_t value) {
281 if (!g_enumsByRawTypeName.count(typeName))
282 return NULL;
283 if (!g_enumsByRawTypeName[typeName].nameByValue.count(value))
284 return NULL;
285 return g_enumsByRawTypeName[typeName].nameByValue[value].c_str();
286 }
287
305 const char* enumKey(const std::type_info& type, size_t value) {
306 return enumKey(RAW_CPP_TYPENAME(type), value);
307 }
308
323 const char** enumKeys(String typeName) {
324 if (!g_enumsByRawTypeName.count(typeName))
325 return NULL;
326 if (!g_enumsByRawTypeName[typeName].allKeys)
327 g_enumsByRawTypeName[typeName].loadAllKeys();
328 return (const char**) g_enumsByRawTypeName[typeName].allKeys;
329 }
330
342 const char** enumKeys(const std::type_info& type) {
343 return enumKeys(RAW_CPP_TYPENAME(type));
344 }
345
346} // namespace gig
Gigasampler/GigaStudio specific classes and definitions.
Definition gig.h:101
size_t enumValue(String key)
Numeric value of enum constant.
Definition typeinfo.cpp:219
const char ** enumKeys(String typeName)
All element names of enum type.
Definition typeinfo.cpp:323
size_t enumCount(String typeName)
Amount of elements in given enum type.
Definition typeinfo.cpp:190
const char * enumKey(String typeName, size_t value)
Enum constant name of numeric value.
Definition typeinfo.cpp:280