diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-22 20:18:05 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-22 20:18:05 +0200 |
commit | 24add11a7236d13738c5db763bfbff4116de4c9b (patch) | |
tree | ef54938add5cccba5248e1da75fe00de2fc560a1 /debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch | |
parent | 78acdaa8fc996dbf70d23d69aea9f81499290c26 (diff) |
drop old 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, 0 insertions, 1181 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 deleted file mode 100644 index b34df7bb..00000000 --- a/debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch +++ /dev/null @@ -1,1181 +0,0 @@ -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 - |