Skip to content

Instantly share code, notes, and snippets.

@NewProggie
Created June 18, 2016 19:05
Show Gist options
  • Save NewProggie/49bae5a9d7737c7e8e4daf7b3d6f8f5f to your computer and use it in GitHub Desktop.
Save NewProggie/49bae5a9d7737c7e8e4daf7b3d6f8f5f to your computer and use it in GitHub Desktop.
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
namespace smart_enum
{
inline std::string trimWhitespace(std::string str)
{
// trim trailing whitespace
size_t endPos = str.find_last_not_of(" \t");
if(std::string::npos != endPos)
{
str = str.substr( 0, endPos + 1);
}
// trim leading spaces
size_t startPos = str.find_first_not_of(" \t");
if(std::string::npos != startPos)
{
str = str.substr(startPos);
}
return str;
}
inline std::string extractEntry(std::string& valuesString)
{
std::string result;
size_t nextCommaPos = valuesString.find(',');
if(nextCommaPos != std::string::npos)
{
std::string segment = valuesString.substr(0, nextCommaPos);
valuesString.erase(0, nextCommaPos + 1);
result = trimWhitespace(segment);
}
else
{
result = trimWhitespace(valuesString);
valuesString = "";
};
return result;
};
inline std::unordered_map<int32_t, std::string> makeEnumNameMap(std::string enumValuesString)
{
std::unordered_map<int32_t, std::string> nameMap;
int32_t currentEnumValue = 0;
while(enumValuesString != "")
{
std::string currentEnumEntry = extractEntry(enumValuesString);
size_t equalSignPos = currentEnumEntry.find('=');
if(equalSignPos != std::string::npos)
{
std::string rightHandSide = currentEnumEntry.substr(equalSignPos + 1);
currentEnumValue = std::stoi(rightHandSide);
currentEnumEntry.erase(equalSignPos);
}
currentEnumEntry = trimWhitespace(currentEnumEntry);
nameMap[currentEnumValue] = currentEnumEntry;
currentEnumValue++;
}
return nameMap;
}
template<typename Type>
std::vector<Type> makeEnumList(std::string enumValuesString)
{
std::vector<Type> enumList;
int32_t currentEnumValue = 0;
while(enumValuesString != "")
{
std::string currentEnumEntry = extractEntry(enumValuesString);
size_t equalSignPos = currentEnumEntry.find('=');
if(equalSignPos != std::string::npos)
{
std::string rightHandSide = currentEnumEntry.substr(equalSignPos + 1);
currentEnumValue = std::stoi(rightHandSide);
currentEnumEntry.erase(equalSignPos);
}
currentEnumEntry = trimWhitespace(currentEnumEntry);
enumList.push_back(static_cast<Type>(currentEnumValue));
currentEnumValue++;
}
return enumList;
}
}
#define smart_enum(Type, ...) enum Type { __VA_ARGS__}; \
static std::unordered_map<int32_t, std::string> Type##_enum_names = smart_enum::makeEnumNameMap(#__VA_ARGS__);\
static std::vector<Type> Type##_list = smart_enum::makeEnumList<Type>(#__VA_ARGS__);\
\
inline const std::string& Type##_to_string(Type value) \
{ \
return Type##_enum_names.at((int32_t)value);\
} \
#define smart_enum_class(Type, ...) enum class Type { __VA_ARGS__}; \
static std::unordered_map<int32_t, std::string> Type##_enum_names = smart_enum::makeEnumNameMap(#__VA_ARGS__);\
static std::vector<Type> Type##_list = smart_enum::makeEnumList<Type>(#__VA_ARGS__);\
\
inline const std::string& to_string(Type value) \
{ \
return Type##_enum_names.at((int32_t)value);\
} \
\
inline std::ostream& operator<<(std::ostream& outStream, Type value)\
{\
outStream << to_string(value);\
return outStream;\
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment