C Switch for Non-Integers

The syntax

//get a string from standard input
char str[256];
fgets(str, 256, stdin);
*(char *)memchr(str, '\n', 256) = '';
JPSwitch([NSString stringWithUTF8String:str]) {
JPCase(@"option one"):
NSLog(@"the first posibility was selected");

JPStringCase(Do Non-NSString objects work?):
NSLog(@"Yes, technically any object would work as a key,"
@"and anything else would work with an NSValue wrapper");
JPDefaultCase:
NSLog(@"None of the possibilities were selected. Oh noes!");
} JPSwitchEnd;
__JPSwitch([NSString stringWithUTF8String:str], ^{
}, @"option one", ^{ JPSwitchCase:
NSLog(@"the first posibility was selected");
}, @"Do Non-NSString objects work?", ^{ JPSwitchCase:
NSLog(@"Yes, technically any object would work as a key,"
@"and anything else would work with an NSValue wrapper");
}, &JPSwitchDefaultCaseIndicator, ^{ JPSwitchCase:
NSLog(@"None of the possiblities were selected. Oh noes!");
} , &JPSwitchTermationIndicator);
The result://JPSwitch.h
extern char JPSwitchTermationIndicator;
extern char JPSwitchDefaultCaseIndicator;
void __JPSwitch(id selector, ...);
#define JPSwitch(selector) __JPSwitch(selector, ^
#define JPCase(obj) }, obj, ^{ JPSwitchCase
#define JPStringCase(str) JPCase(@#str) //Preprocessor stringification
#define JPDefaultCase }, &JPSwitchDefaultCaseIndicator, ^{ JPSwitchCase
#define JPSwitchEnd , &JPSwitchTermationIndicator)
__JPSwitch
//JPSwitch.m
#import "JPSwitch.h"
char JPSwitchTermationIndicator, JPSwitchDefaultCaseIndicator;void __JPSwitch(id selector, ...) {
va_list args;
va_start(args, selector);
id caseLabel;
void(^caseBlock)();
void(^defaultCaseBlock)() = nil;
va_arg(args, void(^)()); //Eat empty first blockNSMapTable *allCases = [NSMapTable mapTableWithWeakToWeakObjects];
while ((caseLabel = va_arg(args, id)) != (void *)&JPSwitchTermationIndicator) {
caseBlock = va_arg(args, id);
if (caseLabel == (void *)&JPSwitchDefaultCaseIndicator) {
defaultCaseBlock = caseBlock;
} else if (caseLabel != nil) {
[allCases setObject:caseBlock forKey:caseLabel];
}
}
caseBlock = (void(^)())[allCases objectForKey:selector] ?: defaultCaseBlock;
if (caseBlock) caseBlock();
}

Conclusion

So now you can use a switch statement over any Objective-C object, including NSStrings. Additionally, you can switch with anything else by wrapping it in an NSValue. I think this could be best used in parsing and especially in command line interfaces.

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store