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 
51 struct 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 
73 struct EnumKeyVal {
74  std::string name;
75  size_t value;
76  bool isValid() const { return !name.empty(); }
77 };
78 
79 static std::map<std::string, EnumDeclaration> g_enumsByRawTypeName;
80 static std::map<std::string, size_t> g_allEnumValuesByKey;
81 
82 
83 
84 // *************** Internal functions **************
85 // *
86 
87 static inline bool isWhiteSpace(const char& c) {
88  return c == ' ' || c == '\t' || c == '\n' || c == '\r';
89 }
90 
91 static size_t decodeEnumValue(const std::string& encodedValue) {
92  return strtoll(encodedValue.c_str(), NULL, 0 /* auto detect base */);
93 }
94 
95 static 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 
147 static 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 
170 namespace 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
const char * enumKey(String typeName, size_t value)
Enum constant name of numeric value.
Definition: typeinfo.cpp:280
size_t enumCount(String typeName)
Amount of elements in given enum type.
Definition: typeinfo.cpp:190
size_t enumValue(String key)
Numeric value of enum constant.
Definition: typeinfo.cpp:219
Gigasampler/GigaStudio specific classes and definitions.
Definition: gig.h:101
const char ** enumKeys(String typeName)
All element names of enum type.
Definition: typeinfo.cpp:323