shithub: riscv

Download patch

ref: 9cf519814591413493be10cfaa00853cb15e7a0b
parent: f2b7f24e4e14099251dd0ed8e7e13d7ca466b0cf
author: spew <devnull@localhost>
date: Sat Apr 22 09:59:37 EDT 2017

libavl: lookup can return the closest match

--- a/sys/include/avl.h
+++ b/sys/include/avl.h
@@ -15,8 +15,9 @@
 	Avl *root;
 };
 
-Avltree *avlcreate(int(*cmp)(Avl*, Avl*));
-Avl *avllookup(Avltree*, Avl*);
+Avltree *avlinit(Avltree*, int(*)(Avl*, Avl*));
+Avltree *avlcreate(int(*)(Avl*, Avl*));
+Avl *avllookup(Avltree*, Avl*, int);
 Avl *avldelete(Avltree*, Avl*);
 Avl *avlinsert(Avltree*, Avl*);
 Avl *avlnext(Avl*);
--- a/sys/man/2/avl
+++ b/sys/man/2/avl
@@ -30,7 +30,7 @@
 Avltree *avlcreate(int(*cmp)(Avl*, Avl*));
 Avl     *avlinsert(Avltree *tree, Avl *new);
 Avl     *avldelete(Avltree *tree, Avl *key);
-Avl     *avllookup(Avltree *tree, Avl *key);
+Avl     *avllookup(Avltree *tree, Avl *key, int dir);
 Avl     *avlnext(Avl *n);
 Avl     *avlprev(Avl *n);
 
@@ -55,13 +55,15 @@
 node with the same key that has been removed
 from the tree and may be freed.
 .I Avllookup
-returns the
-node that matches the key or
-.B nil
-if no node matches.
+searches for a given key and returns
+the closest node less than the given key, 
+.BR nil ,
+or the closest node greater than the key depending on whether
+.I dir
+is less than, equal to, or greater than zero, respectively.
 .I Avldelete
 removes the node matching the key from the tree and returns
-it. It returns nil of no matching key is found.
+it. It returns nil if no matching key is found.
 .PP
 .I Avlnext
 returns the next 
--- a/sys/src/cmd/upas/fs/mtree.c
+++ b/sys/src/cmd/upas/fs/mtree.c
@@ -22,7 +22,7 @@
 		return 0;
 	memset(&t, 0, sizeof t);
 	t.m = m;
-	if(avllookup(mb->mtree, &t))
+	if(avllookup(mb->mtree, &t, 0))
 		return 1;
 	return 0;
 }
@@ -36,7 +36,7 @@
 	m0.digest = digest;
 	memset(&t, 0, sizeof t);
 	t.m = &m0;
-	if(p = (Mtree*)avllookup(mb->mtree, &t))
+	if(p = (Mtree*)avllookup(mb->mtree, &t, 0))
 		return p->m;
 	return nil;
 }
@@ -65,7 +65,7 @@
 	if(m->deleted & ~Deleted){
 		if(m->digest == nil)
 			return;
-		p = (Mtree*)avllookup(mb->mtree, &t);
+		p = (Mtree*)avllookup(mb->mtree, &t, 0);
 		if(p == nil || p->m != m)
 			return;
 		p = (Mtree*)avldelete(mb->mtree, &t);
--- a/sys/src/cmd/upas/imap4d/fstree.c
+++ b/sys/src/cmd/upas/imap4d/fstree.c
@@ -25,7 +25,7 @@
 	memset(&t, 0, sizeof t);
 	m0.id = id;
 	t.m = &m0;
-	if(p = (Fstree*)avllookup(mb->fstree, &t))
+	if(p = (Fstree*)avllookup(mb->fstree, &t, 0))
 		return p->m;
 	return nil;
 }
--- a/sys/src/cmd/upas/imap4d/imp.c
+++ b/sys/src/cmd/upas/imap4d/imp.c
@@ -100,7 +100,7 @@
 		memset(&t, 0, sizeof t);
 		m0.info[Idigest] = f[0];
 		t.m = &m0;
-		p = (Mtree*)avllookup(mtree, &t);
+		p = (Mtree*)avllookup(mtree, &t, 0);
 		if(p){
 			m = p->m;
 			if(m->uid && m->uid != u){
--- a/sys/src/cmd/venti/copy.c
+++ b/sys/src/cmd/venti/copy.c
@@ -51,7 +51,7 @@
 		return 0;
 	memmove(a.score, score, VtScoreSize);
 	a.type = type;
-	return avllookup(scoretree, &a) != nil;
+	return avllookup(scoretree, &a, 0) != nil;
 }
 
 static void
--- a/sys/src/games/galaxy/simulate.c
+++ b/sys/src/games/galaxy/simulate.c
@@ -6,9 +6,9 @@
 
 int extraproc = -1, throttle;
 
-static QLock* golock;
-static Rendez* gorend;
-static int* go;
+static QLock *golock;
+static Rendez *gorend;
+static int *go;
 
 static QLock runninglock;
 static Rendez runningrend;
--- a/sys/src/games/mix/mix.c
+++ b/sys/src/games/mix/mix.c
@@ -413,7 +413,7 @@
 	Sym *s, l;
 
 	l.name = name;
-	s = (Sym*)avllookup(syms, &l);
+	s = (Sym*)avllookup(syms, &l, 0);
 	if(s != nil)
 		return s;
 
--- a/sys/src/libavl/avl.c
+++ b/sys/src/libavl/avl.c
@@ -4,10 +4,6 @@
 
 /* See Knuth Volume 3, 6.2.3 */
 
-Avl *avllookup(Avltree*, Avl*);
-Avl *avldelete(Avltree*, Avl*);
-Avl *avlinsert(Avltree*, Avl*);
-
 Avltree*
 avlcreate(int (*cmp)(Avl*, Avl*))
 {
@@ -16,7 +12,12 @@
 	t = malloc(sizeof(*t));
 	if(t == nil)
 		return nil;
+	return avlinit(t, cmp);
+}
 
+Avltree*
+avlinit(Avltree *t, int (*cmp)(Avl*, Avl*))
+{
 	t->cmp = cmp;
 	t->root = nil;
 	return t;
@@ -23,25 +24,30 @@
 }
 
 Avl*
-avllookup(Avltree *t, Avl *k)
+avllookup(Avltree *t, Avl *k, int d)
 {
-	Avl *h;
+	Avl *h, *n;
 	int c;
 
+	n = nil;
 	h = t->root;
 	while(h != nil){
 		c = (t->cmp)(k, h);
 		if(c < 0){
+			if(d > 0)
+				n = h;
 			h = h->c[0];
 			continue;
 		}
 		if(c > 0){
+			if(d < 0)
+				n = h;
 			h = h->c[1];
 			continue;
 		}
 		return h;
 	}
-	return nil;
+	return n;
 }
 
 static int insert(int (*)(Avl*, Avl*), Avl*, Avl**, Avl*, Avl**);