typeinfo.cpp
/***************************************************************************
* *
* Copyright (C) 2017 Christian Schoenebeck *
* <cuse@users.sourceforge.net> *
* *
* This library is part of libgig. *
* *
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
***************************************************************************/
#include <typeinfo>
#include <map>
#include <string>
#include <stdlib.h>
#include <stdint.h>
#include <string.h> // for strdup()
#if defined _MSC_VER // Microsoft compiler ...
# define RAW_CPP_TYPENAME(t) t.raw_name()
#else // i.e. especially GCC and clang ...
# define RAW_CPP_TYPENAME(t) t.name()
#endif
#define RAW_CPP_TYPENAME_OF(type) RAW_CPP_TYPENAME(typeid(type))
#define GIG_DECLARE_ENUM(type, ...) \
enum type { __VA_ARGS__ }; \
\
struct type##InfoRegistrator { \
type##InfoRegistrator() { \
const char* typeName = RAW_CPP_TYPENAME_OF(type); \
g_enumsByRawTypeName[typeName] = _parseEnumBody( #__VA_ARGS__ ); \
} \
}; \
\
static type##InfoRegistrator g_##type##InfoRegistrator
struct EnumDeclaration {
std::map<size_t, std::string> nameByValue;
std::map<std::string, size_t> valueByName;
char** allKeys;
EnumDeclaration() : allKeys(NULL) {}
const size_t countKeys() const { return valueByName.size(); }
void loadAllKeys() {
const size_t n = valueByName.size();
allKeys = new char*[n + 1];
size_t i = 0;
for (std::map<std::string, size_t>::const_iterator it = valueByName.begin();
it != valueByName.end(); ++it, ++i)
{
allKeys[i] = strdup(it->first.c_str());
}
allKeys[n] = NULL;
}
};
struct EnumKeyVal {
std::string name;
size_t value;
bool isValid() const { return !name.empty(); }
};
static std::map<std::string, EnumDeclaration> g_enumsByRawTypeName;
static std::map<std::string, size_t> g_allEnumValuesByKey;
// *************** Internal functions **************
// *
static inline bool isWhiteSpace(const char& c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
static size_t decodeEnumValue(const std::string& encodedValue) {
return strtoll(encodedValue.c_str(), NULL, 0 /* auto detect base */);
}
static EnumKeyVal _parseEnumKeyVal(const char* start, const char* end, size_t value) {
EnumKeyVal keyval;
if (start >= end)
return keyval; // invalid
// ignore white space
for (; isWhiteSpace(*start); ++start)
if (start >= end)
return keyval; // invalid
if (start >= end)
return keyval; // invalid
// parse key
for (const char* p = start; true; ++p) {
if (p >= end || isWhiteSpace(*p) || *p == '=') {
const size_t sz = p - start;
keyval.name.resize(sz);
memcpy(&keyval.name[0], start, sz);
keyval.value = value;
start = p + 1;
break;
}
}
if (start >= end)
return keyval; // valid, no explicit value provided
// seek forward to start of value
for (; isWhiteSpace(*start) || *start == '='; ++start)
if (start >= end)
return keyval; // valid, no explicit value provided
if (start >= end)
return keyval; // valid, no explicit value provided
std::string encodedValue;
// parse value portion
for (const char* p = start; true; ++p) {
if (p >= end || isWhiteSpace(*p)) {
const size_t sz = p - start;
encodedValue.resize(sz);
memcpy(&encodedValue[0], start, sz);
break;
}
}
if (encodedValue.empty())
return keyval; // valid, no explicit value provided
keyval.value = decodeEnumValue(encodedValue);
return keyval;
}
static EnumDeclaration _parseEnumBody(const char* body) {
EnumDeclaration decl;
size_t value = 0;
for (const char* a = body, *b = body; true; ++b) {
if (*b == 0 || *b == ',') {
const EnumKeyVal keyval = _parseEnumKeyVal(a, b, value);
if (!keyval.isValid()) break;
decl.nameByValue[keyval.value] = keyval.name;
decl.valueByName[keyval.name] = keyval.value;
g_allEnumValuesByKey[keyval.name] = keyval.value;
value = keyval.value + 1;
if (*b == 0) break;
a = b + 1;
}
}
return decl;
}
#include "gig.h"
// *************** gig API functions **************
// *
namespace gig {
// this has to be defined manually, since leverarge_ctrl_t::type_t is a
// class internal member type
static leverage_ctrl_t::type_tInfoRegistrator g_leverageCtrlTTypeT;
size_t enumCount(String typeName) {
if (!g_enumsByRawTypeName.count(typeName))
return 0;
return g_enumsByRawTypeName[typeName].countKeys();
}
size_t enumCount(const std::type_info& type) {
return enumCount(RAW_CPP_TYPENAME(type));
}
size_t enumValue(String key) {
if (!g_allEnumValuesByKey.count(key))
return 0;
return g_allEnumValuesByKey[key];
}
bool enumKey(String typeName, String key) {
if (!g_enumsByRawTypeName.count(typeName))
return false;
return g_enumsByRawTypeName[typeName].valueByName.count(key);
}
bool enumKey(const std::type_info& type, String key) {
return enumKey(RAW_CPP_TYPENAME(type), key);
}
const char* enumKey(String typeName, size_t value) {
if (!g_enumsByRawTypeName.count(typeName))
return NULL;
if (!g_enumsByRawTypeName[typeName].nameByValue.count(value))
return NULL;
return g_enumsByRawTypeName[typeName].nameByValue[value].c_str();
}
const char* enumKey(const std::type_info& type, size_t value) {
return enumKey(RAW_CPP_TYPENAME(type), value);
}
const char** enumKeys(String typeName) {
if (!g_enumsByRawTypeName.count(typeName))
return NULL;
if (!g_enumsByRawTypeName[typeName].allKeys)
g_enumsByRawTypeName[typeName].loadAllKeys();
return (const char**) g_enumsByRawTypeName[typeName].allKeys;
}
const char** enumKeys(const std::type_info& type) {
return enumKeys(RAW_CPP_TYPENAME(type));
}
} // namespace gig
gig
Gigasampler/GigaStudio specific classes and definitions.
Definition gig.h:101
gig::enumValue
size_t enumValue(String key)
Numeric value of enum constant.
Definition typeinfo.cpp:219
gig::enumKeys
const char ** enumKeys(String typeName)
All element names of enum type.
Definition typeinfo.cpp:323
gig::enumCount
size_t enumCount(String typeName)
Amount of elements in given enum type.
Definition typeinfo.cpp:190
gig::enumKey
const char * enumKey(String typeName, size_t value)
Enum constant name of numeric value.
Definition typeinfo.cpp:280