/*
 * Elastic Binary Trees - macros and structures for Multi-Byte data nodes.
 * Version 6.0.6
 * (C) 2002-2011 - Willy Tarreau <w@1wt.eu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, version 2.1
 * exclusively.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _EBMBTREE_H
#define _EBMBTREE_H

#include <string.h>
#include "ebtree.h"

/* Return the structure of type <type> whose member <member> points to <ptr> */
#define ebmb_entry(ptr, type, member) container_of(ptr, type, member)

#define EBMB_ROOT	EB_ROOT
#define EBMB_TREE_HEAD	EB_TREE_HEAD

/* This structure carries a node, a leaf, and a key. It must start with the
 * eb_node so that it can be cast into an eb_node. We could also have put some
 * sort of transparent union here to reduce the indirection level, but the fact
 * is, the end user is not meant to manipulate internals, so this is pointless.
 * The 'node.bit' value here works differently from scalar types, as it contains
 * the number of identical bits between the two branches.
 * Note that we take a great care of making sure the key is located exactly at
 * the end of the struct even if that involves holes before it, so that it
 * always aliases any external key a user would append after. This is why the
 * key uses the same alignment as the struct.
 */
struct ebmb_node {
	struct eb_node node; /* the tree node, must be at the beginning */
	ALWAYS_ALIGN(sizeof(void*));
	unsigned char key[0]; /* the key, its size depends on the application */
} ALIGNED(sizeof(void*));

/*
 * Exported functions and macros.
 * Many of them are always inlined because they are extremely small, and
 * are generally called at most once or twice in a program.
 */

/* Return leftmost node in the tree, or NULL if none */
static forceinline struct ebmb_node *ebmb_first(struct eb_root *root)
{
	return ebmb_entry(eb_first(root), struct ebmb_node, node);
}

/* Return rightmost node in the tree, or NULL if none */
static forceinline struct ebmb_node *ebmb_last(struct eb_root *root)
{
	return ebmb_entry(eb_last(root), struct ebmb_node, node);
}

/* Return next node in the tree, or NULL if none */
static forceinline struct ebmb_node *ebmb_next(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_next(&ebmb->node), struct ebmb_node, node);
}

/* Return previous node in the tree, or NULL if none */
static forceinline struct ebmb_node *ebmb_prev(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_prev(&ebmb->node), struct ebmb_node, node);
}

/* Return next leaf node within a duplicate sub-tree, or NULL if none. */
static inline struct ebmb_node *ebmb_next_dup(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_next_dup(&ebmb->node), struct ebmb_node, node);
}

/* Return previous leaf node within a duplicate sub-tree, or NULL if none. */
static inline struct ebmb_node *ebmb_prev_dup(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_prev_dup(&ebmb->node), struct ebmb_node, node);
}

/* Return next node in the tree, skipping duplicates, or NULL if none */
static forceinline struct ebmb_node *ebmb_next_unique(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_next_unique(&ebmb->node), struct ebmb_node, node);
}

/* Return previous node in the tree, skipping duplicates, or NULL if none */
static forceinline struct ebmb_node *ebmb_prev_unique(struct ebmb_node *ebmb)
{
	return ebmb_entry(eb_prev_unique(&ebmb->node), struct ebmb_node, node);
}

/* Delete node from the tree if it was linked in. Mark the node unused. Note
 * that this function relies on a non-inlined generic function: eb_delete.
 */
static forceinline void ebmb_delete(struct ebmb_node *ebmb)
{
	eb_delete(&ebmb->node);
}

/* The following functions are not inlined by default. They are declared
 * in ebmbtree.c, which simply relies on their inline version.
 */
struct ebmb_node *ebmb_lookup(struct eb_root *root, const void *x, unsigned int len);
struct ebmb_node *ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len);
struct ebmb_node *ebmb_lookup_longest(struct eb_root *root, const void *x);
struct ebmb_node *ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx);
struct ebmb_node *ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len);

/* The following functions are less likely to be used directly, because their
 * code is larger. The non-inlined version is preferred.
 */

/* Delete node from the tree if it was linked in. Mark the node unused. */
static forceinline void __ebmb_delete(struct ebmb_node *ebmb)
{
	__eb_delete(&ebmb->node);
}

/* Find the first occurrence of a key of a least <len> bytes matching <x> in the
 * tree <root>. The caller is responsible for ensuring that <len> will not exceed
 * the common parts between the tree's keys and <x>. In case of multiple matches,
 * the leftmost node is returned. This means that this function can be used to
 * lookup string keys by prefix if all keys in the tree are zero-terminated. If
 * no match is found, NULL is returned. Returns first node if <len> is zero.
 */
static forceinline struct ebmb_node *__ebmb_lookup(struct eb_root *root, const void *x, unsigned int len)
{
	struct ebmb_node *node;
	eb_troot_t *troot;
	int pos, side;
	int node_bit;

	troot = root->b[EB_LEFT];
	if (unlikely(troot == NULL))
		goto ret_null;

	if (unlikely(len == 0))
		goto walk_down;

	pos = 0;
	while (1) {
		if (eb_gettag(troot) == EB_LEAF) {
			node = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			if (eb_memcmp(node->key + pos, x, len) != 0)
				goto ret_null;
			else
				goto ret_node;
		}
		node = container_of(eb_untag(troot, EB_NODE),
				    struct ebmb_node, node.branches);

		node_bit = node->node.bit;
		if (node_bit < 0) {
			/* We have a dup tree now. Either it's for the same
			 * value, and we walk down left, or it's a different
			 * one and we don't have our key.
			 */
			if (eb_memcmp(node->key + pos, x, len) != 0)
				goto ret_null;
			else
				goto walk_left;
		}

		/* OK, normal data node, let's walk down. We check if all full
		 * bytes are equal, and we start from the last one we did not
		 * completely check. We stop as soon as we reach the last byte,
		 * because we must decide to go left/right or abort.
		 */
		node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit)
		if (node_bit < 0) {
			/* This surprising construction gives better performance
			 * because gcc does not try to reorder the loop. Tested to
			 * be fine with 2.95 to 4.2.
			 */
			while (1) {
				if (node->key[pos++] ^ *(unsigned char*)(x++))
					goto ret_null;  /* more than one full byte is different */
				if (--len == 0)
					goto walk_left; /* return first node if all bytes matched */
				node_bit += 8;
				if (node_bit >= 0)
					break;
			}
		}

		/* here we know that only the last byte differs, so node_bit < 8.
		 * We have 2 possibilities :
		 *   - more than the last bit differs => return NULL
		 *   - walk down on side = (x[pos] >> node_bit) & 1
		 */
		side = *(unsigned char *)x >> node_bit;
		if (((node->key[pos] >> node_bit) ^ side) > 1)
			goto ret_null;
		side &= 1;
		troot = node->node.branches.b[side];
	}
 walk_left:
	troot = node->node.branches.b[EB_LEFT];
 walk_down:
	while (eb_gettag(troot) != EB_LEAF)
		troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT];
	node = container_of(eb_untag(troot, EB_LEAF),
			    struct ebmb_node, node.branches);
 ret_node:
	return node;
 ret_null:
	return NULL;
}

/* Insert ebmb_node <new> into subtree starting at node root <root>.
 * Only new->key needs be set with the key. The ebmb_node is returned.
 * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The
 * len is specified in bytes. It is absolutely mandatory that this length
 * is the same for all keys in the tree. This function cannot be used to
 * insert strings.
 */
static forceinline struct ebmb_node *
__ebmb_insert(struct eb_root *root, struct ebmb_node *new, unsigned int len)
{
	struct ebmb_node *old;
	unsigned int side;
	eb_troot_t *troot, **up_ptr;
	eb_troot_t *root_right;
	int diff;
	int bit;
	eb_troot_t *new_left, *new_rght;
	eb_troot_t *new_leaf;
	int old_node_bit;

	side = EB_LEFT;
	troot = root->b[EB_LEFT];
	root_right = root->b[EB_RGHT];
	if (unlikely(troot == NULL)) {
		/* Tree is empty, insert the leaf part below the left branch */
		root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
		new->node.leaf_p = eb_dotag(root, EB_LEFT);
		new->node.node_p = NULL; /* node part unused */
		return new;
	}

	/* The tree descent is fairly easy :
	 *  - first, check if we have reached a leaf node
	 *  - second, check if we have gone too far
	 *  - third, reiterate
	 * Everywhere, we use <new> for the node node we are inserting, <root>
	 * for the node we attach it to, and <old> for the node we are
	 * displacing below <new>. <troot> will always point to the future node
	 * (tagged with its type). <side> carries the side the node <new> is
	 * attached to below its parent, which is also where previous node
	 * was attached.
	 */

	bit = 0;
	while (1) {
		if (unlikely(eb_gettag(troot) == EB_LEAF)) {
			/* insert above a leaf */
			old = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			new->node.node_p = old->node.leaf_p;
			up_ptr = &old->node.leaf_p;
			goto check_bit_and_break;
		}

		/* OK we're walking down this link */
		old = container_of(eb_untag(troot, EB_NODE),
				   struct ebmb_node, node.branches);
		old_node_bit = old->node.bit;

		if (unlikely(old->node.bit < 0)) {
			/* We're above a duplicate tree, so we must compare the whole value */
			new->node.node_p = old->node.node_p;
			up_ptr = &old->node.node_p;
		check_bit_and_break:
			bit = equal_bits(new->key, old->key, bit, len << 3);
			break;
		}

		/* Stop going down when we don't have common bits anymore. We
		 * also stop in front of a duplicates tree because it means we
		 * have to insert above. Note: we can compare more bits than
		 * the current node's because as long as they are identical, we
		 * know we descend along the correct side.
		 */

		bit = equal_bits(new->key, old->key, bit, old_node_bit);
		if (unlikely(bit < old_node_bit)) {
			/* The tree did not contain the key, so we insert <new> before the
			 * node <old>, and set ->bit to designate the lowest bit position in
			 * <new> which applies to ->branches.b[].
			 */
			new->node.node_p = old->node.node_p;
			up_ptr = &old->node.node_p;
			break;
		}
		/* we don't want to skip bits for further comparisons, so we must limit <bit>.
		 * However, since we're going down around <old_node_bit>, we know it will be
		 * properly matched, so we can skip this bit.
		 */
		bit = old_node_bit + 1;

		/* walk down */
		root = &old->node.branches;
		side = old_node_bit & 7;
		side ^= 7;
		side = (new->key[old_node_bit >> 3] >> side) & 1;
		troot = root->b[side];
	}

	new_left = eb_dotag(&new->node.branches, EB_LEFT);
	new_rght = eb_dotag(&new->node.branches, EB_RGHT);
	new_leaf = eb_dotag(&new->node.branches, EB_LEAF);

	new->node.bit = bit;

	/* Note: we can compare more bits than the current node's because as
	 * long as they are identical, we know we descend along the correct
	 * side. However we don't want to start to compare past the end.
	 */
	diff = 0;
	if (((unsigned)bit >> 3) < len)
		diff = cmp_bits(new->key, old->key, bit);

	if (diff == 0) {
		new->node.bit = -1; /* mark as new dup tree, just in case */

		if (likely(eb_gettag(root_right))) {
			/* we refuse to duplicate this key if the tree is
			 * tagged as containing only unique keys.
			 */
			return old;
		}

		if (eb_gettag(troot) != EB_LEAF) {
			/* there was already a dup tree below */
			struct eb_node *ret;
			ret = eb_insert_dup(&old->node, &new->node);
			return container_of(ret, struct ebmb_node, node);
		}
		/* otherwise fall through */
	}

	if (diff >= 0) {
		new->node.branches.b[EB_LEFT] = troot;
		new->node.branches.b[EB_RGHT] = new_leaf;
		new->node.leaf_p = new_rght;
		*up_ptr = new_left;
	}
	else if (diff < 0) {
		new->node.branches.b[EB_LEFT] = new_leaf;
		new->node.branches.b[EB_RGHT] = troot;
		new->node.leaf_p = new_left;
		*up_ptr = new_rght;
	}

	/* Ok, now we are inserting <new> between <root> and <old>. <old>'s
	 * parent is already set to <new>, and the <root>'s branch is still in
	 * <side>. Update the root's leaf till we have it. Note that we can also
	 * find the side by checking the side of new->node.node_p.
	 */

	root->b[side] = eb_dotag(&new->node.branches, EB_NODE);
	return new;
}


/* Find the first occurrence of the longest prefix matching a key <x> in the
 * tree <root>. It's the caller's responsibility to ensure that key <x> is at
 * least as long as the keys in the tree. Note that this can be ensured by
 * having a byte at the end of <x> which cannot be part of any prefix, typically
 * the trailing zero for a string. If none can be found, return NULL.
 */
static forceinline struct ebmb_node *__ebmb_lookup_longest(struct eb_root *root, const void *x)
{
	struct ebmb_node *node;
	eb_troot_t *troot, *cover;
	int pos, side;
	int node_bit;

	troot = root->b[EB_LEFT];
	if (unlikely(troot == NULL))
		return NULL;

	cover = NULL;
	pos = 0;
	while (1) {
		if ((eb_gettag(troot) == EB_LEAF)) {
			node = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			if (check_bits(x - pos, node->key, pos, node->node.pfx))
				goto not_found;

			return node;
		}
		node = container_of(eb_untag(troot, EB_NODE),
				    struct ebmb_node, node.branches);

		node_bit = node->node.bit;
		if (node_bit < 0) {
			/* We have a dup tree now. Either it's for the same
			 * value, and we walk down left, or it's a different
			 * one and we don't have our key.
			 */
			if (check_bits(x - pos, node->key, pos, node->node.pfx))
				goto not_found;

			troot = node->node.branches.b[EB_LEFT];
			while (eb_gettag(troot) != EB_LEAF)
				troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT];
			node = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			return node;
		}

		node_bit >>= 1; /* strip cover bit */
		node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit)
		if (node_bit < 0) {
			/* This uncommon construction gives better performance
			 * because gcc does not try to reorder the loop. Tested to
			 * be fine with 2.95 to 4.2.
			 */
			while (1) {
				x++; pos++;
				if (node->key[pos-1] ^ *(unsigned char*)(x-1))
					goto not_found; /* more than one full byte is different */
				node_bit += 8;
				if (node_bit >= 0)
					break;
			}
		}

		/* here we know that only the last byte differs, so 0 <= node_bit <= 7.
		 * We have 2 possibilities :
		 *   - more than the last bit differs => data does not match
		 *   - walk down on side = (x[pos] >> node_bit) & 1
		 */
		side = *(unsigned char *)x >> node_bit;
		if (((node->key[pos] >> node_bit) ^ side) > 1)
			goto not_found;

		if (!(node->node.bit & 1)) {
			/* This is a cover node, let's keep a reference to it
			 * for later. The covering subtree is on the left, and
			 * the covered subtree is on the right, so we have to
			 * walk down right.
			 */
			cover = node->node.branches.b[EB_LEFT];
			troot = node->node.branches.b[EB_RGHT];
			continue;
		}
		side &= 1;
		troot = node->node.branches.b[side];
	}

 not_found:
	/* Walk down last cover tree if it exists. It does not matter if cover is NULL */
	return ebmb_entry(eb_walk_down(cover, EB_LEFT), struct ebmb_node, node);
}


/* Find the first occurrence of a prefix matching a key <x> of <pfx> BITS in the
 * tree <root>. It's the caller's responsibility to ensure that key <x> is at
 * least as long as the keys in the tree. Note that this can be ensured by
 * having a byte at the end of <x> which cannot be part of any prefix, typically
 * the trailing zero for a string. If none can be found, return NULL.
 */
static forceinline struct ebmb_node *__ebmb_lookup_prefix(struct eb_root *root, const void *x, unsigned int pfx)
{
	struct ebmb_node *node;
	eb_troot_t *troot;
	int pos, side;
	int node_bit;

	troot = root->b[EB_LEFT];
	if (unlikely(troot == NULL))
		return NULL;

	pos = 0;
	while (1) {
		if ((eb_gettag(troot) == EB_LEAF)) {
			node = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			if (node->node.pfx != pfx)
				return NULL;
			if (check_bits(x - pos, node->key, pos, node->node.pfx))
				return NULL;
			return node;
		}
		node = container_of(eb_untag(troot, EB_NODE),
				    struct ebmb_node, node.branches);

		node_bit = node->node.bit;
		if (node_bit < 0) {
			/* We have a dup tree now. Either it's for the same
			 * value, and we walk down left, or it's a different
			 * one and we don't have our key.
			 */
			if (node->node.pfx != pfx)
				return NULL;
			if (check_bits(x - pos, node->key, pos, node->node.pfx))
				return NULL;

			troot = node->node.branches.b[EB_LEFT];
			while (eb_gettag(troot) != EB_LEAF)
				troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT];
			node = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			return node;
		}

		node_bit >>= 1; /* strip cover bit */
		node_bit = ~node_bit + (pos << 3) + 8; // = (pos<<3) + (7 - node_bit)
		if (node_bit < 0) {
			/* This uncommon construction gives better performance
			 * because gcc does not try to reorder the loop. Tested to
			 * be fine with 2.95 to 4.2.
			 */
			while (1) {
				x++; pos++;
				if (node->key[pos-1] ^ *(unsigned char*)(x-1))
					return NULL; /* more than one full byte is different */
				node_bit += 8;
				if (node_bit >= 0)
					break;
			}
		}

		/* here we know that only the last byte differs, so 0 <= node_bit <= 7.
		 * We have 2 possibilities :
		 *   - more than the last bit differs => data does not match
		 *   - walk down on side = (x[pos] >> node_bit) & 1
		 */
		side = *(unsigned char *)x >> node_bit;
		if (((node->key[pos] >> node_bit) ^ side) > 1)
			return NULL;

		if (!(node->node.bit & 1)) {
			/* This is a cover node, it may be the entry we're
			 * looking for. We already know that it matches all the
			 * bits, let's compare prefixes and descend the cover
			 * subtree if they match.
			 */
			if ((unsigned short)node->node.bit >> 1 == pfx)
				troot = node->node.branches.b[EB_LEFT];
			else
				troot = node->node.branches.b[EB_RGHT];
			continue;
		}
		side &= 1;
		troot = node->node.branches.b[side];
	}
}


/* Insert ebmb_node <new> into a prefix subtree starting at node root <root>.
 * Only new->key and new->pfx need be set with the key and its prefix length.
 * Note that bits between <pfx> and <len> are theoretically ignored and should be
 * zero, as it is not certain yet that they will always be ignored everywhere
 * (eg in bit compare functions).
 * The ebmb_node is returned.
 * If root->b[EB_RGHT]==1, the tree may only contain unique keys. The
 * len is specified in bytes.
 */
static forceinline struct ebmb_node *
__ebmb_insert_prefix(struct eb_root *root, struct ebmb_node *new, unsigned int len)
{
	struct ebmb_node *old;
	unsigned int side;
	eb_troot_t *troot, **up_ptr;
	eb_troot_t *root_right;
	int diff;
	int bit;
	eb_troot_t *new_left, *new_rght;
	eb_troot_t *new_leaf;
	int old_node_bit;

	side = EB_LEFT;
	troot = root->b[EB_LEFT];
	root_right = root->b[EB_RGHT];
	if (unlikely(troot == NULL)) {
		/* Tree is empty, insert the leaf part below the left branch */
		root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF);
		new->node.leaf_p = eb_dotag(root, EB_LEFT);
		new->node.node_p = NULL; /* node part unused */
		return new;
	}

	len <<= 3;
	if (len > new->node.pfx)
		len = new->node.pfx;

	/* The tree descent is fairly easy :
	 *  - first, check if we have reached a leaf node
	 *  - second, check if we have gone too far
	 *  - third, reiterate
	 * Everywhere, we use <new> for the node node we are inserting, <root>
	 * for the node we attach it to, and <old> for the node we are
	 * displacing below <new>. <troot> will always point to the future node
	 * (tagged with its type). <side> carries the side the node <new> is
	 * attached to below its parent, which is also where previous node
	 * was attached.
	 */

	bit = 0;
	while (1) {
		if (unlikely(eb_gettag(troot) == EB_LEAF)) {
			/* Insert above a leaf. Note that this leaf could very
			 * well be part of a cover node.
			 */
			old = container_of(eb_untag(troot, EB_LEAF),
					    struct ebmb_node, node.branches);
			new->node.node_p = old->node.leaf_p;
			up_ptr = &old->node.leaf_p;
			goto check_bit_and_break;
		}

		/* OK we're walking down this link */
		old = container_of(eb_untag(troot, EB_NODE),
				   struct ebmb_node, node.branches);
		old_node_bit = old->node.bit;
		/* Note that old_node_bit can be :
		 *   < 0    : dup tree
		 *   = 2N   : cover node for N bits
		 *   = 2N+1 : normal node at N bits
		 */

		if (unlikely(old_node_bit < 0)) {
			/* We're above a duplicate tree, so we must compare the whole value */
			new->node.node_p = old->node.node_p;
			up_ptr = &old->node.node_p;
		check_bit_and_break:
			/* No need to compare everything if the leaves are shorter than the new one. */
			if (len > old->node.pfx)
				len = old->node.pfx;
			bit = equal_bits(new->key, old->key, bit, len);
			break;
		}

		/* WARNING: for the two blocks below, <bit> is counted in half-bits */

		bit = equal_bits(new->key, old->key, bit, old_node_bit >> 1);
		bit = (bit << 1) + 1; // assume comparisons with normal nodes

		/* we must always check that our prefix is larger than the nodes
		 * we visit, otherwise we have to stop going down. The following
		 * test is able to stop before both normal and cover nodes.
		 */
		if (bit >= (new->node.pfx << 1) && (new->node.pfx << 1) < old_node_bit) {
			/* insert cover node here on the left */
			new->node.node_p = old->node.node_p;
			up_ptr = &old->node.node_p;
			new->node.bit = new->node.pfx << 1;
			diff = -1;
			goto insert_above;
		}

		if (unlikely(bit < old_node_bit)) {
			/* The tree did not contain the key, so we insert <new> before the
			 * node <old>, and set ->bit to designate the lowest bit position in
			 * <new> which applies to ->branches.b[]. We know that the bit is not
			 * greater than the prefix length thanks to the test above.
			 */
			new->node.node_p = old->node.node_p;
			up_ptr = &old->node.node_p;
			new->node.bit = bit;
			diff = cmp_bits(new->key, old->key, bit >> 1);
			goto insert_above;
		}

		if (!(old_node_bit & 1)) {
			/* if we encounter a cover node with our exact prefix length, it's
			 * necessarily the same value, so we insert there as a duplicate on
			 * the left. For that, we go down on the left and the leaf detection
			 * code will finish the job.
			 */
			if ((new->node.pfx << 1) == old_node_bit) {
				root = &old->node.branches;
				side = EB_LEFT;
				troot = root->b[side];
				continue;
			}

			/* cover nodes are always walked through on the right */
			side = EB_RGHT;
			bit = old_node_bit >> 1; /* recheck that bit */
			root = &old->node.branches;
			troot = root->b[side];
			continue;
		}

		/* we don't want to skip bits for further comparisons, so we must limit <bit>.
		 * However, since we're going down around <old_node_bit>, we know it will be
		 * properly matched, so we can skip this bit.
		 */
		old_node_bit >>= 1;
		bit = old_node_bit + 1;

		/* walk down */
		root = &old->node.branches;
		side = old_node_bit & 7;
		side ^= 7;
		side = (new->key[old_node_bit >> 3] >> side) & 1;
		troot = root->b[side];
	}

	/* Right here, we have 4 possibilities :
	 * - the tree does not contain any leaf matching the
	 *   key, and we have new->key < old->key. We insert
	 *   new above old, on the left ;
	 *
	 * - the tree does not contain any leaf matching the
	 *   key, and we have new->key > old->key. We insert
	 *   new above old, on the right ;
	 *
	 * - the tree does contain the key with the same prefix
	 *   length. We add the new key next to it as a first
	 *   duplicate (since it was alone).
	 *
	 * The last two cases can easily be partially merged.
	 *
	 * - the tree contains a leaf matching the key, we have
	 *   to insert above it as a cover node. The leaf with
	 *   the shortest prefix becomes the left subtree and
	 *   the leaf with the longest prefix becomes the right
	 *   one. The cover node gets the min of both prefixes
	 *   as its new bit.
	 */

	/* first we want to ensure that we compare the correct bit, which means
	 * the largest common to both nodes.
	 */
	if (bit > new->node.pfx)
		bit = new->node.pfx;
	if (bit > old->node.pfx)
		bit = old->node.pfx;

	new->node.bit = (bit << 1) + 1; /* assume normal node by default */

	/* if one prefix is included in the second one, we don't compare bits
	 * because they won't necessarily match, we just proceed with a cover
	 * node insertion.
	 */
	diff = 0;
	if (bit < old->node.pfx && bit < new->node.pfx)
		diff = cmp_bits(new->key, old->key, bit);

	if (diff == 0) {
		/* Both keys match. Either it's a duplicate entry or we have to
		 * put the shortest prefix left and the largest one right below
		 * a new cover node. By default, diff==0 means we'll be inserted
		 * on the right.
		 */
		new->node.bit--; /* anticipate cover node insertion */
		if (new->node.pfx == old->node.pfx) {
			new->node.bit = -1; /* mark as new dup tree, just in case */

			if (unlikely(eb_gettag(root_right))) {
				/* we refuse to duplicate this key if the tree is
				 * tagged as containing only unique keys.
				 */
				return old;
			}

			if (eb_gettag(troot) != EB_LEAF) {
				/* there was already a dup tree below */
				struct eb_node *ret;
				ret = eb_insert_dup(&old->node, &new->node);
				return container_of(ret, struct ebmb_node, node);
			}
			/* otherwise fall through to insert first duplicate */
		}
		/* otherwise we just rely on the tests below to select the right side */
		else if (new->node.pfx < old->node.pfx)
			diff = -1; /* force insertion to left side */
	}

 insert_above:
	new_left = eb_dotag(&new->node.branches, EB_LEFT);
	new_rght = eb_dotag(&new->node.branches, EB_RGHT);
	new_leaf = eb_dotag(&new->node.branches, EB_LEAF);

	if (diff >= 0) {
		new->node.branches.b[EB_LEFT] = troot;
		new->node.branches.b[EB_RGHT] = new_leaf;
		new->node.leaf_p = new_rght;
		*up_ptr = new_left;
	}
	else {
		new->node.branches.b[EB_LEFT] = new_leaf;
		new->node.branches.b[EB_RGHT] = troot;
		new->node.leaf_p = new_left;
		*up_ptr = new_rght;
	}

	root->b[side] = eb_dotag(&new->node.branches, EB_NODE);
	return new;
}



#endif /* _EBMBTREE_H */

