diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-22 08:23:16 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-22 08:23:16 +0200 |
commit | 78acdaa8fc996dbf70d23d69aea9f81499290c26 (patch) | |
tree | 9013f4a1894213f748a6e31a18a0340d6ee3fefc /debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch | |
parent | bd64a35db772d27e33b6cb1b50446b865b1c837e (diff) |
add patch series
Diffstat (limited to 'debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch')
-rw-r--r-- | debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch | 1181 |
1 files changed, 1181 insertions, 0 deletions
diff --git a/debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch b/debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch new file mode 100644 index 00000000..b34df7bb --- /dev/null +++ b/debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch @@ -0,0 +1,1181 @@ +From 07e6865e754ab651465651c5d9bff7d5c504b447 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Fri, 16 May 2014 20:21:48 +0200 +Subject: [PATCH 10/27] librbtree: add a red-black tree implementation + +Red-black trees offer search, insert, and delete operations with worst +case runtime in O(log n). They are also very space efficient. + +This is an verbatim copy from git://git.sceen.net/rbraun/librbraun.git +as of 45fef4ad. Only macros.h has been slightly amended. This file +defines two macros, which are also defined in cthreads.h. Undefine +the macros first to work around this problem. + +* librbtree/Makefile: New file. +* librbtree/rbtree.c: Likewise. +* librbtree/rbtree.h: Likewise. +* librbtree/rbtree_i.h: Likewise. +* librbtree/macros.h: Likewise. Also, undefine MACRO_{BEGIN,END}. +* Makefile (lib-subdirs): Add librbtree. +--- + Makefile | 3 + + librbtree/Makefile | 27 +++ + librbtree/macros.h | 70 ++++++++ + librbtree/rbtree.c | 498 +++++++++++++++++++++++++++++++++++++++++++++++++++ + librbtree/rbtree.h | 310 ++++++++++++++++++++++++++++++++ + librbtree/rbtree_i.h | 196 ++++++++++++++++++++ + 6 files changed, 1104 insertions(+) + create mode 100644 librbtree/Makefile + create mode 100644 librbtree/macros.h + create mode 100644 librbtree/rbtree.c + create mode 100644 librbtree/rbtree.h + create mode 100644 librbtree/rbtree_i.h + +diff --git a/Makefile b/Makefile +index 106f2f6..8a0be83 100644 +--- a/Makefile ++++ b/Makefile +@@ -46,6 +46,9 @@ endif + # Other directories + other-subdirs = hurd doc config release include + ++# XXX ++lib-subdirs += librbtree ++ + # All the subdirectories together + subdirs = $(lib-subdirs) $(prog-subdirs) $(other-subdirs) + +diff --git a/librbtree/Makefile b/librbtree/Makefile +new file mode 100644 +index 0000000..0f33358 +--- /dev/null ++++ b/librbtree/Makefile +@@ -0,0 +1,27 @@ ++# Copyright (C) 2014 Free Software Foundation, Inc. ++# ++# This file is part of the GNU Hurd. ++# ++# The GNU Hurd is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public License as ++# published by the Free Software Foundation; either version 2, or (at ++# your option) any later version. ++# ++# The GNU Hurd is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. ++ ++dir := librbtree ++makemode := library ++ ++libname := librbtree ++SRCS = rbtree.c ++installhdrs = rbtree.h rbtree_i.h macros.h ++ ++OBJS = $(SRCS:.c=.o) ++ ++include ../Makeconf +diff --git a/librbtree/macros.h b/librbtree/macros.h +new file mode 100644 +index 0000000..f0960a3 +--- /dev/null ++++ b/librbtree/macros.h +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (c) 2009, 2010 Richard Braun. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * ++ * Helper macros. ++ */ ++ ++#ifndef _MACROS_H ++#define _MACROS_H ++ ++#include <stddef.h> ++ ++#undef MACRO_BEGIN ++#undef MACRO_END ++#define MACRO_BEGIN ({ ++#define MACRO_END }) ++ ++#define XQUOTE(x) #x ++#define QUOTE(x) XQUOTE(x) ++ ++#define STRLEN(x) (sizeof(x) - 1) ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++#define MIN(a, b) ((a) < (b) ? (a) : (b)) ++#define MAX(a, b) ((a) > (b) ? (a) : (b)) ++ ++#define P2ALIGNED(x, a) (((x) & ((a) - 1)) == 0) ++#define ISP2(x) P2ALIGNED(x, x) ++#define P2ALIGN(x, a) ((x) & -(a)) ++#define P2ROUND(x, a) (-(-(x) & -(a))) ++#define P2END(x, a) (-(~(x) & -(a))) ++ ++#define structof(ptr, type, member) \ ++ ((type *)((char *)(ptr) - offsetof(type, member))) ++ ++#define alignof(x) __alignof__(x) ++ ++#define likely(expr) __builtin_expect(!!(expr), 1) ++#define unlikely(expr) __builtin_expect(!!(expr), 0) ++ ++#define barrier() asm volatile("" : : : "memory") ++ ++#define __noreturn __attribute__((noreturn)) ++#define __aligned(x) __attribute__((aligned(x))) ++ ++#define __format_printf(fmt, args) \ ++ __attribute__((format(printf, fmt, args))) ++ ++#endif /* _MACROS_H */ +diff --git a/librbtree/rbtree.c b/librbtree/rbtree.c +new file mode 100644 +index 0000000..969a18d +--- /dev/null ++++ b/librbtree/rbtree.c +@@ -0,0 +1,498 @@ ++/* ++ * Copyright (c) 2010, 2012 Richard Braun. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include <assert.h> ++#include <stddef.h> ++ ++#include "macros.h" ++#include "rbtree.h" ++#include "rbtree_i.h" ++ ++/* ++ * Return the index of a node in the children array of its parent. ++ * ++ * The parent parameter must not be NULL, and must be the parent of the ++ * given node. ++ */ ++static inline int ++rbtree_node_index(const struct rbtree_node *node, ++ const struct rbtree_node *parent) ++{ ++ assert(parent != NULL); ++ assert((node == NULL) || (rbtree_node_parent(node) == parent)); ++ ++ if (parent->children[RBTREE_LEFT] == node) ++ return RBTREE_LEFT; ++ ++ assert(parent->children[RBTREE_RIGHT] == node); ++ ++ return RBTREE_RIGHT; ++} ++ ++/* ++ * Return the color of a node. ++ */ ++static inline int ++rbtree_node_color(const struct rbtree_node *node) ++{ ++ return node->parent & RBTREE_COLOR_MASK; ++} ++ ++/* ++ * Return true if the node is red. ++ */ ++static inline int ++rbtree_node_is_red(const struct rbtree_node *node) ++{ ++ return rbtree_node_color(node) == RBTREE_COLOR_RED; ++} ++ ++/* ++ * Return true if the node is black. ++ */ ++static inline int ++rbtree_node_is_black(const struct rbtree_node *node) ++{ ++ return rbtree_node_color(node) == RBTREE_COLOR_BLACK; ++} ++ ++/* ++ * Set the parent of a node, retaining its current color. ++ */ ++static inline void ++rbtree_node_set_parent(struct rbtree_node *node, struct rbtree_node *parent) ++{ ++ assert(rbtree_node_check_alignment(node)); ++ assert(rbtree_node_check_alignment(parent)); ++ ++ node->parent = (unsigned long)parent | (node->parent & RBTREE_COLOR_MASK); ++} ++ ++/* ++ * Set the color of a node, retaining its current parent. ++ */ ++static inline void ++rbtree_node_set_color(struct rbtree_node *node, int color) ++{ ++ assert((color & ~RBTREE_COLOR_MASK) == 0); ++ node->parent = (node->parent & RBTREE_PARENT_MASK) | color; ++} ++ ++/* ++ * Set the color of a node to red, retaining its current parent. ++ */ ++static inline void ++rbtree_node_set_red(struct rbtree_node *node) ++{ ++ rbtree_node_set_color(node, RBTREE_COLOR_RED); ++} ++ ++/* ++ * Set the color of a node to black, retaining its current parent. ++ */ ++static inline void ++rbtree_node_set_black(struct rbtree_node *node) ++{ ++ rbtree_node_set_color(node, RBTREE_COLOR_BLACK); ++} ++ ++/* ++ * Return the left-most deepest child node of the given node. ++ */ ++static struct rbtree_node * ++rbtree_node_find_deepest(struct rbtree_node *node) ++{ ++ struct rbtree_node *parent; ++ ++ assert(node != NULL); ++ ++ for (;;) { ++ parent = node; ++ node = node->children[RBTREE_LEFT]; ++ ++ if (node == NULL) { ++ node = parent->children[RBTREE_RIGHT]; ++ ++ if (node == NULL) ++ return parent; ++ } ++ } ++} ++ ++/* ++ * Perform a tree rotation, rooted at the given node. ++ * ++ * The direction parameter defines the rotation direction and is either ++ * RBTREE_LEFT or RBTREE_RIGHT. ++ */ ++static void ++rbtree_rotate(struct rbtree *tree, struct rbtree_node *node, int direction) ++{ ++ struct rbtree_node *parent, *rnode; ++ int left, right; ++ ++ left = direction; ++ right = 1 - left; ++ parent = rbtree_node_parent(node); ++ rnode = node->children[right]; ++ ++ node->children[right] = rnode->children[left]; ++ ++ if (rnode->children[left] != NULL) ++ rbtree_node_set_parent(rnode->children[left], node); ++ ++ rnode->children[left] = node; ++ rbtree_node_set_parent(rnode, parent); ++ ++ if (unlikely(parent == NULL)) ++ tree->root = rnode; ++ else ++ parent->children[rbtree_node_index(node, parent)] = rnode; ++ ++ rbtree_node_set_parent(node, rnode); ++} ++ ++void ++rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent, ++ int index, struct rbtree_node *node) ++{ ++ struct rbtree_node *grand_parent, *uncle, *tmp; ++ int left, right; ++ ++ assert(rbtree_node_check_alignment(parent)); ++ assert(rbtree_node_check_alignment(node)); ++ ++ node->parent = (unsigned long)parent | RBTREE_COLOR_RED; ++ node->children[RBTREE_LEFT] = NULL; ++ node->children[RBTREE_RIGHT] = NULL; ++ ++ if (unlikely(parent == NULL)) ++ tree->root = node; ++ else ++ parent->children[index] = node; ++ ++ for (;;) { ++ if (parent == NULL) { ++ rbtree_node_set_black(node); ++ break; ++ } ++ ++ if (rbtree_node_is_black(parent)) ++ break; ++ ++ grand_parent = rbtree_node_parent(parent); ++ assert(grand_parent != NULL); ++ ++ left = rbtree_node_index(parent, grand_parent); ++ right = 1 - left; ++ ++ uncle = grand_parent->children[right]; ++ ++ /* ++ * Uncle is red. Flip colors and repeat at grand parent. ++ */ ++ if ((uncle != NULL) && rbtree_node_is_red(uncle)) { ++ rbtree_node_set_black(uncle); ++ rbtree_node_set_black(parent); ++ rbtree_node_set_red(grand_parent); ++ node = grand_parent; ++ parent = rbtree_node_parent(node); ++ continue; ++ } ++ ++ /* ++ * Node is the right child of its parent. Rotate left at parent. ++ */ ++ if (parent->children[right] == node) { ++ rbtree_rotate(tree, parent, left); ++ tmp = node; ++ node = parent; ++ parent = tmp; ++ } ++ ++ /* ++ * Node is the left child of its parent. Handle colors, rotate right ++ * at grand parent, and leave. ++ */ ++ rbtree_node_set_black(parent); ++ rbtree_node_set_red(grand_parent); ++ rbtree_rotate(tree, grand_parent, right); ++ break; ++ } ++ ++ assert(rbtree_node_is_black(tree->root)); ++} ++ ++void ++rbtree_remove(struct rbtree *tree, struct rbtree_node *node) ++{ ++ struct rbtree_node *child, *parent, *brother; ++ int color, left, right; ++ ++ if (node->children[RBTREE_LEFT] == NULL) ++ child = node->children[RBTREE_RIGHT]; ++ else if (node->children[RBTREE_RIGHT] == NULL) ++ child = node->children[RBTREE_LEFT]; ++ else { ++ struct rbtree_node *successor; ++ ++ /* ++ * Two-children case: replace the node with its successor. ++ */ ++ ++ successor = node->children[RBTREE_RIGHT]; ++ ++ while (successor->children[RBTREE_LEFT] != NULL) ++ successor = successor->children[RBTREE_LEFT]; ++ ++ color = rbtree_node_color(successor); ++ child = successor->children[RBTREE_RIGHT]; ++ parent = rbtree_node_parent(node); ++ ++ if (unlikely(parent == NULL)) ++ tree->root = successor; ++ else ++ parent->children[rbtree_node_index(node, parent)] = successor; ++ ++ parent = rbtree_node_parent(successor); ++ ++ /* ++ * Set parent directly to keep the original color. ++ */ ++ successor->parent = node->parent; ++ successor->children[RBTREE_LEFT] = node->children[RBTREE_LEFT]; ++ rbtree_node_set_parent(successor->children[RBTREE_LEFT], successor); ++ ++ if (node == parent) ++ parent = successor; ++ else { ++ successor->children[RBTREE_RIGHT] = node->children[RBTREE_RIGHT]; ++ rbtree_node_set_parent(successor->children[RBTREE_RIGHT], ++ successor); ++ parent->children[RBTREE_LEFT] = child; ++ ++ if (child != NULL) ++ rbtree_node_set_parent(child, parent); ++ } ++ ++ goto update_color; ++ } ++ ++ /* ++ * Node has at most one child. ++ */ ++ ++ color = rbtree_node_color(node); ++ parent = rbtree_node_parent(node); ++ ++ if (child != NULL) ++ rbtree_node_set_parent(child, parent); ++ ++ if (unlikely(parent == NULL)) ++ tree->root = child; ++ else ++ parent->children[rbtree_node_index(node, parent)] = child; ++ ++ /* ++ * The node has been removed, update the colors. The child pointer can ++ * be NULL, in which case it is considered a black leaf. ++ */ ++update_color: ++ if (color == RBTREE_COLOR_RED) ++ return; ++ ++ for (;;) { ++ if ((child != NULL) && rbtree_node_is_red(child)) { ++ rbtree_node_set_black(child); ++ break; ++ } ++ ++ if (parent == NULL) ++ break; ++ ++ left = rbtree_node_index(child, parent); ++ right = 1 - left; ++ ++ brother = parent->children[right]; ++ ++ /* ++ * Brother is red. Recolor and rotate left at parent so that brother ++ * becomes black. ++ */ ++ if (rbtree_node_is_red(brother)) { ++ rbtree_node_set_black(brother); ++ rbtree_node_set_red(parent); ++ rbtree_rotate(tree, parent, left); ++ brother = parent->children[right]; ++ } ++ ++ /* ++ * Brother has no red child. Recolor and repeat at parent. ++ */ ++ if (((brother->children[RBTREE_LEFT] == NULL) ++ || rbtree_node_is_black(brother->children[RBTREE_LEFT])) ++ && ((brother->children[RBTREE_RIGHT] == NULL) ++ || rbtree_node_is_black(brother->children[RBTREE_RIGHT]))) { ++ rbtree_node_set_red(brother); ++ child = parent; ++ parent = rbtree_node_parent(child); ++ continue; ++ } ++ ++ /* ++ * Brother's right child is black. Recolor and rotate right at brother. ++ */ ++ if ((brother->children[right] == NULL) ++ || rbtree_node_is_black(brother->children[right])) { ++ rbtree_node_set_black(brother->children[left]); ++ rbtree_node_set_red(brother); ++ rbtree_rotate(tree, brother, right); ++ brother = parent->children[right]; ++ } ++ ++ /* ++ * Brother's left child is black. Exchange parent and brother colors ++ * (we already know brother is black), set brother's right child black, ++ * rotate left at parent and leave. ++ */ ++ rbtree_node_set_color(brother, rbtree_node_color(parent)); ++ rbtree_node_set_black(parent); ++ rbtree_node_set_black(brother->children[right]); ++ rbtree_rotate(tree, parent, left); ++ break; ++ } ++ ++ assert((tree->root == NULL) || rbtree_node_is_black(tree->root)); ++} ++ ++struct rbtree_node * ++rbtree_nearest(struct rbtree_node *parent, int index, int direction) ++{ ++ assert(rbtree_check_index(direction)); ++ ++ if (parent == NULL) ++ return NULL; ++ ++ assert(rbtree_check_index(index)); ++ ++ if (index != direction) ++ return parent; ++ ++ return rbtree_walk(parent, direction); ++} ++ ++struct rbtree_node * ++rbtree_firstlast(const struct rbtree *tree, int direction) ++{ ++ struct rbtree_node *prev, *cur; ++ ++ assert(rbtree_check_index(direction)); ++ ++ prev = NULL; ++ ++ for (cur = tree->root; cur != NULL; cur = cur->children[direction]) ++ prev = cur; ++ ++ return prev; ++} ++ ++struct rbtree_node * ++rbtree_walk(struct rbtree_node *node, int direction) ++{ ++ int left, right; ++ ++ assert(rbtree_check_index(direction)); ++ ++ left = direction; ++ right = 1 - left; ++ ++ if (node == NULL) ++ return NULL; ++ ++ if (node->children[left] != NULL) { ++ node = node->children[left]; ++ ++ while (node->children[right] != NULL) ++ node = node->children[right]; ++ } else { ++ struct rbtree_node *parent; ++ int index; ++ ++ for (;;) { ++ parent = rbtree_node_parent(node); ++ ++ if (parent == NULL) ++ return NULL; ++ ++ index = rbtree_node_index(node, parent); ++ node = parent; ++ ++ if (index == right) ++ break; ++ } ++ } ++ ++ return node; ++} ++ ++struct rbtree_node * ++rbtree_postwalk_deepest(const struct rbtree *tree) ++{ ++ struct rbtree_node *node; ++ ++ node = tree->root; ++ ++ if (node == NULL) ++ return NULL; ++ ++ return rbtree_node_find_deepest(node); ++} ++ ++struct rbtree_node * ++rbtree_postwalk_unlink(struct rbtree_node *node) ++{ ++ struct rbtree_node *parent; ++ int index; ++ ++ if (node == NULL) ++ return NULL; ++ ++ assert(node->children[RBTREE_LEFT] == NULL); ++ assert(node->children[RBTREE_RIGHT] == NULL); ++ ++ parent = rbtree_node_parent(node); ++ ++ if (parent == NULL) ++ return NULL; ++ ++ index = rbtree_node_index(node, parent); ++ parent->children[index] = NULL; ++ node = parent->children[RBTREE_RIGHT]; ++ ++ if (node == NULL) ++ return parent; ++ ++ return rbtree_node_find_deepest(node); ++} +diff --git a/librbtree/rbtree.h b/librbtree/rbtree.h +new file mode 100644 +index 0000000..cbb519e +--- /dev/null ++++ b/librbtree/rbtree.h +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (c) 2010, 2011, 2012 Richard Braun. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * ++ * Red-black tree. ++ */ ++ ++#ifndef _RBTREE_H ++#define _RBTREE_H ++ ++#include <assert.h> ++#include <stddef.h> ++ ++#include "macros.h" ++ ++/* ++ * Indexes of the left and right nodes in the children array of a node. ++ */ ++#define RBTREE_LEFT 0 ++#define RBTREE_RIGHT 1 ++ ++/* ++ * Red-black node. ++ */ ++struct rbtree_node; ++ ++/* ++ * Red-black tree. ++ */ ++struct rbtree; ++ ++/* ++ * Static tree initializer. ++ */ ++#define RBTREE_INITIALIZER { NULL } ++ ++#include "rbtree_i.h" ++ ++/* ++ * Initialize a tree. ++ */ ++static inline void ++rbtree_init(struct rbtree *tree) ++{ ++ tree->root = NULL; ++} ++ ++/* ++ * Initialize a node. ++ * ++ * A node is in no tree when its parent points to itself. ++ */ ++static inline void ++rbtree_node_init(struct rbtree_node *node) ++{ ++ assert(rbtree_node_check_alignment(node)); ++ ++ node->parent = (unsigned long)node | RBTREE_COLOR_RED; ++ node->children[RBTREE_LEFT] = NULL; ++ node->children[RBTREE_RIGHT] = NULL; ++} ++ ++/* ++ * Return true if node is in no tree. ++ */ ++static inline int ++rbtree_node_unlinked(const struct rbtree_node *node) ++{ ++ return rbtree_node_parent(node) == node; ++} ++ ++/* ++ * Macro that evaluates to the address of the structure containing the ++ * given node based on the given type and member. ++ */ ++#define rbtree_entry(node, type, member) structof(node, type, member) ++ ++/* ++ * Return true if tree is empty. ++ */ ++static inline int ++rbtree_empty(const struct rbtree *tree) ++{ ++ return tree->root == NULL; ++} ++ ++/* ++ * Look up a node in a tree. ++ * ++ * Note that implementing the lookup algorithm as a macro gives two benefits: ++ * First, it avoids the overhead of a callback function. Next, the type of the ++ * cmp_fn parameter isn't rigid. The only guarantee offered by this ++ * implementation is that the key parameter is the first parameter given to ++ * cmp_fn. This way, users can pass only the value they need for comparison ++ * instead of e.g. allocating a full structure on the stack. ++ * ++ * See rbtree_insert(). ++ */ ++#define rbtree_lookup(tree, key, cmp_fn) \ ++MACRO_BEGIN \ ++ struct rbtree_node *___cur; \ ++ int ___diff; \ ++ \ ++ ___cur = (tree)->root; \ ++ \ ++ while (___cur != NULL) { \ ++ ___diff = cmp_fn(key, ___cur); \ ++ \ ++ if (___diff == 0) \ ++ break; \ ++ \ ++ ___cur = ___cur->children[rbtree_d2i(___diff)]; \ ++ } \ ++ \ ++ ___cur; \ ++MACRO_END ++ ++/* ++ * Look up a node or one of its nearest nodes in a tree. ++ * ++ * This macro essentially acts as rbtree_lookup() but if no entry matched ++ * the key, an additional step is performed to obtain the next or previous ++ * node, depending on the direction (left or right). ++ * ++ * The constraints that apply to the key parameter are the same as for ++ * rbtree_lookup(). ++ */ ++#define rbtree_lookup_nearest(tree, key, cmp_fn, dir) \ ++MACRO_BEGIN \ ++ struct rbtree_node *___cur, *___prev; \ ++ int ___diff, ___index; \ ++ \ ++ ___prev = NULL; \ ++ ___index = -1; \ ++ ___cur = (tree)->root; \ ++ \ ++ while (___cur != NULL) { \ ++ ___diff = cmp_fn(key, ___cur); \ ++ \ ++ if (___diff == 0) \ ++ break; \ ++ \ ++ ___prev = ___cur; \ ++ ___index = rbtree_d2i(___diff); \ ++ ___cur = ___cur->children[___index]; \ ++ } \ ++ \ ++ if (___cur == NULL) \ ++ ___cur = rbtree_nearest(___prev, ___index, dir); \ ++ \ ++ ___cur; \ ++MACRO_END ++ ++/* ++ * Insert a node in a tree. ++ * ++ * This macro performs a standard lookup to obtain the insertion point of ++ * the given node in the tree (it is assumed that the inserted node never ++ * compares equal to any other entry in the tree) and links the node. It ++ * then checks red-black rules violations, and rebalances the tree if ++ * necessary. ++ * ++ * Unlike rbtree_lookup(), the cmp_fn parameter must compare two complete ++ * entries, so it is suggested to use two different comparison inline ++ * functions, such as myobj_cmp_lookup() and myobj_cmp_insert(). There is no ++ * guarantee about the order of the nodes given to the comparison function. ++ * ++ * See rbtree_lookup(). ++ */ ++#define rbtree_insert(tree, node, cmp_fn) \ ++MACRO_BEGIN \ ++ struct rbtree_node *___cur, *___prev; \ ++ int ___diff, ___index; \ ++ \ ++ ___prev = NULL; \ ++ ___index = -1; \ ++ ___cur = (tree)->root; \ ++ \ ++ while (___cur != NULL) { \ ++ ___diff = cmp_fn(node, ___cur); \ ++ assert(___diff != 0); \ ++ ___prev = ___cur; \ ++ ___index = rbtree_d2i(___diff); \ ++ ___cur = ___cur->children[___index]; \ ++ } \ ++ \ ++ rbtree_insert_rebalance(tree, ___prev, ___index, node); \ ++MACRO_END ++ ++/* ++ * Look up a node/slot pair in a tree. ++ * ++ * This macro essentially acts as rbtree_lookup() but in addition to a node, ++ * it also returns a slot, which identifies an insertion point in the tree. ++ * If the returned node is NULL, the slot can be used by rbtree_insert_slot() ++ * to insert without the overhead of an additional lookup. The slot is a ++ * simple unsigned long integer. ++ * ++ * The constraints that apply to the key parameter are the same as for ++ * rbtree_lookup(). ++ */ ++#define rbtree_lookup_slot(tree, key, cmp_fn, slot) \ ++MACRO_BEGIN \ ++ struct rbtree_node *___cur, *___prev; \ ++ int ___diff, ___index; \ ++ \ ++ ___prev = NULL; \ ++ ___index = 0; \ ++ ___cur = (tree)->root; \ ++ \ ++ while (___cur != NULL) { \ ++ ___diff = cmp_fn(key, ___cur); \ ++ \ ++ if (___diff == 0) \ ++ break; \ ++ \ ++ ___prev = ___cur; \ ++ ___index = rbtree_d2i(___diff); \ ++ ___cur = ___cur->children[___index]; \ ++ } \ ++ \ ++ (slot) = rbtree_slot(___prev, ___index); \ ++ ___cur; \ ++MACRO_END ++ ++/* ++ * Insert a node at an insertion point in a tree. ++ * ++ * This macro essentially acts as rbtree_insert() except that it doesn't ++ * obtain the insertion point with a standard lookup. The insertion point ++ * is obtained by calling rbtree_lookup_slot(). In addition, the new node ++ * must not compare equal to an existing node in the tree (i.e. the slot ++ * must denote a NULL node). ++ */ ++static inline void ++rbtree_insert_slot(struct rbtree *tree, unsigned long slot, ++ struct rbtree_node *node) ++{ ++ struct rbtree_node *parent; ++ int index; ++ ++ parent = rbtree_slot_parent(slot); ++ index = rbtree_slot_index(slot); ++ rbtree_insert_rebalance(tree, parent, index, node); ++} ++ ++/* ++ * Remove a node from a tree. ++ * ++ * After completion, the node is stale. ++ */ ++void rbtree_remove(struct rbtree *tree, struct rbtree_node *node); ++ ++/* ++ * Return the first node of a tree. ++ */ ++#define rbtree_first(tree) rbtree_firstlast(tree, RBTREE_LEFT) ++ ++/* ++ * Return the last node of a tree. ++ */ ++#define rbtree_last(tree) rbtree_firstlast(tree, RBTREE_RIGHT) ++ ++/* ++ * Return the node previous to the given node. ++ */ ++#define rbtree_prev(node) rbtree_walk(node, RBTREE_LEFT) ++ ++/* ++ * Return the node next to the given node. ++ */ ++#define rbtree_next(node) rbtree_walk(node, RBTREE_RIGHT) ++ ++/* ++ * Forge a loop to process all nodes of a tree, removing them when visited. ++ * ++ * This macro can only be used to destroy a tree, so that the resources used ++ * by the entries can be released by the user. It basically removes all nodes ++ * without doing any color checking. ++ * ++ * After completion, all nodes and the tree root member are stale. ++ */ ++#define rbtree_for_each_remove(tree, node, tmp) \ ++for (node = rbtree_postwalk_deepest(tree), \ ++ tmp = rbtree_postwalk_unlink(node); \ ++ node != NULL; \ ++ node = tmp, tmp = rbtree_postwalk_unlink(node)) \ ++ ++#endif /* _RBTREE_H */ +diff --git a/librbtree/rbtree_i.h b/librbtree/rbtree_i.h +new file mode 100644 +index 0000000..eb1619f +--- /dev/null ++++ b/librbtree/rbtree_i.h +@@ -0,0 +1,196 @@ ++/* ++ * Copyright (c) 2010, 2011, 2012 Richard Braun. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _RBTREE_I_H ++#define _RBTREE_I_H ++ ++#include <assert.h> ++#include <stddef.h> ++ ++#include "macros.h" ++ ++/* ++ * Red-black node structure. ++ * ++ * To reduce the number of branches and the instruction cache footprint, ++ * the left and right child pointers are stored in an array, and the symmetry ++ * of most tree operations is exploited by using left/right variables when ++ * referring to children. ++ * ++ * In addition, this implementation assumes that all nodes are 4-byte aligned, ++ * so that the least significant bit of the parent member can be used to store ++ * the color of the node. This is true for all modern 32 and 64 bits ++ * architectures, as long as the nodes aren't embedded in structures with ++ * special alignment constraints such as member packing. ++ */ ++struct rbtree_node { ++ unsigned long parent; ++ struct rbtree_node *children[2]; ++}; ++ ++/* ++ * Red-black tree structure. ++ */ ++struct rbtree { ++ struct rbtree_node *root; ++}; ++ ++/* ++ * Masks applied on the parent member of a node to obtain either the ++ * color or the parent address. ++ */ ++#define RBTREE_COLOR_MASK 0x1UL ++#define RBTREE_PARENT_MASK (~0x3UL) ++ ++/* ++ * Node colors. ++ */ ++#define RBTREE_COLOR_RED 0 ++#define RBTREE_COLOR_BLACK 1 ++ ++/* ++ * Masks applied on slots to obtain either the child index or the parent ++ * address. ++ */ ++#define RBTREE_SLOT_INDEX_MASK 0x1UL ++#define RBTREE_SLOT_PARENT_MASK (~RBTREE_SLOT_INDEX_MASK) ++ ++/* ++ * Return true if the given index is a valid child index. ++ */ ++static inline int ++rbtree_check_index(int index) ++{ ++ return index == (index & 1); ++} ++ ++/* ++ * Convert the result of a comparison into an index in the children array ++ * (0 or 1). ++ * ++ * This function is mostly used when looking up a node. ++ */ ++static inline int ++rbtree_d2i(int diff) ++{ ++ return !(diff <= 0); ++} ++ ++/* ++ * Return true if the given pointer is suitably aligned. ++ */ ++static inline int ++rbtree_node_check_alignment(const struct rbtree_node *node) ++{ ++ return ((unsigned long)node & (~RBTREE_PARENT_MASK)) == 0; ++} ++ ++/* ++ * Return the parent of a node. ++ */ ++static inline struct rbtree_node * ++rbtree_node_parent(const struct rbtree_node *node) ++{ ++ return (struct rbtree_node *)(node->parent & RBTREE_PARENT_MASK); ++} ++ ++/* ++ * Translate an insertion point into a slot. ++ */ ++static inline unsigned long ++rbtree_slot(struct rbtree_node *parent, int index) ++{ ++ assert(rbtree_node_check_alignment(parent)); ++ assert(rbtree_check_index(index)); ++ return (unsigned long)parent | index; ++} ++ ++/* ++ * Extract the parent address from a slot. ++ */ ++static inline struct rbtree_node * ++rbtree_slot_parent(unsigned long slot) ++{ ++ return (struct rbtree_node *)(slot & RBTREE_SLOT_PARENT_MASK); ++} ++ ++/* ++ * Extract the index from a slot. ++ */ ++static inline int ++rbtree_slot_index(unsigned long slot) ++{ ++ return slot & RBTREE_SLOT_INDEX_MASK; ++} ++ ++/* ++ * Insert a node in a tree, rebalancing it if necessary. ++ * ++ * The index parameter is the index in the children array of the parent where ++ * the new node is to be inserted. It is ignored if the parent is NULL. ++ * ++ * This function is intended to be used by the rbtree_insert() macro only. ++ */ ++void rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent, ++ int index, struct rbtree_node *node); ++ ++/* ++ * Return the previous or next node relative to a location in a tree. ++ * ++ * The parent and index parameters define the location, which can be empty. ++ * The direction parameter is either RBTREE_LEFT (to obtain the previous ++ * node) or RBTREE_RIGHT (to obtain the next one). ++ */ ++struct rbtree_node * rbtree_nearest(struct rbtree_node *parent, int index, ++ int direction); ++ ++/* ++ * Return the first or last node of a tree. ++ * ++ * The direction parameter is either RBTREE_LEFT (to obtain the first node) ++ * or RBTREE_RIGHT (to obtain the last one). ++ */ ++struct rbtree_node * rbtree_firstlast(const struct rbtree *tree, int direction); ++ ++/* ++ * Return the node next to, or previous to the given node. ++ * ++ * The direction parameter is either RBTREE_LEFT (to obtain the previous node) ++ * or RBTREE_RIGHT (to obtain the next one). ++ */ ++struct rbtree_node * rbtree_walk(struct rbtree_node *node, int direction); ++ ++/* ++ * Return the left-most deepest node of a tree, which is the starting point of ++ * the postorder traversal performed by rbtree_for_each_remove(). ++ */ ++struct rbtree_node * rbtree_postwalk_deepest(const struct rbtree *tree); ++ ++/* ++ * Unlink a node from its tree and return the next (right) node in postorder. ++ */ ++struct rbtree_node * rbtree_postwalk_unlink(struct rbtree_node *node); ++ ++#endif /* _RBTREE_I_H */ +-- +2.0.0.rc2 + |