about summary refs log tree commit diff
diff options
context:
space:
mode:
authorblake2-ppc <blake2-ppc>2013-08-18 13:57:34 +0200
committerblake2-ppc <blake2-ppc>2013-08-19 11:20:00 +0200
commitdb3eb7291a3af1b88052f8ad87da79d62bd60b81 (patch)
tree9945bd29ce3b457bbff6e3f594d8655d04c0238e
parent8a5889d2a2eb4b2c9d41f6f3991fdd2622933047 (diff)
std::str: Implement CharIterator separately
Let CharIterator be a separate type from CharOffsetIterator (so that
CharIterator can be cloned, for example).

Implement CharOffsetIterator by using the same technique as the method
subslice_offset.
-rw-r--r--src/libstd/str.rs103
1 files changed, 68 insertions, 35 deletions
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 5022e558884..ccb7349eefd 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -255,56 +255,94 @@ impl<'self, C: CharEq> CharEq for &'self [C] {
 Section: Iterators
 */
 
-/// External iterator for a string's characters and their byte offsets.
-/// Use with the `std::iterator` module.
+/// External iterator for a string's characters.
 #[deriving(Clone)]
-pub struct CharOffsetIterator<'self> {
-    priv index_front: uint,
-    priv index_back: uint,
+pub struct CharIterator<'self> {
     priv string: &'self str,
 }
 
-impl<'self> Iterator<(uint, char)> for CharOffsetIterator<'self> {
+impl<'self> Iterator<char> for CharIterator<'self> {
     #[inline]
-    fn next(&mut self) -> Option<(uint, char)> {
-        if self.index_front < self.index_back {
-            let CharRange {ch, next} = self.string.char_range_at(self.index_front);
-            let index = self.index_front;
-            self.index_front = next;
-            Some((index, ch))
+    fn next(&mut self) -> Option<char> {
+        if self.string.len() != 0 {
+            let CharRange {ch, next} = self.string.char_range_at(0);
+            unsafe {
+                self.string = raw::slice_unchecked(self.string, next, self.string.len());
+            }
+            Some(ch)
         } else {
             None
         }
     }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        (self.string.len().saturating_add(3)/4, Some(self.string.len()))
+    }
 }
 
-impl<'self> DoubleEndedIterator<(uint, char)> for CharOffsetIterator<'self> {
+impl<'self> DoubleEndedIterator<char> for CharIterator<'self> {
     #[inline]
-    fn next_back(&mut self) -> Option<(uint, char)> {
-        if self.index_front < self.index_back {
-            let CharRange {ch, next} = self.string.char_range_at_reverse(self.index_back);
-            self.index_back = next;
-            Some((next, ch))
+    fn next_back(&mut self) -> Option<char> {
+        if self.string.len() != 0 {
+            let CharRange {ch, next} = self.string.char_range_at_reverse(self.string.len());
+            unsafe {
+                self.string = raw::slice_unchecked(self.string, 0, next);
+            }
+            Some(ch)
         } else {
             None
         }
     }
 }
 
-/// External iterator for a string's characters and their byte offsets in reverse order.
-/// Use with the `std::iterator` module.
-pub type CharOffsetRevIterator<'self> =
-    Invert<CharOffsetIterator<'self>>;
 
-/// External iterator for a string's characters.
+/// External iterator for a string's characters and their byte offsets.
 /// Use with the `std::iterator` module.
-pub type CharIterator<'self> =
-    Map<'self, (uint, char), char, CharOffsetIterator<'self>>;
+#[deriving(Clone)]
+pub struct CharOffsetIterator<'self> {
+    priv string: &'self str,
+    priv iter: CharIterator<'self>,
+}
+
+impl<'self> Iterator<(uint, char)> for CharOffsetIterator<'self> {
+    #[inline]
+    fn next(&mut self) -> Option<(uint, char)> {
+        let offset = do self.string.as_imm_buf |a, _| {
+            do self.iter.string.as_imm_buf |b, _| {
+                b as uint - a as uint
+            }
+        };
+        self.iter.next().map_move(|ch| (offset, ch))
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'self> DoubleEndedIterator<(uint, char)> for CharOffsetIterator<'self> {
+    #[inline]
+    fn next_back(&mut self) -> Option<(uint, char)> {
+        self.iter.next_back().map_move(|ch| {
+            let offset = do self.string.as_imm_buf |a, _| {
+                do self.iter.string.as_imm_buf |b, len| {
+                    b as uint - a as uint + len
+                }
+            };
+            (offset, ch)
+        })
+    }
+}
 
 /// External iterator for a string's characters in reverse order.
 /// Use with the `std::iterator` module.
-pub type CharRevIterator<'self> =
-    Invert<Map<'self, (uint, char), char, CharOffsetIterator<'self>>>;
+pub type CharRevIterator<'self> = Invert<CharIterator<'self>>;
+
+/// External iterator for a string's characters and their byte offsets in reverse order.
+/// Use with the `std::iterator` module.
+pub type CharOffsetRevIterator<'self> = Invert<CharOffsetIterator<'self>>;
 
 /// External iterator for a string's bytes.
 /// Use with the `std::iterator` module.
@@ -313,8 +351,7 @@ pub type ByteIterator<'self> =
 
 /// External iterator for a string's bytes in reverse order.
 /// Use with the `std::iterator` module.
-pub type ByteRevIterator<'self> =
-    Invert<Map<'self, &'self u8, u8, vec::VecIterator<'self, u8>>>;
+pub type ByteRevIterator<'self> = Invert<ByteIterator<'self>>;
 
 /// An iterator over the substrings of a string, separated by `sep`.
 #[deriving(Clone)]
@@ -1218,7 +1255,7 @@ impl<'self> StrSlice<'self> for &'self str {
     /// ~~~
     #[inline]
     fn iter(&self) -> CharIterator<'self> {
-        self.char_offset_iter().map(|(_, c)| c)
+        CharIterator{string: *self}
     }
 
     /// An iterator over the characters of `self`, in reverse order.
@@ -1242,11 +1279,7 @@ impl<'self> StrSlice<'self> for &'self str {
     /// An iterator over the characters of `self` and their byte offsets.
     #[inline]
     fn char_offset_iter(&self) -> CharOffsetIterator<'self> {
-        CharOffsetIterator {
-            index_front: 0,
-            index_back: self.len(),
-            string: *self
-        }
+        CharOffsetIterator{string: *self, iter: self.iter()}
     }
 
     /// An iterator over the characters of `self` and their byte offsets.