Created
May 16, 2011 12:23
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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