Blame src/avl/avl.c

Packit Service 102f81
/*
Packit Service 102f81
 * Copyright (C) 1995-1997 by Sam Rushing <rushing@nightmare.com>
Packit Service 102f81
 * 
Packit Service 102f81
 *                         All Rights Reserved
Packit Service 102f81
 * 
Packit Service 102f81
 * Permission to use, copy, modify, and distribute this software and
Packit Service 102f81
 * its documentation for any purpose and without fee is hereby
Packit Service 102f81
 * granted, provided that the above copyright notice appear in all
Packit Service 102f81
 * copies and that both that copyright notice and this permission
Packit Service 102f81
 * notice appear in supporting documentation, and that the name of Sam
Packit Service 102f81
 * Rushing not be used in advertising or publicity pertaining to
Packit Service 102f81
 * distribution of the software without specific, written prior
Packit Service 102f81
 * permission.
Packit Service 102f81
 * 
Packit Service 102f81
 * SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit Service 102f81
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
Packit Service 102f81
 * NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit Service 102f81
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
Packit Service 102f81
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
Packit Service 102f81
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
Packit Service 102f81
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit Service 102f81
 *
Packit Service 102f81
 */
Packit Service 102f81
Packit Service 102f81
/* $Id: avl.c,v 1.11 2004/01/27 02:16:25 karl Exp $ */
Packit Service 102f81
Packit Service 102f81
/*
Packit Service 102f81
 * This is a fairly straightfoward translation of a prototype
Packit Service 102f81
 * written in python, 'avl_tree.py'. Read that file first.
Packit Service 102f81
 */
Packit Service 102f81
Packit Service 102f81
#ifdef HAVE_CONFIG_H
Packit Service 102f81
 #include <config.h>
Packit Service 102f81
#endif
Packit Service 102f81
Packit Service 102f81
#include <stdio.h>
Packit Service 102f81
#include <stdlib.h>
Packit Service 102f81
Packit Service 102f81
#include "avl.h"
Packit Service 102f81
Packit Service 102f81
avl_node *
Packit Service 102f81
avl_node_new (void *        key,
Packit Service 102f81
          avl_node *    parent)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * node = (avl_node *) malloc (sizeof (avl_node));
Packit Service 102f81
Packit Service 102f81
  if (!node) {
Packit Service 102f81
    return NULL;
Packit Service 102f81
  } else {
Packit Service 102f81
    node->parent = parent;
Packit Service 102f81
    node->key = key;
Packit Service 102f81
    node->left = NULL;
Packit Service 102f81
    node->right = NULL;
Packit Service 102f81
    node->rank_and_balance = 0;
Packit Service 102f81
    AVL_SET_BALANCE (node, 0);
Packit Service 102f81
    AVL_SET_RANK (node, 1);
Packit Service 102f81
    thread_rwlock_create(&node->rwlock);
Packit Service 102f81
    return node;
Packit Service 102f81
  }
Packit Service 102f81
}         
Packit Service 102f81
Packit Service 102f81
avl_tree *
Packit Service 102f81
avl_tree_new (avl_key_compare_fun_type compare_fun,
Packit Service 102f81
          void * compare_arg)
Packit Service 102f81
{
Packit Service 102f81
  avl_tree * t = (avl_tree *) malloc (sizeof (avl_tree));
Packit Service 102f81
Packit Service 102f81
  if (!t) {
Packit Service 102f81
    return NULL;
Packit Service 102f81
  } else {
Packit Service 102f81
    avl_node * root = avl_node_new((void *)NULL, (avl_node *) NULL);
Packit Service 102f81
    if (!root) {
Packit Service 102f81
      free (t);
Packit Service 102f81
      return NULL;
Packit Service 102f81
    } else {
Packit Service 102f81
      t->root = root;
Packit Service 102f81
      t->height = 0;
Packit Service 102f81
      t->length = 0;
Packit Service 102f81
      t->compare_fun = compare_fun;
Packit Service 102f81
      t->compare_arg = compare_arg;
Packit Service 102f81
      thread_rwlock_create(&t->rwlock);
Packit Service 102f81
      return t;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
  
Packit Service 102f81
static void
Packit Service 102f81
avl_tree_free_helper (avl_node * node, avl_free_key_fun_type free_key_fun)
Packit Service 102f81
{
Packit Service 102f81
  if (node->left) {
Packit Service 102f81
    avl_tree_free_helper (node->left, free_key_fun);
Packit Service 102f81
  }
Packit Service 102f81
  if (free_key_fun)
Packit Service 102f81
      free_key_fun (node->key);
Packit Service 102f81
  if (node->right) {
Packit Service 102f81
    avl_tree_free_helper (node->right, free_key_fun);
Packit Service 102f81
  }
Packit Service 102f81
  thread_rwlock_destroy (&node->rwlock);
Packit Service 102f81
  free (node);
Packit Service 102f81
}
Packit Service 102f81
  
Packit Service 102f81
void
Packit Service 102f81
avl_tree_free (avl_tree * tree, avl_free_key_fun_type free_key_fun)
Packit Service 102f81
{
Packit Service 102f81
  if (tree->length) {
Packit Service 102f81
    avl_tree_free_helper (tree->root->right, free_key_fun);
Packit Service 102f81
  }
Packit Service 102f81
  if (tree->root) {
Packit Service 102f81
    thread_rwlock_destroy(&tree->root->rwlock);
Packit Service 102f81
    free (tree->root);
Packit Service 102f81
  }
Packit Service 102f81
  thread_rwlock_destroy(&tree->rwlock);
Packit Service 102f81
  free (tree);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_insert (avl_tree * ob,
Packit Service 102f81
           void * key)
Packit Service 102f81
{
Packit Service 102f81
  if (!(ob->root->right)) {
Packit Service 102f81
    avl_node * node = avl_node_new (key, ob->root);
Packit Service 102f81
    if (!node) {
Packit Service 102f81
      return -1;
Packit Service 102f81
    } else {
Packit Service 102f81
      ob->root->right = node;
Packit Service 102f81
      ob->length = ob->length + 1;
Packit Service 102f81
      return 0;
Packit Service 102f81
    }
Packit Service 102f81
  } else { /* not self.right == None */
Packit Service 102f81
    avl_node *t, *p, *s, *q, *r;
Packit Service 102f81
    int a;
Packit Service 102f81
Packit Service 102f81
    t = ob->root;
Packit Service 102f81
    s = p = t->right;
Packit Service 102f81
Packit Service 102f81
    while (1) {
Packit Service 102f81
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
Packit Service 102f81
    /* move left */
Packit Service 102f81
    AVL_SET_RANK (p, (AVL_GET_RANK (p) + 1));
Packit Service 102f81
    q = p->left;
Packit Service 102f81
    if (!q) {
Packit Service 102f81
      /* insert */
Packit Service 102f81
      avl_node * q_node = avl_node_new (key, p);
Packit Service 102f81
      if (!q_node) {
Packit Service 102f81
        return (-1);
Packit Service 102f81
      } else {
Packit Service 102f81
        q = q_node;
Packit Service 102f81
        p->left = q;
Packit Service 102f81
        break;
Packit Service 102f81
      }
Packit Service 102f81
    } else if (AVL_GET_BALANCE(q)) {
Packit Service 102f81
      t = p;
Packit Service 102f81
      s = q;
Packit Service 102f81
    }
Packit Service 102f81
    p = q;
Packit Service 102f81
      } else {
Packit Service 102f81
    /* move right */
Packit Service 102f81
    q = p->right;
Packit Service 102f81
    if (!q) {
Packit Service 102f81
      /* insert */
Packit Service 102f81
      avl_node * q_node = avl_node_new (key, p);
Packit Service 102f81
      if (!q_node) {
Packit Service 102f81
        return -1;
Packit Service 102f81
      } else {
Packit Service 102f81
        q = q_node;
Packit Service 102f81
        p->right = q;
Packit Service 102f81
        break;
Packit Service 102f81
      }
Packit Service 102f81
    } else if (AVL_GET_BALANCE(q)) {
Packit Service 102f81
      t = p;
Packit Service 102f81
      s = q;
Packit Service 102f81
    }
Packit Service 102f81
    p = q;
Packit Service 102f81
      }
Packit Service 102f81
    }
Packit Service 102f81
    
Packit Service 102f81
    ob->length = ob->length + 1;
Packit Service 102f81
    
Packit Service 102f81
    /* adjust balance factors */
Packit Service 102f81
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
Packit Service 102f81
      r = p = s->left;
Packit Service 102f81
    } else {
Packit Service 102f81
      r = p = s->right;
Packit Service 102f81
    }
Packit Service 102f81
    while (p != q) {
Packit Service 102f81
      if (ob->compare_fun (ob->compare_arg, key, p->key) < 1) {
Packit Service 102f81
    AVL_SET_BALANCE (p, -1);
Packit Service 102f81
    p = p->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    AVL_SET_BALANCE (p, +1);
Packit Service 102f81
    p = p->right;
Packit Service 102f81
      }
Packit Service 102f81
    }
Packit Service 102f81
    
Packit Service 102f81
    /* balancing act */
Packit Service 102f81
    
Packit Service 102f81
    if (ob->compare_fun (ob->compare_arg, key, s->key) < 1) {
Packit Service 102f81
      a = -1;
Packit Service 102f81
    } else {
Packit Service 102f81
      a = +1;
Packit Service 102f81
    }
Packit Service 102f81
    
Packit Service 102f81
    if (AVL_GET_BALANCE (s) == 0) {
Packit Service 102f81
      AVL_SET_BALANCE (s, a);
Packit Service 102f81
      ob->height = ob->height + 1;
Packit Service 102f81
      return 0;
Packit Service 102f81
    } else if (AVL_GET_BALANCE (s) == -a) {
Packit Service 102f81
      AVL_SET_BALANCE (s, 0);
Packit Service 102f81
      return 0;
Packit Service 102f81
    } else if (AVL_GET_BALANCE(s) == a) {
Packit Service 102f81
      if (AVL_GET_BALANCE (r) == a) {
Packit Service 102f81
    /* single rotation */
Packit Service 102f81
    p = r;
Packit Service 102f81
    if (a == -1) {
Packit Service 102f81
      s->left = r->right;
Packit Service 102f81
      if (r->right) {
Packit Service 102f81
        r->right->parent = s;
Packit Service 102f81
      }
Packit Service 102f81
      r->right = s;
Packit Service 102f81
      s->parent = r;
Packit Service 102f81
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (r)));
Packit Service 102f81
    } else {
Packit Service 102f81
      s->right = r->left;
Packit Service 102f81
      if (r->left) {
Packit Service 102f81
        r->left->parent = s;
Packit Service 102f81
      }
Packit Service 102f81
      r->left = s;
Packit Service 102f81
      s->parent = r;
Packit Service 102f81
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (s)));
Packit Service 102f81
    }
Packit Service 102f81
    AVL_SET_BALANCE (s, 0);
Packit Service 102f81
    AVL_SET_BALANCE (r, 0);
Packit Service 102f81
      } else if (AVL_GET_BALANCE (r) == -a) {
Packit Service 102f81
    /* double rotation */
Packit Service 102f81
    if (a == -1) {
Packit Service 102f81
      p = r->right;
Packit Service 102f81
      r->right = p->left;
Packit Service 102f81
      if (p->left) {
Packit Service 102f81
        p->left->parent = r;
Packit Service 102f81
      }
Packit Service 102f81
      p->left = r;
Packit Service 102f81
      r->parent = p;
Packit Service 102f81
      s->left = p->right;
Packit Service 102f81
      if (p->right) {
Packit Service 102f81
        p->right->parent = s;
Packit Service 102f81
      }
Packit Service 102f81
      p->right = s;
Packit Service 102f81
      s->parent = p;
Packit Service 102f81
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (r)));
Packit Service 102f81
      AVL_SET_RANK (s, (AVL_GET_RANK (s) - AVL_GET_RANK (p)));
Packit Service 102f81
    } else {
Packit Service 102f81
      p = r->left;
Packit Service 102f81
      r->left = p->right;
Packit Service 102f81
      if (p->right) {
Packit Service 102f81
        p->right->parent = r;
Packit Service 102f81
      }
Packit Service 102f81
      p->right = r;
Packit Service 102f81
      r->parent = p;
Packit Service 102f81
      s->right = p->left;
Packit Service 102f81
      if (p->left) {
Packit Service 102f81
        p->left->parent = s;
Packit Service 102f81
      }
Packit Service 102f81
      p->left = s;
Packit Service 102f81
      s->parent = p;
Packit Service 102f81
      AVL_SET_RANK (r, (AVL_GET_RANK (r) - AVL_GET_RANK (p)));
Packit Service 102f81
      AVL_SET_RANK (p, (AVL_GET_RANK (p) + AVL_GET_RANK (s)));
Packit Service 102f81
    }
Packit Service 102f81
    if (AVL_GET_BALANCE (p) == a) {
Packit Service 102f81
      AVL_SET_BALANCE (s, -a);
Packit Service 102f81
      AVL_SET_BALANCE (r, 0);
Packit Service 102f81
    } else if (AVL_GET_BALANCE (p) == -a) {
Packit Service 102f81
      AVL_SET_BALANCE (s, 0);
Packit Service 102f81
      AVL_SET_BALANCE (r, a);
Packit Service 102f81
    } else {
Packit Service 102f81
      AVL_SET_BALANCE (s, 0);
Packit Service 102f81
      AVL_SET_BALANCE (r, 0);
Packit Service 102f81
    }
Packit Service 102f81
    AVL_SET_BALANCE (p, 0);
Packit Service 102f81
      }
Packit Service 102f81
      /* finishing touch */
Packit Service 102f81
      if (s == t->right) {
Packit Service 102f81
    t->right = p;
Packit Service 102f81
      } else {
Packit Service 102f81
    t->left = p;
Packit Service 102f81
      }
Packit Service 102f81
      p->parent = t;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
  return 0;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_get_by_index (avl_tree * tree,
Packit Service 102f81
           unsigned long index,
Packit Service 102f81
           void ** value_address)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * p = tree->root->right;
Packit Service 102f81
  unsigned long m = index + 1;
Packit Service 102f81
  while (1) {
Packit Service 102f81
    if (!p) {
Packit Service 102f81
      return -1;
Packit Service 102f81
    }
Packit Service 102f81
    if (m < AVL_GET_RANK(p)) {
Packit Service 102f81
      p = p->left;
Packit Service 102f81
    } else if (m > AVL_GET_RANK(p)) {
Packit Service 102f81
      m = m - AVL_GET_RANK(p);
Packit Service 102f81
      p = p->right;
Packit Service 102f81
    } else {
Packit Service 102f81
      *value_address = p->key;
Packit Service 102f81
      return 0;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
           
Packit Service 102f81
int
Packit Service 102f81
avl_get_by_key (avl_tree * tree,
Packit Service 102f81
         void * key,
Packit Service 102f81
         void **value_address)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * x = tree->root->right;
Packit Service 102f81
  if (!x) {
Packit Service 102f81
    return -1;
Packit Service 102f81
  }
Packit Service 102f81
  while (1) {
Packit Service 102f81
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
Packit Service 102f81
    if (compare_result < 0) {
Packit Service 102f81
      if (x->left) {
Packit Service 102f81
    x = x->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    return -1;
Packit Service 102f81
      }
Packit Service 102f81
    } else if (compare_result > 0) {
Packit Service 102f81
      if (x->right) {
Packit Service 102f81
    x = x->right;
Packit Service 102f81
      } else {
Packit Service 102f81
    return -1;
Packit Service 102f81
      }
Packit Service 102f81
    } else {
Packit Service 102f81
      *value_address = x->key;
Packit Service 102f81
      return 0;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
int avl_delete(avl_tree *tree, void *key, avl_free_key_fun_type free_key_fun)
Packit Service 102f81
{
Packit Service 102f81
  avl_node *x, *y, *p, *q, *r, *top, *x_child;
Packit Service 102f81
  int shortened_side, shorter;
Packit Service 102f81
  
Packit Service 102f81
  x = tree->root->right;
Packit Service 102f81
  if (!x) {
Packit Service 102f81
    return -1;
Packit Service 102f81
  }
Packit Service 102f81
  while (1) {
Packit Service 102f81
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
Packit Service 102f81
    if (compare_result < 0) {
Packit Service 102f81
      /* move left
Packit Service 102f81
       * We will be deleting from the left, adjust this node's
Packit Service 102f81
       * rank accordingly
Packit Service 102f81
       */
Packit Service 102f81
      AVL_SET_RANK (x, (AVL_GET_RANK(x) - 1));
Packit Service 102f81
      if (x->left) {
Packit Service 102f81
    x = x->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    /* Oops! now we have to undo the rank changes
Packit Service 102f81
     * all the way up the tree
Packit Service 102f81
     */
Packit Service 102f81
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
Packit Service 102f81
    while (x != tree->root->right) {
Packit Service 102f81
      if (x->parent->left == x) {
Packit Service 102f81
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
Packit Service 102f81
      }
Packit Service 102f81
      x = x->parent;
Packit Service 102f81
    }
Packit Service 102f81
    return -1;        /* key not in tree */
Packit Service 102f81
      }
Packit Service 102f81
    } else if (compare_result > 0) {
Packit Service 102f81
      /* move right */
Packit Service 102f81
      if (x->right) {
Packit Service 102f81
    x = x->right;
Packit Service 102f81
      } else {
Packit Service 102f81
    AVL_SET_RANK(x, (AVL_GET_RANK (x) + 1));
Packit Service 102f81
    while (x != tree->root->right) {
Packit Service 102f81
      if (x->parent->left == x) {
Packit Service 102f81
        AVL_SET_RANK(x->parent, (AVL_GET_RANK (x->parent) + 1));
Packit Service 102f81
      }
Packit Service 102f81
      x = x->parent;
Packit Service 102f81
    }
Packit Service 102f81
    return -1;        /* key not in tree */
Packit Service 102f81
      }
Packit Service 102f81
    } else {
Packit Service 102f81
      break;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
Packit Service 102f81
  if (x->left && x->right) {
Packit Service 102f81
    void * temp_key;
Packit Service 102f81
Packit Service 102f81
    /* The complicated case.
Packit Service 102f81
     * reduce this to the simple case where we are deleting
Packit Service 102f81
     * a node with at most one child.
Packit Service 102f81
     */
Packit Service 102f81
    
Packit Service 102f81
    /* find the immediate predecessor <y> */
Packit Service 102f81
    y = x->left;
Packit Service 102f81
    while (y->right) {
Packit Service 102f81
      y = y->right;
Packit Service 102f81
    }
Packit Service 102f81
    /* swap <x> with <y> */
Packit Service 102f81
    temp_key = x->key;
Packit Service 102f81
    x->key = y->key;
Packit Service 102f81
    y->key = temp_key;
Packit Service 102f81
    /* we know <x>'s left subtree lost a node because that's
Packit Service 102f81
     * where we took it from
Packit Service 102f81
     */
Packit Service 102f81
    AVL_SET_RANK (x, (AVL_GET_RANK (x) - 1));
Packit Service 102f81
    x = y;
Packit Service 102f81
  }
Packit Service 102f81
  /* now <x> has at most one child
Packit Service 102f81
   * scoot this child into the place of <x>
Packit Service 102f81
   */
Packit Service 102f81
  if (x->left) {
Packit Service 102f81
    x_child = x->left;
Packit Service 102f81
    x_child->parent = x->parent;
Packit Service 102f81
  } else if (x->right) {
Packit Service 102f81
    x_child = x->right;
Packit Service 102f81
    x_child->parent = x->parent;
Packit Service 102f81
  } else {
Packit Service 102f81
    x_child = NULL;
Packit Service 102f81
  }
Packit Service 102f81
Packit Service 102f81
  /* now tell <x>'s parent that a grandchild became a child */
Packit Service 102f81
  if (x == x->parent->left) {
Packit Service 102f81
    x->parent->left = x_child;
Packit Service 102f81
    shortened_side = -1;
Packit Service 102f81
  } else {
Packit Service 102f81
    x->parent->right = x_child;
Packit Service 102f81
    shortened_side = +1;
Packit Service 102f81
  }
Packit Service 102f81
Packit Service 102f81
  /*
Packit Service 102f81
   * the height of the subtree <x>
Packit Service 102f81
   * has now been shortened.  climb back up
Packit Service 102f81
   * the tree, rotating when necessary to adjust
Packit Service 102f81
   * for the change.
Packit Service 102f81
   */
Packit Service 102f81
  shorter = 1;
Packit Service 102f81
  p = x->parent;
Packit Service 102f81
  
Packit Service 102f81
  /* return the key and node to storage */
Packit Service 102f81
  if (free_key_fun)
Packit Service 102f81
      free_key_fun (x->key);
Packit Service 102f81
  thread_rwlock_destroy (&x->rwlock);
Packit Service 102f81
  free (x);
Packit Service 102f81
Packit Service 102f81
  while (shorter && p->parent) {
Packit Service 102f81
    
Packit Service 102f81
    /* case 1: height unchanged */
Packit Service 102f81
    if (AVL_GET_BALANCE(p) == 0) {
Packit Service 102f81
      if (shortened_side == -1) {
Packit Service 102f81
    /* we removed a left child, the tree is now heavier
Packit Service 102f81
     * on the right
Packit Service 102f81
     */
Packit Service 102f81
    AVL_SET_BALANCE (p, +1);
Packit Service 102f81
      } else {
Packit Service 102f81
    /* we removed a right child, the tree is now heavier
Packit Service 102f81
     * on the left
Packit Service 102f81
     */
Packit Service 102f81
    AVL_SET_BALANCE (p, -1);
Packit Service 102f81
      }
Packit Service 102f81
      shorter = 0;
Packit Service 102f81
      
Packit Service 102f81
    } else if (AVL_GET_BALANCE (p) == shortened_side) {
Packit Service 102f81
      /* case 2: taller subtree shortened, height reduced */
Packit Service 102f81
      AVL_SET_BALANCE (p, 0);
Packit Service 102f81
    } else {
Packit Service 102f81
      /* case 3: shorter subtree shortened */
Packit Service 102f81
      top = p->parent;
Packit Service 102f81
      /* set <q> to the taller of the two subtrees of 

*/

Packit Service 102f81
      if (shortened_side == 1) {
Packit Service 102f81
    q = p->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    q = p->right;
Packit Service 102f81
      }
Packit Service 102f81
      if (AVL_GET_BALANCE (q) == 0) {
Packit Service 102f81
    /* case 3a: height unchanged */
Packit Service 102f81
    if (shortened_side == -1) {
Packit Service 102f81
      /* single rotate left */
Packit Service 102f81
      q->parent = p->parent;
Packit Service 102f81
      p->right = q->left;
Packit Service 102f81
      if (q->left) {
Packit Service 102f81
        q->left->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      q->left = p;
Packit Service 102f81
      p->parent = q;
Packit Service 102f81
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
Packit Service 102f81
    } else {
Packit Service 102f81
      /* single rotate right */
Packit Service 102f81
      q->parent = p->parent;
Packit Service 102f81
      p->left = q->right;
Packit Service 102f81
      if (q->right) {
Packit Service 102f81
        q->right->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      q->right = p;
Packit Service 102f81
      p->parent = q;
Packit Service 102f81
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
Packit Service 102f81
    }
Packit Service 102f81
    shorter = 0;
Packit Service 102f81
    AVL_SET_BALANCE (q, shortened_side);
Packit Service 102f81
    AVL_SET_BALANCE (p, (- shortened_side));
Packit Service 102f81
      } else if (AVL_GET_BALANCE (q) == AVL_GET_BALANCE (p)) {
Packit Service 102f81
    /* case 3b: height reduced */
Packit Service 102f81
    if (shortened_side == -1) {
Packit Service 102f81
      /* single rotate left */
Packit Service 102f81
      q->parent = p->parent;
Packit Service 102f81
      p->right = q->left;
Packit Service 102f81
      if (q->left) {
Packit Service 102f81
        q->left->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      q->left = p;
Packit Service 102f81
      p->parent = q;
Packit Service 102f81
      AVL_SET_RANK (q, (AVL_GET_RANK (q) + AVL_GET_RANK (p)));
Packit Service 102f81
    } else {
Packit Service 102f81
      /* single rotate right */
Packit Service 102f81
      q->parent = p->parent;
Packit Service 102f81
      p->left = q->right;
Packit Service 102f81
      if (q->right) {
Packit Service 102f81
        q->right->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      q->right = p;
Packit Service 102f81
      p->parent = q;
Packit Service 102f81
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (q)));
Packit Service 102f81
    }
Packit Service 102f81
    shorter = 1;
Packit Service 102f81
    AVL_SET_BALANCE (q, 0);
Packit Service 102f81
    AVL_SET_BALANCE (p, 0);
Packit Service 102f81
      } else {
Packit Service 102f81
    /* case 3c: height reduced, balance factors opposite */
Packit Service 102f81
    if (shortened_side == 1) {
Packit Service 102f81
      /* double rotate right */
Packit Service 102f81
      /* first, a left rotation around q */
Packit Service 102f81
      r = q->right;
Packit Service 102f81
      r->parent = p->parent;
Packit Service 102f81
      q->right = r->left;
Packit Service 102f81
      if (r->left) {
Packit Service 102f81
        r->left->parent = q;
Packit Service 102f81
      }
Packit Service 102f81
      r->left = q;
Packit Service 102f81
      q->parent = r;
Packit Service 102f81
      /* now, a right rotation around p */
Packit Service 102f81
      p->left = r->right;
Packit Service 102f81
      if (r->right) {
Packit Service 102f81
        r->right->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      r->right = p;
Packit Service 102f81
      p->parent = r;
Packit Service 102f81
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (q)));
Packit Service 102f81
      AVL_SET_RANK (p, (AVL_GET_RANK (p) - AVL_GET_RANK (r)));
Packit Service 102f81
    } else {
Packit Service 102f81
      /* double rotate left */
Packit Service 102f81
      /* first, a right rotation around q */
Packit Service 102f81
      r = q->left;
Packit Service 102f81
      r->parent = p->parent;
Packit Service 102f81
      q->left = r->right;
Packit Service 102f81
      if (r->right) {
Packit Service 102f81
        r->right->parent = q;
Packit Service 102f81
      }
Packit Service 102f81
      r->right = q;
Packit Service 102f81
      q->parent = r;
Packit Service 102f81
      /* now a left rotation around p */
Packit Service 102f81
      p->right = r->left;
Packit Service 102f81
      if (r->left) {
Packit Service 102f81
        r->left->parent = p;
Packit Service 102f81
      }
Packit Service 102f81
      r->left = p;
Packit Service 102f81
      p->parent = r;
Packit Service 102f81
      AVL_SET_RANK (q, (AVL_GET_RANK (q) - AVL_GET_RANK (r)));
Packit Service 102f81
      AVL_SET_RANK (r, (AVL_GET_RANK (r) + AVL_GET_RANK (p)));        
Packit Service 102f81
    }
Packit Service 102f81
    if (AVL_GET_BALANCE (r) == shortened_side) {
Packit Service 102f81
      AVL_SET_BALANCE (q, (- shortened_side));
Packit Service 102f81
      AVL_SET_BALANCE (p, 0);
Packit Service 102f81
    } else if (AVL_GET_BALANCE (r) == (- shortened_side)) {
Packit Service 102f81
      AVL_SET_BALANCE (q, 0);
Packit Service 102f81
      AVL_SET_BALANCE (p, shortened_side);
Packit Service 102f81
    } else {
Packit Service 102f81
      AVL_SET_BALANCE (q, 0);
Packit Service 102f81
      AVL_SET_BALANCE (p, 0);
Packit Service 102f81
    }
Packit Service 102f81
    AVL_SET_BALANCE (r, 0);
Packit Service 102f81
    q = r;
Packit Service 102f81
      }
Packit Service 102f81
      /* a rotation has caused <q> (or <r> in case 3c) to become
Packit Service 102f81
       * the root.  let 

's former parent know this.

Packit Service 102f81
       */
Packit Service 102f81
      if (top->left == p) {
Packit Service 102f81
    top->left = q;
Packit Service 102f81
      } else {
Packit Service 102f81
    top->right = q;
Packit Service 102f81
      }
Packit Service 102f81
      /* end case 3 */
Packit Service 102f81
      p = q;
Packit Service 102f81
    }
Packit Service 102f81
    x = p;
Packit Service 102f81
    p = x->parent;
Packit Service 102f81
    /* shortened_side tells us which side we came up from */
Packit Service 102f81
    if (x == p->left) {
Packit Service 102f81
      shortened_side = -1;
Packit Service 102f81
    } else {
Packit Service 102f81
      shortened_side = +1;
Packit Service 102f81
    }
Packit Service 102f81
  } /* end while(shorter) */
Packit Service 102f81
  /* when we're all done, we're one shorter */
Packit Service 102f81
  tree->length = tree->length - 1;
Packit Service 102f81
  return (0);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
static int
Packit Service 102f81
avl_iterate_inorder_helper (avl_node * node,
Packit Service 102f81
            avl_iter_fun_type iter_fun,
Packit Service 102f81
            void * iter_arg)
Packit Service 102f81
{
Packit Service 102f81
  int result;
Packit Service 102f81
  if (node->left) {
Packit Service 102f81
    result = avl_iterate_inorder_helper (node->left, iter_fun, iter_arg);
Packit Service 102f81
    if (result != 0) {
Packit Service 102f81
      return result;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
  result = (iter_fun (node->key, iter_arg));
Packit Service 102f81
  if (result != 0) {
Packit Service 102f81
    return result;
Packit Service 102f81
  }
Packit Service 102f81
  if (node->right) {
Packit Service 102f81
    result = avl_iterate_inorder_helper (node->right, iter_fun, iter_arg);
Packit Service 102f81
    if (result != 0) {
Packit Service 102f81
      return result;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
  return 0;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_iterate_inorder (avl_tree * tree,
Packit Service 102f81
         avl_iter_fun_type iter_fun,
Packit Service 102f81
         void * iter_arg)
Packit Service 102f81
{
Packit Service 102f81
  int result;
Packit Service 102f81
Packit Service 102f81
  if (tree->length) {
Packit Service 102f81
    result = avl_iterate_inorder_helper (tree->root->right, iter_fun, iter_arg);
Packit Service 102f81
    return (result);
Packit Service 102f81
  } else {
Packit Service 102f81
    return 0;
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
avl_node *avl_get_first(avl_tree *tree)
Packit Service 102f81
{
Packit Service 102f81
    avl_node *node;
Packit Service 102f81
    
Packit Service 102f81
    node = tree->root->right;
Packit Service 102f81
    if (node == NULL || node->key == NULL) return NULL;
Packit Service 102f81
Packit Service 102f81
    while (node->left)
Packit Service 102f81
        node = node->left;
Packit Service 102f81
Packit Service 102f81
    return node;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
avl_node *avl_get_prev(avl_node *node)
Packit Service 102f81
{
Packit Service 102f81
    if (node->left) {
Packit Service 102f81
        node = node->left;
Packit Service 102f81
        while (node->right) {
Packit Service 102f81
            node = node->right;
Packit Service 102f81
        }
Packit Service 102f81
Packit Service 102f81
        return node;
Packit Service 102f81
    } else {
Packit Service 102f81
        avl_node *child = node;
Packit Service 102f81
        while (node->parent && node->parent->key) {
Packit Service 102f81
            node = node->parent;
Packit Service 102f81
            if (child == node->right) {
Packit Service 102f81
                return node;
Packit Service 102f81
            }
Packit Service 102f81
            child = node;
Packit Service 102f81
        }
Packit Service 102f81
        
Packit Service 102f81
        return NULL;
Packit Service 102f81
    }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
avl_node *avl_get_next(avl_node *node)
Packit Service 102f81
{
Packit Service 102f81
    if (node->right) {
Packit Service 102f81
        node = node->right;
Packit Service 102f81
        while (node->left) {
Packit Service 102f81
            node = node->left;
Packit Service 102f81
        }
Packit Service 102f81
        
Packit Service 102f81
        return node;
Packit Service 102f81
    } else {
Packit Service 102f81
        avl_node *child = node;
Packit Service 102f81
        while (node->parent && node->parent->key) {
Packit Service 102f81
            node = node->parent;
Packit Service 102f81
            if (child == node->left) {
Packit Service 102f81
                return node;
Packit Service 102f81
            }
Packit Service 102f81
            child = node;
Packit Service 102f81
        }
Packit Service 102f81
        
Packit Service 102f81
        return NULL;
Packit Service 102f81
    }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/* iterate a function over a range of indices, using get_predecessor */
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_iterate_index_range (avl_tree * tree,
Packit Service 102f81
             avl_iter_index_fun_type iter_fun,
Packit Service 102f81
             unsigned long low,
Packit Service 102f81
             unsigned long high,
Packit Service 102f81
             void * iter_arg)
Packit Service 102f81
{
Packit Service 102f81
  unsigned long m;
Packit Service 102f81
  unsigned long num_left;
Packit Service 102f81
  avl_node * node;
Packit Service 102f81
Packit Service 102f81
  if (high > tree->length) {
Packit Service 102f81
    return -1;
Packit Service 102f81
  }
Packit Service 102f81
  num_left = (high - low);
Packit Service 102f81
  /* find the <high-1>th node */
Packit Service 102f81
  m = high;
Packit Service 102f81
  node = tree->root->right;
Packit Service 102f81
  while (1) {
Packit Service 102f81
    if (m < AVL_GET_RANK (node)) {
Packit Service 102f81
      node = node->left;
Packit Service 102f81
    } else if (m > AVL_GET_RANK (node)) {
Packit Service 102f81
      m = m - AVL_GET_RANK (node);
Packit Service 102f81
      node = node->right;
Packit Service 102f81
    } else {
Packit Service 102f81
      break;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
  /* call <iter_fun> on <node>, <get_pred(node)>, ... */
Packit Service 102f81
  while (num_left) {
Packit Service 102f81
    num_left = num_left - 1;
Packit Service 102f81
    if (iter_fun (num_left, node->key, iter_arg) != 0) {
Packit Service 102f81
      return -1;
Packit Service 102f81
    }
Packit Service 102f81
    node = avl_get_prev (node);
Packit Service 102f81
  }
Packit Service 102f81
  return 0;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/* If <key> is present in the tree, return that key's node, and set <*index>
Packit Service 102f81
 * appropriately.  If not, return NULL, and set <*index> to the position
Packit Service 102f81
 * representing the closest preceding value.
Packit Service 102f81
 */
Packit Service 102f81
Packit Service 102f81
static avl_node *
Packit Service 102f81
avl_get_index_by_key (avl_tree * tree,
Packit Service 102f81
          void * key,
Packit Service 102f81
          unsigned long * index)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * x = tree->root->right;
Packit Service 102f81
  unsigned long m;
Packit Service 102f81
  
Packit Service 102f81
  if (!x) {
Packit Service 102f81
    return NULL;
Packit Service 102f81
  }
Packit Service 102f81
  m = AVL_GET_RANK (x);
Packit Service 102f81
Packit Service 102f81
  while (1) {
Packit Service 102f81
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
Packit Service 102f81
    if (compare_result < 0) {
Packit Service 102f81
      if (x->left) {
Packit Service 102f81
    m = m - AVL_GET_RANK(x);
Packit Service 102f81
    x = x->left;
Packit Service 102f81
    m = m + AVL_GET_RANK(x);
Packit Service 102f81
      } else {
Packit Service 102f81
    *index = m - 2;
Packit Service 102f81
    return NULL;
Packit Service 102f81
      }
Packit Service 102f81
    } else if (compare_result > 0) {
Packit Service 102f81
      if (x->right) {
Packit Service 102f81
    x = x->right;
Packit Service 102f81
    m = m + AVL_GET_RANK(x);
Packit Service 102f81
      } else {
Packit Service 102f81
    *index = m - 1;
Packit Service 102f81
    return NULL;
Packit Service 102f81
      }
Packit Service 102f81
    } else {
Packit Service 102f81
      *index = m - 1;
Packit Service 102f81
      return x;
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/* return the (low index, high index) pair that spans the given key */
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_get_span_by_key (avl_tree * tree,
Packit Service 102f81
         void * key,
Packit Service 102f81
         unsigned long * low,
Packit Service 102f81
         unsigned long * high)
Packit Service 102f81
{
Packit Service 102f81
  unsigned long m, i, j;
Packit Service 102f81
  avl_node * node;
Packit Service 102f81
Packit Service 102f81
  node = avl_get_index_by_key (tree, key, &m);
Packit Service 102f81
Packit Service 102f81
  /* did we find an exact match?
Packit Service 102f81
   * if so, we have to search left and right
Packit Service 102f81
   * to find the span, since we know nothing about
Packit Service 102f81
   * the arrangement of like keys.
Packit Service 102f81
   */
Packit Service 102f81
  if (node) {
Packit Service 102f81
    avl_node * left, * right;
Packit Service 102f81
    /* search left */
Packit Service 102f81
    left = avl_get_prev (node);
Packit Service 102f81
    i = m;
Packit Service 102f81
    while ((i > 0) && (tree->compare_fun (tree->compare_arg, key, left->key) == 0)) {
Packit Service 102f81
      left = avl_get_prev (left);
Packit Service 102f81
      i = i - 1;
Packit Service 102f81
    }
Packit Service 102f81
    /* search right */
Packit Service 102f81
    right = avl_get_next (node);
Packit Service 102f81
    j = m;
Packit Service 102f81
    while ((j <= tree->length) && (tree->compare_fun (tree->compare_arg, key, right->key) == 0)) {
Packit Service 102f81
      right = avl_get_next (right);
Packit Service 102f81
      j = j + 1;
Packit Service 102f81
    }
Packit Service 102f81
    *low = i;
Packit Service 102f81
    *high = j + 1;
Packit Service 102f81
    return 0;
Packit Service 102f81
  } else {
Packit Service 102f81
    *low = *high = m;
Packit Service 102f81
  }
Packit Service 102f81
  return 0;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/* return the (low index, high index) pair that spans the given key */
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_get_span_by_two_keys (avl_tree * tree,
Packit Service 102f81
              void * low_key,
Packit Service 102f81
              void * high_key,
Packit Service 102f81
              unsigned long * low,
Packit Service 102f81
              unsigned long * high)
Packit Service 102f81
{
Packit Service 102f81
  unsigned long i, j;
Packit Service 102f81
  avl_node * low_node, * high_node;
Packit Service 102f81
  int order;
Packit Service 102f81
Packit Service 102f81
  /* we may need to swap them */
Packit Service 102f81
  order = tree->compare_fun (tree->compare_arg, low_key, high_key);
Packit Service 102f81
  if (order > 0) {
Packit Service 102f81
    void * temp = low_key;
Packit Service 102f81
    low_key = high_key;
Packit Service 102f81
    high_key = temp;
Packit Service 102f81
  }
Packit Service 102f81
Packit Service 102f81
  low_node = avl_get_index_by_key (tree, low_key, &i);
Packit Service 102f81
  high_node = avl_get_index_by_key (tree, high_key, &j);
Packit Service 102f81
Packit Service 102f81
  if (low_node) {
Packit Service 102f81
    avl_node * left;
Packit Service 102f81
    /* search left */
Packit Service 102f81
    left = avl_get_prev (low_node);
Packit Service 102f81
    while ((i > 0) && (tree->compare_fun (tree->compare_arg, low_key, left->key) == 0)) {
Packit Service 102f81
      left = avl_get_prev (left);
Packit Service 102f81
      i = i - 1;
Packit Service 102f81
    }
Packit Service 102f81
  } else {
Packit Service 102f81
    i = i + 1;
Packit Service 102f81
  }
Packit Service 102f81
  if (high_node) {
Packit Service 102f81
    avl_node * right;
Packit Service 102f81
    /* search right */
Packit Service 102f81
    right = avl_get_next (high_node);
Packit Service 102f81
    while ((j <= tree->length) && (tree->compare_fun (tree->compare_arg, high_key, right->key) == 0)) {
Packit Service 102f81
      right = avl_get_next (right);
Packit Service 102f81
      j = j + 1;
Packit Service 102f81
    }
Packit Service 102f81
  } else {
Packit Service 102f81
    j = j + 1;
Packit Service 102f81
  }
Packit Service 102f81
Packit Service 102f81
  *low = i;
Packit Service 102f81
  *high = j;
Packit Service 102f81
  return 0;
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
           
Packit Service 102f81
int
Packit Service 102f81
avl_get_item_by_key_most (avl_tree * tree,
Packit Service 102f81
              void * key,
Packit Service 102f81
              void **value_address)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * x = tree->root->right;
Packit Service 102f81
  *value_address = NULL;
Packit Service 102f81
Packit Service 102f81
  if (!x) {
Packit Service 102f81
    return -1;
Packit Service 102f81
  }
Packit Service 102f81
  while (1) {
Packit Service 102f81
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
Packit Service 102f81
Packit Service 102f81
    if (compare_result == 0) {
Packit Service 102f81
      *value_address = x->key;
Packit Service 102f81
      return 0;
Packit Service 102f81
    } else if (compare_result < 0) {
Packit Service 102f81
      /* the given key is less than the current key */
Packit Service 102f81
      if (x->left) {
Packit Service 102f81
    x = x->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    if (*value_address) 
Packit Service 102f81
      return 0;
Packit Service 102f81
    else
Packit Service 102f81
      return -1;
Packit Service 102f81
      }
Packit Service 102f81
    } else {
Packit Service 102f81
      /* the given key is more than the current key */
Packit Service 102f81
      /* save this value, it might end up being the right one! */
Packit Service 102f81
      *value_address = x->key;
Packit Service 102f81
      if (x->right) {
Packit Service 102f81
    /* there is a bigger entry */
Packit Service 102f81
    x = x->right;
Packit Service 102f81
      } else {
Packit Service 102f81
    if (*value_address) 
Packit Service 102f81
      return 0;
Packit Service 102f81
    else
Packit Service 102f81
      return -1;
Packit Service 102f81
      }
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_get_item_by_key_least (avl_tree * tree,
Packit Service 102f81
               void * key,
Packit Service 102f81
               void **value_address)
Packit Service 102f81
{
Packit Service 102f81
  avl_node * x = tree->root->right;
Packit Service 102f81
  *value_address = NULL;
Packit Service 102f81
Packit Service 102f81
  if (!x) {
Packit Service 102f81
    return -1;
Packit Service 102f81
  }
Packit Service 102f81
  while (1) {
Packit Service 102f81
    int compare_result = tree->compare_fun (tree->compare_arg, key, x->key);
Packit Service 102f81
    if (compare_result == 0) {
Packit Service 102f81
      *value_address = x->key;
Packit Service 102f81
      return 0;  /* exact match */
Packit Service 102f81
    } else if (compare_result < 0) {
Packit Service 102f81
      /* the given key is less than the current key */
Packit Service 102f81
      /* save this value, it might end up being the right one! */
Packit Service 102f81
      *value_address = x->key;
Packit Service 102f81
      if (x->left) {
Packit Service 102f81
    x = x->left;
Packit Service 102f81
      } else {
Packit Service 102f81
    if (*value_address)  /* we have found a valid entry */
Packit Service 102f81
      return 0; 
Packit Service 102f81
    else
Packit Service 102f81
      return -1;
Packit Service 102f81
      }
Packit Service 102f81
    } else {
Packit Service 102f81
      if (x->right) {
Packit Service 102f81
    /* there is a bigger entry */
Packit Service 102f81
    x = x->right;
Packit Service 102f81
      } else {
Packit Service 102f81
    if (*value_address)  /* we have found a valid entry */
Packit Service 102f81
      return 0; 
Packit Service 102f81
    else
Packit Service 102f81
      return -1;
Packit Service 102f81
      }
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
#define AVL_MAX(X, Y)  ((X) > (Y) ? (X) : (Y))
Packit Service 102f81
Packit Service 102f81
static long
Packit Service 102f81
avl_verify_balance (avl_node * node)
Packit Service 102f81
{
Packit Service 102f81
  if (!node) {
Packit Service 102f81
    return 0;
Packit Service 102f81
  } else {
Packit Service 102f81
    long lh = avl_verify_balance (node->left);
Packit Service 102f81
    long rh = avl_verify_balance (node->right);
Packit Service 102f81
    if ((rh - lh) != AVL_GET_BALANCE(node)) {
Packit Service 102f81
      return 0;
Packit Service 102f81
    }
Packit Service 102f81
    if (((lh - rh) > 1) || ((lh - rh) < -1)) {
Packit Service 102f81
      return 0;
Packit Service 102f81
    }
Packit Service 102f81
    return (1 + AVL_MAX (lh, rh));
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
    
Packit Service 102f81
static void
Packit Service 102f81
avl_verify_parent (avl_node * node, avl_node * parent)
Packit Service 102f81
{
Packit Service 102f81
  if (node->parent != parent) {
Packit Service 102f81
    return;
Packit Service 102f81
  }
Packit Service 102f81
  if (node->left) {
Packit Service 102f81
    avl_verify_parent (node->left, node);
Packit Service 102f81
  }
Packit Service 102f81
  if (node->right) {
Packit Service 102f81
    avl_verify_parent (node->right, node);
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
static long
Packit Service 102f81
avl_verify_rank (avl_node * node)
Packit Service 102f81
{
Packit Service 102f81
  if (!node) {
Packit Service 102f81
    return 0;
Packit Service 102f81
  } else {
Packit Service 102f81
    unsigned long num_left=0, num_right=0;
Packit Service 102f81
    if (node->left) {
Packit Service 102f81
      num_left = avl_verify_rank (node->left);
Packit Service 102f81
    }
Packit Service 102f81
    if (node->right) {
Packit Service 102f81
      num_right = avl_verify_rank (node->right);
Packit Service 102f81
    }
Packit Service 102f81
    if (AVL_GET_RANK (node) != num_left + 1) {
Packit Service 102f81
      fprintf (stderr, "invalid rank at node %ld\n", (long) node->key);
Packit Service 102f81
      exit (1);
Packit Service 102f81
    }
Packit Service 102f81
    return (num_left + num_right + 1);
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/* sanity-check the tree */
Packit Service 102f81
Packit Service 102f81
int
Packit Service 102f81
avl_verify (avl_tree * tree)
Packit Service 102f81
{
Packit Service 102f81
  if (tree->length) {
Packit Service 102f81
    avl_verify_balance (tree->root->right);
Packit Service 102f81
    avl_verify_parent  (tree->root->right, tree->root);
Packit Service 102f81
    avl_verify_rank    (tree->root->right);
Packit Service 102f81
  }
Packit Service 102f81
  return (0);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/*
Packit Service 102f81
 * These structures are accumulated on the stack during print_tree
Packit Service 102f81
 * and are used to keep track of the width and direction of each
Packit Service 102f81
 * branch in the history of a particular line <node>.
Packit Service 102f81
 */ 
Packit Service 102f81
Packit Service 102f81
typedef struct _link_node {
Packit Service 102f81
  struct _link_node    * parent;
Packit Service 102f81
  char            direction;
Packit Service 102f81
  int            width;
Packit Service 102f81
} link_node;  
Packit Service 102f81
Packit Service 102f81
static char balance_chars[3] = {'\\', '-', '/'};
Packit Service 102f81
Packit Service 102f81
static int
Packit Service 102f81
default_key_printer (char * buffer, void * key)
Packit Service 102f81
{
Packit Service 102f81
  return sprintf (buffer, "%p", key);
Packit Service 102f81
}  
Packit Service 102f81
Packit Service 102f81
/*
Packit Service 102f81
 * When traveling the family tree, a change in direction
Packit Service 102f81
 * indicates when to print a connector.  This is kinda crazy,
Packit Service 102f81
 * we use the stack to build a linked list, and then travel
Packit Service 102f81
 * it backwards using recursion.
Packit Service 102f81
 */
Packit Service 102f81
Packit Service 102f81
static void
Packit Service 102f81
print_connectors (link_node * link)
Packit Service 102f81
{
Packit Service 102f81
  if (link->parent) {
Packit Service 102f81
    print_connectors (link->parent);
Packit Service 102f81
  }
Packit Service 102f81
  if (link->parent && (link->parent->direction != link->direction) && (link->parent->parent)) {
Packit Service 102f81
    int i;
Packit Service 102f81
    fprintf (stdout, "|");
Packit Service 102f81
    for (i=0; i < (link->width - 1); i++) {
Packit Service 102f81
      fprintf (stdout, " ");
Packit Service 102f81
    }
Packit Service 102f81
  } else {
Packit Service 102f81
    int i;
Packit Service 102f81
    for (i=0; i < (link->width); i++) {
Packit Service 102f81
      fprintf (stdout, " ");
Packit Service 102f81
    }
Packit Service 102f81
  }
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
/*
Packit Service 102f81
 * The <key_printer> function writes a representation of the
Packit Service 102f81
 * key into <buffer> (which is conveniently fixed in size to add
Packit Service 102f81
 * the spice of danger).  It should return the size of the
Packit Service 102f81
 * representation.
Packit Service 102f81
 */
Packit Service 102f81
Packit Service 102f81
static void
Packit Service 102f81
print_node (avl_key_printer_fun_type key_printer,
Packit Service 102f81
        avl_node * node,
Packit Service 102f81
        link_node * link)
Packit Service 102f81
{
Packit Service 102f81
  char buffer[256];
Packit Service 102f81
  unsigned int width;
Packit Service 102f81
  width = key_printer (buffer, node->key);
Packit Service 102f81
Packit Service 102f81
  if (node->right) {
Packit Service 102f81
      link_node here;
Packit Service 102f81
      here.parent = link;
Packit Service 102f81
      here.direction = 1;
Packit Service 102f81
      here.width = width + 11;
Packit Service 102f81
    print_node (key_printer, node->right, &here;;
Packit Service 102f81
  }
Packit Service 102f81
  print_connectors (link);
Packit Service 102f81
  fprintf (stdout, "+-[%c %s %03d]",
Packit Service 102f81
       balance_chars[AVL_GET_BALANCE(node)+1],
Packit Service 102f81
       buffer,
Packit Service 102f81
       (int)AVL_GET_RANK(node));
Packit Service 102f81
  if (node->left || node->right) {
Packit Service 102f81
    fprintf (stdout, "-|\n");
Packit Service 102f81
  } else {
Packit Service 102f81
    fprintf (stdout, "\n");
Packit Service 102f81
  }
Packit Service 102f81
  if (node->left) {
Packit Service 102f81
      link_node here;
Packit Service 102f81
      here.parent = link;
Packit Service 102f81
      here.direction = -1;
Packit Service 102f81
      here.width = width + 11;
Packit Service 102f81
      print_node (key_printer, node->left, &here;;
Packit Service 102f81
  } 
Packit Service 102f81
}  
Packit Service 102f81
Packit Service 102f81
void
Packit Service 102f81
avl_print_tree (avl_tree * tree, avl_key_printer_fun_type key_printer)
Packit Service 102f81
{
Packit Service 102f81
  link_node top = {NULL, 0, 0};
Packit Service 102f81
  if (!key_printer) {
Packit Service 102f81
    key_printer = default_key_printer;
Packit Service 102f81
  }
Packit Service 102f81
  if (tree->length) {
Packit Service 102f81
    print_node (key_printer, tree->root->right, &top);
Packit Service 102f81
  } else {
Packit Service 102f81
    fprintf (stdout, "<empty tree>\n");
Packit Service 102f81
  }  
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
Packit Service 102f81
void avl_tree_rlock(avl_tree *tree)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_rlock(&tree->rwlock);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
void avl_tree_wlock(avl_tree *tree)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_wlock(&tree->rwlock);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
void avl_tree_unlock(avl_tree *tree)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_unlock(&tree->rwlock);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
void avl_node_rlock(avl_node *node)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_rlock(&node->rwlock);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
void avl_node_wlock(avl_node *node)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_wlock(&node->rwlock);
Packit Service 102f81
}
Packit Service 102f81
Packit Service 102f81
void avl_node_unlock(avl_node *node)
Packit Service 102f81
{
Packit Service 102f81
    thread_rwlock_unlock(&node->rwlock);
Packit Service 102f81
}