aboutsummaryrefslogtreecommitdiff
path: root/src/lib/map.rs
diff options
context:
space:
mode:
authorRoy Frostig <[email protected]>2010-08-03 18:43:57 -0700
committerRoy Frostig <[email protected]>2010-08-03 18:43:57 -0700
commit6277b462e938d9df8b75126244817d2e28dab80a (patch)
tree3c749931de346aabaeaeafc86a2620da6f799fc5 /src/lib/map.rs
parentAddress _vec.map allocation FIXME. Add test. (diff)
downloadrust-6277b462e938d9df8b75126244817d2e28dab80a.tar.xz
rust-6277b462e938d9df8b75126244817d2e28dab80a.zip
More stdlib hashmap work. Add a simple test and XFAIL it due to a valgrind-spotted UMR.
Diffstat (limited to 'src/lib/map.rs')
-rw-r--r--src/lib/map.rs50
1 files changed, 29 insertions, 21 deletions
diff --git a/src/lib/map.rs b/src/lib/map.rs
index 5c66b7a3..c00ee75d 100644
--- a/src/lib/map.rs
+++ b/src/lib/map.rs
@@ -10,7 +10,7 @@ import std._vec;
type hashfn[K] = fn(&K) -> uint;
-type eqfn[K] = fn(&K) -> bool;
+type eqfn[K] = fn(&K, &K) -> bool;
type hashmap[K, V] = obj {
fn insert(&K key, &V val);
@@ -46,18 +46,18 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
// is always a power of 2), so that all buckets are probed for a
// fixed key.
- fn hashl[K](hashfn[K] hasher, uint nbkts, &K key) -> uint {
+ fn hashl[K](&hashfn[K] hasher, uint nbkts, &K key) -> uint {
ret (hasher(key) >>> (sys.rustrt.size_of[uint]() * 8u / 2u))
% nbkts;
}
- fn hashr[K](hashfn[K] hasher, uint nbkts, &K key) -> uint {
+ fn hashr[K](&hashfn[K] hasher, uint nbkts, &K key) -> uint {
ret ((((~ 0u) >>> (sys.rustrt.size_of[uint]() * 8u / 2u))
& hasher(key)) * 2u + 1u)
% nbkts;
}
- fn hash[K](hashfn[K] hasher, uint nbkts, &K key, uint i) -> uint {
+ fn hash[K](&hashfn[K] hasher, uint nbkts, &K key, uint i) -> uint {
ret hashl[K](hasher, nbkts, key) + i * hashr[K](hasher, nbkts, key);
}
@@ -65,30 +65,36 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
* We attempt to never call this with a full table. If we do, it
* will fail.
*/
- fn insert_common[K, V](hashfn[K] hasher,
+ fn insert_common[K, V](&hashfn[K] hasher,
+ &eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts,
uint nbkts,
&K key,
&V val)
+ -> bool
{
let uint i = 0u;
while (i < nbkts) {
// FIXME (issue #94): as in find_common()
let int j = (hash[K](hasher, nbkts, key, i)) as int;
alt (bkts.(j)) {
- case (some[K, V](_, _)) {
+ case (some[K, V](k, _)) {
+ if (eqer(key, k)) {
+ ret false;
+ }
i += 1u;
}
case (_) {
bkts.(j) = some[K, V](key, val);
- ret;
+ ret true;
}
}
}
fail; // full table
}
- fn find_common[K, V](hashfn[K] hasher,
+ fn find_common[K, V](&hashfn[K] hasher,
+ &eqfn[K] eqer,
vec[mutable bucket[K, V]] bkts,
uint nbkts,
&K key)
@@ -99,29 +105,31 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
// FIXME (issue #94): Pending bugfix, remove uint coercion.
let int j = (hash[K](hasher, nbkts, key, i)) as int;
alt (bkts.(j)) {
- case (some[K, V](_, val)) {
- ret util.some[V](val);
+ case (some[K, V](k, v)) {
+ if (eqer(key, k)) {
+ ret util.some[V](v);
+ }
}
case (nil[K, V]()) {
ret util.none[V]();
}
- case (deleted[K, V]()) {
- i += 1u;
- }
+ case (deleted[K, V]()) { }
}
+ i += 1u;
}
ret util.none[V]();
}
- fn rehash[K, V](hashfn[K] hasher,
+ fn rehash[K, V](&hashfn[K] hasher,
+ &eqfn[K] eqer,
vec[mutable bucket[K, V]] oldbkts, uint noldbkts,
vec[mutable bucket[K, V]] newbkts, uint nnewbkts)
{
for (bucket[K, V] b in oldbkts) {
alt (b) {
case (some[K, V](k, v)) {
- insert_common[K, V](hasher, newbkts, nnewbkts, k, v);
+ insert_common[K, V](hasher, eqer, newbkts, nnewbkts, k, v);
}
case (_) { }
}
@@ -144,28 +152,28 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
check ((nnewbkts as int) > 0);
let vec[mutable bucket[K, V]] newbkts = make_buckets[K, V](nnewbkts);
- rehash[K, V](hasher, bkts, nbkts, newbkts, nnewbkts);
+ rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nnewbkts);
}
- insert_common[K, V](hasher, bkts, nbkts, key, val);
+ insert_common[K, V](hasher, eqer, bkts, nbkts, key, val);
nelts += 1u;
}
fn contains_key(&K key) -> bool {
- alt (find_common[K, V](hasher, bkts, nbkts, key)) {
+ alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (util.some[V](_)) { ret true; }
case (_) { ret false; }
}
}
fn get(&K key) -> V {
- alt (find_common[K, V](hasher, bkts, nbkts, key)) {
+ alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
case (util.some[V](val)) { ret val; }
case (_) { fail; }
}
}
fn find(&K key) -> util.option[V] {
- be find_common[K, V](hasher, bkts, nbkts, key);
+ be find_common[K, V](hasher, eqer, bkts, nbkts, key);
}
fn remove(&K key) -> util.option[V] {
@@ -191,7 +199,7 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
fn rehash() {
let vec[mutable bucket[K, V]] newbkts = make_buckets[K, V](nbkts);
- rehash[K, V](hasher, bkts, nbkts, newbkts, nbkts);
+ rehash[K, V](hasher, eqer, bkts, nbkts, newbkts, nbkts);
bkts = newbkts;
}
}