@@ -69,6 +69,8 @@ iface map<K: copy, V: copy> {
69
69
// FIXME: package this up and export it as a datatype usable for
70
70
// external code that doesn't want to pay the cost of a box. (#2344)
71
71
mod chained {
72
+ export t, mk, hashmap;
73
+
72
74
type entry < K , V > = {
73
75
hash : uint ,
74
76
key : K ,
@@ -94,186 +96,172 @@ mod chained {
94
96
found_after( @entry < K , V > , @entry < K , V > )
95
97
}
96
98
97
- fn search_rem < K : copy , V : copy > (
98
- tbl : t < K , V > , k : K , h : uint , idx : uint ,
99
- e_root : @entry < K , V > ) -> search_result < K , V > {
100
- let mut e0 = e_root;
101
- let mut comp = 1 u; // for logging
102
- loop {
103
- alt e0. next {
99
+ impl private_methods < K : copy , V : copy > for t < K , V > {
100
+ fn search_rem ( k : K , h : uint , idx : uint ,
101
+ e_root : @entry < K , V > ) -> search_result < K , V > {
102
+ let mut e0 = e_root;
103
+ let mut comp = 1 u; // for logging
104
+ loop {
105
+ alt e0. next {
106
+ absent {
107
+ #debug( "search_tbl: absent, comp %u, hash %u, idx %u" ,
108
+ comp, h, idx) ;
109
+ ret not_found;
110
+ }
111
+ present ( e1) {
112
+ comp += 1 u;
113
+ let e1_key = e1. key ; // Satisfy alias checker.
114
+ if e1. hash == h && self . eqer ( e1_key, k) {
115
+ #debug ( "search_tbl: present, comp %u, \
116
+ hash %u, idx %u",
117
+ comp, h, idx) ;
118
+ ret found_after ( e0, e1) ;
119
+ } else {
120
+ e0 = e1;
121
+ }
122
+ }
123
+ }
124
+ } ;
125
+ }
126
+
127
+ fn search_tbl ( k : K , h : uint ) -> search_result < K , V > {
128
+ let idx = h % vec:: len ( self . chains ) ;
129
+ alt self. chains [ idx] {
104
130
absent {
105
131
#debug( "search_tbl: absent, comp %u, hash %u, idx %u" ,
106
- comp , h, idx) ;
132
+ 0 u , h, idx) ;
107
133
ret not_found;
108
134
}
109
- present ( e1) {
110
- comp += 1 u;
111
- let e1_key = e1. key ; // Satisfy alias checker.
112
- if e1. hash == h && tbl. eqer ( e1_key, k) {
135
+ present ( e) {
136
+ // FIXME: This copy of the key is not good for perf
137
+ if e. hash == h && self . eqer ( copy e. key , k) {
113
138
#debug ( "search_tbl: present, comp %u, hash %u, idx %u" ,
114
- comp , h, idx) ;
115
- ret found_after ( e0 , e1 ) ;
139
+ 1 u , h, idx) ;
140
+ ret found_first ( idx , e ) ;
116
141
} else {
117
- e0 = e1 ;
142
+ ret self . search_rem ( k , h , idx , e ) ;
118
143
}
119
144
}
120
145
}
121
- } ;
122
- }
123
-
124
- fn search_tbl < K : copy , V : copy > (
125
- tbl : t < K , V > , k : K , h : uint ) -> search_result < K , V > {
126
- let idx = h % vec:: len ( tbl. chains ) ;
127
- alt tbl. chains [ idx] {
128
- absent {
129
- #debug( "search_tbl: absent, comp %u, hash %u, idx %u" ,
130
- 0 u, h, idx) ;
131
- ret not_found;
132
- }
133
- present ( e) {
134
- // FIXME: This copy of the key is not good for perf
135
- if e. hash == h && tbl. eqer ( copy e. key , k) {
136
- #debug ( "search_tbl: present, comp %u, hash %u, idx %u" ,
137
- 1 u, h, idx) ;
138
- ret found_first ( idx, e) ;
139
- } else {
140
- ret search_rem ( tbl, k, h, idx, e) ;
141
- }
142
- }
143
146
}
144
- }
145
147
146
- fn insert < K : copy , V : copy > ( tbl : t < K , V > , k : K , v : V ) -> bool {
147
- let hash = tbl. hasher ( k) ;
148
- alt search_tbl( tbl, k, hash) {
149
- not_found {
150
- tbl. count += 1 u;
151
- let idx = hash % vec:: len ( tbl. chains ) ;
152
- let old_chain = tbl. chains [ idx] ;
153
- tbl. chains [ idx] = present ( @{
154
- hash: hash,
155
- key: k,
156
- mut value: v,
157
- mut next: old_chain} ) ;
158
- ret true;
159
- }
160
- found_first ( _, entry) {
161
- entry. value = v;
162
- ret false;
163
- }
164
- found_after ( _, entry) {
165
- entry. value = v;
166
- ret false
167
- }
168
- }
169
- }
170
-
171
- fn get < K : copy , V : copy > ( tbl : t < K , V > , k : K ) -> core:: option < V > {
172
- alt search_tbl ( tbl, k, tbl. hasher ( k) ) {
173
- not_found {
174
- ret core:: option:: none;
175
- }
176
-
177
- found_first ( _, entry) {
178
- ret core:: option:: some ( entry. value ) ;
179
- }
180
-
181
- found_after ( _, entry) {
182
- ret core:: option:: some ( entry. value ) ;
183
- }
184
- }
185
- }
186
-
187
- fn remove < K : copy , V : copy > ( tbl : t < K , V > , k : K ) -> core:: option < V > {
188
- alt search_tbl ( tbl, k, tbl. hasher ( k) ) {
189
- not_found {
190
- ret core:: option:: none;
191
- }
192
-
193
- found_first ( idx, entry) {
194
- tbl. count -= 1 u;
195
- tbl. chains [ idx] = entry. next ;
196
- ret core:: option:: some ( entry. value ) ;
197
- }
198
-
199
- found_after ( eprev, entry) {
200
- tbl. count -= 1 u;
201
- eprev. next = entry. next ;
202
- ret core:: option:: some ( entry. value ) ;
203
- }
148
+ fn rehash ( ) {
149
+ let n_old_chains = vec:: len ( self . chains ) ;
150
+ let n_new_chains: uint = uint:: next_power_of_two ( n_old_chains+1 u) ;
151
+ let new_chains = chains ( n_new_chains) ;
152
+ for self . each_entry { |entry|
153
+ let idx = entry. hash % n_new_chains;
154
+ entry. next = new_chains[ idx] ;
155
+ new_chains[ idx] = present ( entry) ;
156
+ }
157
+ self . chains = new_chains;
204
158
}
205
- }
206
-
207
- fn chains < K : copy , V : copy > ( nchains : uint ) -> [ mut chain < K , V > ] {
208
- ret vec:: to_mut ( vec:: from_elem ( nchains, absent) ) ;
209
- }
210
159
211
- fn each_entry < K : copy , V : copy > ( tbl : t < K , V > ,
212
- blk : fn ( @ entry < K , V > ) -> bool ) {
213
- let mut i = 0 u , n = vec :: len ( tbl . chains ) ;
214
- while i < n {
215
- let mut chain = tbl . chains [ i ] ;
216
- loop {
217
- chain = alt chain {
218
- absent { break ; }
219
- present ( entry ) {
220
- let next = entry. next ;
221
- if ! blk ( entry ) { ret ; }
222
- next
223
- }
160
+ fn each_entry ( blk : fn ( @ entry < K , V > ) -> bool ) {
161
+ let mut i = 0 u , n = vec :: len ( self . chains ) ;
162
+ while i < n {
163
+ let mut chain = self . chains [ i ] ;
164
+ loop {
165
+ chain = alt chain {
166
+ absent { break ; }
167
+ present ( entry ) {
168
+ let next = entry . next ;
169
+ if ! blk ( entry) { ret ; }
170
+ next
171
+ }
172
+ }
224
173
}
174
+ i += 1 u;
225
175
}
226
- i += 1 u;
227
- }
228
- }
229
-
230
- fn rehash<K : copy, V : copy>( tbl: t<K , V >) {
231
- let n_old_chains = vec:: len ( tbl. chains ) ;
232
- let n_new_chains: uint = uint:: next_power_of_two ( n_old_chains + 1 u) ;
233
- let new_chains = chains ( n_new_chains) ;
234
- for each_entry( tbl) { |entry|
235
- let idx = entry. hash % n_new_chains;
236
- entry. next = new_chains[ idx] ;
237
- new_chains[ idx] = present ( entry) ;
238
- }
239
- tbl. chains = new_chains;
240
- }
241
-
242
- fn each < K : copy , V : copy > ( tbl : t < K , V > , blk : fn ( K , V ) -> bool ) {
243
- for each_entry( tbl) { |entry|
244
- if !blk ( copy entry. key , copy entry. value ) { break ; }
245
176
}
246
177
}
247
178
248
179
impl hashmap<K : copy, V : copy> of map<K , V > for t < K , V > {
249
180
fn size ( ) -> uint { self . count }
250
181
182
+ fn contains_key ( k : K ) -> bool {
183
+ let hash = self . hasher ( k) ;
184
+ alt self. search_tbl ( k, hash) {
185
+ not_found { false}
186
+ found_first ( * ) | found_after ( * ) { true }
187
+ }
188
+ }
189
+
251
190
fn insert ( k : K , v : V ) -> bool {
252
- let grew = insert ( self , k, v) ;
253
- if grew {
191
+ let hash = self . hasher ( k) ;
192
+ alt self. search_tbl ( k, hash) {
193
+ not_found {
194
+ self. count += 1 u;
195
+ let idx = hash % vec:: len ( self . chains ) ;
196
+ let old_chain = self . chains [ idx] ;
197
+ self . chains [ idx] = present ( @{
198
+ hash: hash,
199
+ key: k,
200
+ mut value: v,
201
+ mut next: old_chain} ) ;
202
+
203
+ // consider rehashing if more 3/4 full
254
204
let nchains = vec:: len ( self . chains ) ;
255
205
let load = { num : ( self . count + 1 u) as int ,
256
206
den: nchains as int } ;
257
- // Structural consts would be nice. This is a const 3/4
258
- // load factor that we compare against.
259
- if !util:: rational_leq ( load, { num: 3 , den: 4 } ) { rehash ( self ) ; }
207
+ if !util:: rational_leq ( load, { num: 3 , den: 4 } ) {
208
+ self . rehash ( ) ;
209
+ }
210
+
211
+ ret true;
212
+ }
213
+ found_first ( _, entry) {
214
+ entry. value = v;
215
+ ret false;
216
+ }
217
+ found_after ( _, entry) {
218
+ entry. value = v;
219
+ ret false
220
+ }
260
221
}
261
- grew
262
222
}
263
223
264
- fn contains_key ( k : K ) -> bool { option:: is_some ( get ( self , k) ) }
224
+ fn find ( k : K ) -> option < V > {
225
+ alt self . search_tbl ( k, self . hasher ( k) ) {
226
+ not_found { none}
227
+ found_first ( _, entry) { some ( entry. value ) }
228
+ found_after ( _, entry) { some ( entry. value ) }
229
+ }
230
+ }
265
231
266
- fn get ( k : K ) -> V { option:: get ( get ( self , k) ) }
232
+ fn get ( k : K ) -> V {
233
+ option:: get ( self . find ( k) )
234
+ }
267
235
268
- fn find ( k : K ) -> option < V > { get ( self , k) }
236
+ fn remove ( k : K ) -> option < V > {
237
+ alt self . search_tbl ( k, self . hasher ( k) ) {
238
+ not_found { none}
239
+ found_first ( idx, entry) {
240
+ self . count -= 1 u;
241
+ self . chains [ idx] = entry. next ;
242
+ some ( entry. value )
243
+ }
244
+ found_after ( eprev, entry) {
245
+ self . count -= 1 u;
246
+ eprev. next = entry. next ;
247
+ some ( entry. value )
248
+ }
249
+ }
250
+ }
269
251
270
- fn remove ( k : K ) -> option < V > { remove ( self , k) }
252
+ fn each ( blk : fn ( K , V ) -> bool ) {
253
+ for self . each_entry { |entry|
254
+ if ! blk( copy entry. key, copy entry. value) { break ; }
255
+ }
256
+ }
271
257
272
- fn each ( blk : fn ( K , V ) -> bool ) { each ( self , blk) ; }
258
+ fn each_key ( blk : fn ( K ) -> bool ) { self . each { |k , _v| blk ( k ) } }
273
259
274
- fn each_key ( blk : fn ( K ) -> bool ) { each ( self ) { |k, _v| blk ( k) } }
260
+ fn each_value ( blk : fn ( V ) -> bool ) { self . each { |_k, v| blk ( v) } }
261
+ }
275
262
276
- fn each_value ( blk : fn ( V ) -> bool ) { each ( self ) { |_k, v| blk ( v) } }
263
+ fn chains < K , V > ( nchains : uint ) -> [ mut chain < K , V > ] {
264
+ ret vec:: to_mut ( vec:: from_elem ( nchains, absent) ) ;
277
265
}
278
266
279
267
fn mk < K : copy , V : copy > ( hasher : hashfn < K > , eqer : eqfn < K > ) -> t < K , V > {
0 commit comments