You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.9 KiB
C

// File name: "EnumToString.h"
#undef DECL_ENUM_ELEMENT
#undef BEGIN_ENUM
#undef END_ENUM
#include <vector>
#include <map>
#if (defined _WINDOWS) || (defined WIN32)
#include <string.h>
#define NAME_CMP_FUNC _stricmp
#else
#define NAME_CMP_FUNC strcasecmp
#endif
#include "CyclopsCommon.h"
#include <typeinfo>
#ifndef GENERATE_ENUM_STRINGS
CYCLOPS_DLLSPEC const char* getEnumName(size_t enumHash, int value);
CYCLOPS_DLLSPEC int fromEnumName(size_t enumHash, const char* name);
bool addEnumName(size_t enumHash, const std::vector<const char*>* pNameMap);
#define DECL_ENUM_ELEMENT( element ) element
#define BEGIN_ENUM( ENUM_NAME ) struct ENUM_NAME {\
enum NameEnum
#define END_ENUM( ENUM_NAME ) ;\
int value;\
ENUM_NAME () : value(-1) {}\
ENUM_NAME (int _value) : value(_value) {}\
ENUM_NAME (NameEnum _value) : value(_value) {}\
static inline const char* GetEnumName() { return #ENUM_NAME; }\
static inline const char* GetName(ENUM_NAME _value) { return getEnumName(typeid(ENUM_NAME).hash_code(), _value.value); }\
static inline ENUM_NAME FromName(const char* n) {\
return ENUM_NAME(static_cast<NameEnum>(fromEnumName(typeid(ENUM_NAME).hash_code(), n)));\
}\
bool equal(int _value) const { return value == _value; }\
bool operator >= (const NameEnum& other) const { return value >= other; }\
bool operator <= (const NameEnum& other) const { return value <= other; }\
bool operator == (const NameEnum& other) const { return value == other; }\
operator int() const { return value; }\
};
#else
#define DECL_ENUM_ELEMENT( element ) #element
#define BEGIN_ENUM( ENUM_NAME ) const std::vector<const char*> gsNameMap##ENUM_NAME## =
#define END_ENUM( ENUM_NAME ) ; bool ret##ENUM_NAME## = addEnumName(typeid(ENUM_NAME).hash_code(), &gsNameMap##ENUM_NAME##);
static std::map<size_t, const std::vector<const char*>* > gsNameMap;
bool addEnumName(size_t enumHash, const std::vector<const char*>* pNameMap) {
gsNameMap[enumHash] = pNameMap;
return true;
}
const char* getEnumName(size_t enumHash, int value) {
auto it = gsNameMap.find(enumHash);
if (it == gsNameMap.end()) return "";
const std::vector<const char*>* pNameMap = it->second;
if (!pNameMap || value < 0 || value >= pNameMap->size()) return "";
return pNameMap->at(value);
}
int fromEnumName(size_t enumHash, const char* name) {
auto it = gsNameMap.find(enumHash);
if (it == gsNameMap.end()) return 0;
const std::vector<const char*>* pNameMap = it->second;
if (!pNameMap) return 0;
for (size_t i = 0; i < pNameMap->size(); ++i) {
if (NAME_CMP_FUNC(name, pNameMap->at(i)) == 0) return i;
}
return 0;
}
#endif
#undef DECL_ENUM_ELEMENT2
#undef DECL_ENUM_ELEMENT2_S
#undef BEGIN_ENUM2
#undef END_ENUM2
#ifndef GENERATE_ENUM_STRINGS
struct NameEnumValueElement {
int value;
const char* name;
const char* prettyName;
NameEnumValueElement(int v, const char* n, const char* pn = nullptr) : value(v), name(n), prettyName(pn) {}
};
CYCLOPS_DLLSPEC const char* getEnumName2(size_t enumHash, int value, bool pretty);
CYCLOPS_DLLSPEC int fromEnumName2(size_t enumHash, const char* name);
bool addEnumName2(size_t enumHash, const std::vector<const char*>* pNameMap);
#define DECL_ENUM_ELEMENT2( element, value, prettyName ) element = value
#define DECL_ENUM_ELEMENT2_S( element, value ) element = value
#define BEGIN_ENUM2( ENUM_NAME ) struct ENUM_NAME {\
enum NameEnum
#define END_ENUM2( ENUM_NAME ) ;\
int value;\
ENUM_NAME () : value(-1) {}\
ENUM_NAME (int _value) : value(_value) {}\
ENUM_NAME (NameEnum _value) : value(_value) {}\
static inline const char* GetEnumName() { return #ENUM_NAME; }\
static inline const char* GetName(ENUM_NAME _value) {\
return getEnumName2(typeid(ENUM_NAME).hash_code(), _value.value, false);\
}\
static inline const char* GetPrettyName(ENUM_NAME _value){\
return getEnumName2(typeid(ENUM_NAME).hash_code(), _value.value, true);\
}\
static inline ENUM_NAME FromName(const char* n) {\
return ENUM_NAME (static_cast<NameEnum>(fromEnumName2(typeid(ENUM_NAME).hash_code(), n)));\
}\
bool equal(int _value) const { return value == _value; }\
bool test(int _value) const { return (value & _value) != 0; }\
bool operator >= (const NameEnum& other) const { return value >= other; }\
bool operator <= (const NameEnum& other) const { return value <= other; }\
bool operator == (const NameEnum& other) const { return value == other; }\
bool operator += (const ENUM_NAME& other) { return value |= other.value; }\
operator int() const { return value; }\
};
#else
#define DECL_ENUM_ELEMENT2( element, value, prettyName ) NameEnumValueElement(value, #element, prettyName)
#define DECL_ENUM_ELEMENT2_S( element, value ) NameEnumValueElement(value, #element)
#define BEGIN_ENUM2( ENUM_NAME ) const std::vector<NameEnumValueElement> gsNameMap##ENUM_NAME## =
#define END_ENUM2( ENUM_NAME ) ; bool ret##ENUM_NAME## = addEnumName2(typeid(ENUM_NAME).hash_code(), &gsNameMap##ENUM_NAME##);
static std::map<size_t, const std::vector<NameEnumValueElement>* > gsNameMap2;
bool addEnumName2(size_t enumHash, const std::vector<NameEnumValueElement>* pNameMap) {
gsNameMap2[enumHash] = pNameMap;
return true;
}
const char* getEnumName2(size_t enumHash, int value, bool pretty) {
auto it = gsNameMap2.find(enumHash);
if (it == gsNameMap2.end()) return "";
const std::vector<NameEnumValueElement>* pNameMap = it->second;
for (size_t i = 0; i < pNameMap->size(); i++) {
const NameEnumValueElement& e = pNameMap->at(i);
if (value == e.value) return pretty ? e.prettyName : e.name;
}
return "";
}
int fromEnumName2(size_t enumHash, const char* name) {
auto it = gsNameMap2.find(enumHash);
if (it == gsNameMap2.end()) return 0;
const std::vector<NameEnumValueElement>* pNameMap = it->second;
for (size_t i = 0; i < pNameMap->size(); i++) {
const NameEnumValueElement& e = pNameMap->at(i);
if (NAME_CMP_FUNC(name, e.name) == 0)
return e.value;
}
return 0;
}
#endif