From db3eb7291a3af1b88052f8ad87da79d62bd60b81 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sun, 18 Aug 2013 13:57:34 +0200 Subject: [PATCH] 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. --- src/libstd/str.rs | 107 ++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 5022e558884f..ccb7349eefd7 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. +#[deriving(Clone)] +pub struct CharIterator<'self> { + priv string: &'self str, +} + +impl<'self> Iterator for CharIterator<'self> { + #[inline] + fn next(&mut self) -> Option { + 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) { + (self.string.len().saturating_add(3)/4, Some(self.string.len())) + } +} + +impl<'self> DoubleEndedIterator for CharIterator<'self> { + #[inline] + fn next_back(&mut self) -> Option { + 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. /// Use with the `std::iterator` module. #[deriving(Clone)] pub struct CharOffsetIterator<'self> { - priv index_front: uint, - priv index_back: uint, priv string: &'self str, + priv iter: CharIterator<'self>, } impl<'self> Iterator<(uint, char)> for CharOffsetIterator<'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)) - } else { - None - } + 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) { + self.iter.size_hint() } } impl<'self> DoubleEndedIterator<(uint, char)> for CharOffsetIterator<'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)) - } else { - None - } + 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 and their byte offsets in reverse order. -/// Use with the `std::iterator` module. -pub type CharOffsetRevIterator<'self> = - Invert>; - -/// External iterator for a string's characters. -/// Use with the `std::iterator` module. -pub type CharIterator<'self> = - Map<'self, (uint, char), char, CharOffsetIterator<'self>>; - /// External iterator for a string's characters in reverse order. /// Use with the `std::iterator` module. -pub type CharRevIterator<'self> = - Invert>>; +pub type CharRevIterator<'self> = Invert>; + +/// 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>; /// 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>>; +pub type ByteRevIterator<'self> = Invert>; /// 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.