Skip to content

Instantly share code, notes, and snippets.

@a2
Last active August 29, 2015 14:06
Show Gist options
  • Save a2/27d18e34021b5c2486d5 to your computer and use it in GitHub Desktop.
Save a2/27d18e34021b5c2486d5 to your computer and use it in GitHub Desktop.
A2DictionaryOfVariableBindings
@import Foundation;
#define A2DictionaryOfVariableBindings(...) _A2DictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)
extern NSDictionary *_A2DictionaryOfVariableBindings(NSString *commaSeparatedKeysString, id firstValue, ...); // not for direct use
#import "A2DictionaryOfVariableBindings.h"
static NSCharacterSet *commaAndWhitespaceCharacterSet;
static NSCharacterSet *commaAndWhitespaceInvertedCharacterSet;
NSDictionary *_A2DictionaryOfVariableBindings(NSString *commaSeparatedKeysString, id firstValue, ...) {
if (commaAndWhitespaceCharacterSet == nil) {
commaAndWhitespaceCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@", \t\n\r\x0B"];
commaAndWhitespaceInvertedCharacterSet = [commaAndWhitespaceCharacterSet invertedSet];
}
NSScanner *scanner = [[NSScanner alloc] initWithString:commaSeparatedKeysString];
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSString *key;
[scanner scanUpToCharactersFromSet:commaAndWhitespaceInvertedCharacterSet intoString:NULL];
[scanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:&key];
while (key != nil) {
NSUInteger lastDotIndex = [key rangeOfString:@"." options:NSBackwardsSearch].location;
if (lastDotIndex != NSNotFound) {
key = [key substringFromIndex:lastDotIndex + 1];
}
NSCAssert(![keys containsObject:key], @"A2DictionaryOfVariableBindings failed because multiple values have \"%@\" as the last path component", key);
[keys addObject:key];
[scanner scanUpToCharactersFromSet:commaAndWhitespaceInvertedCharacterSet intoString:NULL];
if (![scanner scanUpToCharactersFromSet:commaAndWhitespaceCharacterSet intoString:&key]) {
key = nil;
}
}
NSMutableArray *values = [NSMutableArray arrayWithCapacity:keys.count];
va_list ap;
va_start(ap, firstValue);
id value = firstValue;
while (value != nil) {
[values addObject:value];
value = va_arg(ap, id);
}
va_end(ap);
NSCAssert(values.count == keys.count, @"Unequal key and value counts. This may be because %@ is nil.", keys[values.count]);
return [NSDictionary dictionaryWithObjects:values forKeys:keys];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment