blob: 88b85a8f3212c06d06a29feadad70866852946ac [file] [log] [blame]
//
// AMutableDictionary.m
// ST4
//
// Created by Alan Condit on 4/18/11.
// Copyright 2011 Alan Condit. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "AMutableDictionary.h"
#import "ACBTree.h"
@implementation AMutableDictionary
@synthesize root;
@synthesize nodes_av;
@synthesize nodes_inuse;
@synthesize nxt_nodeid;
//@synthesize count;
@synthesize data;
@synthesize ptrBuffer;
+ (AMutableDictionary *) newDictionary
{
return [[AMutableDictionary alloc] init];
}
/** dictionaryWithCapacity
* capacity is meaningless to ACBTree because
* capacity is automatically increased
*/
+ (AMutableDictionary *) dictionaryWithCapacity
{
return [[AMutableDictionary alloc] init];
}
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
nxt_nodeid = 0;
count = 0;
root = [ACBTree newNodeWithDictionary:self];
root.nodeType = LEAF;
root.numrecs = 0;
root.updtd = NO;
root.lnodeid = 1;
root.lnode = nil;
root.rnodeid = 0xffff;
root.rnode = nil;
}
return self;
}
/** initWithCapacity
* capacity is meaningless to ACBTree because
* capacity is automatically increased
*/
- (id) initWithCapacity:(NSUInteger)numItems
{
self = [super init];
if (self) {
// Initialization code here.
nxt_nodeid = 0;
count = 0;
root = [ACBTree newNodeWithDictionary:self];
root.nodeType = LEAF;
root.numrecs = 0;
root.updtd = NO;
root.lnodeid = 1;
root.lnode = nil;
root.rnodeid = 0xffff;
root.rnode = nil;
}
return self;
}
- (void) dealloc
{
#ifdef DEBUG_DEALLOC
NSLog( @"called dealloc in AMutableDictionary" );
#endif
if ( data ) [data release];
if ( root ) [root release];
[super dealloc];
}
- (id) objectForKey:(id)aKey
{
id obj = nil;
ACBTree *node;
ACBKey *kp;
NSInteger ret;
BOOL mustRelease = NO;
if ( [aKey isKindOfClass:[NSString class]] ) {
kp = [ACBKey newKeyWithKStr:aKey];
mustRelease = YES;
}
else if ( [aKey isKindOfClass:[ACBKey class]] ) {
kp = aKey;
//ACBKey *akey = [ACBKey newKey:aKey];
}
else {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:[NSString stringWithFormat:@"What kind of key is this? %@", aKey]
userInfo:nil];
return nil; // not a key that I know how to deal with
}
node = [root search:kp.key];
if ( node != nil ) {
ret = [node searchnode:kp.key match:YES];
if ( ret >= 0 && ret < node.numkeys ) {
obj = node.btNodes[ret];
if ( obj == [NSNull null] ) {
obj = nil;
}
}
}
if ( mustRelease ) [kp release];
return obj;
}
- (void) setObject:(id)obj forKey:(id)aKey
{
ACBKey *kp;
BOOL mustRelease = NO;
if ( [aKey isKindOfClass:[NSString class]] ) {
kp = [ACBKey newKeyWithKStr:aKey];
mustRelease = YES;
}
else if ( [aKey isKindOfClass:[ACBKey class]] ) {
kp = (ACBKey *)aKey;
}
else {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:[NSString stringWithFormat:@"What kind of key is this? %@", aKey]
userInfo:nil];
}
if ( [root search:kp.key] == nil ) {
if ( obj == nil ) {
obj = [NSNull null];
}
root = [root insertkey:kp value:obj];
[kp retain];
[obj retain];
kp.recnum = count++;
}
else {
if ( mustRelease ) [kp release];
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"key alreadyExists" userInfo:nil];
}
return;
}
- (BOOL) isEqual:(id)object
{
return [super isEqual:object];
}
- (void) removeObjectForKey:(id)aKey
{
if ( [root deletekey:aKey] == SUCCESS )
count--;
}
- (NSUInteger) count
{
return count;
}
- (NSArray *) allKeys
{
NSUInteger cnt = [root keyWalkLeaves];
return [NSArray arrayWithObjects:ptrBuffer count:cnt];
}
- (NSArray *) allValues
{
NSUInteger cnt = [root objectWalkLeaves];
return [NSArray arrayWithObjects:ptrBuffer count:cnt];
}
- (ArrayIterator *) keyEnumerator
{
return [ArrayIterator newIterator:[self allKeys]];
}
- (ArrayIterator *) objectEnumerator
{
return [ArrayIterator newIterator:[self allValues]];
}
// This is where all the magic happens.
// You have two choices when implementing this method:
// 1) Use the stack based array provided by stackbuf. If you do this, then you must respect the value of 'len'.
// 2) Return your own array of objects. If you do this, return the full length of the array returned until you run out of objects, then return 0. For example, a linked-array implementation may return each array in order until you iterate through all arrays.
// In either case, state->itemsPtr MUST be a valid array (non-nil). This sample takes approach #1, using stackbuf to store results.
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
{
NSUInteger cnt = 0;
// This is the initialization condition, so we'll do one-time setup here.
// Ensure that you never set state->state back to 0, or use another method to detect initialization
// (such as using one of the values of state->extra).
if (state->state == 0) {
// We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values,
// since these values are not otherwise used by the protocol.
// If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated.
// state->mutationsPtr MUST NOT be NULL.
state->mutationsPtr = &state->extra[0];
[self.root objectWalkLeaves];
}
// Now we provide items, which we track with state->state, and determine if we have finished iterating.
if (state->state < self.count) {
// Set state->itemsPtr to the provided buffer.
// Alternate implementations may set state->itemsPtr to an internal C array of objects.
// state->itemsPtr MUST NOT be NULL.
state->itemsPtr = stackbuf;
// Fill in the stack array, either until we've provided all items from the list
// or until we've provided as many items as the stack based buffer will hold.
while((state->state < self.count) && (cnt < len)) {
// For this sample, we generate the contents on the fly.
// A real implementation would likely just be copying objects from internal storage.
stackbuf[cnt++] = ptrBuffer[state->state++];
}
// state->state = ((cnt < len)? cnt : len);
}
else
{
// We've already provided all our items, so we signal we are done by returning 0.
cnt = 0;
}
return cnt;
}
- (void) clear
{
if ( count ) [self removeAllObjects];
}
- (void) removeAllObjects
{
root = [ACBTree newNodeWithDictionary:self];
root.nodeid = 0;
nxt_nodeid = 1;
}
- (NSInteger) nextNodeId
{
return nxt_nodeid++;
}
- (NSArray *) toKeyArray
{
return nil;
}
- (NSArray *) toValueArray
{
return nil;
}
@end