Index: uspace/lib/c/generic/adt/odict.c
===================================================================
--- uspace/lib/c/generic/adt/odict.c	(revision 09ab0a9afc9379f1604c0fd75cac2d9287ba022c)
+++ uspace/lib/c/generic/adt/odict.c	(revision c70e841f6a85411231802dfe4e856bb07dbb8cbc)
@@ -1,1135 +1,1 @@
-/*
- * Copyright (c) 2016 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * 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.
- */
-
-/** @addtogroup libc
- * @{
- */
-
-/** @file Ordered dictionary.
- *
- * Implementation based on red-black trees.
- * Note that non-data ('leaf') nodes are implemented as NULLs, not
- * as actual nodes.
- */
-
-#include <adt/list.h>
-#include <adt/odict.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static void odict_pgu(odlink_t *, odlink_t **, odict_child_sel_t *,
-    odlink_t **, odict_child_sel_t *, odlink_t **);
-
-static void odict_rotate_left(odlink_t *);
-static void odict_rotate_right(odlink_t *);
-static void odict_swap_node(odlink_t *, odlink_t *);
-static void odict_replace_subtree(odlink_t *, odlink_t *);
-static void odict_unlink(odlink_t *);
-static void odict_link_child_a(odlink_t *, odlink_t *);
-static void odict_link_child_b(odlink_t *, odlink_t *);
-static void odict_sibling(odlink_t *, odlink_t *, odict_child_sel_t *,
-    odlink_t **);
-static odlink_t *odict_search_start_node(odict_t *, void *, odlink_t *);
-
-/** Print subtree.
- *
- * Print subtree rooted at @a cur
- *
- * @param cur Root of tree to print
- */
-static void odict_print_tree(odlink_t *cur)
-{
-	if (cur == NULL) {
-		printf("0");
-		return;
-	}
-
-	printf("[%p/%c", cur, cur->color == odc_red ? 'r' : 'b');
-	if (cur->a != NULL || cur->b != NULL) {
-		putchar(' ');
-		odict_print_tree(cur->a);
-		putchar(',');
-		odict_print_tree(cur->b);
-	}
-	putchar(']');
-}
-
-/** Validate ordered dictionary subtree.
- *
- * Verify that red-black tree properties are satisfied.
- *
- * @param cur Root of tree to verify
- * @param rbd Place to store black depth of the subtree
- *
- * @return EOK on success, EINVAL on failure
- */
-static errno_t odict_validate_tree(odlink_t *cur, int *rbd)
-{
-	errno_t rc;
-	int bd_a, bd_b;
-	int cur_d;
-
-	if (cur->up == NULL) {
-		/* Verify root pointer */
-		if (cur->odict->root != cur) {
-			printf("cur->up == NULL and yet cur != root\n");
-			return EINVAL;
-		}
-
-		/* Verify root color */
-		if (cur->color != odc_black) {
-			printf("Root is not black\n");
-			return EINVAL;
-		}
-	}
-
-	if (cur->a != NULL) {
-		/* Verify symmetry of a - up links */
-		if (cur->a->up != cur) {
-			printf("cur->a->up != cur\n");
-			return EINVAL;
-		}
-
-		/* Verify that if a node is red, its left child is red */
-		if (cur->a->color == odc_red && cur->color == odc_red) {
-			printf("cur->a is red, cur is red\n");
-			return EINVAL;
-		}
-
-		/* Recurse to left child */
-		rc = odict_validate_tree(cur->a, &bd_a);
-		if (rc != EOK)
-			return rc;
-	} else {
-		bd_a = -1;
-	}
-
-	if (cur->b != NULL) {
-		/* Verify symmetry of b - up links */
-		if (cur->b->up != cur) {
-			printf("cur->b->up != cur\n");
-			return EINVAL;
-		}
-
-		/* Verify that if a node is red, its right child is red */
-		if (cur->b->color == odc_red && cur->color == odc_red) {
-			printf("cur->b is red, cur is red\n");
-			return EINVAL;
-		}
-
-		/* Recurse to right child */
-		rc = odict_validate_tree(cur->b, &bd_b);
-		if (rc != EOK)
-			return rc;
-	} else {
-		bd_b = -1;
-	}
-
-	/* Verify that black depths of both children are equal */
-	if (bd_a >= 0 && bd_b >= 0) {
-		if (bd_a != bd_b) {
-			printf("Black depth %d != %d\n", bd_a, bd_b);
-			return EINVAL;
-		}
-	}
-
-	cur_d = cur->color == odc_black ? 1 : 0;
-	if (bd_a >= 0)
-		*rbd = bd_a + cur_d;
-	else if (bd_b >= 0)
-		*rbd = bd_b + cur_d;
-	else
-		*rbd = cur_d;
-
-	return EOK;
-}
-
-/** Validate ordered dictionary properties.
- *
- * @param odict Ordered dictionary
- */
-errno_t odict_validate(odict_t *odict)
-{
-	int bd;
-	errno_t rc;
-
-	if (odict->root == NULL)
-		return EOK;
-
-	rc = odict_validate_tree(odict->root, &bd);
-	if (rc != EOK)
-		odict_print_tree(odict->root);
-
-	return rc;
-}
-
-/** Initialize ordered dictionary.
- *
- * @param odict Ordered dictionary
- * @param getkey Funcition to get key
- * @param cmp Function to compare entries
- */
-void odict_initialize(odict_t *odict, odgetkey_t getkey, odcmp_t cmp)
-{
-	odict->root = NULL;
-	list_initialize(&odict->entries);
-	odict->getkey = getkey;
-	odict->cmp = cmp;
-}
-
-/** Initialize ordered dictionary link.
- *
- * @param odlink Ordered dictionary link
- */
-void odlink_initialize(odlink_t *odlink)
-{
-	odlink->odict = NULL;
-	odlink->up = NULL;
-	odlink->a = NULL;
-	odlink->b = NULL;
-	link_initialize(&odlink->lentries);
-}
-
-/** Insert entry in ordered dictionary.
- *
- * Insert entry in ordered dictionary, placing it after other entries
- * with the same key.
- *
- * @param odlink New entry
- * @param odict Ordered dictionary
- * @param hint An entry that might be near the new entry or @c NULL
- */
-void odict_insert(odlink_t *odlink, odict_t *odict, odlink_t *hint)
-{
-	int d;
-	odlink_t *cur;
-	odlink_t *p;
-	odlink_t *g;
-	odlink_t *u;
-	odict_child_sel_t pcs, gcs;
-
-	assert(!odlink_used(odlink));
-
-	if (odict->root == NULL) {
-		/* odlink is the root node */
-		odict->root = odlink;
-		odlink->odict = odict;
-		odlink->color = odc_black;
-		list_append(&odlink->lentries, &odict->entries);
-		return;
-	}
-
-	cur = odict_search_start_node(odict, odict->getkey(odlink), hint);
-	while (true) {
-		d = odict->cmp(odict->getkey(odlink), odict->getkey(cur));
-		if (d < 0) {
-			if (cur->a == NULL) {
-				odict_link_child_a(odlink, cur);
-				break;
-			}
-			cur = cur->a;
-		} else {
-			if (cur->b == NULL) {
-				odict_link_child_b(odlink, cur);
-				break;
-			}
-			cur = cur->b;
-		}
-	}
-
-	odlink->color = odc_red;
-
-	while (true) {
-		/* Fix up odlink and its parent potentially being red */
-		if (odlink->up == NULL) {
-			odlink->color = odc_black;
-			break;
-		}
-
-		if (odlink->up->color == odc_black)
-			break;
-
-		/* Get parent, grandparent, uncle */
-		odict_pgu(odlink, &p, &pcs, &g, &gcs, &u);
-
-		if (g == NULL) {
-			p->color = odc_black;
-			break;
-		}
-
-		if (p->color == odc_red && u != NULL && u->color == odc_red) {
-			/* Parent and uncle are both red */
-			p->color = odc_black;
-			u->color = odc_black;
-			g->color = odc_red;
-			odlink = g;
-			continue;
-		}
-
-		/* Parent is red but uncle is black, odlink-P-G is trans */
-		if (pcs != gcs) {
-			if (gcs == odcs_a) {
-				/* odlink is right child of P */
-				/* P is left child of G */
-				odict_rotate_left(p);
-			} else {
-				/* odlink is left child of P */
-				/* P is right child of G */
-				odict_rotate_right(p);
-			}
-
-			odlink = p;
-			odict_pgu(odlink, &p, &pcs, &g, &gcs, &u);
-		}
-
-		/* odlink-P-G is now cis */
-		assert(pcs == gcs);
-		if (pcs == odcs_a) {
-			/* odlink is left child of P */
-			/* P is left child of G */
-			odict_rotate_right(g);
-		} else {
-			/* odlink is right child of P */
-			/* P is right child of G */
-			odict_rotate_left(g);
-		}
-
-		p->color = odc_black;
-		g->color = odc_red;
-		break;
-	}
-}
-
-/** Remove entry from ordered dictionary.
- *
- * @param odlink Ordered dictionary link
- */
-void odict_remove(odlink_t *odlink)
-{
-	odlink_t *n;
-	odlink_t *c;
-	odlink_t *p;
-	odlink_t *s;
-	odlink_t *sc, *st;
-	odict_child_sel_t pcs;
-
-	if (odlink->a != NULL && odlink->b != NULL) {
-		n = odict_next(odlink, odlink->odict);
-		assert(n != NULL);
-
-		odict_swap_node(odlink, n);
-	}
-
-	/* odlink has at most one child */
-	if (odlink->a != NULL) {
-		assert(odlink->b == NULL);
-		c = odlink->a;
-	} else {
-		c = odlink->b;
-	}
-
-	if (odlink->color == odc_red) {
-		/* We can remove it harmlessly */
-		assert(c == NULL);
-		odict_unlink(odlink);
-		return;
-	}
-
-	/* odlink->color == odc_black */
-	if (c != NULL && c->color == odc_red) {
-		/* Child is red: swap colors of S and C */
-		c->color = odc_black;
-		odict_replace_subtree(c, odlink);
-		odlink->up = odlink->a = odlink->b = NULL;
-		odlink->odict = NULL;
-		list_remove(&odlink->lentries);
-		return;
-	}
-
-	/* There cannot be one black child */
-	assert(c == NULL);
-
-	n = NULL;
-	p = odlink->up;
-	odict_unlink(odlink);
-	/* We removed one black node, creating imbalance */
-again:
-	/* Case 1: N is the new root */
-	if (p == NULL)
-		return;
-
-	odict_sibling(n, p, &pcs, &s);
-
-	/* Paths through N have one less black node than paths through S */
-
-	/* Case 2: S is red */
-	if (s->color == odc_red) {
-		assert(p->color == odc_black);
-		p->color = odc_red;
-		s->color = odc_black;
-		if (n == p->a)
-			odict_rotate_left(p);
-		else
-			odict_rotate_right(p);
-		odict_sibling(n, p, &pcs, &s);
-		/* Now S is black */
-		assert(s->color == odc_black);
-	}
-
-	/* Case 3: P, S and S's children are black */
-	if (p->color == odc_black &&
-	    s->color == odc_black &&
-	    (s->a == NULL || s->a->color == odc_black) &&
-	    (s->b == NULL || s->b->color == odc_black)) {
-		/*
-		 * Changing S to red means all paths through S or N have one
-		 * less black node than they should. So redo the same for P.
-		 */
-		s->color = odc_red;
-		n = p;
-		p = n->up;
-		goto again;
-	}
-
-	/* Case 4: P is red, S and S's children are black */
-	if (p->color == odc_red &&
-	    s->color == odc_black &&
-	    (s->a == NULL || s->a->color == odc_black) &&
-	    (s->b == NULL || s->b->color == odc_black)) {
-		/* Swap colors of S and P */
-		s->color = odc_red;
-		p->color = odc_black;
-		return;
-	}
-
-	/* N is the left child */
-	if (pcs == odcs_a) {
-		st = s->a;
-		sc = s->b;
-	} else {
-		st = s->b;
-		sc = s->a;
-	}
-
-	/* Case 5: S is black and S's trans child is red, S's cis child is black */
-	if (s->color == odc_black &&
-	    (st != NULL && st->color == odc_red) &&
-	    (sc == NULL || sc->color == odc_black)) {
-		/* N is the left child */
-		if (pcs == odcs_a)
-			odict_rotate_right(s);
-		else
-			odict_rotate_left(s);
-		s->color = odc_red;
-		s->up->color = odc_black;
-		/* Now N has a black sibling whose cis child is red */
-		odict_sibling(n, p, &pcs, &s);
-		/* N is the left child */
-		if (pcs == odcs_a) {
-			st = s->a;
-			sc = s->b;
-		} else {
-			st = s->b;
-			sc = s->a;
-		}
-	}
-
-	/* Case 6: S is black, S's cis child is red */
-	assert(s->color == odc_black);
-	assert(sc != NULL);
-	assert(sc->color == odc_red);
-
-	if (pcs == odcs_a)
-		odict_rotate_left(p);
-	else
-		odict_rotate_right(p);
-
-	s->color = p->color;
-	p->color = odc_black;
-	sc->color = odc_black;
-}
-
-/** Update dictionary after entry key has been changed.
- *
- * After the caller modifies the key of an entry, they need to call
- * this function so that the dictionary can update itself accordingly.
- *
- * @param odlink Ordered dictionary entry
- * @param odict Ordered dictionary
- */
-void odict_key_update(odlink_t *odlink, odict_t *odict)
-{
-	odlink_t *n;
-
-	n = odict_next(odlink, odict);
-	odict_remove(odlink);
-	odict_insert(odlink, odict, n);
-}
-
-/** Return true if entry is in a dictionary.
- *
- * @param odlink Ordered dictionary entry
- * @return @c true if entry is in a dictionary, @c false otherwise
- */
-bool odlink_used(odlink_t *odlink)
-{
-	return odlink->odict != NULL;
-}
-
-/** Return true if ordered dictionary is empty.
- *
- * @param odict Ordered dictionary
- * @return @c true if @a odict is emptry, @c false otherwise
- */
-bool odict_empty(odict_t *odict)
-{
-	return odict->root == NULL;
-}
-
-/** Return the number of entries in @a odict.
- *
- * @param odict Ordered dictionary
- */
-unsigned long odict_count(odict_t *odict)
-{
-	unsigned long cnt;
-	odlink_t *cur;
-
-	cnt = 0;
-	cur = odict_first(odict);
-	while (cur != NULL) {
-		++cnt;
-		cur = odict_next(cur, odict);
-	}
-
-	return cnt;
-}
-
-/** Return first entry in a list or @c NULL if list is empty.
- *
- * @param odict Ordered dictionary
- * @return First entry
- */
-odlink_t *odict_first(odict_t *odict)
-{
-	link_t *link;
-
-	link = list_first(&odict->entries);
-	if (link == NULL)
-		return NULL;
-
-	return list_get_instance(link, odlink_t, lentries);
-}
-
-/** Return last entry in a list or @c NULL if list is empty
- *
- * @param odict Ordered dictionary
- * @return Last entry
- */
-odlink_t *odict_last(odict_t *odict)
-{
-	link_t *link;
-
-	link = list_last(&odict->entries);
-	if (link == NULL)
-		return NULL;
-
-	return list_get_instance(link, odlink_t, lentries);
-}
-
-/** Return previous entry in list or @c NULL if @a link is the first one.
- *
- * @param odlink Entry
- * @param odict Ordered dictionary
- * @return Previous entry
- */
-odlink_t *odict_prev(odlink_t *odlink, odict_t *odict)
-{
-	link_t *link;
-
-	link = list_prev(&odlink->lentries, &odlink->odict->entries);
-	if (link == NULL)
-		return NULL;
-
-	return list_get_instance(link, odlink_t, lentries);
-}
-
-/** Return next entry in dictionary or @c NULL if @a odlink is the last one
- *
- * @param odlink Entry
- * @param odict Ordered dictionary
- * @return Next entry
- */
-odlink_t *odict_next(odlink_t *odlink, odict_t *odict)
-{
-	link_t *link;
-
-	link = list_next(&odlink->lentries, &odlink->odict->entries);
-	if (link == NULL)
-		return NULL;
-
-	return list_get_instance(link, odlink_t, lentries);
-}
-
-/** Find first entry whose key is equal to @a key/
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_eq(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *geq;
-
-	geq = odict_find_geq(odict, key, hint);
-	if (geq == NULL)
-		return NULL;
-
-	if (odict->cmp(odict->getkey(geq), key) == 0)
-		return geq;
-	else
-		return NULL;
-}
-
-/** Find last entry whose key is equal to @a key/
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_eq_last(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *leq;
-
-	leq = odict_find_leq(odict, key, hint);
-	if (leq == NULL)
-		return NULL;
-
-	if (odict->cmp(odict->getkey(leq), key) == 0)
-		return leq;
-	else
-		return NULL;
-}
-
-/** Find first entry whose key is greater than or equal to @a key
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_geq(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *cur;
-	odlink_t *next;
-	int d;
-
-	cur = odict_search_start_node(odict, key, hint);
-	if (cur == NULL)
-		return NULL;
-
-	while (true) {
-		d = odict->cmp(odict->getkey(cur), key);
-		if (d >= 0)
-			next = cur->a;
-		else
-			next = cur->b;
-
-		if (next == NULL)
-			break;
-
-		cur = next;
-	}
-
-	if (d >= 0) {
-		return cur;
-	} else {
-		return odict_next(cur, odict);
-	}
-}
-
-/** Find last entry whose key is greater than @a key.
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_gt(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *leq;
-
-	leq = odict_find_leq(odict, key, hint);
-	if (leq != NULL)
-		return odict_next(leq, odict);
-	else
-		return odict_first(odict);
-}
-
-/** Find last entry whose key is less than or equal to @a key
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_leq(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *cur;
-	odlink_t *next;
-	int d;
-
-	cur = odict_search_start_node(odict, key, hint);
-	if (cur == NULL)
-		return NULL;
-
-	while (true) {
-		d = odict->cmp(key, odict->getkey(cur));
-		if (d >= 0)
-			next = cur->b;
-		else
-			next = cur->a;
-
-		if (next == NULL)
-			break;
-
-		cur = next;
-	}
-
-	if (d >= 0) {
-		return cur;
-	} else {
-		return odict_prev(cur, odict);
-	}
-}
-
-/** Find last entry whose key is less than @a key.
- *
- * @param odict Ordered dictionary
- * @param key Key
- * @param hint Nearby entry
- * @return Pointer to entry on success, @c NULL on failure
- */
-odlink_t *odict_find_lt(odict_t *odict, void *key, odlink_t *hint)
-{
-	odlink_t *geq;
-
-	geq = odict_find_geq(odict, key, hint);
-	if (geq != NULL)
-		return odict_prev(geq, odict);
-	else
-		return odict_last(odict);
-}
-
-/** Return parent, grandparent and uncle.
- *
- * @param n Node
- * @param p Place to store pointer to parent of @a n
- * @param pcs Place to store position of @a n w.r.t. @a p
- * @param g Place to store pointer to grandparent of @a n
- * @param gcs Place to store position of @a p w.r.t. @a g
- * @param u Place to store pointer to uncle of @a n
- */
-static void odict_pgu(odlink_t *n, odlink_t **p, odict_child_sel_t *pcs,
-    odlink_t **g, odict_child_sel_t *gcs, odlink_t **u)
-{
-	*p = n->up;
-
-	if (*p == NULL) {
-		/* No parent */
-		*g = NULL;
-		*u = NULL;
-		return;
-	}
-
-	if ((*p)->a == n) {
-		*pcs = odcs_a;
-	} else {
-		assert((*p)->b == n);
-		*pcs = odcs_b;
-	}
-
-	*g = (*p)->up;
-	if (*g == NULL) {
-		/* No grandparent */
-		*u = NULL;
-		return;
-	}
-
-	if ((*g)->a == *p) {
-		*gcs = odcs_a;
-		*u = (*g)->b;
-	} else {
-		assert((*g)->b == *p);
-		*gcs = odcs_b;
-		*u = (*g)->a;
-	}
-}
-
-/** Return sibling and parent w.r.t. parent.
- *
- * @param n Node
- * @param p Parent of @ an
- * @param pcs Place to store position of @a n w.r.t. @a p.
- * @param rs Place to strore pointer to sibling
- */
-static void odict_sibling(odlink_t *n, odlink_t *p, odict_child_sel_t *pcs,
-    odlink_t **rs)
-{
-	if (p->a == n) {
-		*pcs = odcs_a;
-		*rs = p->b;
-	} else {
-		*pcs = odcs_b;
-		*rs = p->a;
-	}
-}
-
-/** Ordered dictionary left rotation.
- *
- *    Q           P
- *  P   C   <- A    Q
- * A B             B C
- *
- */
-static void odict_rotate_left(odlink_t *p)
-{
-	odlink_t *q;
-
-	q = p->b;
-	assert(q != NULL);
-
-	/* Replace P with Q as the root of the subtree */
-	odict_replace_subtree(q, p);
-
-	/* Relink P under Q, B under P */
-	p->up = q;
-	p->b = q->a;
-	if (p->b != NULL)
-		p->b->up = p;
-	q->a = p;
-
-	/* Fix odict root */
-	if (p->odict->root == p)
-		p->odict->root = q;
-}
-
-/** Ordered dictionary right rotation.
- *
- *    Q           P
- *  P   C   -> A    Q
- * A B             B C
- *
- */
-static void odict_rotate_right(odlink_t *q)
-{
-	odlink_t *p;
-
-	p = q->a;
-	assert(p != NULL);
-
-	/* Replace Q with P as the root of the subtree */
-	odict_replace_subtree(p, q);
-
-	/* Relink Q under P, B under Q */
-	q->up = p;
-	q->a = p->b;
-	if (q->a != NULL)
-		q->a->up = q;
-	p->b = q;
-
-	/* Fix odict root */
-	if (q->odict->root == q)
-		q->odict->root = p;
-}
-
-/** Swap two nodes.
- *
- * Swap position of two nodes in the tree, keeping their identity.
- * This means we don't copy the contents, instead we shuffle around pointers
- * from and to the nodes.
- *
- * @param a First node
- * @param b Second node
- */
-static void odict_swap_node(odlink_t *a, odlink_t *b)
-{
-	odlink_t *n;
-	odict_color_t c;
-
-	/* Backlink from A's parent */
-	if (a->up != NULL && a->up != b) {
-		if (a->up->a == a) {
-			a->up->a = b;
-		} else {
-			assert(a->up->b == a);
-			a->up->b = b;
-		}
-	}
-
-	/* Backlink from A's left child */
-	if (a->a != NULL && a->a != b)
-		a->a->up = b;
-	/* Backling from A's right child */
-	if (a->b != NULL && a->b != b)
-		a->b->up = b;
-
-	/* Backlink from B's parent */
-	if (b->up != NULL && b->up != a) {
-		if (b->up->a == b) {
-			b->up->a = a;
-		} else {
-			assert(b->up->b == b);
-			b->up->b = a;
-		}
-	}
-
-	/* Backlink from B's left child */
-	if (b->a != NULL && b->a != a)
-		b->a->up = a;
-	/* Backling from B's right child */
-	if (b->b != NULL && b->b != a)
-		b->b->up = a;
-
-	/*
-	 * Swap links going out of A and out of B
-	 */
-	n = a->up;
-	a->up = b->up;
-	b->up = n;
-
-	n = a->a;
-	a->a = b->a;
-	b->a = n;
-
-	n = a->b;
-	a->b = b->b;
-	b->b = n;
-
-	c = a->color;
-	a->color = b->color;
-	b->color = c;
-
-	/* When A and B are adjacent, fix self-loops that might have arisen */
-	if (a->up == a)
-		a->up = b;
-	if (a->a == a)
-		a->a = b;
-	if (a->b == a)
-		a->b = b;
-	if (b->up == b)
-		b->up = a;
-	if (b->a == b)
-		b->a = a;
-	if (b->b == b)
-		b->b = a;
-
-	/* Fix odict root */
-	if (a == a->odict->root)
-		a->odict->root = b;
-	else if (b == a->odict->root)
-		a->odict->root = a;
-}
-
-/** Replace subtree.
- *
- * Replace subtree @a old with another subtree @a n. This makes the parent
- * point to the new subtree root and the up pointer of @a n to point to
- * the parent.
- *
- * @param old Subtree to be replaced
- * @param n New subtree
- */
-static void odict_replace_subtree(odlink_t *n, odlink_t *old)
-{
-	if (old->up != NULL) {
-		if (old->up->a == old) {
-			old->up->a = n;
-		} else {
-			assert(old->up->b == old);
-			old->up->b = n;
-		}
-	} else {
-		assert(old->odict->root == old);
-		old->odict->root = n;
-	}
-
-	n->up = old->up;
-}
-
-/** Unlink node.
- *
- * @param n Ordered dictionary node
- */
-static void odict_unlink(odlink_t *n)
-{
-	if (n->up != NULL) {
-		if (n->up->a == n) {
-			n->up->a = NULL;
-		} else {
-			assert(n->up->b == n);
-			n->up->b = NULL;
-		}
-
-		n->up = NULL;
-	} else {
-		assert(n->odict->root == n);
-		n->odict->root = NULL;
-	}
-
-	if (n->a != NULL) {
-		n->a->up = NULL;
-		n->a = NULL;
-	}
-
-	if (n->b != NULL) {
-		n->b->up = NULL;
-		n->b = NULL;
-	}
-
-	n->odict = NULL;
-	list_remove(&n->lentries);
-}
-
-/** Link node as left child.
- *
- * Append new node @a n as left child of existing node @a old.
- *
- * @param n New node
- * @param old Old node
- */
-static void odict_link_child_a(odlink_t *n, odlink_t *old)
-{
-	old->a = n;
-	n->up = old;
-	n->odict = old->odict;
-	list_insert_before(&n->lentries, &old->lentries);
-}
-
-/** Link node as right child.
- *
- * Append new node @a n as right child of existing node @a old.
- *
- * @param n New node
- * @param old Old node
- */
-static void odict_link_child_b(odlink_t *n, odlink_t *old)
-{
-	old->b = n;
-	n->up = old;
-	n->odict = old->odict;
-	list_insert_after(&n->lentries, &old->lentries);
-}
-
-/** Get node where search should be started.
- *
- * @param odict Ordered dictionary
- * @param key Key being searched for
- * @param hint Node that might be near the search target or @c NULL
- *
- * @return Node from where search should be started
- */
-static odlink_t *odict_search_start_node(odict_t *odict, void *key,
-    odlink_t *hint)
-{
-	odlink_t *a;
-	odlink_t *b;
-	odlink_t *cur;
-	int d, da, db;
-
-	assert(hint == NULL || hint->odict == odict);
-
-	/* If the key is greater than the maximum, start search in the maximum */
-	b = odict_last(odict);
-	if (b != NULL) {
-		d = odict->cmp(odict->getkey(b), key);
-		if (d < 0)
-			return b;
-	}
-
-	/* If the key is less tna the minimum, start search in the minimum */
-	a = odict_first(odict);
-	if (a != NULL) {
-		d = odict->cmp(key, odict->getkey(a));
-		if (d < 0)
-			return a;
-	}
-
-	/*
-	 * Proposition: Let A, B be two BST nodes such that B is a descendant
-	 * of A. Let N be a node such that either key(A) < key(N) < key(B)
-	 * Then N is a descendant of A.
-	 * Corollary: We can start searching for N from A, instead from
-	 * the root.
-	 *
-	 * Proof: When walking the BST in order, visit_tree(A) does a
-	 * visit_tree(A->a), visit(A), visit(A->b). If key(A) < key(B),
-	 * we will first visit A, then while visiting all nodes with values
-	 * between A and B we will not leave subtree A->b.
-	 */
-
-	/* If there is no hint, start search from the root */
-	if (hint == NULL)
-		return odict->root;
-
-	/*
-	 * Start from hint and walk up to the root, keeping track of
-	 * minimum and maximum. Once key is strictly between them,
-	 * we can return the current node, which we've proven to be
-	 * an ancestor of a potential node with the given key
-	 */
-	a = b = cur = hint;
-	while (cur->up != NULL) {
-		cur = cur->up;
-
-		d = odict->cmp(odict->getkey(cur), odict->getkey(a));
-		if (d < 0)
-			a = cur;
-
-		d = odict->cmp(odict->getkey(b), odict->getkey(cur));
-		if (d < 0)
-			b = cur;
-
-		da = odict->cmp(odict->getkey(a), key);
-		db = odict->cmp(key, odict->getkey(b));
-		if (da < 0 && db < 0) {
-			/* Both a and b are descendants of cur */
-			return cur;
-		}
-	}
-
-	return odict->root;
-}
-
-/** @}
- */
+../../../../../kernel/generic/src/adt/odict.c
