Skip to content

Commit 1cbdc79

Browse files
committed
---
yaml --- r: 6621 b: refs/heads/master c: 729345c h: refs/heads/master i: 6619: 8984cc5 v: v3
1 parent 8fd6728 commit 1cbdc79

File tree

2 files changed

+244
-3
lines changed

2 files changed

+244
-3
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 501c514e892b4d3a4b8ce1f89d4bd42b3f266ef2
2+
refs/heads/master: 729345cb97f32839bd00cb2546314865cb2a9964

trunk/src/libstd/map.rs

Lines changed: 243 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,242 @@ type hashmap<K, V> = obj {
104104

105105
/* Section: Operations */
106106

107+
mod chained {
108+
type entry<copy K, copy V> = {
109+
hash: uint,
110+
key: K,
111+
mutable value: V,
112+
mutable next: chain<K, V>
113+
};
114+
115+
tag chain<copy K, copy V> {
116+
present(@entry<K, V>);
117+
absent;
118+
}
119+
120+
type t<copy K, copy V> = {
121+
mutable size: uint,
122+
mutable chains: [mutable chain<K,V>],
123+
hasher: hashfn<K>,
124+
eqer: eqfn<K>
125+
};
126+
127+
tag search_result<copy K, copy V> {
128+
not_found(uint);
129+
found_first(uint, @entry<K,V>);
130+
found_after(@entry<K,V>, @entry<K,V>);
131+
}
132+
133+
fn search_rem<copy K, copy V>(tbl: t<K,V>,
134+
k: K,
135+
h: uint,
136+
idx: uint,
137+
e_root: @entry<K,V>) -> search_result<K,V> {
138+
let e0 = e_root;
139+
while true {
140+
alt e0.next {
141+
absent. {
142+
ret not_found(idx);
143+
}
144+
present(e1) {
145+
let e1_key = e1.key; // Satisfy alias checker.
146+
if e1.hash == h && tbl.eqer(e1_key, k) {
147+
ret found_after(e0, e1);
148+
} else {
149+
e0 = e1;
150+
}
151+
}
152+
}
153+
}
154+
util::unreachable();
155+
}
156+
157+
fn search_tbl<copy K, copy V>(
158+
tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> {
159+
160+
let idx = h % vec::len(tbl.chains);
161+
162+
alt tbl.chains[idx] {
163+
absent. {
164+
ret not_found(idx);
165+
}
166+
present(e) {
167+
let e_key = e.key; // Satisfy alias checker.
168+
if e.hash == h && tbl.eqer(e_key, k) {
169+
ret found_first(idx, e);
170+
} else {
171+
ret search_rem(tbl, k, h, idx, e);
172+
}
173+
}
174+
}
175+
}
176+
177+
fn insert_h<copy K, copy V>(tbl: t<K,V>, k: K, v: V, hash: uint) -> bool {
178+
// internal routine: does not update size
179+
alt search_tbl(tbl, k, hash) {
180+
not_found(idx) {
181+
let old_chain = tbl.chains[idx];
182+
tbl.chains[idx] = present(@{
183+
hash: hash,
184+
key: k,
185+
mutable value: v,
186+
mutable next: old_chain});
187+
ret true;
188+
}
189+
found_first(_, entry) {
190+
entry.value = v;
191+
ret false;
192+
}
193+
found_after(_, entry) {
194+
entry.value = v;
195+
ret false
196+
}
197+
}
198+
}
199+
200+
fn insert<copy K, copy V>(tbl: t<K,V>, k: K, v: V) -> bool {
201+
tbl.size += 1u;
202+
ret insert_h(tbl, k, v, tbl.hasher(k));
203+
}
204+
205+
fn get<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
206+
alt search_tbl(tbl, k, tbl.hasher(k)) {
207+
not_found(_) {
208+
ret option::none;
209+
}
210+
211+
found_first(_, entry) {
212+
ret option::some(entry.value);
213+
}
214+
215+
found_after(_, entry) {
216+
ret option::some(entry.value);
217+
}
218+
}
219+
}
220+
221+
fn remove<copy K, copy V>(tbl: t<K,V>, k: K) -> option::t<V> {
222+
alt search_tbl(tbl, k, tbl.hasher(k)) {
223+
not_found(_) {
224+
ret option::none;
225+
}
226+
227+
found_first(idx, entry) {
228+
tbl.chains[idx] = entry.next;
229+
ret option::some(entry.value);
230+
}
231+
232+
found_after(eprev, entry) {
233+
eprev.next = entry.next;
234+
ret option::some(entry.value);
235+
}
236+
}
237+
}
238+
239+
fn chains<copy K, copy V>(nchains: uint) -> [mutable chain<K,V>] {
240+
ret vec::init_elt_mut(absent, nchains);
241+
}
242+
243+
fn foreach_entry<copy K, copy V>(chain0: chain<K,V>,
244+
blk: block(@entry<K,V>)) {
245+
let chain = chain0;
246+
while true {
247+
alt chain {
248+
absent. { ret; }
249+
present(entry) {
250+
blk(entry);
251+
chain = entry.next;
252+
}
253+
}
254+
}
255+
}
256+
257+
fn foreach_chain<copy K, copy V>(chains: [const chain<K,V>],
258+
blk: block(@entry<K,V>)) {
259+
let i = 0u, n = vec::len(chains);
260+
while i < n {
261+
foreach_entry(chains[i], blk);
262+
i += 1u;
263+
}
264+
}
265+
266+
fn rehash<copy K, copy V>(tbl: t<K,V>) {
267+
let old_chains = tbl.chains;
268+
let n_old_chains = vec::len(old_chains);
269+
let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u);
270+
tbl.chains = chains(n_new_chains);
271+
foreach_chain(old_chains) { |entry|
272+
insert_h(tbl, entry.key, entry.value, entry.hash);
273+
}
274+
}
275+
276+
fn items<copy K, copy V>(tbl: t<K,V>, blk: block(K,V)) {
277+
let tbl_chains = tbl.chains; // Satisfy alias checker.
278+
foreach_chain(tbl_chains) { |entry|
279+
let key = entry.key;
280+
let value = entry.value;
281+
blk(key, value);
282+
}
283+
}
284+
285+
obj o<copy K, copy V>(tbl: @t<K,V>,
286+
lf: float) {
287+
fn size() -> uint {
288+
ret tbl.size;
289+
}
290+
291+
fn insert(k: K, v: V) -> bool {
292+
let nchains = vec::len(tbl.chains);
293+
let load = (tbl.size + 1u as float) / (nchains as float);
294+
if load > lf {
295+
rehash(*tbl);
296+
}
297+
ret insert(*tbl, k, v);
298+
}
299+
300+
fn contains_key(k: K) -> bool {
301+
ret option::is_some(get(*tbl, k));
302+
}
303+
304+
fn get(k: K) -> V {
305+
ret option::get(get(*tbl, k));
306+
}
307+
308+
fn find(k: K) -> option::t<V> {
309+
ret get(*tbl, k);
310+
}
311+
312+
fn remove(k: K) -> option::t<V> {
313+
ret remove(*tbl, k);
314+
}
315+
316+
fn rehash() {
317+
rehash(*tbl);
318+
}
319+
320+
fn items(blk: block(K, V)) {
321+
items(*tbl, blk);
322+
}
323+
324+
fn keys(blk: block(K)) {
325+
items(*tbl) { |k, _v| blk(k) }
326+
}
327+
328+
fn values(blk: block(V)) {
329+
items(*tbl) { |_k, v| blk(v) }
330+
}
331+
}
332+
333+
fn mk<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K,V> {
334+
let initial_capacity: uint = 32u; // 2^5
335+
let t = @{mutable size: 0u,
336+
mutable chains: chains(initial_capacity),
337+
hasher: hasher,
338+
eqer: eqer};
339+
ret o(t, 0.75);
340+
}
341+
}
342+
107343
/*
108344
Function: mk_hashmap
109345
@@ -114,7 +350,7 @@ Parameters:
114350
hasher - The hash function for key type K
115351
eqer - The equality function for key type K
116352
*/
117-
fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
353+
fn mk_flat_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
118354
-> hashmap<K, V> {
119355
let initial_capacity: uint = 32u; // 2^5
120356

@@ -134,7 +370,7 @@ fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
134370
// buckets before the resulting pair of hash functions no longer
135371
// probes all buckets for a fixed key. Note that hashl is made to
136372
// output odd numbers (hence coprime to the number of nbkts, which
137-
// is always a power of 2), so that all buckets are probed for a
373+
// is always a power? of 2), so that all buckets are probed for a
138374
// fixed key.
139375

140376
fn hashl(n: u32) -> u32 { ret (n >>> 16u32) * 2u32 + 1u32; }
@@ -293,6 +529,11 @@ fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
293529
ret hashmap(hasher, eqer, bkts, initial_capacity, 0u, load_factor);
294530
}
295531

532+
fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>)
533+
-> hashmap<K, V> {
534+
ret chained::mk(hasher, eqer);
535+
}
536+
296537
/*
297538
Function: new_str_hash
298539

0 commit comments

Comments
 (0)