about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorblake2-ppc <blake2-ppc>2013-06-21 17:05:05 +0200
committerDaniel Micay <danielmicay@gmail.com>2013-06-23 04:23:00 -0400
commit080d498af224ac4b60efe6e92aed08db3f247bc5 (patch)
tree4fc127615adf42ac73455458e726a12bb01fb9c4 /src
parent3b126e4d6dda1eac3881b8ca19772071997a7992 (diff)
downloadrust-080d498af224ac4b60efe6e92aed08db3f247bc5.tar.gz
rust-080d498af224ac4b60efe6e92aed08db3f247bc5.zip
std::hashmap: Implement external iterator for HashMap and HashSet
Diffstat (limited to 'src')
-rw-r--r--src/libstd/hashmap.rs91
1 files changed, 79 insertions, 12 deletions
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs
index 02fa2de4b03..c275e8a99ff 100644
--- a/src/libstd/hashmap.rs
+++ b/src/libstd/hashmap.rs
@@ -20,13 +20,13 @@ use cmp::{Eq, Equiv};
 use hash::Hash;
 use old_iter::BaseIter;
 use old_iter;
-use iterator::IteratorUtil;
+use iterator::{Iterator, IteratorUtil};
 use option::{None, Option, Some};
 use rand::RngUtil;
 use rand;
 use uint;
 use vec;
-use vec::ImmutableVector;
+use vec::{ImmutableVector, MutableVector};
 use kinds::Copy;
 use util::{replace, unreachable};
 
@@ -311,24 +311,17 @@ impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
 
     /// Visit all key-value pairs
     fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
-        for self.buckets.iter().advance |bucket| {
-            for bucket.iter().advance |pair| {
-                if !blk(&pair.key, &pair.value) {
-                    return false;
-                }
-            }
-        }
-        return true;
+        self.iter().advance(|(k, v)| blk(k, v))
     }
 
     /// Visit all keys
     fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
-        self.each(|k, _| blk(k))
+        self.iter().advance(|(k, _)| blk(k))
     }
 
     /// Visit all values
     fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
-        self.each(|_, v| blk(v))
+        self.iter().advance(|(_, v)| blk(v))
     }
 
     /// Iterate over the map and mutate the contained values
@@ -524,6 +517,19 @@ impl<K: Hash + Eq, V> HashMap<K, V> {
             TableFull | FoundHole(_) => None,
         }
     }
+
+    /// An iterator visiting all key-value pairs in arbitrary order.
+    /// Iterator element type is (&'a K, &'a V).
+    pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
+        HashMapIterator { iter: self.buckets.iter() }
+    }
+
+    /// An iterator visiting all key-value pairs in arbitrary order,
+    /// with mutable references to the values.
+    /// Iterator element type is (&'a K, &'a mut V).
+    pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
+        HashMapMutIterator { iter: self.buckets.mut_iter() }
+    }
 }
 
 impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
@@ -555,6 +561,61 @@ impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
     fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
 }
 
+/// HashMap iterator
+pub struct HashMapIterator<'self, K, V> {
+    priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
+}
+
+/// HashMap mutable values iterator
+pub struct HashMapMutIterator<'self, K, V> {
+    priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
+}
+
+/// HashSet iterator
+pub struct HashSetIterator<'self, K> {
+    priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
+}
+
+impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
+    #[inline]
+    fn next(&mut self) -> Option<(&'self K, &'self V)> {
+        for self.iter.advance |elt| {
+            match elt {
+                &Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
+                &None => {},
+            }
+        }
+        None
+    }
+}
+
+impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'self, K, V> {
+    #[inline]
+    fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
+        for self.iter.advance |elt| {
+            match elt {
+                &Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
+                &None => {},
+            }
+        }
+        None
+    }
+}
+
+impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
+    #[inline]
+    fn next(&mut self) -> Option<&'self K> {
+        for self.iter.advance |elt| {
+            match elt {
+                &Some(ref bucket) => return Some(&bucket.key),
+                &None => {},
+            }
+        }
+        None
+    }
+}
+
+
 /// An implementation of a hash set using the underlying representation of a
 /// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
 /// requires that the elements implement the `Eq` and `Hash` traits.
@@ -664,6 +725,12 @@ impl<T:Hash + Eq> HashSet<T> {
     pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
       self.map.contains_key_equiv(value)
     }
+
+    /// An iterator visiting all elements in arbitrary order.
+    /// Iterator element type is &'a T.
+    pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
+        HashSetIterator { iter: self.map.buckets.iter() }
+    }
 }
 
 #[cfg(test)]