shithub: mc

Download patch

ref: 8c37b110a65ac1365ac9d0ae600a5cd368c11c34
parent: f263a4c9f2a8e254bacecfb2c5f48535c24e2c0e
author: Ori Bernstein <[email protected]>
date: Fri Dec 20 09:10:11 EST 2013

Fix hash table implementation.

--- a/libstd/htab.myr
+++ b/libstd/htab.myr
@@ -1,6 +1,8 @@
 use "alloc.use"
 use "option.use"
 use "types.use"
+use "extremum.use"
+use "fmt.use"
 
 pkg std =
 	type htab(@k, @v) = struct
@@ -23,7 +25,7 @@
 	/* FIXME: Automatically pull out internal declarations as hidden */
 	const Initsz = 32
 	generic hash
-	generic grow
+	generic resize
 	generic idx
 ;;
 
@@ -38,7 +40,7 @@
 	;;
 }
 
-generic grow = {ht
+generic resize = {ht
 	var oldk
 	var oldv
 	var oldh
@@ -50,7 +52,11 @@
 	oldv = ht.vals
 	oldh = ht.hashes
 	oldd = ht.dead
-	sz = 2*ht.keys.len
+	sz = 2*max(ht.keys.len, 1)
+	ht.keys = slalloc(sz)
+	ht.vals = slalloc(sz)
+	ht.hashes = slzalloc(sz)
+	ht.dead = slzalloc(sz)
 
 	ht.nelt = 0
 	for i = 0; i < ht.keys.len; i++
@@ -98,8 +104,8 @@
 	ht.nelt = 0
 	ht.keys = slalloc(Initsz)
 	ht.vals = slalloc(Initsz)
-	ht.hashes = slalloc(Initsz)
-	ht.dead = slalloc(Initsz)
+	ht.hashes = slzalloc(Initsz)
+	ht.dead = slzalloc(Initsz)
 	-> ht
 }
 
@@ -137,7 +143,7 @@
 	ht.dead[i] = false
 	ht.nelt++
 	if ht.keys.len < ht.nelt * 2
-		grow(ht)
+		resize(ht)
 	;;
 }
 
@@ -146,6 +152,10 @@
 	| `Some i:
 		ht.dead[i] = true
 		ht.nelt--
+		/* remove tombstones if we shrink enough */
+		if ht.keys.len > ht.nelt * 4
+			resize(ht)
+		;;
 	| _:	
 		/* do nothing */
 	;;
@@ -171,6 +181,7 @@
 	var j
 
 	keys = slalloc(ht.nelt)
+	j = 0
 	for i = 0; i < ht.keys.len; i++
 		if ht.hashes[i] != 0 && !ht.dead[i]
 			keys[j++] = ht.keys[i]