diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 4affea37e35b2..eceeb73a0157e 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -16,11 +16,11 @@ use clone::Clone; use cmp::{Eq, TotalEq}; use from_str::FromStr; use io::Writer; -use iter::{AdditiveIterator, Extendable, Iterator, Map}; +use iter::{DoubleEndedIterator, Rev, AdditiveIterator, Extendable, Iterator, Map}; use option::{Option, None, Some}; use str; use str::Str; -use slice::{CloneableVector, RevSplits, Splits, Vector, VectorVector, +use slice::{CloneableVector, Splits, Vector, VectorVector, ImmutableEqVector, OwnedVector, ImmutableVector}; use vec::Vec; @@ -29,14 +29,13 @@ use super::{BytesContainer, GenericPath, GenericPathUnsafe}; /// Iterator that yields successive components of a Path as &[u8] pub type Components<'a> = Splits<'a, u8>; /// Iterator that yields components of a Path in reverse as &[u8] -pub type RevComponents<'a> = RevSplits<'a, u8>; +pub type RevComponents<'a> = Rev>; /// Iterator that yields successive components of a Path as Option<&str> pub type StrComponents<'a> = Map<'a, &'a [u8], Option<&'a str>, Components<'a>>; /// Iterator that yields components of a Path in reverse as Option<&str> -pub type RevStrComponents<'a> = Map<'a, &'a [u8], Option<&'a str>, - RevComponents<'a>>; +pub type RevStrComponents<'a> = Rev>; /// Represents a POSIX file path #[deriving(Clone)] @@ -397,15 +396,7 @@ impl Path { /// Returns an iterator that yields each component of the path in reverse. /// See components() for details. pub fn rev_components<'a>(&'a self) -> RevComponents<'a> { - let v = if *self.repr.get(0) == SEP_BYTE { - self.repr.slice_from(1) - } else { self.repr.as_slice() }; - let mut ret = v.rsplit(is_sep_byte); - if v.is_empty() { - // consume the empty "" component - ret.next(); - } - ret + self.components().rev() } /// Returns an iterator that yields each component of the path as Option<&str>. @@ -417,7 +408,7 @@ impl Path { /// Returns an iterator that yields each component of the path in reverse as Option<&str>. /// See components() for details. pub fn rev_str_components<'a>(&'a self) -> RevStrComponents<'a> { - self.rev_components().map(str::from_utf8) + self.str_components().rev() } } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 74ca8dc57859a..679075fe6ca06 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -37,15 +37,13 @@ pub type StrComponents<'a> = Map<'a, &'a str, Option<&'a str>, /// /// Each component is yielded as Option<&str> for compatibility with PosixPath, but /// every component in WindowsPath is guaranteed to be Some. -pub type RevStrComponents<'a> = Rev, - CharSplits<'a, char>>>; +pub type RevStrComponents<'a> = Rev>; /// Iterator that yields successive components of a Path as &[u8] pub type Components<'a> = Map<'a, Option<&'a str>, &'a [u8], StrComponents<'a>>; /// Iterator that yields components of a Path in reverse as &[u8] -pub type RevComponents<'a> = Map<'a, Option<&'a str>, &'a [u8], - RevStrComponents<'a>>; +pub type RevComponents<'a> = Rev>; /// Represents a Windows path // Notes for Windows path impl: @@ -650,11 +648,7 @@ impl Path { /// Returns an iterator that yields each component of the path in reverse as a &[u8]. /// See str_components() for details. pub fn rev_components<'a>(&'a self) -> RevComponents<'a> { - fn convert<'a>(x: Option<&'a str>) -> &'a [u8] { - #![inline] - x.unwrap().as_bytes() - } - self.rev_str_components().map(convert) + self.components().rev() } fn equiv_prefix(&self, other: &Path) -> bool { diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index f5e064942e68b..180a142dea1f6 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -119,7 +119,6 @@ use result::{Ok, Err}; use mem; use mem::size_of; use kinds::marker; -use uint; use unstable::finally::try_finally; use raw::{Repr, Slice}; use RawVec = raw::Vec; @@ -148,7 +147,6 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { /// match a predicate function. pub struct Splits<'a, T> { v: &'a [T], - n: uint, pred: |t: &T|: 'a -> bool, finished: bool } @@ -158,11 +156,6 @@ impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { fn next(&mut self) -> Option<&'a [T]> { if self.finished { return None; } - if self.n == 0 { - self.finished = true; - return Some(self.v); - } - match self.v.iter().position(|x| (self.pred)(x)) { None => { self.finished = true; @@ -171,7 +164,6 @@ impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { Some(idx) => { let ret = Some(self.v.slice(0, idx)); self.v = self.v.slice(idx + 1, self.v.len()); - self.n -= 1; ret } } @@ -180,38 +172,18 @@ impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { #[inline] fn size_hint(&self) -> (uint, Option) { if self.finished { - return (0, Some(0)) - } - // if the predicate doesn't match anything, we yield one slice - // if it matches every element, we yield N+1 empty slices where - // N is either the number of elements or the number of splits. - match (self.v.len(), self.n) { - (0,_) => (1, Some(1)), - (_,0) => (1, Some(1)), - (l,n) => (1, cmp::min(l,n).checked_add(&1u)) + (0, Some(0)) + } else { + (1, Some(self.v.len() + 1)) } } } -/// An iterator over the slices of a vector separated by elements that -/// match a predicate function, from back to front. -pub struct RevSplits<'a, T> { - v: &'a [T], - n: uint, - pred: |t: &T|: 'a -> bool, - finished: bool -} - -impl<'a, T> Iterator<&'a [T]> for RevSplits<'a, T> { +impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> { #[inline] - fn next(&mut self) -> Option<&'a [T]> { + fn next_back(&mut self) -> Option<&'a [T]> { if self.finished { return None; } - if self.n == 0 { - self.finished = true; - return Some(self.v); - } - match self.v.iter().rposition(|x| (self.pred)(x)) { None => { self.finished = true; @@ -220,21 +192,42 @@ impl<'a, T> Iterator<&'a [T]> for RevSplits<'a, T> { Some(idx) => { let ret = Some(self.v.slice(idx + 1, self.v.len())); self.v = self.v.slice(0, idx); - self.n -= 1; ret } } } +} +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function, splitting at most a fixed number of times. +pub struct SplitsN<'a, T> { + iter: Splits<'a, T>, + count: uint, + invert: bool +} + +impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> { #[inline] - fn size_hint(&self) -> (uint, Option) { - if self.finished { - return (0, Some(0)) + fn next(&mut self) -> Option<&'a [T]> { + if self.count == 0 { + if self.iter.finished { + None + } else { + self.iter.finished = true; + Some(self.iter.v) + } + } else { + self.count -= 1; + if self.invert { self.iter.next_back() } else { self.iter.next() } } - match (self.v.len(), self.n) { - (0,_) => (1, Some(1)), - (_,0) => (1, Some(1)), - (l,n) => (1, cmp::min(l,n).checked_add(&1u)) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + if self.iter.finished { + (0, Some(0)) + } else { + (1, Some(cmp::min(self.count, self.iter.v.len()) + 1)) } } } @@ -747,18 +740,18 @@ pub trait ImmutableVector<'a, T> { /// separated by elements that match `pred`, limited to splitting /// at most `n` times. The matched element is not contained in /// the subslices. - fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> Splits<'a, T>; + fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; /// Returns an iterator over the subslices of the vector which are /// separated by elements that match `pred`. This starts at the /// end of the vector and works backwards. The matched element is /// not contained in the subslices. - fn rsplit(self, pred: |&T|: 'a -> bool) -> RevSplits<'a, T>; + fn rsplit(self, pred: |&T|: 'a -> bool) -> Rev>; /// Returns an iterator over the subslices of the vector which are /// separated by elements that match `pred` limited to splitting /// at most `n` times. This starts at the end of the vector and /// works backwards. The matched element is not contained in the /// subslices. - fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> RevSplits<'a, T>; + fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>; /** * Returns an iterator over all contiguous windows of length @@ -936,31 +929,33 @@ impl<'a,T> ImmutableVector<'a, T> for &'a [T] { #[inline] fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> { - self.splitn(uint::MAX, pred) - } - - #[inline] - fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> Splits<'a, T> { Splits { v: self, - n: n, pred: pred, finished: false } } #[inline] - fn rsplit(self, pred: |&T|: 'a -> bool) -> RevSplits<'a, T> { - self.rsplitn(uint::MAX, pred) + fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { + SplitsN { + iter: self.split(pred), + count: n, + invert: false + } } #[inline] - fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> RevSplits<'a, T> { - RevSplits { - v: self, - n: n, - pred: pred, - finished: false + fn rsplit(self, pred: |&T|: 'a -> bool) -> Rev> { + self.split(pred).rev() + } + + #[inline] + fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T> { + SplitsN { + iter: self.split(pred), + count: n, + invert: true } }