git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

HexFiend/HFAnnotatedTree.m

      1 //
      2 //  HFAnnotatedTree.m
      3 //  HexFiend_2
      4 //
      5 //  Copyright 2010 ridiculous_fish. All rights reserved.
      6 //
      7 
      8 #import "HFAnnotatedTree.h"
      9 
     10 #if NDEBUG
     11 #define VERIFY_INTEGRITY() do { } while (0)
     12 #else
     13 #define VERIFY_INTEGRITY() [self verifyIntegrity]
     14 #endif
     15 
     16 /* HFAnnotatedTree is an AA tree.  */
     17 
     18 static unsigned long long null_annotater(id left, id right) { USE(left); USE(right); return 0; }
     19 static void skew(HFAnnotatedTreeNode *node, HFAnnotatedTree *tree);
     20 static BOOL split(HFAnnotatedTreeNode *oldparent, HFAnnotatedTree *tree);
     21 static void rebalanceAfterLeafAdd(HFAnnotatedTreeNode *n, HFAnnotatedTree *tree);
     22 static void delete(HFAnnotatedTreeNode *n, HFAnnotatedTree *tree);
     23 static void verify_integrity(HFAnnotatedTreeNode *n);
     24 
     25 static HFAnnotatedTreeNode *next_node(HFAnnotatedTreeNode *node);
     26 
     27 static void insert(HFAnnotatedTreeNode *root, HFAnnotatedTreeNode *node, HFAnnotatedTree *tree);
     28 
     29 static inline HFAnnotatedTreeNode *get_parent(HFAnnotatedTreeNode *node);
     30 static inline HFAnnotatedTreeNode *get_root(HFAnnotatedTree *tree);
     31 static inline HFAnnotatedTreeNode *create_root(void);
     32 static inline HFAnnotatedTreeAnnotaterFunction_t get_annotater(HFAnnotatedTree *tree);
     33 
     34 static void reannotate(HFAnnotatedTreeNode *node, HFAnnotatedTree *tree);
     35 
     36 static HFAnnotatedTreeNode *first_node(HFAnnotatedTreeNode *node);
     37 
     38 static HFAnnotatedTreeNode *left_child(HFAnnotatedTreeNode *node);
     39 static HFAnnotatedTreeNode *right_child(HFAnnotatedTreeNode *node);
     40 
     41 @implementation HFAnnotatedTree
     42 
     43 - (instancetype)initWithAnnotater:(HFAnnotatedTreeAnnotaterFunction_t)annot {
     44     self = [super init];
     45     annotater = annot ? annot : null_annotater;    
     46     /* root is always an HFAnnotatedTreeNode with a left child but no right child */
     47     root = create_root();
     48     return self;
     49 }
     50 
     51 - (void)dealloc {
     52     [root release];
     53     [super dealloc];
     54 }
     55 
     56 - (id)rootNode {
     57     return root;
     58 }
     59 
     60 - (id)firstNode {
     61     return first_node(root);
     62 }
     63 
     64 - (id)mutableCopyWithZone:(NSZone *)zone {
     65     HFAnnotatedTree *copied = [[[self class] alloc] init];
     66     copied->annotater = annotater;
     67     [copied->root release];
     68     copied->root = [root mutableCopyWithZone:zone];
     69     return copied;
     70 }
     71 
     72 - (BOOL)isEmpty {
     73     /* We're empty if our root has no children. */
     74     return left_child(root) == nil && right_child(root) == nil;
     75 }
     76 
     77 - (void)insertNode:(HFAnnotatedTreeNode *)node {
     78     HFASSERT(node != nil);
     79     HFASSERT(get_parent(node) == nil);    
     80     /* Insert into the root */
     81     insert(root, [node retain], self);
     82     VERIFY_INTEGRITY();
     83 }
     84 
     85 - (void)removeNode:(HFAnnotatedTreeNode *)node {
     86     HFASSERT(node != nil);
     87     HFASSERT(get_parent(node) != nil);
     88     delete(node, self);
     89     [node release];
     90     VERIFY_INTEGRITY();
     91 }
     92 
     93 #if ! NDEBUG
     94 - (void)verifyIntegrity {
     95     [root verifyIntegrity];
     96     [root verifyAnnotation:annotater];
     97 }
     98 #endif
     99 
    100 static HFAnnotatedTreeNode *get_root(HFAnnotatedTree *tree) {
    101     return tree->root;
    102 }
    103 
    104 static HFAnnotatedTreeAnnotaterFunction_t get_annotater(HFAnnotatedTree *tree) {
    105     return tree->annotater;
    106 }
    107 
    108 @end
    109 
    110 @implementation HFAnnotatedTreeNode
    111 
    112 - (void)dealloc {
    113     [left release];
    114     [right release];
    115     [super dealloc];
    116 }
    117 
    118 - (NSComparisonResult)compare:(HFAnnotatedTreeNode *)node {
    119     USE(node);
    120     UNIMPLEMENTED();
    121 }
    122 
    123 - (id)nextNode {
    124     return next_node(self);
    125 }
    126 
    127 - (id)leftNode { return left; }
    128 - (id)rightNode { return right; }
    129 - (id)parentNode { return parent; }
    130 
    131 - (id)mutableCopyWithZone:(NSZone *)zone {
    132     HFAnnotatedTreeNode *copied = [[[self class] alloc] init];
    133     if (left) {
    134         copied->left = [left mutableCopyWithZone:zone];
    135         copied->left->parent = copied;
    136     }
    137     if (right) {
    138         copied->right = [right mutableCopyWithZone:zone];
    139         copied->right->parent = copied;
    140     }
    141     copied->level = level;
    142     copied->annotation = annotation;
    143     return copied;
    144 }
    145 
    146 static HFAnnotatedTreeNode *left_child(HFAnnotatedTreeNode *node) {
    147     return node->left;
    148 }
    149 
    150 static HFAnnotatedTreeNode *right_child(HFAnnotatedTreeNode *node) {
    151     return node->right;    
    152 }
    153 
    154 
    155 static HFAnnotatedTreeNode *create_root(void) {
    156     HFAnnotatedTreeNode *result = [[HFAnnotatedTreeNode alloc] init];
    157     result->level = UINT_MAX; //the root has a huge level
    158     return result;
    159 }
    160 
    161 static void reannotate(HFAnnotatedTreeNode *node, HFAnnotatedTree *tree) {
    162     HFASSERT(node != nil);
    163     HFASSERT(tree != nil);
    164     const HFAnnotatedTreeAnnotaterFunction_t annotater = get_annotater(tree);
    165     node->annotation = annotater(node->left, node->right);
    166 }
    167 
    168 static void insert(HFAnnotatedTreeNode *root, HFAnnotatedTreeNode *node, HFAnnotatedTree *tree) {
    169     /* Insert node at the proper place in the tree.  root is the root node, and we always insert to the left of root */
    170     BOOL left = YES;
    171     HFAnnotatedTreeNode *parentNode = root, *currentChild;
    172     /* Descend the tree until we find where to insert */
    173     while ((currentChild = (left ? parentNode->left : parentNode->right)) != nil) {
    174         parentNode = currentChild;
    175         left = ([parentNode compare:node] >= 0); //if parentNode is larger than the child, then the child goes to the left of node
    176     }
    177     
    178     /* Now insert, potentially unbalancing the tree */
    179     if (left) {
    180         parentNode->left = node;
    181     }
    182     else {
    183         parentNode->right = node;
    184     }
    185     
    186     /* Tell our node about its new parent */
    187     node->parent = parentNode;
    188     
    189     /* Rebalance and update annotations */
    190     rebalanceAfterLeafAdd(node, tree);
    191 }
    192 
    193 static void skew(HFAnnotatedTreeNode *oldparent, HFAnnotatedTree *tree) {
    194     HFAnnotatedTreeNode *newp = oldparent->left;
    195     
    196     if (oldparent->parent->left == oldparent) {
    197         /* oldparent is the left child of its parent.  Substitute in our left child. */
    198         oldparent->parent->left = newp;
    199     }
    200     else {
    201         /* oldparent is the right child of its parent.  Substitute in our left child. */
    202         oldparent->parent->right = newp;
    203     }
    204     
    205     /* Tell the child about its new parent */
    206     newp->parent = oldparent->parent;
    207     
    208     /* Adopt its right child as our left child, and tell it about its new parent */
    209     oldparent->left = newp->right;
    210     if (oldparent->left) oldparent->left->parent = oldparent;
    211     
    212     /* We are now the right child of the new parent */
    213     newp->right = oldparent;
    214     oldparent->parent = newp;
    215     
    216     /* If we're now a leaf, our level is 1.  Otherwise, it's one more than the level of our child. */
    217     oldparent->level = oldparent->left ? oldparent->left->level + 1 : 1;
    218     
    219     /* oldparent and newp both had their children changed, so need to be reannotated */
    220     reannotate(oldparent, tree);
    221     reannotate(newp, tree);
    222 }
    223 
    224 static BOOL split(HFAnnotatedTreeNode *oldparent, HFAnnotatedTree *tree) {
    225     HFAnnotatedTreeNode *newp = oldparent->right;
    226     if (newp && newp->right && newp->right->level == oldparent->level) { 
    227         if (oldparent->parent->left == oldparent) oldparent->parent->left = newp;
    228         else oldparent->parent->right = newp;
    229         newp->parent = oldparent->parent;
    230         oldparent->parent = newp;
    231         
    232         oldparent->right = newp->left;
    233         if (oldparent->right) oldparent->right->parent = oldparent;
    234         newp->left = oldparent;
    235         newp->level = oldparent->level + 1;
    236         
    237         /* oldparent and newp both had their children changed, so need to be reannotated */
    238         reannotate(oldparent, tree);
    239         reannotate(newp, tree);
    240         
    241         return YES;
    242     }
    243     return NO;
    244 }
    245 
    246 static void rebalanceAfterLeafAdd(HFAnnotatedTreeNode *node, HFAnnotatedTree *tree) { // n is a node that has just been inserted and is now a leaf node.
    247     node->level = 1;
    248     node->left = nil;
    249     node->right = nil;
    250     reannotate(node, tree);
    251     HFAnnotatedTreeNode * const root = get_root(tree);
    252     HFAnnotatedTreeNode *probe;
    253     for (probe = node->parent; probe != root; probe = probe->parent) {
    254         reannotate(probe, tree);
    255         // At this point probe->parent->level == probe->level
    256         if (probe->level != (probe->left ? probe->left->level + 1 : 1)) {
    257             // At this point the tree is correct, except (AA2) for n->parent
    258             skew(probe, tree);
    259             // We handle it (a left add) by changing it into a right add using Skew
    260             // If the original add was to the left side of a node that is on the
    261             // right side of a horisontal link, probe now points to the rights side
    262             // of the second horisontal link, which is correct.
    263             
    264             // However if the original add was to the left of node with a horizontal
    265             // link, we must get to the right side of the second link.
    266             if (!probe->right || probe->level != probe->right->level) probe = probe->parent;
    267         }
    268         if (! split(probe->parent, tree)) break;
    269     }
    270     while (probe) {
    271         reannotate(probe, tree);
    272         probe = probe->parent;
    273     }
    274 }
    275 
    276 static void delete(HFAnnotatedTreeNode *n, HFAnnotatedTree *tree) { // If n is not a leaf, we first swap it out with the leaf node that just
    277     // precedes it.
    278     HFAnnotatedTreeNode *leaf = n, *tmp;
    279     
    280     if (n->left) {
    281         /* Descend the right subtree of our left child, to get the closest predecessor */
    282         for (leaf = n->left; leaf->right; leaf = leaf->right) {}
    283         // When we stop, leaf has no 'right' child so it cannot have a left one
    284     }
    285     else if (n->right) {
    286         /* We have no children that precede us, but we have a child after us, so use our closest successor */
    287         leaf = n->right;
    288     }
    289     
    290     /* tmp is either the parent who loses the child, or tmp is our right subtree.  Either way, we will have to reduce its level. */
    291     tmp = leaf->parent == n ? leaf : leaf->parent;
    292     
    293     /* Tell leaf's parent to forget about leaf */
    294     if (leaf->parent->left == leaf) {
    295         leaf->parent->left = NULL;
    296     }
    297     else {
    298         leaf->parent->right = NULL;
    299     }
    300     reannotate(leaf->parent, tree);
    301     
    302     if (n != leaf) {
    303         /* Replace ourself as our parent's child with leaf */
    304         if (n->parent->left == n) n->parent->left = leaf;
    305         else n->parent->right = leaf;
    306         
    307         /* Leaf's parent is our parent */
    308         leaf->parent = n->parent;
    309         
    310         /* Our left and right children are now leaf's left and right children */
    311         if (n->left) n->left->parent = leaf;
    312         leaf->left = n->left;
    313         if (n->right) n->right->parent = leaf;
    314         leaf->right = n->right;
    315         
    316         /* Leaf's level is our level */
    317         leaf->level = n->level;
    318     }
    319     /* Since we adopted n's children, transferring the retain, tell n to forget about them so it doesn't release them */
    320     n->left = nil;
    321     n->right = nil;
    322     
    323     // free (n);
    324     
    325     HFAnnotatedTreeNode * const root = get_root(tree);
    326     while (tmp != root) {
    327         reannotate(tmp, tree);
    328         // One of tmp's childern had its level reduced
    329         if (tmp->level > (tmp->left ? tmp->left->level + 1 : 1)) { // AA2 failed
    330             tmp->level--;
    331             if (split(tmp, tree)) {
    332                 if (split(tmp, tree)) skew(tmp->parent->parent, tree);
    333                 break;
    334             }
    335             tmp = tmp->parent;
    336         }
    337         else if (tmp->level <= (tmp->right ? tmp->right->level + 1 : 1)){
    338             break;
    339         }
    340         else { // AA3 failed
    341             skew(tmp, tree);
    342             //if (tmp->right) tmp->right->level = tmp->right->left ? tmp->right->left->level + 1 : 1;
    343             if (tmp->level > tmp->parent->level) {
    344                 skew(tmp, tree);
    345                 split(tmp->parent->parent, tree);
    346                 break;
    347             }
    348             tmp = tmp->parent->parent;
    349         }
    350     }
    351     while (tmp) {
    352         reannotate(tmp, tree);
    353         tmp = tmp->parent;
    354     }
    355 }
    356 
    357 static HFAnnotatedTreeNode *next_node(HFAnnotatedTreeNode *node) {
    358     /* Return the next in-order node */
    359     HFAnnotatedTreeNode *result;
    360     if (node->right) {
    361         /* We have a right child, which is after us.  Descend its left subtree. */
    362         result = node->right;
    363         while (result->left) {
    364             result = result->left;
    365         }
    366     }
    367     else {
    368         /* We have no right child.  If we are our parent's left child, then our parent is after us.  Otherwise,  we're our parent's right child and it was before us, so ascend while we're the parent's right child. */
    369         result = node;
    370         while (result->parent && result->parent->right == result) {
    371             result = result->parent;
    372         }
    373         /* Now result is the left child of the parent (or has NULL parents), so its parent is the next node */
    374         result = result->parent;
    375     }
    376     /* Don't return the root */
    377     if (result != nil && result->parent == nil) {
    378         result = next_node(result);
    379     }
    380     return result;
    381 }
    382 
    383 static HFAnnotatedTreeNode *first_node(HFAnnotatedTreeNode *node) {
    384     /* Return the first node */ 
    385     HFAnnotatedTreeNode *result = nil, *cursor = node->left;
    386     while (cursor) {
    387         /* Descend the left subtree */
    388         result = cursor;
    389         cursor = cursor->left;
    390     }
    391     return result;
    392 }
    393 
    394 static HFAnnotatedTreeNode *get_parent(HFAnnotatedTreeNode *node) {
    395     HFASSERT(node != nil);
    396     return node->parent;
    397 }
    398 
    399 static void __attribute__((unused))verify_integrity(HFAnnotatedTreeNode *n) {
    400     HFASSERT(!n->left || n->left->parent == n);
    401     HFASSERT(!n->right || n->right->parent == n);
    402     HFASSERT(!next_node(n) || [n compare:next_node(n)] <= 0);
    403     HFASSERT(!n->parent || n->parent->level >= n->level);
    404     if (n->parent == nil) {
    405         /* root node */
    406         HFASSERT(n->level == UINT_MAX);
    407     }
    408     else {
    409         /* non-root node */
    410         HFASSERT(n->level == (n->left == NULL ? 1 : n->left->level + 1));
    411         HFASSERT((n->level <= 1) || (n->right && n->level - n->right->level <= 1));
    412     }
    413     HFASSERT(!n->parent || !n->parent->parent ||
    414              n->parent->parent->level > n->level);
    415 }
    416 
    417 #if ! NDEBUG
    418 - (void)verifyIntegrity {
    419     [left verifyIntegrity];
    420     [right verifyIntegrity];
    421     verify_integrity(self);
    422 }
    423 
    424 - (void)verifyAnnotation:(HFAnnotatedTreeAnnotaterFunction_t)annotater {
    425     [left verifyAnnotation:annotater];
    426     [right verifyAnnotation:annotater];
    427     unsigned long long expectedAnnotation = annotater(left, right);
    428     HFASSERT(annotation == expectedAnnotation);
    429 }
    430 #endif
    431 
    432 @end

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.