about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/path/posix.rs23
-rw-r--r--src/libstd/path/windows.rs14
-rw-r--r--src/libstd/slice.rs111
3 files changed, 64 insertions, 84 deletions
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 4affea37e35..eceeb73a015 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<Components<'a>>;
 
 /// 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<StrComponents<'a>>;
 
 /// 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 74ca8dc5785..679075fe6ca 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<Map<'a, &'a str, Option<&'a str>,
-                                                 CharSplits<'a, char>>>;
+pub type RevStrComponents<'a> = Rev<StrComponents<'a>>;
 
 /// 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<Components<'a>>;
 
 /// 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 f5e064942e6..180a142dea1 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<uint>) {
         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<uint>) {
-        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<uint>) {
+        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<Splits<'a, T>>;
     /// 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<Splits<'a, T>> {
+        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
         }
     }