diff options
| author | Roy Frostig <[email protected]> | 2010-08-03 18:43:57 -0700 |
|---|---|---|
| committer | Roy Frostig <[email protected]> | 2010-08-03 18:43:57 -0700 |
| commit | 6277b462e938d9df8b75126244817d2e28dab80a (patch) | |
| tree | 3c749931de346aabaeaeafc86a2620da6f799fc5 /src/lib | |
| parent | Address _vec.map allocation FIXME. Add test. (diff) | |
| download | rust-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')
| -rw-r--r-- | src/lib/map.rs | 50 |
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; } } |