// Renamed from Map to Tree to avoid conflict with libmach.

/*
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
	Massachusetts Institute of Technology
Portions Copyright (c) 2009 The Go Authors. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

// Mutable map structure, but still based on
// Okasaki, Red Black Trees in a Functional Setting, JFP 1999,
// which is a lot easier than the traditional red-black
// and plenty fast enough for me.  (Also I could copy
// and edit fmap.c.)

#include <u.h>
#include <libc.h>
#include "tree.h"

enum
{
	Red = 0,
	Black = 1
};


// Red-black trees are binary trees with this property:
//	1. No red node has a red parent.
//	2. Every path from the root to a leaf contains the
//		same number of black nodes.

static TreeNode*
rwTreeNode(TreeNode *p, int color, TreeNode *left, void *key, void *value, TreeNode *right)
{
	if(p == nil)
		p = malloc(sizeof *p);
	p->color = color;
	p->left = left;
	p->key = key;
	p->value = value;
	p->right = right;
	return p;
}

static TreeNode*
balance(TreeNode *m0)
{
	void *xk, *xv, *yk, *yv, *zk, *zv;
	TreeNode *a, *b, *c, *d;
	TreeNode *m1, *m2;
	int color;
	TreeNode *left, *right;
	void *key, *value;

	color = m0->color;
	left = m0->left;
	key = m0->key;
	value = m0->value;
	right = m0->right;

	// Okasaki notation: (T is mkTreeNode, B is Black, R is Red, x, y, z are key-value.
	//
	// balance B (T R (T R a x b) y c) z d
	// balance B (T R a x (T R b y c)) z d
	// balance B a x (T R (T R b y c) z d)
	// balance B a x (T R b y (T R c z d))
	//
	//     = T R (T B a x b) y (T B c z d)

	if(color == Black){
		if(left && left->color == Red){
			if(left->left && left->left->color == Red){
				a = left->left->left;
				xk = left->left->key;
				xv = left->left->value;
				b = left->left->right;
				yk = left->key;
				yv = left->value;
				c = left->right;
				zk = key;
				zv = value;
				d = right;
				m1 = left;
				m2 = left->left;
				goto hard;
			}else if(left->right && left->right->color == Red){
				a = left->left;
				xk = left->key;
				xv = left->value;
				b = left->right->left;
				yk = left->right->key;
				yv = left->right->value;
				c = left->right->right;
				zk = key;
				zv = value;
				d = right;
				m1 = left;
				m2 = left->right;
				goto hard;
			}
		}else if(right && right->color == Red){
			if(right->left && right->left->color == Red){
				a = left;
				xk = key;
				xv = value;
				b = right->left->left;
				yk = right->left->key;
				yv = right->left->value;
				c = right->left->right;
				zk = right->key;
				zv = right->value;
				d = right->right;
				m1 = right;
				m2 = right->left;
				goto hard;
			}else if(right->right && right->right->color == Red){
				a = left;
				xk = key;
				xv = value;
				b = right->left;
				yk = right->key;
				yv = right->value;
				c = right->right->left;
				zk = right->right->key;
				zv = right->right->value;
				d = right->right->right;
				m1 = right;
				m2 = right->right;
				goto hard;
			}
		}
	}
	return rwTreeNode(m0, color, left, key, value, right);

hard:
	return rwTreeNode(m0, Red, rwTreeNode(m1, Black, a, xk, xv, b),
		yk, yv, rwTreeNode(m2, Black, c, zk, zv, d));
}

static TreeNode*
ins0(TreeNode *p, void *k, void *v, TreeNode *rw)
{
	if(p == nil)
		return rwTreeNode(rw, Red, nil, k, v, nil);
	if(p->key == k){
		if(rw)
			return rwTreeNode(rw, p->color, p->left, k, v, p->right);
		p->value = v;
		return p;
	}
	if(p->key < k)
		p->left = ins0(p->left, k, v, rw);
	else
		p->right = ins0(p->right, k, v, rw);
	return balance(p);
}

static TreeNode*
ins1(Tree *m, TreeNode *p, void *k, void *v, TreeNode *rw)
{
	int i;

	if(p == nil)
		return rwTreeNode(rw, Red, nil, k, v, nil);
	i = m->cmp(p->key, k);
	if(i == 0){
		if(rw)
			return rwTreeNode(rw, p->color, p->left, k, v, p->right);
		p->value = v;
		return p;
	}
	if(i < 0)
		p->left = ins1(m, p->left, k, v, rw);
	else
		p->right = ins1(m, p->right, k, v, rw);
	return balance(p);
}

void
treeputelem(Tree *m, void *key, void *val, TreeNode *rw)
{
	if(m->cmp)
		m->root = ins1(m, m->root, key, val, rw);
	else
		m->root = ins0(m->root, key, val, rw);
}

void
treeput(Tree *m, void *key, void *val)
{
	treeputelem(m, key, val, nil);
}

void*
treeget(Tree *m, void *key)
{
	int i;
	TreeNode *p;

	p = m->root;
	if(m->cmp){
		for(;;){
			if(p == nil)
				return nil;
			i = m->cmp(p->key, key);
			if(i < 0)
				p = p->left;
			else if(i > 0)
				p = p->right;
			else
				return p->value;
		}
	}else{
		for(;;){
			if(p == nil)
				return nil;
			if(p->key == key)
				return p->value;
			if(p->key < key)
				p = p->left;
			else
				p = p->right;
		}
	}
}
