-
-
Save hezi/3098340 to your computer and use it in GitHub Desktop.
// Declare enums like so: | |
#define IMAGE_STATUS(XX) \ | |
XX(kDOImageStatusOK, = 0) \ | |
XX(kDOImageStatusCached, )\ | |
XX(kDOImageStatusRetry, ) | |
DECLARE_ENUM(DOImageStatus, IMAGE_STATUS) |
// Define Enum-To-NSString functions like so: | |
DEFINE_ENUM(DOImageStatus, IMAGE_STATUS) | |
// use them like this: | |
NSString *imageStatus = NSStringFromDOImageStatus(kDOImageStatusOK); | |
DOImageStatus statusFromString = DOImageStatusFromNSString(@"kDOImageStatusCached"); |
// | |
// Based on http://stackoverflow.com/a/202511 | |
// | |
#pragma mark - Enum Factory Macros | |
// expansion macro for enum value definition | |
#define ENUM_VALUE(name,assign) name assign, | |
// expansion macro for enum to string conversion | |
#define ENUM_CASE(name,assign) case name: return @#name; | |
// expansion macro for string to enum conversion | |
#define ENUM_STRCMP(name,assign) if (![string isEqualToString:@#name]) return name; | |
/// declare the access function and define enum values | |
#define DECLARE_ENUM(EnumType,ENUM_DEF) \ | |
typedef enum EnumType { \ | |
ENUM_DEF(ENUM_VALUE) \ | |
}EnumType; \ | |
NSString *NSStringFrom##EnumType(EnumType value); \ | |
EnumType EnumType##FromNSString(NSString *string); \ | |
// Define Functions | |
#define DEFINE_ENUM(EnumType, ENUM_DEF) \ | |
NSString *NSStringFrom##EnumType(EnumType value) \ | |
{ \ | |
switch(value) \ | |
{ \ | |
ENUM_DEF(ENUM_CASE) \ | |
default: return @""; \ | |
} \ | |
} \ | |
EnumType EnumType##FromNSString(NSString *string) \ | |
{ \ | |
ENUM_DEF(ENUM_STRCMP) \ | |
return (EnumType)0; \ | |
} |
I like the macro approach.
Yet, it can be tricky to debug code generated with macros.
Alternatively, you can generate a table for the conversion.
You can extend the idea of have any arbitrary information per enum.
// enum to string example
define FOR_EACH_GENDER(tbd) \
tbd(GENDER_MALE) \
tbd(GENDER_FEMALE) \
tbd(GENDER_INTERSEX) \
define ONE_GENDER_ENUM(name) name,
enum
{
FOR_EACH_GENDER(ONE_GENDER_ENUM)
MAX_GENDER
};
define ONE_GENDER(name) #name,
static const char *enumGENDER_TO_STRING[] =
{
FOR_EACH_GENDER(ONE_GENDER)
};
// access string name with enumGENDER_TO_STRING[value]
// or, to be safe converting from a untrustworthy caller
static const char *enumGenderToString(unsigned int value)
{
if (value < MAX_GENDER)
{
return enumGENDER_TO_STRING[value];
}
return NULL;
}
static void printAllGenders(void)
{
for (int ii = 0; ii < MAX_GENDER; ii++)
{
printf("%d) gender %s\n", ii, enumGENDER_TO_STRING[ii]);
}
}
//------------------------------------------------------------------------------
// you can assign an arbitrary value and/or information to each enum,
define FOR_EACH_PERSON(tbd) \
tbd(2, PERSON_FRED, "Fred", "Weasley", GENDER_MALE, 12) \
tbd(4, PERSON_GEORGE, "George", "Weasley", GENDER_MALE, 12) \
tbd(6, PERSON_HARRY, "Harry", "Potter", GENDER_MALE, 10) \
tbd(8, PERSON_HERMIONE, "Hermione", "Granger", GENDER_FEMALE, 10) \
define ONE_PERSON_ENUM(value, ename, first, last, gender, age) ename = value,
enum
{
FOR_EACH_PERSON(ONE_PERSON_ENUM)
};
typedef struct PersonInfoRec
{
int value;
const char *ename;
const char *first;
const char *last;
int gender;
int age;
} PersonInfo;
define ONE_PERSON_INFO(value, ename, first, last, gender, age) \
{ ename, #ename, first, last, gender, age },
static const PersonInfo personInfo[] =
{
FOR_EACH_PERSON(ONE_PERSON_INFO)
{ 0, NULL, NULL, NULL, 0, 0 }
};
// note: if the enum values are not sequential, you need another way to lookup
// the information besides personInfo[ENUM_NAME]
static void printAllPersons(void)
{
for (int ii = 0; ; ii++)
{
const PersonInfo *pPI = &personInfo[ii];
if (!pPI->ename)
{
break;
}
printf("%d) enum %-15s %8s %-8s %13s %2d\n",
pPI->value, pPI->ename, pPI->first, pPI->last,
enumGenderToString(pPI->gender), pPI->age);
}
}
hmm.. I was disappointed how github left-justified all my lines of code.
I suggest they improve this as it's common for people to supply code in the replies...
@fredwork you can format your code by putting triple backticks before and after it: https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks
(The Objective-C language specifier is objc
)
Very good macros, you saved a lot of time on my project with this.
However I needed to change
to
in order to have the EnumType##FromNSString working properly
Cheers