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