@@ -794,6 +794,97 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
794
794
fn search ( & self , k : & K ) -> Option < table:: FullIndex > {
795
795
self . search_hashed ( & self . make_hash ( k) , k)
796
796
}
797
+
798
+ fn pop_internal ( & mut self , starting_index : table:: FullIndex ) -> Option < V > {
799
+ let starting_probe = starting_index. raw_index ( ) ;
800
+
801
+ let ending_probe = {
802
+ let mut probe = self . probe_next ( starting_probe) ;
803
+ for _ in range ( 0 u, self . table . size ( ) ) {
804
+ match self . table . peek ( probe) {
805
+ table:: Empty ( _) => { } , // empty bucket. this is the end of our shifting.
806
+ table:: Full ( idx) => {
807
+ // Bucket that isn't us, which has a non-zero probe distance.
808
+ // This isn't the ending index, so keep searching.
809
+ if self . bucket_distance ( & idx) != 0 {
810
+ probe = self . probe_next ( probe) ;
811
+ continue ;
812
+ }
813
+
814
+ // if we do have a bucket_distance of zero, we're at the end
815
+ // of what we need to shift.
816
+ }
817
+ }
818
+ break ;
819
+ }
820
+
821
+ probe
822
+ } ;
823
+
824
+ let ( _, _, retval) = self . table . take ( starting_index) ;
825
+
826
+ let mut probe = starting_probe;
827
+ let mut next_probe = self . probe_next ( probe) ;
828
+
829
+ // backwards-shift all the elements after our newly-deleted one.
830
+ while next_probe != ending_probe {
831
+ match self . table . peek ( next_probe) {
832
+ table:: Empty ( _) => {
833
+ // nothing to shift in. just empty it out.
834
+ match self . table . peek ( probe) {
835
+ table:: Empty ( _) => { } ,
836
+ table:: Full ( idx) => { self . table . take ( idx) ; }
837
+ }
838
+ } ,
839
+ table:: Full ( next_idx) => {
840
+ // something to shift. move it over!
841
+ let next_hash = next_idx. hash ( ) ;
842
+ let ( _, next_key, next_val) = self . table . take ( next_idx) ;
843
+ match self . table . peek ( probe) {
844
+ table:: Empty ( idx) => {
845
+ self . table . put ( idx, next_hash, next_key, next_val) ;
846
+ } ,
847
+ table:: Full ( idx) => {
848
+ let ( emptyidx, _, _) = self . table . take ( idx) ;
849
+ self . table . put ( emptyidx, next_hash, next_key, next_val) ;
850
+ }
851
+ }
852
+ }
853
+ }
854
+
855
+ probe = next_probe;
856
+ next_probe = self . probe_next ( next_probe) ;
857
+ }
858
+
859
+ // Done the backwards shift, but there's still an element left!
860
+ // Empty it out.
861
+ match self . table . peek ( probe) {
862
+ table:: Empty ( _) => { } ,
863
+ table:: Full ( idx) => { self . table . take ( idx) ; }
864
+ }
865
+
866
+ // Now we're done all our shifting. Return the value we grabbed
867
+ // earlier.
868
+ return Some ( retval) ;
869
+ }
870
+
871
+ /// Like `pop`, but can operate on any type that is equivalent to a key.
872
+ #[ experimental]
873
+ pub fn pop_equiv < Q : Hash < S > + Equiv < K > > ( & mut self , k : & Q ) -> Option < V > {
874
+ if self . table . size ( ) == 0 {
875
+ return None
876
+ }
877
+
878
+ let potential_new_size = self . table . size ( ) - 1 ;
879
+ self . make_some_room ( potential_new_size) ;
880
+
881
+ let starting_index = match self . search_equiv ( k) {
882
+ Some ( idx) => idx,
883
+ None => return None ,
884
+ } ;
885
+
886
+ self . pop_internal ( starting_index)
887
+ }
797
888
}
798
889
799
890
impl < K : TotalEq + Hash < S > , V , S , H : Hasher < S > > Container for HashMap < K , V , H > {
@@ -893,77 +984,9 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V
893
984
None => return None ,
894
985
} ;
895
986
896
- let starting_probe = starting_index. raw_index ( ) ;
897
-
898
- let ending_probe = {
899
- let mut probe = self . probe_next ( starting_probe) ;
900
- for _ in range ( 0 u, self . table . size ( ) ) {
901
- match self . table . peek ( probe) {
902
- table:: Empty ( _) => { } , // empty bucket. this is the end of our shifting.
903
- table:: Full ( idx) => {
904
- // Bucket that isn't us, which has a non-zero probe distance.
905
- // This isn't the ending index, so keep searching.
906
- if self . bucket_distance ( & idx) != 0 {
907
- probe = self . probe_next ( probe) ;
908
- continue ;
909
- }
910
-
911
- // if we do have a bucket_distance of zero, we're at the end
912
- // of what we need to shift.
913
- }
914
- }
915
- break ;
916
- }
917
-
918
- probe
919
- } ;
920
-
921
- let ( _, _, retval) = self . table . take ( starting_index) ;
922
-
923
- let mut probe = starting_probe;
924
- let mut next_probe = self . probe_next ( probe) ;
925
-
926
- // backwards-shift all the elements after our newly-deleted one.
927
- while next_probe != ending_probe {
928
- match self . table . peek ( next_probe) {
929
- table:: Empty ( _) => {
930
- // nothing to shift in. just empty it out.
931
- match self . table . peek ( probe) {
932
- table:: Empty ( _) => { } ,
933
- table:: Full ( idx) => { self . table . take ( idx) ; }
934
- }
935
- } ,
936
- table:: Full ( next_idx) => {
937
- // something to shift. move it over!
938
- let next_hash = next_idx. hash ( ) ;
939
- let ( _, next_key, next_val) = self . table . take ( next_idx) ;
940
- match self . table . peek ( probe) {
941
- table:: Empty ( idx) => {
942
- self . table . put ( idx, next_hash, next_key, next_val) ;
943
- } ,
944
- table:: Full ( idx) => {
945
- let ( emptyidx, _, _) = self . table . take ( idx) ;
946
- self . table . put ( emptyidx, next_hash, next_key, next_val) ;
947
- }
948
- }
949
- }
950
- }
951
-
952
- probe = next_probe;
953
- next_probe = self . probe_next ( next_probe) ;
954
- }
955
-
956
- // Done the backwards shift, but there's still an element left!
957
- // Empty it out.
958
- match self . table . peek ( probe) {
959
- table:: Empty ( _) => { } ,
960
- table:: Full ( idx) => { self . table . take ( idx) ; }
961
- }
962
-
963
- // Now we're done all our shifting. Return the value we grabbed
964
- // earlier.
965
- return Some ( retval) ;
987
+ self . pop_internal ( starting_index)
966
988
}
989
+
967
990
}
968
991
969
992
impl < K : Hash + TotalEq , V > HashMap < K , V , sip:: SipHasher > {
@@ -1570,10 +1593,20 @@ pub type SetAlgebraItems<'a, T, H> =
1570
1593
#[ cfg( test) ]
1571
1594
mod test_map {
1572
1595
use super :: HashMap ;
1596
+ use std:: cmp:: Equiv ;
1573
1597
use std:: iter:: { Iterator , range_inclusive, range_step_inclusive} ;
1574
1598
use std:: local_data;
1575
1599
use std:: vec;
1576
1600
1601
+ struct KindaIntLike ( int ) ;
1602
+
1603
+ impl Equiv < int > for KindaIntLike {
1604
+ fn equiv ( & self , other : & int ) -> bool {
1605
+ let KindaIntLike ( this) = * self ;
1606
+ this == * other
1607
+ }
1608
+ }
1609
+
1577
1610
#[ test]
1578
1611
fn test_create_capacity_zero ( ) {
1579
1612
let mut m = HashMap :: with_capacity ( 0 ) ;
@@ -1813,6 +1846,14 @@ mod test_map {
1813
1846
assert_eq ! ( m. pop( & 1 ) , None ) ;
1814
1847
}
1815
1848
1849
+ #[ test]
1850
+ fn test_pop_equiv ( ) {
1851
+ let mut m = HashMap :: new ( ) ;
1852
+ m. insert ( 1 , 2 ) ;
1853
+ assert_eq ! ( m. pop_equiv( & KindaIntLike ( 1 ) , Some ( 2 ) ) ) ;
1854
+ assert_eq ! ( m. pop_equiv( & KindaIntLike ( 1 ) , None ) ) ;
1855
+ }
1856
+
1816
1857
#[ test]
1817
1858
fn test_swap ( ) {
1818
1859
let mut m = HashMap :: new ( ) ;
0 commit comments