Skip to content

Instantly share code, notes, and snippets.

@kongtomorrow
Created May 16, 2011 12:23
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kongtomorrow/974350 to your computer and use it in GitHub Desktop.
Save kongtomorrow/974350 to your computer and use it in GitHub Desktop.
Get debug descriptions for enums in Objective-C via terrible terrible macro hackery.
/* Get strings descriptions for enum values for debugging.
Usage:
With enum
typedef enum {
AppleFruit = 0,
BlueberryFruit = 1,
BlackberryFruit = -1
} Fruit;
This declares a function DescriptionOfFruit:
IMPLEMENT_DESCRIPTION_OF_ENUM(Fruit, AppleFruit, BlueberryFruit, BlackberryFruit)
This:
for (int fruit = -1; fruit < 2; fruit++) {
NSLog(@"fruit:%@", DescriptionOfFruit(fruit));
}
Prints @"fruit:BlackberryFruit", @"fruit:AppleFruit", @"fruit:BlueberryFruit"
*/
#define IMPLEMENT_DESCRIPTION_OF_ENUM(type, ...) \
static NSString *DescriptionOf##type(type val) { \
return _DescriptionForEnumValue(val, @""#type, @""#__VA_ARGS__, ## __VA_ARGS__); \
}
static NSString *_DescriptionForEnumValue(long enumVal, NSString *descriptionOfEnumeration, NSString *commaSeparatedEnumValueDescriptions, int firstEnumValue, ...) {
NSString *enumValueDescription = nil;
NSScanner *enumValueDescriptionScanner = [[NSScanner alloc] initWithString:commaSeparatedEnumValueDescriptions];
NSCharacterSet *commaAndWhitespaceCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@", \t\n\r\v"];
NSCharacterSet *commaAndWhitespaceInvertedCharacterSet = [commaAndWhitespaceCharacterSet invertedSet];
if (firstEnumValue == enumVal) {
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:&enumValueDescription];
} else {
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:NULL];
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceInvertedCharacterSet intoString:NULL];
va_list args;
va_start(args, firstEnumValue);
while (![enumValueDescriptionScanner isAtEnd]) {
NSInteger candidateEnumVal;
candidateEnumVal = va_arg(args, int); // by my read of C99 6.7.2.2, enum values are always representable as int. Thus they'll always get promoted to int bit-width if smaller for a varargs call, and unsigned and signed ints are bit-compatible on the range representable by ints (6.2.6.2)
if (candidateEnumVal == enumVal) {
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:&enumValueDescription];
break;
} else {
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:NULL];
[enumValueDescriptionScanner scanUpToCharactersFromSet:commaAndWhitespaceInvertedCharacterSet intoString:NULL];
}
}
va_end(args);
}
enumValueDescription = enumValueDescription ?: [NSString stringWithFormat:@"<unknown value %ld in enumeration %@>", (long)enumVal, descriptionOfEnumeration];
return enumValueDescription;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment