diff options
Diffstat (limited to 'antlr-3.4/runtime/ObjC/Framework/ACBTree.m')
-rw-r--r-- | antlr-3.4/runtime/ObjC/Framework/ACBTree.m | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/antlr-3.4/runtime/ObjC/Framework/ACBTree.m b/antlr-3.4/runtime/ObjC/Framework/ACBTree.m new file mode 100644 index 0000000..99c0cda --- /dev/null +++ b/antlr-3.4/runtime/ObjC/Framework/ACBTree.m @@ -0,0 +1,721 @@ +// +// ACBTree.m +// ST4 +// +// Created by Alan Condit on 4/18/11. +// Copyright 2011 Alan Condit. All rights reserved. +// + +#import <Cocoa/Cocoa.h> +#import "ACBTree.h" +#import "AMutableDictionary.h" +#import "ANTLRRuntimeException.h" + +@class AMutableDictionary; + +@implementation ACBKey + +static NSInteger RECNUM = 0; + +@synthesize recnum; +@synthesize key; + ++ (ACBKey *)newKey +{ + return [[ACBKey alloc] init]; +} + ++ (ACBKey *)newKeyWithKStr:(NSString *)aKey +{ + return [[ACBKey alloc] initWithKStr:(NSString *)aKey]; +} + +- (id) init +{ + self =[super init]; + if ( self != nil ) { + recnum = RECNUM++; + } + return self; +} + +- (id) initWithKStr:(NSString *)aKey +{ + self =[super init]; + if ( self != nil ) { + NSInteger len; + recnum = RECNUM++; + key = aKey; + len = [aKey length]; + if ( len >= BTKeySize ) { + len = BTKeySize - 1; + } + strncpy( kstr, [aKey cStringUsingEncoding:NSASCIIStringEncoding], len); + kstr[len] = '\0'; + } + return self; +} + +@end + +@implementation ACBTree + +@synthesize dict; +@synthesize lnode; +@synthesize rnode; +@synthesize keys; +@synthesize btNodes; +@synthesize lnodeid; +@synthesize rnodeid; +@synthesize nodeid; +@synthesize nodeType; +@synthesize numkeys; +@synthesize numrecs; +@synthesize updtd; +@synthesize keylen; +@synthesize kidx; + ++ (ACBTree *) newNodeWithDictionary:(AMutableDictionary *)theDict +{ + return [[ACBTree alloc] initWithDictionary:theDict]; +} + +- (id)initWithDictionary:(AMutableDictionary *)theDict +{ + self = [super init]; + if (self) { + // Initialization code here. + dict = theDict; + nodeid = theDict.nxt_nodeid++; + keys = keyArray; + btNodes = btNodeArray; + if ( nodeid == 0 ) { + numkeys = 0; + } + } + + return self; +} + +- (ACBTree *)createnode:(ACBKey *)kp +{ + ACBTree *tmp; + + tmp = [ACBTree newNodeWithDictionary:dict]; + tmp.nodeType = nodeType; + tmp.lnode = self; + tmp.rnode = self.rnode; + self.rnode = tmp; + //tmp.btNodes[0] = self; + //tmp.keys[0] = kp; + tmp.updtd = YES; + tmp.numrecs = ((nodeType == LEAF)?1:numrecs); + updtd = YES; + tmp.numkeys = 1; + [tmp retain]; + return(tmp); +} + +- (ACBTree *)deletekey:(NSString *)dkey +{ + ACBKey /* *del, */ *dkp; + ACBTree *told, *sNode; + BOOL mustRelease = NO; + + if ( [dkey isKindOfClass:[NSString class]] ) { + dkp = [ACBKey newKeyWithKStr:dkey]; + mustRelease = YES; + } + else if ( [dkey isKindOfClass:[ACBKey class]] ) + dkp = (ACBKey *)dkey; + else + @throw [ANTLRIllegalArgumentException newException:[NSString stringWithFormat:@"Don't understand this key:\"%@\"", dkey]]; + sNode = [self search:dkp.key]; + if ( sNode == nil || [sNode searchnode:dkp.key match:YES] == FAILURE ) { + if ( mustRelease ) [dkp release]; + return(self); + } + told = dict.root; + /* del = */[self internaldelete:dkp]; + + /* check for shrink at the root */ + if ( numkeys == 1 && nodeType != LEAF ) { + told = btNodes[0]; + told.nodeid = 1; + told.updtd = YES; + dict.root = told; + } +#ifdef DONTUSENOMO + if (debug == 'd') [self printtree]; +#endif + if ( mustRelease ) [dkp release]; + return(told); +} + +/** insertKey is the insertion entry point + * It determines if the key exists in the tree already + * it calls internalInsert to determine if the key already exists in the tree, + * and returns the node to be updated + */ +- (ACBTree *)insertkey:(ACBKey *)kp value:(id)value +{ + ACBTree *tnew, *q; + NSInteger h, nodeNum; + + tnew = self; + q = [self internalinsert:kp value:value split:&h]; + /* check for growth at the root */ + if ( q != nil ) { + tnew = [[ACBTree newNodeWithDictionary:dict] retain]; + tnew.nodeType = BTNODE; + nodeNum = tnew.nodeid; + tnew.nodeid = 0; + self.nodeid = nodeNum; + [tnew insert:self.keys[numkeys-1] value:self index:0 split:&h]; + [tnew insert:q.keys[q.numkeys-1] value:q index:1 split:&h]; + tnew.numrecs = self.numrecs + q.numrecs; + tnew.lnodeid = self.nodeid; + tnew.rnodeid = self.rnodeid; + self.rnodeid = tnew.nodeid; + tnew.lnode = self; + tnew.rnode = self.rnode; + self.rnode = tnew; + /* affected by nodeid swap */ + // newnode.lnodeid = tnew.btNodes[0].nodeid; + } + //dict.root = t; + //l.reccnt++; + return(tnew); +} + +- (ACBTree *)search:(NSString *)kstr +{ + NSInteger i, ret; + NSInteger srchlvl = 0; + ACBTree *t; + + t = self; + if ( self.numkeys == 0 && self.nodeType == LEAF ) + return nil; + while (t != nil) { + for (i = 0; i < t.numkeys; i++) { + ret = [t.keys[i].key compare:kstr]; + if ( ret >= 0 ) { + if ( t.nodeType == LEAF ) { + if ( ret == 0 ) return (t); /* node containing keyentry found */ + else return nil; + } + else { + break; + } + } + } + srchlvl++; + if ( t.nodeType == BTNODE ) t = t.btNodes[i]; + else { + t = nil; + } + } + return(nil); /* entry not found */ +} + +/** SEARCHNODE + * calling parameters -- + * BKEY PTR for key to search for. + * TYPE for exact match(YES) or position(NO) + * returns -- i + * i == FAILURE when match required but does not exist. + * i == t.numkeys if no existing insertion branch found. + * otherwise i == insertion branch. + */ +- (NSInteger)searchnode:(NSString *)kstr match:(BOOL)match +{ + NSInteger i, ret; + for ( i = 0; i < numkeys; i++ ) { + ret = [keys[i].key compare:kstr]; + if ( ret >= 0 ) { /* key node found */ + if ( ret == 0 && match == NO ) { + return FAILURE; + } + else if ( ret > 0 && match == YES ) { + return FAILURE; + } + break; + } + } + if ( i == numkeys && match == YES ) { + i = FAILURE; + } + return(i); +} + +- (ACBKey *)internaldelete:(ACBKey *)dkp +{ + NSInteger i, nkey; + __strong ACBKey *del = nil; + ACBTree *tsb; + NSInteger srchlvl = 0; + + /* find deletion branch */ + if ( self.nodeType != LEAF ) { + srchlvl++; + /* search for end of tree */ + i = [self searchnode:dkp.key match:NO]; + del = [btNodes[i] internaldelete:dkp]; + srchlvl--; + /* if not LEAF propagate back high key */ + tsb = btNodes[i]; + nkey = tsb.numkeys - 1; + } + /*** the bottom of the tree has been reached ***/ + else { /* set up deletion ptrs */ + if ( [self delfrmnode:dkp] == SUCCESS ) { + if ( numkeys < BTHNODESIZE+1 ) { + del = dkp; + } + else { + del = nil; + } + dkp.recnum = nodeid; + return(del); + } + } + /*** indicate deletion to be done ***/ + if ( del != nil ) { + /*** the key in "del" has to be deleted from in present node ***/ + if ( btNodes[i].numkeys >= BTHNODESIZE+1 ) { + /* node does not need balancing */ + del = nil; + self.keys[i] = tsb.keys[nkey]; + } + else { /* node requires balancing */ + if ( i == 0 ) { + [self rotateright:0]; + self.btNodes[0] = tsb; + } else if ( i < numkeys-1 ) { /* look to the right first */ + if ( self.btNodes[i+1].numkeys > BTHNODESIZE+1 ) { /* carry from right */ + [self borrowright:i]; + } + else { /* merge present node with right node */ + [self mergenode:i]; + } + } + else { /* look to the left */ + if ( i > 0 ) { /* carry or merge with left node */ + if ( self.btNodes[i-1].numkeys > BTHNODESIZE+1 ) { /* carry from left */ + [self borrowleft:i]; + } + else { /*** merge present node with left node ***/ + i--; + [self mergenode:i]; + tsb = self.btNodes[i]; + } + } + } + self.keys[i] = tsb.keys[nkey]; + } + } + numrecs--; + updtd = TRUE; + return(del); +} + +/** Search key kp on B-tree with root t; if found increment counter. + * otherwise insert an item with key kp in tree. If an ACBKey + * emerges to be passed to a lower level, then assign it to kp; + * h = "tree t has become higher" + */ +- (ACBTree *) internalinsert:(ACBKey *)kp value:(id)value split:(NSInteger *)h +{ + /* search key ins on node t^; h = false */ + NSInteger i, ret; + ACBTree *q, *tmp; + + for (i = 0; i < numkeys; i++) { + ret = [keys[i].key compare:kp.key]; + if ( ret >= 0 ) { + if ( nodeType == LEAF && ret == 0 ) return (self); /* node containing keyentry found */ + break; + } + } + if ( nodeType == LEAF ) { /* key goes in this node */ + q = [self insert:kp value:value index:i split:h]; + } + else { /* nodeType == BTNODE */ + /* key is not on this node */ + q = [self.btNodes[i] internalinsert:kp value:value split:h]; + if ( *h ) { + [self insert:kp value:q index:i split:h]; + } + else { + self.numrecs++; + } + tmp = self.btNodes[numkeys-1]; + keys[numkeys-1] = tmp.keys[tmp.numkeys-1]; + if ( i != numkeys-1 ) { + tmp = self.btNodes[i]; + keys[i] = tmp.keys[tmp.numkeys-1]; + } + updtd = YES; + } /* search */ + return q; +} + +/** Do the actual insertion or split and insert + * insert key to the right of t.keys[hi] + */ +- (ACBTree *) insert:(ACBKey *)kp value:(id)value index:(NSInteger)hi split:(NSInteger *)h +{ + ACBTree *b; + + if ( numkeys < BTNODESIZE ) { + *h = NO; + [self rotateright:hi]; + keys[hi] = kp; + btNodes[hi] = value; + numrecs++; + numkeys++; + updtd = YES; + //[kp retain]; + return nil; + } + else { /* node t is full; split it and assign the emerging ACBKey to olditem */ + b = [self splitnode:hi]; + if ( hi <= BTHNODESIZE ) { /* insert key in left page */ + [self rotateright:hi]; + keys[hi] = kp; + btNodes[hi] = value; + numrecs++; + numkeys++; + } + else { /* insert key in right page */ + hi -= BTHNODESIZE; + if ( b.rnode == nil ) hi--; + [b rotateright:hi]; + b.keys[hi] = kp; + b.btNodes[hi] = value; + b.numrecs++; + b.numkeys++; + } + numkeys = b.numkeys = BTHNODESIZE+1; + b.updtd = updtd = YES; + } + return b; +} /* insert */ + +- (void)borrowleft:(NSInteger)i +{ + ACBTree *t0, *t1; + NSInteger nkey; + + t0 = btNodes[i]; + t1 = btNodes[i-1]; + nkey = t1.numkeys-1; + [t0 insinnode:t1.keys[nkey] value:t1.btNodes[nkey]]; + [t1 delfrmnode:t1.keys[nkey]]; + nkey--; + keys[i-1] = t1.keys[nkey]; + keys[i-1].recnum = t1.nodeid; +} + +- (void)borrowright:(NSInteger)i +{ + ACBTree *t0, *t1; + NSInteger nkey; + + t0 = btNodes[i]; + t1 = btNodes[i+1]; + [t0 insinnode:t1.keys[0] value:t1.btNodes[0]]; + [t1 delfrmnode:t1.keys[0]]; + nkey = t0.numkeys - 1; + keys[i] = t0.keys[nkey]; + keys[i].recnum = t0.nodeid; +} + +- (NSInteger)delfrmnode:(ACBKey *)ikp +{ + NSInteger j; + + j = [self searchnode:ikp.key match:YES]; + if (j == FAILURE) { + return(FAILURE); + } + ACBKey *k0 = nil; + ACBTree *n0 = nil; + if ( self.nodeType == LEAF ) { + k0 = self.keys[j]; + n0 = self.btNodes[j]; + } + [self rotateleft:j]; + self.numkeys--; + numrecs -= ((self.nodeType == LEAF)?1:btNodes[j].numrecs); + if ( k0 ) [k0 release]; + if ( n0 ) [n0 release]; + updtd = TRUE; + return(SUCCESS); +} + +- (NSInteger)insinnode:(ACBKey *)ikp value:(id)value +{ + NSInteger j; + + j = [self searchnode:ikp.key match:NO]; + [self rotateright:j]; + keys[j] = ikp; + btNodes[j] = value; + numkeys++; + if ( nodeType == LEAF ) { + numrecs++; + } + else { + numrecs += btNodes[j].numrecs; + } + updtd = TRUE; + return(j); +} + +- (void)mergenode:(NSInteger)i +{ + ACBTree *t0, *t1, *tr; + NSInteger j, k, nkeys; + + t0 = btNodes[i]; + t1 = btNodes[i+1]; + /*** move keys and pointers from + t1 node to t0 node ***/ + for (j=t0.numkeys, k=0; j < BTNODESIZE && k < t1.numkeys; j++, k++) { + t0.keys[j] = t1.keys[k]; + t0.btNodes[j] = t1.btNodes[k]; + t0.numkeys++; + } + t0.numrecs += t1.numrecs; + t0.rnode = t1.rnode; + t0.rnodeid = t1.rnodeid; + t0.updtd = YES; + nkeys = t0.numkeys - 1; + keys[i] = t0.keys[nkeys]; /* update key to point to new high key */ + [self rotateleft:i+1]; /* copy over the keys and nodes */ + + t1.nodeType = -1; + if (t1.rnodeid != 0xffff && i < numkeys - 2) { + tr = btNodes[i+1]; + tr.lnodeid = t0.nodeid; + tr.lnode = t0; + tr.updtd = YES; + } + self.numkeys--; + updtd = YES; +} + +- (ACBTree *)splitnode:(NSInteger)idx +{ + ACBTree *t1; + NSInteger j, k; + + k = (idx <= BTHNODESIZE) ? BTHNODESIZE : BTHNODESIZE+1; + /*** create new node ***/ + // checknode(l, t, k); + t1 = [ACBTree newNodeWithDictionary:dict]; + t1.nodeType = nodeType; + t1.rnode = self.rnode; + self.rnode = t1; + t1.lnode = self; + self.updtd = t1.updtd = YES; + /*** move keys and pointers ***/ + NSInteger i = 0; + for (j = k; j < BTNODESIZE; j++, i++ ) { + t1.keys[i] = keys[j]; + t1.btNodes[i] = btNodes[j]; + t1.numrecs += ((nodeType == LEAF) ? 1 : btNodes[j].numrecs); + numrecs -= ((nodeType == LEAF) ? 1 : btNodes[j].numrecs); + keys[j] = nil; + btNodes[j] = nil; + } + t1.numkeys = BTNODESIZE-k; + self.numkeys = k; + return(t1); +} + +#ifdef DONTUSENOMO +freetree(l, t) +FIDB *l; +ACBTree *t; +{ + ACBTree *tmp; + NSInteger i; + + if (dict.root == nil) return(SUCCESS); + if (t.nodeid == 1) { + srchlvl = 0; + } + else srchlvl++; + for (i = 0; i < t.numkeys; i++) { + tmp = t.btNodes[i]; + if (tmp != nil) { + if (tmp.nodeType == LEAF) { + free(tmp); /* free the leaf */ + if (tmp == l.rrnode) { + l.rrnode = nil; + } + t.btNodes[i] = nil; + l.chknode.nods_inuse--; + /* putpage(l, l.chknode, 0); + */ + } + else { + freetree(l, tmp); /* continue up the tree */ + srchlvl--; /* decrement the srchlvl on return */ + } + } + } + free(t); /* free the node entered with */ + if (t == l.rrnode) { + l.rrnode = nil; + } + l.chknode.nods_inuse--; + /* putpage(l, l.chknode, 0); + */ + t = nil; +} + +- (void) notfound:(ACBKey *)kp +{ + /* error routine to perform if entry was expected and not found */ +} + +- (void)printtree:(ACBTree *)t +{ + BYTE *str; + NSInteger i, j; + NSUInteger *pdate, *ptime; + + syslst = stdprn; + if ( t.nodeid == 1 ) { + srchlvl = 0; + } + else srchlvl++; + for (j = 0; j < t.numkeys; j++) { + checknode(l, t, j); + if ( t.btNodes[j] != nil ) [self printtree:t.btNodes[j]]; + } + NSLog(@"Nodeid = %d, nodeType = %s, numkeys = %d, numrecs = %d\n", + t.nodeid, (t.nodeType == BTNODE)?@"NODE":@"LEAF", t.numkeys, t.numrecs); + NSLog(@"Left nodeid = %d, Right nodeid = %d\n", t.lnodeid, t.rnodeid); + for (i = 0; i < t.numkeys; i++) { + NSLog(@" t.keys[%d] recnum = %d, keyval = %@", + i, t.keys[i].recnum, t.keys[i]); + str = t.keys[i].kstr; + pdate = (NSUInteger *) (str + 6); + ptime = (NSUInteger *) (str + 8); + NSLog(@" date = %04.4x, time = %04.4x\n", + *pdate, *ptime); + } +} + +- (BOOL)puttree:(ACBTree *)t +{ + NSInteger i; + if (t.nodeType != LEAF) { + for (i = 0; i < t.numkeys; i++) { + if ( t.btNodes[i] != nil ) puttree(l, t.btNodes[i]); + } + } + if ( t.updtd ) { + putnode(l, t, t.nodeid); + return(YES); + } + return(NO); +} + +#endif + +/** ROTATELEFT -- rotate keys from right to the left + * starting at position j + */ +- (void)rotateleft:(NSInteger)j +{ + while ( j+1 < numkeys ) { + keys[j] = keys[j+1]; + btNodes[j] = btNodes[j+1]; + j++; + } +} + +/** ROTATERIGHT -- rotate keys to the right by 1 position + * starting at the last key down to position j. + */ +- (void)rotateright:(NSInteger)j +{ + NSInteger k; + + for ( k = numkeys; k > j; k-- ) { + keys[k] = keys[k-1]; + btNodes[k] = btNodes[k-1]; + } + keys[j] = nil; + btNodes[j] = nil; +} + +- (NSInteger) keyWalkLeaves +{ + NSInteger i, idx = 0; + NSInteger keycnt; + ACBTree *t; + + if ( self != dict.root ) { + return 0; // maybe I need to throw an exception here + } + t = self; + self.dict.data = [[NSMutableData dataWithLength:(numkeys * sizeof(id))] retain]; + self.dict.ptrBuffer = [self.dict.data mutableBytes]; + while ( t != nil && t.nodeType != LEAF ) { + t = t.btNodes[0]; + } + do { + keycnt = t.numkeys; + for ( i = 0; i < keycnt; i++ ) { + if ( t.btNodes[i] != nil ) { + dict.ptrBuffer[idx++] = (id) t.keys[i].key; + } + } + t = t.rnode; + } while ( t != nil ); + return( idx ); +} + +- (NSInteger) objectWalkLeaves +{ + NSInteger i, idx = 0; + NSInteger keycnt; + ACBTree *t; + + if ( self != dict.root ) { + return 0; // maybe I need to throw an exception here + } + t = self; + self.dict.data = [[NSMutableData dataWithLength:(numrecs * sizeof(id))] retain]; + self.dict.ptrBuffer = [self.dict.data mutableBytes]; + while ( t != nil && t.nodeType != LEAF ) { + t = t.btNodes[0]; + } + do { + keycnt = t.numkeys; + for ( i = 0; i < keycnt; i++ ) { + if ( t.btNodes[i] != nil ) { + dict.ptrBuffer[idx++] = (id) t.btNodes[i]; + } + } + t = t.rnode; + } while ( t != nil ); + return( idx ); +} + +- (void)dealloc +{ +#ifdef DEBUG_DEALLOC + NSLog( @"called dealloc in ACBTree" ); +#endif + [super dealloc]; +} + +@end |