@@ -108,19 +108,17 @@ pub mod linear {
108
108
}
109
109
110
110
#[ inline( always) ]
111
- pure fn bucket_for_key ( & self , buckets : & [ Option < Bucket < K , V > > ] ,
112
- k : & K ) -> SearchResult {
111
+ pure fn bucket_for_key ( & self , k : & K ) -> SearchResult {
113
112
let hash = k. hash_keyed ( self . k0 , self . k1 ) as uint ;
114
- self . bucket_for_key_with_hash ( buckets , hash, k)
113
+ self . bucket_for_key_with_hash ( hash, k)
115
114
}
116
115
117
116
#[ inline( always) ]
118
117
pure fn bucket_for_key_with_hash ( & self ,
119
- buckets : & [ Option < Bucket < K , V > > ] ,
120
118
hash : uint ,
121
119
k : & K ) -> SearchResult {
122
120
let _ = for self . bucket_sequence( hash) |i| {
123
- match buckets[ i] {
121
+ match self . buckets [ i] {
124
122
Some ( ref bkt) => if bkt. hash == hash && * k == bkt. key {
125
123
return FoundEntry ( i) ;
126
124
} ,
@@ -157,11 +155,19 @@ pub mod linear {
157
155
}
158
156
}
159
157
158
+ #[ inline( always) ]
159
+ pure fn value_for_bucket ( & self , idx : uint ) -> & self /V {
160
+ match self . buckets [ idx] {
161
+ Some ( ref bkt) => & bkt. value ,
162
+ None => die ! ( ~"LinearMap :: find: internal logic error"),
163
+ }
164
+ }
165
+
160
166
/// Inserts the key value pair into the buckets.
161
167
/// Assumes that there will be a bucket.
162
168
/// True if there was no previous entry with that key
163
169
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> bool {
164
- match self . bucket_for_key_with_hash ( self . buckets , hash, & k) {
170
+ match self.bucket_for_key_with_hash(hash, &k) {
165
171
TableFull => { die!(~" Internal logic error"); }
166
172
FoundHole(idx) => {
167
173
debug!(" insert fresh ( %?->%?) at idx %?, hash %?",
@@ -196,8 +202,7 @@ pub mod linear {
196
202
//
197
203
// I found this explanation elucidating:
198
204
// http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf
199
- let mut idx = match self.bucket_for_key_with_hash(self.buckets,
200
- hash, k) {
205
+ let mut idx = match self.bucket_for_key_with_hash(hash, k) {
201
206
TableFull | FoundHole(_) => return None,
202
207
FoundEntry(idx) => idx
203
208
};
@@ -273,7 +278,7 @@ pub mod linear {
273
278
impl <K: Hash IterBytes Eq, V> LinearMap<K, V>: Map<K, V> {
274
279
/// Return true if the map contains a value for the specified key
275
280
pure fn contains_key(&self, k: &K) -> bool {
276
- match self.bucket_for_key(self.buckets, k) {
281
+ match self.bucket_for_key(k) {
277
282
FoundEntry(_) => {true}
278
283
TableFull | FoundHole(_) => {false}
279
284
}
@@ -291,20 +296,9 @@ pub mod linear {
291
296
292
297
/// Return the value corresponding to the key in the map
293
298
pure fn find(&self, k: &K) -> Option<&self/V> {
294
- match self.bucket_for_key(self.buckets, k) {
295
- FoundEntry(idx) => {
296
- match self.buckets[idx] {
297
- Some(ref bkt) => {
298
- Some(&bkt.value)
299
- }
300
- None => {
301
- die!(~" LinearMap :: find: internal logic error")
302
- }
303
- }
304
- }
305
- TableFull | FoundHole(_) => {
306
- None
307
- }
299
+ match self.bucket_for_key(k) {
300
+ FoundEntry(idx) => Some(self.value_for_bucket(idx)),
301
+ TableFull | FoundHole(_) => None,
308
302
}
309
303
}
310
304
@@ -364,6 +358,63 @@ pub mod linear {
364
358
old_value
365
359
}
366
360
361
+ /// Return the value corresponding to the key in the map, or insert
362
+ /// and return the value if it doesn't exist.
363
+ fn find_or_insert(&mut self, k: K, v: V) -> &self/V {
364
+ if self.size >= self.resize_at {
365
+ // n.b.: We could also do this after searching, so
366
+ // that we do not resize if this call to insert is
367
+ // simply going to update a key in place. My sense
368
+ // though is that it's worse to have to search through
369
+ // buckets to find the right spot twice than to just
370
+ // resize in this corner case.
371
+ self.expand();
372
+ }
373
+
374
+ let hash = k.hash_keyed(self.k0, self.k1) as uint;
375
+ let idx = match self.bucket_for_key_with_hash(hash, &k) {
376
+ TableFull => die!(~" Internal logic error"),
377
+ FoundEntry(idx) => idx,
378
+ FoundHole(idx) => {
379
+ self.buckets[idx] = Some(Bucket{hash: hash, key: k,
380
+ value: v});
381
+ self.size += 1;
382
+ idx
383
+ },
384
+ };
385
+
386
+ self.value_for_bucket(idx)
387
+ }
388
+
389
+ /// Return the value corresponding to the key in the map, or create,
390
+ /// insert, and return a new value if it doesn't exist.
391
+ fn find_or_insert_with(&mut self, k: K, f: fn(&K) -> V) -> &self/V {
392
+ if self.size >= self.resize_at {
393
+ // n.b.: We could also do this after searching, so
394
+ // that we do not resize if this call to insert is
395
+ // simply going to update a key in place. My sense
396
+ // though is that it's worse to have to search through
397
+ // buckets to find the right spot twice than to just
398
+ // resize in this corner case.
399
+ self.expand();
400
+ }
401
+
402
+ let hash = k.hash_keyed(self.k0, self.k1) as uint;
403
+ let idx = match self.bucket_for_key_with_hash(hash, &k) {
404
+ TableFull => die!(~" Internal logic error"),
405
+ FoundEntry(idx) => idx,
406
+ FoundHole(idx) => {
407
+ let v = f(&k);
408
+ self.buckets[idx] = Some(Bucket{hash: hash, key: k,
409
+ value: v});
410
+ self.size += 1;
411
+ idx
412
+ },
413
+ };
414
+
415
+ self.value_for_bucket(idx)
416
+ }
417
+
367
418
fn consume(&mut self, f: fn(K, V)) {
368
419
let mut buckets = ~[];
369
420
self.buckets <-> buckets;
@@ -521,7 +572,7 @@ mod test_map {
521
572
use uint;
522
573
523
574
#[ test]
524
- pub fn inserts ( ) {
575
+ pub fn test_insert ( ) {
525
576
let mut m = LinearMap :: new ( ) ;
526
577
assert m. insert ( 1 , 2 ) ;
527
578
assert m. insert ( 2 , 4 ) ;
@@ -530,7 +581,7 @@ mod test_map {
530
581
}
531
582
532
583
#[ test]
533
- pub fn overwrite ( ) {
584
+ pub fn test_insert_overwrite ( ) {
534
585
let mut m = LinearMap :: new ( ) ;
535
586
assert m. insert ( 1 , 2 ) ;
536
587
assert * m. get ( & 1 ) == 2 ;
@@ -539,7 +590,7 @@ mod test_map {
539
590
}
540
591
541
592
#[ test]
542
- pub fn conflicts ( ) {
593
+ pub fn test_insert_conflicts ( ) {
543
594
let mut m = linear:: linear_map_with_capacity ( 4 ) ;
544
595
assert m. insert ( 1 , 2 ) ;
545
596
assert m. insert ( 5 , 3 ) ;
@@ -550,7 +601,7 @@ mod test_map {
550
601
}
551
602
552
603
#[ test]
553
- pub fn conflict_remove ( ) {
604
+ pub fn test_conflict_remove ( ) {
554
605
let mut m = linear:: linear_map_with_capacity ( 4 ) ;
555
606
assert m. insert ( 1 , 2 ) ;
556
607
assert m. insert ( 5 , 3 ) ;
@@ -561,7 +612,7 @@ mod test_map {
561
612
}
562
613
563
614
#[ test]
564
- pub fn empty ( ) {
615
+ pub fn test_is_empty ( ) {
565
616
let mut m = linear:: linear_map_with_capacity ( 4 ) ;
566
617
assert m. insert ( 1 , 2 ) ;
567
618
assert !m. is_empty ( ) ;
@@ -570,23 +621,37 @@ mod test_map {
570
621
}
571
622
572
623
#[ test]
573
- pub fn pops ( ) {
624
+ pub fn test_pop ( ) {
574
625
let mut m = LinearMap :: new ( ) ;
575
626
m. insert ( 1 , 2 ) ;
576
627
assert m. pop ( & 1 ) == Some ( 2 ) ;
577
628
assert m. pop ( & 1 ) == None ;
578
629
}
579
630
580
631
#[ test]
581
- pub fn swaps ( ) {
632
+ pub fn test_swap ( ) {
582
633
let mut m = LinearMap :: new ( ) ;
583
634
assert m. swap ( 1 , 2 ) == None ;
584
635
assert m. swap ( 1 , 3 ) == Some ( 2 ) ;
585
636
assert m. swap ( 1 , 4 ) == Some ( 3 ) ;
586
637
}
587
638
588
639
#[ test]
589
- pub fn consumes ( ) {
640
+ pub fn test_find_or_insert ( ) {
641
+ let mut m = LinearMap :: new :: < int , int > ( ) ;
642
+ assert m. find_or_insert ( 1 , 2 ) == & 2 ;
643
+ assert m. find_or_insert ( 1 , 3 ) == & 2 ;
644
+ }
645
+
646
+ #[ test]
647
+ pub fn test_find_or_insert_with ( ) {
648
+ let mut m = LinearMap :: new :: < int , int > ( ) ;
649
+ assert m. find_or_insert_with ( 1 , |_| 2 ) == & 2 ;
650
+ assert m. find_or_insert_with ( 1 , |_| 3 ) == & 2 ;
651
+ }
652
+
653
+ #[ test]
654
+ pub fn test_consume ( ) {
590
655
let mut m = LinearMap :: new ( ) ;
591
656
assert m. insert ( 1 , 2 ) ;
592
657
assert m. insert ( 2 , 3 ) ;
@@ -601,7 +666,7 @@ mod test_map {
601
666
}
602
667
603
668
#[ test]
604
- pub fn iterate ( ) {
669
+ pub fn test_iterate ( ) {
605
670
let mut m = linear:: linear_map_with_capacity ( 4 ) ;
606
671
for uint:: range( 0 , 32 ) |i| {
607
672
assert m. insert( i, i* 2 ) ;
@@ -615,7 +680,7 @@ mod test_map {
615
680
}
616
681
617
682
#[ test]
618
- pub fn find ( ) {
683
+ pub fn test_find ( ) {
619
684
let mut m = LinearMap :: new ( ) ;
620
685
assert m. find ( & 1 ) . is_none ( ) ;
621
686
m. insert ( 1 , 2 ) ;
0 commit comments