1*16467b97STreehugger Robot// 2*16467b97STreehugger Robot// AMutableDictionary.m 3*16467b97STreehugger Robot// ST4 4*16467b97STreehugger Robot// 5*16467b97STreehugger Robot// Created by Alan Condit on 4/18/11. 6*16467b97STreehugger Robot// Copyright 2011 Alan Condit. All rights reserved. 7*16467b97STreehugger Robot// 8*16467b97STreehugger Robot 9*16467b97STreehugger Robot#import <Foundation/Foundation.h> 10*16467b97STreehugger Robot#import "AMutableDictionary.h" 11*16467b97STreehugger Robot#import "ACBTree.h" 12*16467b97STreehugger Robot 13*16467b97STreehugger Robot@implementation AMutableDictionary 14*16467b97STreehugger Robot 15*16467b97STreehugger Robot@synthesize root; 16*16467b97STreehugger Robot@synthesize nodes_av; 17*16467b97STreehugger Robot@synthesize nodes_inuse; 18*16467b97STreehugger Robot@synthesize nxt_nodeid; 19*16467b97STreehugger Robot//@synthesize count; 20*16467b97STreehugger Robot@synthesize data; 21*16467b97STreehugger Robot@synthesize ptrBuffer; 22*16467b97STreehugger Robot 23*16467b97STreehugger Robot+ (AMutableDictionary *) newDictionary 24*16467b97STreehugger Robot{ 25*16467b97STreehugger Robot return [[AMutableDictionary alloc] init]; 26*16467b97STreehugger Robot} 27*16467b97STreehugger Robot 28*16467b97STreehugger Robot/** dictionaryWithCapacity 29*16467b97STreehugger Robot * capacity is meaningless to ACBTree because 30*16467b97STreehugger Robot * capacity is automatically increased 31*16467b97STreehugger Robot */ 32*16467b97STreehugger Robot+ (AMutableDictionary *) dictionaryWithCapacity 33*16467b97STreehugger Robot{ 34*16467b97STreehugger Robot return [[AMutableDictionary alloc] init]; 35*16467b97STreehugger Robot} 36*16467b97STreehugger Robot 37*16467b97STreehugger Robot- (id)init 38*16467b97STreehugger Robot{ 39*16467b97STreehugger Robot self = [super init]; 40*16467b97STreehugger Robot if (self) { 41*16467b97STreehugger Robot // Initialization code here. 42*16467b97STreehugger Robot nxt_nodeid = 0; 43*16467b97STreehugger Robot count = 0; 44*16467b97STreehugger Robot root = [ACBTree newNodeWithDictionary:self]; 45*16467b97STreehugger Robot root.nodeType = LEAF; 46*16467b97STreehugger Robot root.numrecs = 0; 47*16467b97STreehugger Robot root.updtd = NO; 48*16467b97STreehugger Robot root.lnodeid = 1; 49*16467b97STreehugger Robot root.lnode = nil; 50*16467b97STreehugger Robot root.rnodeid = 0xffff; 51*16467b97STreehugger Robot root.rnode = nil; 52*16467b97STreehugger Robot } 53*16467b97STreehugger Robot return self; 54*16467b97STreehugger Robot} 55*16467b97STreehugger Robot 56*16467b97STreehugger Robot/** initWithCapacity 57*16467b97STreehugger Robot * capacity is meaningless to ACBTree because 58*16467b97STreehugger Robot * capacity is automatically increased 59*16467b97STreehugger Robot */ 60*16467b97STreehugger Robot- (id) initWithCapacity:(NSUInteger)numItems 61*16467b97STreehugger Robot{ 62*16467b97STreehugger Robot self = [super init]; 63*16467b97STreehugger Robot if (self) { 64*16467b97STreehugger Robot // Initialization code here. 65*16467b97STreehugger Robot nxt_nodeid = 0; 66*16467b97STreehugger Robot count = 0; 67*16467b97STreehugger Robot root = [ACBTree newNodeWithDictionary:self]; 68*16467b97STreehugger Robot root.nodeType = LEAF; 69*16467b97STreehugger Robot root.numrecs = 0; 70*16467b97STreehugger Robot root.updtd = NO; 71*16467b97STreehugger Robot root.lnodeid = 1; 72*16467b97STreehugger Robot root.lnode = nil; 73*16467b97STreehugger Robot root.rnodeid = 0xffff; 74*16467b97STreehugger Robot root.rnode = nil; 75*16467b97STreehugger Robot } 76*16467b97STreehugger Robot return self; 77*16467b97STreehugger Robot} 78*16467b97STreehugger Robot 79*16467b97STreehugger Robot- (void) dealloc 80*16467b97STreehugger Robot{ 81*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC 82*16467b97STreehugger Robot NSLog( @"called dealloc in AMutableDictionary" ); 83*16467b97STreehugger Robot#endif 84*16467b97STreehugger Robot if ( data ) [data release]; 85*16467b97STreehugger Robot if ( root ) [root release]; 86*16467b97STreehugger Robot [super dealloc]; 87*16467b97STreehugger Robot} 88*16467b97STreehugger Robot 89*16467b97STreehugger Robot- (id) objectForKey:(id)aKey 90*16467b97STreehugger Robot{ 91*16467b97STreehugger Robot id obj = nil; 92*16467b97STreehugger Robot ACBTree *node; 93*16467b97STreehugger Robot ACBKey *kp; 94*16467b97STreehugger Robot NSInteger ret; 95*16467b97STreehugger Robot BOOL mustRelease = NO; 96*16467b97STreehugger Robot 97*16467b97STreehugger Robot if ( [aKey isKindOfClass:[NSString class]] ) { 98*16467b97STreehugger Robot kp = [ACBKey newKeyWithKStr:aKey]; 99*16467b97STreehugger Robot mustRelease = YES; 100*16467b97STreehugger Robot } 101*16467b97STreehugger Robot else if ( [aKey isKindOfClass:[ACBKey class]] ) { 102*16467b97STreehugger Robot kp = aKey; 103*16467b97STreehugger Robot //ACBKey *akey = [ACBKey newKey:aKey]; 104*16467b97STreehugger Robot } 105*16467b97STreehugger Robot else { 106*16467b97STreehugger Robot @throw [NSException exceptionWithName:NSInvalidArgumentException 107*16467b97STreehugger Robot reason:[NSString stringWithFormat:@"What kind of key is this? %@", aKey] 108*16467b97STreehugger Robot userInfo:nil]; 109*16467b97STreehugger Robot return nil; // not a key that I know how to deal with 110*16467b97STreehugger Robot } 111*16467b97STreehugger Robot node = [root search:kp.key]; 112*16467b97STreehugger Robot if ( node != nil ) { 113*16467b97STreehugger Robot ret = [node searchnode:kp.key match:YES]; 114*16467b97STreehugger Robot if ( ret >= 0 && ret < node.numkeys ) { 115*16467b97STreehugger Robot obj = node.btNodes[ret]; 116*16467b97STreehugger Robot if ( obj == [NSNull null] ) { 117*16467b97STreehugger Robot obj = nil; 118*16467b97STreehugger Robot } 119*16467b97STreehugger Robot } 120*16467b97STreehugger Robot } 121*16467b97STreehugger Robot if ( mustRelease ) [kp release]; 122*16467b97STreehugger Robot return obj; 123*16467b97STreehugger Robot} 124*16467b97STreehugger Robot 125*16467b97STreehugger Robot- (void) setObject:(id)obj forKey:(id)aKey 126*16467b97STreehugger Robot{ 127*16467b97STreehugger Robot ACBKey *kp; 128*16467b97STreehugger Robot BOOL mustRelease = NO; 129*16467b97STreehugger Robot if ( [aKey isKindOfClass:[NSString class]] ) { 130*16467b97STreehugger Robot kp = [ACBKey newKeyWithKStr:aKey]; 131*16467b97STreehugger Robot mustRelease = YES; 132*16467b97STreehugger Robot } 133*16467b97STreehugger Robot else if ( [aKey isKindOfClass:[ACBKey class]] ) { 134*16467b97STreehugger Robot kp = (ACBKey *)aKey; 135*16467b97STreehugger Robot } 136*16467b97STreehugger Robot else { 137*16467b97STreehugger Robot @throw [NSException exceptionWithName:NSInvalidArgumentException 138*16467b97STreehugger Robot reason:[NSString stringWithFormat:@"What kind of key is this? %@", aKey] 139*16467b97STreehugger Robot userInfo:nil]; 140*16467b97STreehugger Robot } 141*16467b97STreehugger Robot if ( [root search:kp.key] == nil ) { 142*16467b97STreehugger Robot if ( obj == nil ) { 143*16467b97STreehugger Robot obj = [NSNull null]; 144*16467b97STreehugger Robot } 145*16467b97STreehugger Robot root = [root insertkey:kp value:obj]; 146*16467b97STreehugger Robot [kp retain]; 147*16467b97STreehugger Robot [obj retain]; 148*16467b97STreehugger Robot kp.recnum = count++; 149*16467b97STreehugger Robot } 150*16467b97STreehugger Robot else { 151*16467b97STreehugger Robot if ( mustRelease ) [kp release]; 152*16467b97STreehugger Robot @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"key alreadyExists" userInfo:nil]; 153*16467b97STreehugger Robot } 154*16467b97STreehugger Robot return; 155*16467b97STreehugger Robot} 156*16467b97STreehugger Robot 157*16467b97STreehugger Robot- (BOOL) isEqual:(id)object 158*16467b97STreehugger Robot{ 159*16467b97STreehugger Robot return [super isEqual:object]; 160*16467b97STreehugger Robot} 161*16467b97STreehugger Robot 162*16467b97STreehugger Robot- (void) removeObjectForKey:(id)aKey 163*16467b97STreehugger Robot{ 164*16467b97STreehugger Robot if ( [root deletekey:aKey] == SUCCESS ) 165*16467b97STreehugger Robot count--; 166*16467b97STreehugger Robot} 167*16467b97STreehugger Robot 168*16467b97STreehugger Robot- (NSUInteger) count 169*16467b97STreehugger Robot{ 170*16467b97STreehugger Robot return count; 171*16467b97STreehugger Robot} 172*16467b97STreehugger Robot 173*16467b97STreehugger Robot- (NSArray *) allKeys 174*16467b97STreehugger Robot{ 175*16467b97STreehugger Robot NSUInteger cnt = [root keyWalkLeaves]; 176*16467b97STreehugger Robot return [NSArray arrayWithObjects:ptrBuffer count:cnt]; 177*16467b97STreehugger Robot} 178*16467b97STreehugger Robot 179*16467b97STreehugger Robot- (NSArray *) allValues 180*16467b97STreehugger Robot{ 181*16467b97STreehugger Robot NSUInteger cnt = [root objectWalkLeaves]; 182*16467b97STreehugger Robot return [NSArray arrayWithObjects:ptrBuffer count:cnt]; 183*16467b97STreehugger Robot} 184*16467b97STreehugger Robot 185*16467b97STreehugger Robot- (ArrayIterator *) keyEnumerator 186*16467b97STreehugger Robot{ 187*16467b97STreehugger Robot return [ArrayIterator newIterator:[self allKeys]]; 188*16467b97STreehugger Robot} 189*16467b97STreehugger Robot 190*16467b97STreehugger Robot- (ArrayIterator *) objectEnumerator 191*16467b97STreehugger Robot{ 192*16467b97STreehugger Robot return [ArrayIterator newIterator:[self allValues]]; 193*16467b97STreehugger Robot} 194*16467b97STreehugger Robot 195*16467b97STreehugger Robot// This is where all the magic happens. 196*16467b97STreehugger Robot// You have two choices when implementing this method: 197*16467b97STreehugger Robot// 1) Use the stack based array provided by stackbuf. If you do this, then you must respect the value of 'len'. 198*16467b97STreehugger Robot// 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. 199*16467b97STreehugger Robot// In either case, state->itemsPtr MUST be a valid array (non-nil). This sample takes approach #1, using stackbuf to store results. 200*16467b97STreehugger Robot- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len 201*16467b97STreehugger Robot{ 202*16467b97STreehugger Robot NSUInteger cnt = 0; 203*16467b97STreehugger Robot // This is the initialization condition, so we'll do one-time setup here. 204*16467b97STreehugger Robot // Ensure that you never set state->state back to 0, or use another method to detect initialization 205*16467b97STreehugger Robot // (such as using one of the values of state->extra). 206*16467b97STreehugger Robot if (state->state == 0) { 207*16467b97STreehugger Robot // We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values, 208*16467b97STreehugger Robot // since these values are not otherwise used by the protocol. 209*16467b97STreehugger Robot // If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated. 210*16467b97STreehugger Robot // state->mutationsPtr MUST NOT be NULL. 211*16467b97STreehugger Robot state->mutationsPtr = &state->extra[0]; 212*16467b97STreehugger Robot [self.root objectWalkLeaves]; 213*16467b97STreehugger Robot } 214*16467b97STreehugger Robot // Now we provide items, which we track with state->state, and determine if we have finished iterating. 215*16467b97STreehugger Robot if (state->state < self.count) { 216*16467b97STreehugger Robot // Set state->itemsPtr to the provided buffer. 217*16467b97STreehugger Robot // Alternate implementations may set state->itemsPtr to an internal C array of objects. 218*16467b97STreehugger Robot // state->itemsPtr MUST NOT be NULL. 219*16467b97STreehugger Robot state->itemsPtr = stackbuf; 220*16467b97STreehugger Robot // Fill in the stack array, either until we've provided all items from the list 221*16467b97STreehugger Robot // or until we've provided as many items as the stack based buffer will hold. 222*16467b97STreehugger Robot while((state->state < self.count) && (cnt < len)) { 223*16467b97STreehugger Robot // For this sample, we generate the contents on the fly. 224*16467b97STreehugger Robot // A real implementation would likely just be copying objects from internal storage. 225*16467b97STreehugger Robot stackbuf[cnt++] = ptrBuffer[state->state++]; 226*16467b97STreehugger Robot } 227*16467b97STreehugger Robot // state->state = ((cnt < len)? cnt : len); 228*16467b97STreehugger Robot } 229*16467b97STreehugger Robot else 230*16467b97STreehugger Robot { 231*16467b97STreehugger Robot // We've already provided all our items, so we signal we are done by returning 0. 232*16467b97STreehugger Robot cnt = 0; 233*16467b97STreehugger Robot } 234*16467b97STreehugger Robot return cnt; 235*16467b97STreehugger Robot} 236*16467b97STreehugger Robot 237*16467b97STreehugger Robot- (void) clear 238*16467b97STreehugger Robot{ 239*16467b97STreehugger Robot if ( count ) [self removeAllObjects]; 240*16467b97STreehugger Robot} 241*16467b97STreehugger Robot 242*16467b97STreehugger Robot- (void) removeAllObjects 243*16467b97STreehugger Robot{ 244*16467b97STreehugger Robot if ( [self count] > 0 ) { 245*16467b97STreehugger Robot // root = [ACBTree newNodeWithDictionary:self]; 246*16467b97STreehugger Robot NSArray *list = [self allKeys]; 247*16467b97STreehugger Robot for ( NSInteger i = [self count] - 1; i >= 0; i-- ) { 248*16467b97STreehugger Robot [self removeObjectForKey:[list objectAtIndex:i]]; 249*16467b97STreehugger Robot } 250*16467b97STreehugger Robot root.nodeid = 0; 251*16467b97STreehugger Robot nxt_nodeid = 1; 252*16467b97STreehugger Robot } 253*16467b97STreehugger Robot} 254*16467b97STreehugger Robot 255*16467b97STreehugger Robot- (NSInteger) nextNodeId 256*16467b97STreehugger Robot{ 257*16467b97STreehugger Robot return nxt_nodeid++; 258*16467b97STreehugger Robot} 259*16467b97STreehugger Robot 260*16467b97STreehugger Robot- (NSArray *) toKeyArray 261*16467b97STreehugger Robot{ 262*16467b97STreehugger Robot return nil; 263*16467b97STreehugger Robot} 264*16467b97STreehugger Robot 265*16467b97STreehugger Robot- (NSArray *) toValueArray 266*16467b97STreehugger Robot{ 267*16467b97STreehugger Robot return nil; 268*16467b97STreehugger Robot} 269*16467b97STreehugger Robot 270*16467b97STreehugger Robot@end 271