From 794814945674d27a4fb68aedcea86c39dd5ccd4e Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 24 Mar 2013 16:55:51 -0400 Subject: [PATCH 1/6] treemap: add a find_mut method --- src/libcore/container.rs | 5 ++++- src/libstd/treemap.rs | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index 1cda04ee06ec1..9eba2c7105c1c 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -38,9 +38,12 @@ pub trait Map: Mutable { /// Iterate over the map and mutate the contained values fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool); - /// Return the value corresponding to the key in the map + /// Return a reference to the value corresponding to the key fn find(&self, key: &K) -> Option<&'self V>; + /// Return a mutable reference to the value corresponding to the key + //fn find_mut(&mut self, key: &K) -> Option<&'self mut V>; + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 1da1edae7d245..b77037ba3adef 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -135,7 +135,7 @@ impl Map for TreeMap { mutate_values(&mut self.root, f); } - /// Return the value corresponding to the key in the map + /// Return a reference to the value corresponding to the key fn find(&self, key: &K) -> Option<&'self V> { let mut current: &'self Option<~TreeNode> = &self.root; loop { @@ -189,6 +189,12 @@ pub impl TreeMap { fn iter(&self) -> TreeMapIterator<'self, K, V> { TreeMapIterator{stack: ~[], node: &self.root} } + + /// Return a mutable reference to the value corresponding to the key + #[inline(always)] + fn find_mut(&mut self, key: &K) -> Option<&'self mut V> { + find_mut(&mut self.root, key) + } } /// Lazy forward iterator over a map @@ -584,8 +590,20 @@ fn split(node: &mut ~TreeNode) { } } -fn insert(node: &mut Option<~TreeNode>, key: K, - value: V) -> bool { +fn find_mut(node: &'r mut Option<~TreeNode>, key: &K) -> Option<&'r mut V> { + match *node { + Some(ref mut x) => { + match key.cmp(&x.key) { + Less => find_mut(&mut x.left, key), + Greater => find_mut(&mut x.right, key), + Equal => Some(&mut x.value), + } + } + None => None + } +} + +fn insert(node: &mut Option<~TreeNode>, key: K, value: V) -> bool { match *node { Some(ref mut save) => { match key.cmp(&save.key) { @@ -716,6 +734,19 @@ mod test_treemap { fail_unless!(m.find(&2) == None); } + #[test] + fn test_find_mut() { + let mut m = TreeMap::new(); + fail_unless!(m.insert(1, 12)); + fail_unless!(m.insert(2, 8)); + fail_unless!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + #[test] fn insert_replace() { let mut m = TreeMap::new(); From d77433386be3d5afa201cfd40dbaaa4d20dbbd80 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 24 Mar 2013 19:07:36 -0400 Subject: [PATCH 2/6] hashmap: add find_mut method --- src/libcore/hashmap.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index f5a97bdaca3ac..b980082a88c0c 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -24,6 +24,7 @@ pub mod linear { use rand; use uint; use vec; + use util::unreachable; static INITIAL_CAPACITY: uint = 32u; // 2^5 @@ -192,6 +193,14 @@ pub mod linear { } } + #[inline(always)] + fn mut_value_for_bucket(&mut self, idx: uint) -> &'self mut V { + match self.buckets[idx] { + Some(ref mut bkt) => &mut bkt.value, + None => unreachable() + } + } + /// Inserts the key value pair into the buckets. /// Assumes that there will be a bucket. /// True if there was no previous entry with that key @@ -338,7 +347,7 @@ pub mod linear { } } - /// Return the value corresponding to the key in the map + /// Return a reference to the value corresponding to the key fn find(&self, k: &K) -> Option<&'self V> { match self.bucket_for_key(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), @@ -410,6 +419,17 @@ pub mod linear { old_value } + /// Return a mutable reference to the value corresponding to the key + fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { + let idx = match self.bucket_for_key(k) { + FoundEntry(idx) => idx, + TableFull | FoundHole(_) => return None + }; + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) + } + } + /// Return the value corresponding to the key in the map, or insert /// and return the value if it doesn't exist. fn find_or_insert(&mut self, k: K, v: V) -> &'self V { @@ -655,6 +675,19 @@ pub mod linear { fail_unless!(*m.get(&2) == 4); } + #[test] + fn test_find_mut() { + let mut m = LinearMap::new(); + fail_unless!(m.insert(1, 12)); + fail_unless!(m.insert(2, 8)); + fail_unless!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + #[test] pub fn test_insert_overwrite() { let mut m = LinearMap::new(); From 89e2578a9d1cd18270b7148a5d5d6b8bee051ac5 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 24 Mar 2013 20:30:35 -0400 Subject: [PATCH 3/6] trie: add find_mut method --- src/libcore/trie.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index 40ef5fee47aa4..007bafcd03d96 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -90,7 +90,7 @@ impl Map for TrieMap { self.root.mutate_values(f); } - /// Return the value corresponding to the key in the map + /// Return a reference to the value corresponding to the key #[inline(hint)] fn find(&self, key: &uint) -> Option<&'self T> { let mut node: &'self TrieNode = &self.root; @@ -153,6 +153,12 @@ pub impl TrieMap { fn each_value_reverse(&self, f: &fn(&T) -> bool) { self.each_reverse(|&(_, v)| f(v)) } + + /// Return a mutable reference to the value corresponding to the key + #[inline(always)] + fn find_mut(&mut self, key: &uint) -> Option<&'self mut T> { + find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) + } } pub struct TrieSet { @@ -276,6 +282,17 @@ fn chunk(n: uint, idx: uint) -> uint { (n >> sh) & MASK } +fn find_mut(child: &'r mut Child, key: uint, idx: uint) -> Option<&'r mut T> { + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + (match *child { + External(_, ref value) => Some(cast::transmute_mut(value)), + Internal(ref x) => find_mut(cast::transmute_mut(&x.children[chunk(key, idx)]), + key, idx + 1), + Nothing => None + }).map_consume(|x| cast::transmute_mut_region(x)) + } +} + fn insert(count: &mut uint, child: &mut Child, key: uint, value: T, idx: uint) -> bool { let mut tmp = Nothing; @@ -357,8 +374,22 @@ pub fn check_integrity(trie: &TrieNode) { #[cfg(test)] mod tests { use super::*; + use core::option::{Some, None}; use uint; + #[test] + fn test_find_mut() { + let mut m = TrieMap::new(); + fail_unless!(m.insert(1, 12)); + fail_unless!(m.insert(2, 8)); + fail_unless!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + #[test] fn test_step() { let mut trie = TrieMap::new(); From f0f4a00e88fc374b2b3096789a11bf429d42c3a9 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 24 Mar 2013 20:35:23 -0400 Subject: [PATCH 4/6] smallintmap: add find_mut method --- src/libstd/smallintmap.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index a559e7540d414..fffd6c9ee4fe3 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -86,7 +86,7 @@ impl Map for SmallIntMap { self.each(|&(_, v)| blk(v)) } - /// Visit all key-value pairs in order + /// Iterate over the map and mutate the contained values fn mutate_values(&mut self, it: &fn(&uint, &'self mut V) -> bool) { for uint::range(0, self.v.len()) |i| { match self.v[i] { @@ -96,7 +96,7 @@ impl Map for SmallIntMap { } } - /// Iterate over the map and mutate the contained values + /// Return a reference to the value corresponding to the key fn find(&self, key: &uint) -> Option<&'self V> { if *key < self.v.len() { match self.v[*key] { @@ -140,6 +140,18 @@ pub impl SmallIntMap { fn get(&self, key: &uint) -> &'self V { self.find(key).expect("key not present") } + + /// Return a mutable reference to the value corresponding to the key + fn find_mut(&mut self, key: &uint) -> Option<&'self mut V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref mut value) => Some(value), + None => None + } + } else { + None + } + } } pub impl SmallIntMap { @@ -160,6 +172,20 @@ pub impl SmallIntMap { #[cfg(test)] mod tests { use super::SmallIntMap; + use core::prelude::*; + + #[test] + fn test_find_mut() { + let mut m = SmallIntMap::new(); + fail_unless!(m.insert(1, 12)); + fail_unless!(m.insert(2, 8)); + fail_unless!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } #[test] fn test_len() { From 38f39ac540d2a8b42c650e3aae9eaa715d47c554 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 24 Mar 2013 20:40:17 -0400 Subject: [PATCH 5/6] expose find_mut in the Map trait --- src/libcore/container.rs | 2 +- src/libcore/hashmap.rs | 22 ++++++++--------- src/libcore/trie.rs | 12 +++++----- src/libstd/smallintmap.rs | 24 +++++++++---------- src/libstd/treemap.rs | 12 +++++----- .../class-impl-very-parameterized-trait.rs | 2 ++ 6 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/libcore/container.rs b/src/libcore/container.rs index 9eba2c7105c1c..e20821b919b6c 100644 --- a/src/libcore/container.rs +++ b/src/libcore/container.rs @@ -42,7 +42,7 @@ pub trait Map: Mutable { fn find(&self, key: &K) -> Option<&'self V>; /// Return a mutable reference to the value corresponding to the key - //fn find_mut(&mut self, key: &K) -> Option<&'self mut V>; + fn find_mut(&mut self, key: &K) -> Option<&'self mut V>; /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index b980082a88c0c..8c290553a4599 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -355,6 +355,17 @@ pub mod linear { } } + /// Return a mutable reference to the value corresponding to the key + fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { + let idx = match self.bucket_for_key(k) { + FoundEntry(idx) => idx, + TableFull | FoundHole(_) => return None + }; + unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker + Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) + } + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -419,17 +430,6 @@ pub mod linear { old_value } - /// Return a mutable reference to the value corresponding to the key - fn find_mut(&mut self, k: &K) -> Option<&'self mut V> { - let idx = match self.bucket_for_key(k) { - FoundEntry(idx) => idx, - TableFull | FoundHole(_) => return None - }; - unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker - Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) - } - } - /// Return the value corresponding to the key in the map, or insert /// and return the value if it doesn't exist. fn find_or_insert(&mut self, k: K, v: V) -> &'self V { diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index 007bafcd03d96..5921ae5b3f588 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -111,6 +111,12 @@ impl Map for TrieMap { } } + /// Return a mutable reference to the value corresponding to the key + #[inline(always)] + fn find_mut(&mut self, key: &uint) -> Option<&'self mut T> { + find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -153,12 +159,6 @@ pub impl TrieMap { fn each_value_reverse(&self, f: &fn(&T) -> bool) { self.each_reverse(|&(_, v)| f(v)) } - - /// Return a mutable reference to the value corresponding to the key - #[inline(always)] - fn find_mut(&mut self, key: &uint) -> Option<&'self mut T> { - find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) - } } pub struct TrieSet { diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index fffd6c9ee4fe3..4ad8d38b072b1 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -108,6 +108,18 @@ impl Map for SmallIntMap { } } + /// Return a mutable reference to the value corresponding to the key + fn find_mut(&mut self, key: &uint) -> Option<&'self mut V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref mut value) => Some(value), + None => None + } + } else { + None + } + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -140,18 +152,6 @@ pub impl SmallIntMap { fn get(&self, key: &uint) -> &'self V { self.find(key).expect("key not present") } - - /// Return a mutable reference to the value corresponding to the key - fn find_mut(&mut self, key: &uint) -> Option<&'self mut V> { - if *key < self.v.len() { - match self.v[*key] { - Some(ref mut value) => Some(value), - None => None - } - } else { - None - } - } } pub impl SmallIntMap { diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index b77037ba3adef..fccf58ddb6f74 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -152,6 +152,12 @@ impl Map for TreeMap { } } + /// Return a mutable reference to the value corresponding to the key + #[inline(always)] + fn find_mut(&mut self, key: &K) -> Option<&'self mut V> { + find_mut(&mut self.root, key) + } + /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. @@ -189,12 +195,6 @@ pub impl TreeMap { fn iter(&self) -> TreeMapIterator<'self, K, V> { TreeMapIterator{stack: ~[], node: &self.root} } - - /// Return a mutable reference to the value corresponding to the key - #[inline(always)] - fn find_mut(&mut self, key: &K) -> Option<&'self mut V> { - find_mut(&mut self.root, key) - } } /// Lazy forward iterator over a map diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index 40dd1a46574b1..281d520be0f60 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -98,6 +98,8 @@ impl Map for cat { } } + fn find_mut(&mut self, k: &int) -> Option<&'self mut T> { fail!() } + fn remove(&mut self, k: &int) -> bool { if self.find(k).is_some() { self.meows -= *k; true From e8bf0a4a49405cfde21910af889d626fbdd5bd52 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 25 Mar 2013 00:22:23 -0400 Subject: [PATCH 6/6] trie: improve docstring --- src/libcore/trie.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/trie.rs b/src/libcore/trie.rs index 5921ae5b3f588..012e005567434 100644 --- a/src/libcore/trie.rs +++ b/src/libcore/trie.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A radix trie for storing integers in sorted order +//! An ordered map and set for integer keys implemented as a radix trie use prelude::*;