Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.