Create a gist now

Instantly share code, notes, and snippets.

Objective-C Literals, part 2 support files.
#import <Foundation/Foundation.h>
@interface BNRDiggyDict : NSObject
// React to object indexing. Would be nice to have a @protocol for this
- (id) objectForKeyedSubscript: (id) key;
- (void) setObject: (id) thing forKeyedSubscript: (id<NSCopying>) key;
// And for fun, it also can react to scalar indexing.
// Returns the N'th key of the top-level collection.
- (id) objectAtIndexedSubscript: (NSInteger) index;
@end // BWDiggyDict
#import "BNRDiggyDict.h"
@interface BNRDiggyDict () {
NSMutableDictionary *_rootDictionary;
}
@end // BWDiggyDict
@implementation BNRDiggyDict
- (id) init {
if ((self = [super init])) {
_rootDictionary = [NSMutableDictionary dictionary];
}
return self;
} // init
- (NSString *) description {
return [_rootDictionary description];
} // description
- (NSMutableDictionary *) innerDictionaryForSplitKey: (NSArray *) splitKey {
NSMutableDictionary *interim = _rootDictionary;
for (int i = 0; i < splitKey.count - 1; i++) {
id key = [splitKey objectAtIndex: i];
NSMutableDictionary *next = interim[key];
if (next == nil) {
next = [NSMutableDictionary dictionary];
interim[key] = next;
}
interim = next;
}
return interim;
} // innerDictionaryForSplitKey
- (id) objectForKeyedSubscript: (id) key {
if (![key respondsToSelector: @selector(componentsSeparatedByString:)]) {
return nil;
}
// Use slashes rather than periods since we're not really doing KVC
NSArray *splitKey = [key componentsSeparatedByString: @"/"];
NSMutableDictionary *dict = [self innerDictionaryForSplitKey: splitKey];
id leafKey = [splitKey lastObject];
id result = dict[leafKey];
return result;
} // objectForKeyedSubscript
- (void) setObject: (id) thing forKeyedSubscript: (id<NSCopying>) key {
id idKey = (id) key; // Strip off <NSCopying> so we can send it other messages.
if (![idKey respondsToSelector: @selector(componentsSeparatedByString:)]) {
return;
}
// Use slashes rather than periods since we're not really doing KVC
NSArray *splitKey = [idKey componentsSeparatedByString: @"/"];
NSMutableDictionary *dict = [self innerDictionaryForSplitKey: splitKey];
id leafKey = [splitKey lastObject];
[dict setObject: thing forKey: leafKey];
} // setObject forKeyedSubscript
// And just for fun
- (id) objectAtIndexedSubscript: (NSInteger) index {
NSArray *keys = [_rootDictionary.allKeys
sortedArrayUsingSelector: @selector(compare:)];
return [keys objectAtIndex: index];
} // objectAtIndexedSubscript
@end // BWDiggyDict
#import <Foundation/Foundation.h>
@interface BNRNegativeArray : NSObject
// Necessary to declare these. Would be nice to have a protocol to adopt.
- (id) objectAtIndexedSubscript: (NSInteger) index;
- (void) setObject: (id) thing atIndexedSubscript: (NSInteger) index;
@end // BWNegativeArray
#import "BNRNegativeArray.h"
@interface BNRNegativeArray () {
NSMutableArray *_backingstore;
}
@end // extension
@implementation BNRNegativeArray
- (id) init {
if ((self = [super init])) {
_backingstore = [NSMutableArray array];
}
return self;
} // init
- (NSString *) description {
return [_backingstore description];
} // descriptioin
- (id) objectAtIndexedSubscript: (NSInteger) index {
if (index < 0) index = _backingstore.count + index;
return [_backingstore objectAtIndex: index];
} // objectAtIndexedSubscript
- (void) setObject: (id) thing atIndexedSubscript: (NSInteger) index {
if (index < 0) index = _backingstore.count + index;
// Mutable array only allows setting the first-empty-index, like
// -insertObject:atIndex:. Any past that throws a range exception.
// So let's be different and fill in intervening spaces with [NSNull null]
// If you want to see @NULL, dupe rdar://10892975
NSInteger toAdd = index - _backingstore.count;;
for (int i = 0; i < toAdd; i++) {
[_backingstore addObject: [NSNull null]];
}
if (index >= _backingstore.count) {
[_backingstore addObject: thing];
} else {
[_backingstore replaceObjectAtIndex: index withObject: thing];
}
} // setObject atIndexedSubscript
@end // BWNegativeArray
#import <Foundation/Foundation.h>
#import "BNRNegativeArray.h"
#import "BNRDiggyDict.h"
int main (int argc, const char * argv[]) {
@autoreleasepool {
BNRNegativeArray *negatory = [[BNRNegativeArray alloc] init];
negatory[0] = @"hi";
negatory[1] = @"ohai";
negatory[0] = @"obai";
negatory[10] = @"end!";
NSLog (@"negatory: %@", negatory);
NSLog (@"0 - %@", negatory[0]);
NSLog (@"5 - %@", negatory[5]);
NSLog (@"10 - %@", negatory[10]);
NSLog (@"-1 - %@", negatory[-1]);
NSLog (@"-10 - %@", negatory[-10]);
NSLog (@"-11 - %@", negatory[-11]);
BNRDiggyDict *dauchs = [[BNRDiggyDict alloc] init];
dauchs[@"i can has"] = @"cheezburger";
NSLog (@"badger: %@", dauchs);
dauchs[@"for/great/justice"] = @"every 'ZIG'";
NSLog (@"badger: %@", dauchs);
NSLog (@"TAKE OFF %@", dauchs[@"for/great/justice"]);
// Exercise a scalar accessor on the diggydict
dauchs[@"Alphabet"] = @"A";
dauchs[@"Badger"] = @"B";
dauchs[@"Carnivorous Tofu"] = @"Nom!";
NSLog (@"second key: %@", dauchs[2]);
}
return 0;
} // main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment