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