summaryrefslogtreecommitdiff
path: root/debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-22 20:18:05 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-05-22 20:18:05 +0200
commit24add11a7236d13738c5db763bfbff4116de4c9b (patch)
treeef54938add5cccba5248e1da75fe00de2fc560a1 /debian/patches/0010-librbtree-add-a-red-black-tree-implementation.patch
parent78acdaa8fc996dbf70d23d69aea9f81499290c26 (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.patch1181
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
-