Skip to content

fix trie iteration #5237

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 2 commits into from
Mar 5, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 91 additions & 12 deletions src/libcore/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<T> BaseIter<(uint, &T)> for TrieMap<T> {
/// Visit all key-value pairs in order
#[inline(always)]
pure fn each(&self, f: fn(&(uint, &self/T)) -> bool) {
self.root.each(f)
self.root.each(f);
}
#[inline(always)]
pure fn size_hint(&self) -> Option<uint> { Some(self.len()) }
Expand All @@ -42,7 +42,7 @@ impl<T> ReverseIter<(uint, &T)> for TrieMap<T> {
/// Visit all key-value pairs in reverse order
#[inline(always)]
pure fn each_reverse(&self, f: fn(&(uint, &self/T)) -> bool) {
self.root.each_reverse(f)
self.root.each_reverse(f);
}
}

Expand Down Expand Up @@ -149,7 +149,7 @@ impl<T> TrieMap<T> {

/// Iterate over the map and mutate the contained values
fn mutate_values(&mut self, f: fn(uint, &mut T) -> bool) {
self.root.mutate_values(f)
self.root.mutate_values(f);
}
}

Expand Down Expand Up @@ -217,34 +217,39 @@ impl<T: Copy> TrieNode<T> {
}

impl<T> TrieNode<T> {
pure fn each(&self, f: fn(&(uint, &self/T)) -> bool) {
pure fn each(&self, f: fn(&(uint, &self/T)) -> bool) -> bool {
for uint::range(0, self.children.len()) |idx| {
match self.children[idx] {
Internal(ref x) => x.each(f),
External(k, ref v) => if !f(&(k, v)) { return },
Internal(ref x) => if !x.each(f) { return false },
External(k, ref v) => if !f(&(k, v)) { return false },
Nothing => ()
}
}
true
}

pure fn each_reverse(&self, f: fn(&(uint, &self/T)) -> bool) {
pure fn each_reverse(&self, f: fn(&(uint, &self/T)) -> bool) -> bool {
for uint::range_rev(self.children.len(), 0) |idx| {
match self.children[idx - 1] {
Internal(ref x) => x.each(f),
External(k, ref v) => if !f(&(k, v)) { return },
Internal(ref x) => if !x.each_reverse(f) { return false },
External(k, ref v) => if !f(&(k, v)) { return false },
Nothing => ()
}
}
true
}

fn mutate_values(&mut self, f: fn(uint, &mut T) -> bool) {
fn mutate_values(&mut self, f: fn(uint, &mut T) -> bool) -> bool {
for vec::each_mut(self.children) |child| {
match *child {
Internal(ref mut x) => x.mutate_values(f),
External(k, ref mut v) => if !f(k, v) { return },
Internal(ref mut x) => if !x.mutate_values(f) {
return false
},
External(k, ref mut v) => if !f(k, v) { return false },
Nothing => ()
}
}
true
}
}

Expand Down Expand Up @@ -366,4 +371,78 @@ mod tests {
check_integrity(&trie.root);
}
}

#[test]
fn test_each() {
let mut m = TrieMap::new();

assert m.insert(3, 6);
assert m.insert(0, 0);
assert m.insert(4, 8);
assert m.insert(2, 4);
assert m.insert(1, 2);

let mut n = 0;
for m.each |&(k, v)| {
assert k == n;
assert *v == n * 2;
n += 1;
}
}

#[test]
fn test_each_break() {
let mut m = TrieMap::new();

for uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
m.insert(x, x / 2);
}

let mut n = uint::max_value - 9999;
for m.each |&(k, v)| {
if n == uint::max_value - 5000 { break }
assert n < uint::max_value - 5000;

assert k == n;
assert *v == n / 2;
n += 1;
}
}

#[test]
fn test_each_reverse() {
let mut m = TrieMap::new();

assert m.insert(3, 6);
assert m.insert(0, 0);
assert m.insert(4, 8);
assert m.insert(2, 4);
assert m.insert(1, 2);

let mut n = 4;
for m.each_reverse |&(k, v)| {
assert k == n;
assert *v == n * 2;
n -= 1;
}
}

#[test]
fn test_each_reverse_break() {
let mut m = TrieMap::new();

for uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
m.insert(x, x / 2);
}

let mut n = uint::max_value;
for m.each_reverse |&(k, v)| {
if n == uint::max_value - 5000 { break }
assert n > uint::max_value - 5000;

assert k == n;
assert *v == n / 2;
n -= 1;
}
}
}