pike.git / src / rbtree.h

version» Context lines:

pike.git/src/rbtree.h:1:   /* An implementation of a threaded red/black balanced binary tree.    *    * Created 2001-04-27 by Martin Stjernholm    * -  * $Id: rbtree.h,v 1.1 2001/04/30 17:30:25 mast Exp $ +  * $Id: rbtree.h,v 1.2 2001/05/01 01:11:23 mast Exp $    */      #ifndef RBTREE_H   #define RBTREE_H    -  + #include "array.h" +    /* A red/black tree is a binary tree with one extra bit of info in    * each node - the color of it. The following properties holds:    *    * o Every node is either red or black.    * o A NULL leaf is considered black.    * o If a node is red, its children must be black.    * o Every path from a node down to all its leafs have the same    * number of black nodes.    *    * The longest possible path in a given tree thus have alternating red
pike.git/src/rbtree.h:24:    */      struct rb_node_hdr {    struct rb_node_hdr *prev, *next;    unsigned INT16 flags; /* Overlays svalue type field in    * rb_node_ind and rb_node_indval. */   };      /* Note: Don't access the ind svalue (or at least not its type field)    * in the following directly, since the flags above overlay that. Use -  * assign_rb_node_ind_no_free() instead. */ +  * assign_rb_node_ind_no_free() or similar instead. */      struct rb_node_ind {    struct rb_node_ind *prev, *next; /* Must be first. */    struct svalue ind;   };      struct rb_node_indval {    struct rb_node_indval *prev, *next; /* Must be first. */    struct svalue ind, val;   };
pike.git/src/rbtree.h:72:    * ... . thread pointer . ...    * \ . . /    * c . . c    * / \.. ../ \    */      #define RB_FLAG_MARKER 0x1000   #define RB_IND_FLAG_MASK 0xf000   /* The flag marker is set to nail direct uses of the ind type field. */    + PMOD_EXPORT int rb_ind_default_cmp (struct svalue *key, union rb_node *node); + typedef int low_rb_cmp_fn (void *key, struct rb_node_hdr *node); +  + PMOD_EXPORT union rb_node *rb_find_eq_extcmp (union rb_node *tree, struct svalue *key, +  struct svalue *cmp_less); + PMOD_EXPORT union rb_node *rb_find_lt_extcmp (union rb_node *tree, struct svalue *key, +  struct svalue *cmp_less); + PMOD_EXPORT union rb_node *rb_find_gt_extcmp (union rb_node *tree, struct svalue *key, +  struct svalue *cmp_less); + PMOD_EXPORT union rb_node *rb_find_le_extcmp (union rb_node *tree, struct svalue *key, +  struct svalue *cmp_less); + PMOD_EXPORT union rb_node *rb_find_ge_extcmp (union rb_node *tree, struct svalue *key, +  struct svalue *cmp_less); + PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *tree); + PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *tree); + PMOD_EXPORT struct rb_node_hdr *rb_prev (struct rb_node_hdr *node); + PMOD_EXPORT struct rb_node_hdr *rb_next (struct rb_node_hdr *node); +  + #ifdef PIKE_DEBUG + /* To get good type checking. */ + static inline struct rb_node_hdr *rb_node_ind_check (struct rb_node_ind *node) +  {return (struct rb_node_hdr *) node;} + static inline struct rb_node_hdr *rb_node_indval_check (struct rb_node_indval *node) +  {return (struct rb_node_hdr *) node;} + #else + #define rb_node_ind_check(node) ((struct rb_node_hdr *) (node)) + #define rb_node_indval_check(node) ((struct rb_node_hdr *) (node)) + #endif +  + #define RB_DECL_FIND_FUNC(type, func, tree, key, cmp_less) \ +  ((struct type *) debug_malloc_pass ( \ +  (cmp_less) ? (struct rb_node_hdr *) PIKE_CONCAT (func, _extcmp) ( \ +  (union rb_node *) debug_malloc_pass (PIKE_CONCAT (type, _check) (tree)), \ +  dmalloc_touch (struct svalue *, key), \ +  (cmp_less)) \ +  : PIKE_CONCAT (low_, func) ( \ +  (struct rb_node_hdr *) debug_malloc_pass (PIKE_CONCAT (type, _check) (tree)), \ +  (low_rb_cmp_fn *) rb_ind_default_cmp, \ +  dmalloc_touch (struct svalue *, key)))) + #define RB_DECL_STEP_FUNC(type, func, node) \ +  ((struct type *) debug_malloc_pass ( \ +  func ((struct rb_node_hdr *) debug_malloc_pass (PIKE_CONCAT (type, _check) (node))))) +    /* Operations:    *    * insert:    * Adds a new entry only if one with the same index doesn't exist    * already, replaces it otherwise. If a node was added it's    * returned, otherwise zero is returned.    *    * add:    * Adds a new entry, even if one with the same index already    * exists. Returns the newly created node.
pike.git/src/rbtree.h:98:    * Deletes an arbitrary entry with the specified index, if one    * exists. Returns nonzero in that case, zero otherwise.    *    * delete_node:    * Deletes the given node from the tree. Useful to get the right    * entry when several have the same index. The node is assumed to    * exist in the tree. Note that it's a linear search to get the    * right node among several with the same index.    *    * find_eq: -  * Returns an arbitrary entry which have the given index, or zero +  * Returns an arbitrary entry which has the given index, or zero    * if none exists.    *    * find_lt, find_gt, find_le, find_ge:    * find_lt and find_le returns the biggest entry which satisfy the    * condition, and vice versa for the other two. This means that    * e.g. rb_next when used on the returned node from find_le never    * returns an entry with the same index.    *    * If cmp_less is nonzero, it's a function pointer used as `< to    * compare the entries. If it's zero the internal set order is used.
pike.git/src/rbtree.h:124:    struct svalue *ind,    struct svalue *cmp_less);   PMOD_EXPORT struct rb_node_ind *rb_ind_add (struct rb_node_ind **tree,    struct svalue *ind,    struct svalue *cmp_less);   PMOD_EXPORT int rb_ind_delete (struct rb_node_ind **tree,    struct svalue *ind,    struct svalue *cmp_less);   PMOD_EXPORT struct rb_node_ind *rb_ind_copy (struct rb_node_ind *tree);   PMOD_EXPORT void rb_ind_free (struct rb_node_ind *tree); + #define rb_ind_find_eq(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_eq, tree, key, cmp_less) + #define rb_ind_find_lt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_lt, tree, key, cmp_less) + #define rb_ind_find_gt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_gt, tree, key, cmp_less) + #define rb_ind_find_le(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_le, tree, key, cmp_less) + #define rb_ind_find_ge(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_ind, rb_find_ge, tree, key, cmp_less) + #define rb_ind_first(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_first, tree) + #define rb_ind_last(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_last, tree) + #define rb_ind_prev(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_prev, tree) + #define rb_ind_next(tree) RB_DECL_STEP_FUNC (rb_node_ind, rb_next, tree)      /* Functions for handling nodes with index and value. */   PMOD_EXPORT struct rb_node_indval *rb_indval_insert (struct rb_node_indval **tree,    struct svalue *ind,    struct svalue *val,    struct svalue *cmp_less);   PMOD_EXPORT struct rb_node_indval *rb_indval_add (struct rb_node_indval **tree,    struct svalue *ind,    struct svalue *val,    struct svalue *cmp_less);
pike.git/src/rbtree.h:147:    struct svalue *val,    struct svalue *cmp_less);   PMOD_EXPORT int rb_indval_delete (struct rb_node_indval **tree,    struct svalue *ind,    struct svalue *cmp_less);   PMOD_EXPORT struct rb_node_indval *rb_indval_delete_node (struct rb_node_indval **tree,    struct rb_node_indval *node,    struct svalue *cmp_less);   PMOD_EXPORT struct rb_node_indval *rb_indval_copy (struct rb_node_indval *tree);   PMOD_EXPORT void rb_indval_free (struct rb_node_indval *tree); + #define rb_indval_find_eq(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_eq, tree, key, cmp_less) + #define rb_indval_find_lt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_lt, tree, key, cmp_less) + #define rb_indval_find_gt(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_gt, tree, key, cmp_less) + #define rb_indval_find_le(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_le, tree, key, cmp_less) + #define rb_indval_find_ge(tree, key, cmp_less) RB_DECL_FIND_FUNC (rb_node_indval, rb_find_ge, tree, key, cmp_less) + #define rb_indval_first(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_first, tree) + #define rb_indval_last(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_last, tree) + #define rb_indval_prev(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_prev, tree) + #define rb_indval_next(tree) RB_DECL_STEP_FUNC (rb_node_indval, rb_next, tree)    - /* Functions for handling both types of nodes. */ - PMOD_EXPORT union rb_node *rb_find_eq (union rb_node *tree, struct svalue *key, -  struct svalue *cmp_less); - PMOD_EXPORT union rb_node *rb_find_lt (union rb_node *tree, struct svalue *key, -  struct svalue *cmp_less); - PMOD_EXPORT union rb_node *rb_find_gt (union rb_node *tree, struct svalue *key, -  struct svalue *cmp_less); - PMOD_EXPORT union rb_node *rb_find_le (union rb_node *tree, struct svalue *key, -  struct svalue *cmp_less); - PMOD_EXPORT union rb_node *rb_find_ge (union rb_node *tree, struct svalue *key, -  struct svalue *cmp_less); -  - /* Functions for handling any type of node. */ - PMOD_EXPORT struct rb_node_hdr *rb_first (struct rb_node_hdr *tree); - PMOD_EXPORT struct rb_node_hdr *rb_last (struct rb_node_hdr *tree); - PMOD_EXPORT struct rb_node_hdr *rb_prev (struct rb_node_hdr *node); - PMOD_EXPORT struct rb_node_hdr *rb_next (struct rb_node_hdr *node); -  - #define RB_IND_FIND_FUNC(func, tree, key, cmp_less) \ -  ((struct rb_node_ind *) func ((union rb_node *) (tree), (key), (cmp_less))) - #define RB_IND_STEP_FUNC(func, tree) \ -  ((struct rb_node_ind *) func ((struct rb_node_hdr *) (tree))) -  - #define rb_ind_find_eq(tree, key, cmp_less) \ -  RB_IND_FIND_FUNC (rb_find_eq, tree, key, cmp_less) - #define rb_ind_find_lt(tree, key, cmp_less) \ -  RB_IND_FIND_FUNC (rb_find_lt, tree, key, cmp_less) - #define rb_ind_find_gt(tree, key, cmp_less) \ -  RB_IND_FIND_FUNC (rb_find_gt, tree, key, cmp_less) - #define rb_ind_find_le(tree, key, cmp_less) \ -  RB_IND_FIND_FUNC (rb_find_le, tree, key, cmp_less) - #define rb_ind_find_ge(tree, key, cmp_less) \ -  RB_IND_FIND_FUNC (rb_find_ge, tree, key, cmp_less) - #define rb_ind_first(tree) RB_IND_STEP_FUNC (rb_first, tree) - #define rb_ind_last(tree) RB_IND_STEP_FUNC (rb_last, tree) - #define rb_ind_prev(tree) RB_IND_STEP_FUNC (rb_prev, tree) - #define rb_ind_next(tree) RB_IND_STEP_FUNC (rb_next, tree) -  - #define RB_INDVAL_FIND_FUNC(func, tree, key, cmp_less) \ -  ((struct rb_node_indval *) func ((union rb_node *) (tree), (key), (cmp_less))) - #define RB_INDVAL_STEP_FUNC(func, tree) \ -  ((struct rb_node_indval *) func ((struct rb_node_hdr *) (tree))) -  - #define rb_indval_find_eq(tree, key, cmp_less) \ -  RB_INDVAL_FIND_FUNC (rb_find_eq, tree, key, cmp_less) - #define rb_indval_find_lt(tree, key, cmp_less) \ -  RB_INDVAL_FIND_FUNC (rb_find_lt, tree, key, cmp_less) - #define rb_indval_find_gt(tree, key, cmp_less) \ -  RB_INDVAL_FIND_FUNC (rb_find_gt, tree, key, cmp_less) - #define rb_indval_find_le(tree, key, cmp_less) \ -  RB_INDVAL_FIND_FUNC (rb_find_le, tree, key, cmp_less) - #define rb_indval_find_ge(tree, key, cmp_less) \ -  RB_INDVAL_FIND_FUNC (rb_find_ge, tree, key, cmp_less) - #define rb_indval_first(tree) RB_INDVAL_STEP_FUNC (rb_first, tree) - #define rb_indval_last(tree) RB_INDVAL_STEP_FUNC (rb_last, tree) - #define rb_indval_prev(tree) RB_INDVAL_STEP_FUNC (rb_prev, tree) - #define rb_indval_next(tree) RB_INDVAL_STEP_FUNC (rb_next, tree) -  +    /* Accessing the index svalue in a node. */   #define assign_rb_node_ind_no_free(to, node) do { \    struct svalue *_rb_node_to = (to); \    *_rb_node_to = (node)->ind; \    _rb_node_to->type &= ~RB_IND_FLAG_MASK; \    add_ref_svalue (_rb_node_to); \   } while (0)      #define assign_rb_node_ind(to, node) do { \    struct svalue *_rb_node_to2 = (to); \
pike.git/src/rbtree.h:390:    fprintf (stderr, "%*s%p between\n", \    PIKE_CONCAT (depth_, label) - 1, "", node); {between;}, \    fprintf (stderr, "%*s%p next leaf\n", \    PIKE_CONCAT (depth_, label), "", node); {n_leaf;}, \    fprintf (stderr, "%*s%p next subtree\n", \    PIKE_CONCAT (depth_, label), "", node); {n_sub;}, \    fprintf (stderr, "%*s%p leave\n", \    --PIKE_CONCAT (depth_, label), "", node); {pop;}); \   } while (0)    + /* The `cmp' code should set the variable cmp_res to the result of the +  * comparison between the key and the current node `node'. */   #define LOW_RB_FIND(node, cmp, got_lt, got_eq, got_gt) \   do { \    int cmp_res; \    while (1) { \    DO_IF_DEBUG (if (!node) fatal ("Recursing into null node.\n")); \    {cmp;} \    if (cmp_res > 0) { \    if ((node)->flags & RB_THREAD_NEXT) { \    {got_lt;} \    break; \
pike.git/src/rbtree.h:452:    else { \    node = node->next; \    RBSTACK_PUSH (slice, ssp, node); \    while (!(node->flags & RB_THREAD_PREV)) { \    node = node->prev; \    RBSTACK_PUSH (slice, ssp, node); \    } \    } \   } while (0)    - typedef int low_rb_cmp_fn (void *key, struct rb_node_hdr *node); + /* An alternative to low_rb_insert, which might or might not insert +  * the newly created node. This one compares nodes like LOW_RB_FIND +  * and will only run the code `insert' when a new node actually is to +  * be inserted, otherwise it runs the code `replace' on the matching +  * existing node. */ + #define LOW_RB_INSERT(tree, node, cmp, insert, replace) \ + do { \ +  if (((node) = *(tree))) { \ +  RBSTACK_INIT (slice, ssp); \ +  LOW_RB_TRACK (slice, ssp, node, cmp, { \ +  DO_IF_DEBUG ((node) = 0); \ +  {insert;} \ +  low_rb_link_at_next ((tree), slice, ssp, (node)); \ +  }, { \ +  {replace;} \ +  RBSTACK_FREE (slice); \ +  }, { \ +  DO_IF_DEBUG ((node) = 0); \ +  {insert;} \ +  low_rb_link_at_prev ((tree), slice, ssp, (node)); \ +  }); \ +  } \ +  else { \ +  {insert;} \ +  low_rb_init_root (*(tree) = (node)); \ +  } \ + } while (0)      /* Used when unlinking nodes. Since an interior node can't be unlinked    * we need to move over the data from a leaf node and unlink that    * instead. */   typedef void low_rb_move_data_fn (struct rb_node_hdr *to,    struct rb_node_hdr *from);      typedef struct rb_node_hdr *low_rb_alloc_copy_fn (struct rb_node_hdr *node);      void low_rb_init_root (struct rb_node_hdr *new_root);