/* rbTree - rbTreeRed-rbTreeBlack Tree - a type of binary tree which 
 * automatically keeps relatively balanced during
 * inserts and deletions.
 *   original author: Shane Saunders
 *   adapted into local conventions: Jim Kent
 */
#ifndef RBTREE_H
#define RBTREE_H

typedef enum {rbTreeRed,rbTreeBlack} rbTreeColor;


/* Structure type for nodes in the red-black tree. */
struct rbTreeNode 
    {
    struct rbTreeNode *left, *right;		/* Children. */
    rbTreeColor color;				/* Heart of algorithm. */
    void *item;					/* Item stored in tree */
    };

/* Structure type for the red-black tree. */
struct rbTree 
    {
    struct rbTree *next;			/* Next tree in list. */
    struct rbTreeNode *root;			/* Root of tree */
    int n;					/* Number of items in tree. */
    int (* compare)(void *, void *);/* Comparison function */
    struct rbTreeNode **stack;                  /* Ancestor stack. */
    struct lm *lm;	                        /* Local memory pool. */
    struct rbTreeNode *freeList;		/* List of nodes to reuse. */
    };

struct rbTree *rbTreeNew(int (*compare)(void *, void *));
/* Allocates space for a red-black tree and returns a pointer
 * to it.  The function compare compares they keys of two items, and returns a
 * negative, zero, or positive integer depending on whether the first item is
 * less than, equal to, or greater than the second. */

void rbTreeFree(struct rbTree **pTree);
/* Frees space used by the red-black tree pointed to by t. */

void rbTreeFreeList(struct rbTree **pList);
/* Free up a list of rbTrees. */

struct rbTree *rbTreeNewDetailed(int (*compare)(void *, void *), struct lm *lm, 
	struct rbTreeNode *stack[128]);
/* Allocate rbTree on an existing local memory & stack.  This is for cases
 * where you want a lot of trees, and don't want the overhead for each one. 
 * Note, to clean these up, just do freez(&rbTree) rather than rbFreeTree(&rbTree). */

void *rbTreeAdd(struct rbTree *t, void *item);
/* Inserts an item into the red-black tree pointed to by t,
 * according the the value its key.  The key of an item in the red-black
 * tree must be unique among items in the tree.  If an item with the same key
 * already exists in the tree, a pointer to that item is returned.  Otherwise,
 * NULL is returned, indicating insertion was successful.
 */

void *rbTreeFind(struct rbTree *t, void *item);
/* Find an item in the red-black tree with the same key as the
 * item pointed to by `item'.  Returns a pointer to the item found, or NULL
 * if no item was found.
 */

void *rbTreeRemove(struct rbTree *t, void *item);
/* rbTreeRemove() - Delete an item in the red-black tree with the same key as
 * the item pointed to by `item'.  Returns a pointer to the  deleted item,
 * and NULL if no item was found.
 */

void rbTreeTraverseRange(struct rbTree *tree, void *minItem, void *maxItem,
	void (*doItem)(void *item));
/* Apply doItem function to all items in tree such that
 * minItem <= item <= maxItem */

struct slRef *rbTreeItemsInRange(struct rbTree *tree, void *minItem, void *maxItem);
/* Return a sorted list of references to items in tree between range.
 * slFreeList this list when done. */

void rbTreeTraverse(struct rbTree *tree, void (*doItem)(void *item));
/* Apply doItem function to all items in tree */

void rbTreeTraverseWithContext(struct rbTree *tree, 
	void (*doItem)(void *item, void *context), void *context);
/* Traverse tree calling doItem on every item with context pointer passed through to doItem.
 * This often avoids having to declare global or static variables for the doItem callback to use. */

struct slRef *rbTreeItems(struct rbTree *tree);
/* Return sorted list of items.  slFreeList this when done.*/

void rbTreeDump(struct rbTree *tree, FILE *f, 
	void (*dumpItem)(void *item, FILE *f));
/* Dump out rb tree to file, mostly for debugging. */

int rbTreeCmpString(void *a, void *b);	
/* Set up rbTree so as to work on strings. */

int rbTreeCmpWord(void *a, void *b);	
/* Set up rbTree so as to work on case-insensitive strings. */

#endif /* RBTREE_H */

