Skip to content

Commit eb1b706

Browse files
committed
---
yaml --- r: 32500 b: refs/heads/dist-snap c: 4ea4566 h: refs/heads/master v: v3
1 parent 9951bc6 commit eb1b706

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
10-
refs/heads/dist-snap: e5cb6cc1237caeaa998a632c0dcf0bb067e6afef
10+
refs/heads/dist-snap: 4ea45669b8d5b7017acd5555163e2a15e85da46c
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/dist-snap/src/libcore/vec.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export grow;
4343
export grow_fn;
4444
export grow_set;
4545
export truncate;
46+
export dedup;
4647
export map;
4748
export mapi;
4849
export map2;
@@ -625,6 +626,41 @@ fn truncate<T>(&v: ~[const T], newlen: uint) {
625626
}
626627
}
627628

629+
/**
630+
* Remove consecutive repeated elements from a vector; if the vector is
631+
* sorted, this removes all duplicates.
632+
*/
633+
fn dedup<T: Eq>(&v: ~[const T]) unsafe {
634+
if v.len() < 1 { return; }
635+
let mut last_written = 0, next_to_read = 1;
636+
do as_const_buf(v) |p, ln| {
637+
// We have a mutable reference to v, so we can make arbitrary changes.
638+
// (cf. push and pop)
639+
let p = p as *mut T;
640+
// last_written < next_to_read <= ln
641+
while next_to_read < ln {
642+
// last_written < next_to_read < ln
643+
if *ptr::mut_offset(p, next_to_read) ==
644+
*ptr::mut_offset(p, last_written) {
645+
let _dropped <- *ptr::mut_offset(p, next_to_read);
646+
} else {
647+
last_written += 1;
648+
// last_written <= next_to_read < ln
649+
if next_to_read != last_written {
650+
*ptr::mut_offset(p, last_written) <-
651+
*ptr::mut_offset(p, next_to_read);
652+
}
653+
}
654+
// last_written <= next_to_read < ln
655+
next_to_read += 1;
656+
// last_written < next_to_read <= ln
657+
}
658+
}
659+
// last_written < next_to_read == ln
660+
unsafe::set_len(v, last_written + 1);
661+
}
662+
663+
628664
// Appending
629665
#[inline(always)]
630666
pure fn append<T: Copy>(+lhs: ~[T], rhs: &[const T]) -> ~[T] {
@@ -2218,6 +2254,51 @@ mod tests {
22182254
// If the unsafe block didn't drop things properly, we blow up here.
22192255
}
22202256

2257+
#[test]
2258+
fn test_dedup() {
2259+
fn case(-a: ~[uint], -b: ~[uint]) {
2260+
let mut v = a;
2261+
dedup(v);
2262+
assert(v == b);
2263+
}
2264+
case(~[], ~[]);
2265+
case(~[1], ~[1]);
2266+
case(~[1,1], ~[1]);
2267+
case(~[1,2,3], ~[1,2,3]);
2268+
case(~[1,1,2,3], ~[1,2,3]);
2269+
case(~[1,2,2,3], ~[1,2,3]);
2270+
case(~[1,2,3,3], ~[1,2,3]);
2271+
case(~[1,1,2,2,2,3,3], ~[1,2,3]);
2272+
}
2273+
2274+
#[test]
2275+
fn test_dedup_unique() {
2276+
let mut v0 = ~[~1, ~1, ~2, ~3];
2277+
dedup(v0);
2278+
let mut v1 = ~[~1, ~2, ~2, ~3];
2279+
dedup(v1);
2280+
let mut v2 = ~[~1, ~2, ~3, ~3];
2281+
dedup(v2);
2282+
/*
2283+
* If the ~pointers were leaked or otherwise misused, valgrind and/or
2284+
* rustrt should raise errors.
2285+
*/
2286+
}
2287+
2288+
#[test]
2289+
fn test_dedup_shared() {
2290+
let mut v0 = ~[@1, @1, @2, @3];
2291+
dedup(v0);
2292+
let mut v1 = ~[@1, @2, @2, @3];
2293+
dedup(v1);
2294+
let mut v2 = ~[@1, @2, @3, @3];
2295+
dedup(v2);
2296+
/*
2297+
* If the @pointers were leaked or otherwise misused, valgrind and/or
2298+
* rustrt should raise errors.
2299+
*/
2300+
}
2301+
22212302
#[test]
22222303
fn test_map() {
22232304
// Test on-stack map.

0 commit comments

Comments
 (0)