Suppose we have some named enums:
enum MyEnum {
FOO,
BAR = 0x50
};
What I googled for is a script (any language) that scans all the headers in my project and generates a header with one function per enum.
char* enum_to_string(MyEnum t);
And a implementation with something like this:
char* enum_to_string(MyEnum t){
switch(t){
case FOO:
return "FOO";
case BAR:
return "BAR";
default:
return "INVALID ENUM";
}
}
The gotcha is really with typedefed enums, and unnamed C style enums. Does anybody know something for this?
EDIT: The solution should not modify my source, except for the generated functions. The enums are in an API, so using the solutions proposed until now is just not an option.
You may want to check out GCCXML.
Running GCCXML on your sample code produces:
<GCC_XML>
<Namespace id="_1" name="::" members="_3 " mangled="_Z2::"/>
<Namespace id="_2" name="std" context="_1" members="" mangled="_Z3std"/>
<Enumeration id="_3" name="MyEnum" context="_1" location="f0:1" file="f0" line="1">
<EnumValue name="FOO" init="0"/>
<EnumValue name="BAR" init="80"/>
</Enumeration>
<File id="f0" name="my_enum.h"/>
</GCC_XML>
You could use any language you prefer to pull out the Enumeration and EnumValue tags and generate your desired code.
X-macros are the best solution. Example:
#include <iostream>
enum Colours {
# define X(a) a,
# include "colours.def"
# undef X
ColoursCount
};
char const* const colours_str[] = {
# define X(a) #a,
# include "colours.def"
# undef X
0
};
std::ostream& operator<<(std::ostream& os, enum Colours c)
{
if (c >= ColoursCount || c < 0) return os << "???";
return os << colours_str[c];
}
int main()
{
std::cout << Red << Blue << Green << Cyan << Yellow << Magenta << std::endl;
}
colours.def:
X(Red)
X(Green)
X(Blue)
X(Cyan)
X(Yellow)
X(Magenta)
However, I usually prefer the following method, so that it's possible to tweak the string a bit.
#define X(a, b) a,
#define X(a, b) b,
X(Red, "red")
X(Green, "green")
// etc.