From f690cc2c63d436434412cef56154627d94b6284e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 4 Mar 2014 10:39:49 -0800 Subject: libstd: Add some more functionality to Vec --- src/libstd/vec_ng.rs | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'src') diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index ae918bfa98b..f625e638ae8 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -20,6 +20,7 @@ use fmt; use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator}; use libc::{free, c_void}; use mem::{size_of, move_val_init}; +use mem; use num; use num::{CheckedMul, CheckedAdd}; use ops::Drop; @@ -66,6 +67,14 @@ impl Vec { } impl Vec { + pub fn from_slice(values: &[T]) -> Vec { + let mut vector = Vec::new(); + for value in values.iter() { + vector.push((*value).clone()) + } + vector + } + pub fn from_elem(length: uint, value: T) -> Vec { unsafe { let mut xs = Vec::with_capacity(length); @@ -282,6 +291,12 @@ impl Vec { } } + #[inline] + pub fn move_rev_iter(mut self) -> MoveItems { + self.reverse(); + self.move_iter() + } + #[inline] pub unsafe fn set_len(&mut self, len: uint) { self.len = len; @@ -322,6 +337,11 @@ impl Vec { self.as_slice().tail() } + #[inline] + pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] { + self.as_slice().tailn(n) + } + #[inline] pub fn last<'a>(&'a self) -> Option<&'a T> { self.as_slice().last() @@ -387,14 +407,41 @@ impl Vec { } } + #[inline] + pub fn mut_slice<'a>(&'a mut self, start: uint, end: uint) + -> &'a mut [T] { + self.as_mut_slice().mut_slice(start, end) + } + + #[inline] + pub fn reverse(&mut self) { + self.as_mut_slice().reverse() + } + + #[inline] pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] { self.as_slice().slice_from(start) } + #[inline] + pub fn slice_to<'a>(&'a self, end: uint) -> &'a [T] { + self.as_slice().slice_to(end) + } + #[inline] pub fn init<'a>(&'a self) -> &'a [T] { self.slice(0, self.len() - 1) } + + #[inline] + pub fn as_ptr(&self) -> *T { + self.as_slice().as_ptr() + } + + #[inline] + pub fn clear(&mut self) { + self.truncate(0) + } } impl Vec { @@ -402,6 +449,90 @@ impl Vec { pub fn contains(&self, x: &T) -> bool { self.as_slice().contains(x) } + + pub fn dedup(&mut self) { + unsafe { + // Although we have a mutable reference to `self`, we cannot make + // *arbitrary* changes. The `Eq` comparisons could fail, so we + // must ensure that the vector is in a valid state at all time. + // + // The way that we handle this is by using swaps; we iterate + // over all the elements, swapping as we go so that at the end + // the elements we wish to keep are in the front, and those we + // wish to reject are at the back. We can then truncate the + // vector. This operation is still O(n). + // + // Example: We start in this state, where `r` represents "next + // read" and `w` represents "next_write`. + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], tis is not a duplicate, so + // we swap self[r] and self[w] (no effect as r==w) and then increment both + // r and w, leaving us with: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], this value is a duplicate, + // so we increment `r` but leave everything else unchanged: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 1 | 2 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Comparing self[r] against self[w-1], this is not a duplicate, + // so swap self[r] and self[w] and advance r and w: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 1 | 3 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Not a duplicate, repeat: + // + // r + // +---+---+---+---+---+---+ + // | 0 | 1 | 2 | 3 | 1 | 3 | + // +---+---+---+---+---+---+ + // w + // + // Duplicate, advance r. End of vec. Truncate to w. + + let ln = self.len(); + if ln < 1 { return; } + + // Avoid bounds checks by using unsafe pointers. + let p = self.as_mut_slice().as_mut_ptr(); + let mut r = 1; + let mut w = 1; + + while r < ln { + let p_r = p.offset(r as int); + let p_wm1 = p.offset((w - 1) as int); + if *p_r != *p_wm1 { + if r != w { + let p_w = p_wm1.offset(1); + mem::swap(&mut *p_r, &mut *p_w); + } + w += 1; + } + r += 1; + } + + self.truncate(w); + } + } } #[inline] -- cgit 1.4.1-3-g733a5