diff --git a/src/libextra/time.rs b/src/libextra/time.rs index 758181980a8..dd3e4f48c63 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -16,6 +16,7 @@ use core::i32; use core::int; use core::io; use core::str; +use core::iterator::IteratorUtil; static NSEC_PER_SEC: i32 = 1_000_000_000_i32; @@ -261,7 +262,7 @@ impl Tm { priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> { fn match_str(s: &str, pos: uint, needle: &str) -> bool { let mut i = pos; - for str::each(needle) |ch| { + for needle.bytes_iter().advance |ch| { if s[i] != ch { return false; } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 739825ff0c5..f9d11164995 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -35,7 +35,7 @@ use str; use to_str::ToStr; use uint; use vec; -use vec::{OwnedVector, OwnedCopyableVector}; +use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector}; #[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq}; @@ -1249,42 +1249,6 @@ pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { result } -/// Iterate over the bytes in a string -#[inline(always)] -pub fn each(s: &str, it: &fn(u8) -> bool) -> bool { - eachi(s, |_i, b| it(b)) -} - -/// Iterate over the bytes in a string, with indices -#[inline(always)] -pub fn eachi(s: &str, it: &fn(uint, u8) -> bool) -> bool { - let mut pos = 0; - let len = s.len(); - - while pos < len { - if !it(pos, s[pos]) { return false; } - pos += 1; - } - return true; -} - -/// Iterate over the bytes in a string in reverse -#[inline(always)] -pub fn each_reverse(s: &str, it: &fn(u8) -> bool) -> bool { - eachi_reverse(s, |_i, b| it(b) ) -} - -/// Iterate over the bytes in a string in reverse, with indices -#[inline(always)] -pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) -> bool { - let mut pos = s.len(); - while pos > 0 { - pos -= 1; - if !it(pos, s[pos]) { return false; } - } - return true; -} - /* Section: Searching */ @@ -1604,7 +1568,7 @@ pub fn rfind_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> O // Utility used by various searching functions fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { let mut i = at; - for each(needle) |c| { if haystack[i] != c { return false; } i += 1u; } + for needle.bytes_iter().advance |c| { if haystack[i] != c { return false; } i += 1u; } return true; } @@ -2557,10 +2521,8 @@ pub trait StrSlice<'self> { fn contains_char(&self, needle: char) -> bool; fn iter(&self) -> StrCharIterator<'self>; fn rev_iter(&self) -> StrCharRevIterator<'self>; - fn each(&self, it: &fn(u8) -> bool) -> bool; - fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool; - fn each_reverse(&self, it: &fn(u8) -> bool) -> bool; - fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool; + fn bytes_iter(&self) -> StrBytesIterator<'self>; + fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; fn is_whitespace(&self) -> bool; @@ -2628,20 +2590,14 @@ impl<'self> StrSlice<'self> for &'self str { } } - /// Iterate over the bytes in a string - #[inline] - fn each(&self, it: &fn(u8) -> bool) -> bool { each(*self, it) } - /// Iterate over the bytes in a string, with indices - #[inline] - fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool { eachi(*self, it) } - /// Iterate over the bytes in a string - #[inline] - fn each_reverse(&self, it: &fn(u8) -> bool) -> bool { each_reverse(*self, it) } - /// Iterate over the bytes in a string, with indices - #[inline] - fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool { - eachi_reverse(*self, it) + fn bytes_iter(&self) -> StrBytesIterator<'self> { + StrBytesIterator { it: as_bytes_slice(*self).iter() } } + fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self> { + StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() } + } + + /// Returns true if one string ends with another #[inline] fn ends_with(&self, needle: &str) -> bool { @@ -2832,6 +2788,32 @@ impl<'self> Iterator<char> for StrCharRevIterator<'self> { } } +/// External iterator for a string's bytes. Use with the `std::iterator` +/// module. +pub struct StrBytesIterator<'self> { + priv it: vec::VecIterator<'self, u8> +} + +impl<'self> Iterator<u8> for StrBytesIterator<'self> { + #[inline] + fn next(&mut self) -> Option<u8> { + self.it.next().map_consume(|&x| x) + } +} + +/// External iterator for a string's bytes in reverse order. Use with +/// the `std::iterator` module. +pub struct StrBytesRevIterator<'self> { + priv it: vec::VecRevIterator<'self, u8> +} + +impl<'self> Iterator<u8> for StrBytesRevIterator<'self> { + #[inline] + fn next(&mut self) -> Option<u8> { + self.it.next().map_consume(|&x| x) + } +} + #[cfg(test)] mod tests { use iterator::IteratorUtil; @@ -3922,102 +3904,6 @@ mod tests { } } - #[test] - fn test_each() { - let s = ~"ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = 0; - - for s.each |b| { - assert_eq!(b, v[pos]); - pos += 1; - } - } - - #[test] - fn test_each_empty() { - for "".each |b| { - assert_eq!(b, 0u8); - } - } - - #[test] - fn test_eachi() { - let s = ~"ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = 0; - - for s.eachi |i, b| { - assert_eq!(pos, i); - assert_eq!(b, v[pos]); - pos += 1; - } - } - - #[test] - fn test_eachi_empty() { - for "".eachi |i, b| { - assert_eq!(i, 0); - assert_eq!(b, 0); - } - } - - #[test] - fn test_each_reverse() { - let s = ~"ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = v.len(); - - for s.each_reverse |b| { - pos -= 1; - assert_eq!(b, v[pos]); - } - } - - #[test] - fn test_each_empty_reverse() { - for "".each_reverse |b| { - assert_eq!(b, 0u8); - } - } - - #[test] - fn test_eachi_reverse() { - let s = ~"ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = v.len(); - - for s.eachi_reverse |i, b| { - pos -= 1; - assert_eq!(pos, i); - assert_eq!(b, v[pos]); - } - } - - #[test] - fn test_eachi_reverse_empty() { - for "".eachi_reverse |i, b| { - assert_eq!(i, 0); - assert_eq!(b, 0); - } - } - #[test] fn test_escape_unicode() { assert_eq!(escape_unicode("abc"), ~"\\x61\\x62\\x63"); @@ -4097,4 +3983,36 @@ mod tests { } assert_eq!(pos, v.len()); } + + #[test] + fn test_bytes_iterator() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = 0; + + for s.bytes_iter().advance |b| { + assert_eq!(b, v[pos]); + pos += 1; + } + } + + #[test] + fn test_bytes_rev_iterator() { + let s = ~"ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = v.len(); + + for s.bytes_rev_iter().advance |b| { + pos -= 1; + assert_eq!(b, v[pos]); + } + } } diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index 3b31d70f7a1..e288d605714 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -15,6 +15,7 @@ use str; use str::StrSlice; use cast; use old_iter::BaseIter; +use iterator::IteratorUtil; use vec::{CopyableVector, ImmutableVector, OwnedVector}; /// Datatype to hold one ascii character. It is 8 bit long. @@ -101,10 +102,7 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self str { #[inline(always)] fn is_ascii(&self) -> bool { - for self.each |b| { - if !b.is_ascii() { return false; } - } - true + self.bytes_iter().all(|b| b.is_ascii()) } } diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index a046395b6f5..51fbaee7a33 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -10,6 +10,7 @@ /* The compiler code necessary to support the bytes! extension. */ +use core::iterator::IteratorUtil; use ast; use codemap::span; use ext::base::*; @@ -27,7 +28,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> bas ast::expr_lit(lit) => match lit.node { // string literal, push each byte to vector expression ast::lit_str(s) => { - for s.each |byte| { + for s.bytes_iter().advance |byte| { bytes.push(cx.expr_u8(sp, byte)); } } diff --git a/src/test/run-pass/linear-for-loop.rs b/src/test/run-pass/linear-for-loop.rs index 7ab915a9628..a42d70f5ae2 100644 --- a/src/test/run-pass/linear-for-loop.rs +++ b/src/test/run-pass/linear-for-loop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::str; +use std::iterator::IteratorUtil; pub fn main() { let x = ~[1, 2, 3]; @@ -18,7 +18,7 @@ pub fn main() { assert_eq!(y, 6); let s = ~"hello there"; let mut i: int = 0; - for str::each(s) |c| { + for s.bytes_iter().advance |c| { if i == 0 { assert!((c == 'h' as u8)); } if i == 1 { assert!((c == 'e' as u8)); } if i == 2 { assert!((c == 'l' as u8)); } diff --git a/src/test/run-pass/utf8.rs b/src/test/run-pass/utf8.rs index fd5bc07e015..8a845439058 100644 --- a/src/test/run-pass/utf8.rs +++ b/src/test/run-pass/utf8.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::str; +use std::iterator::IteratorUtil; pub fn main() { let yen: char = '¥'; // 0xa5 @@ -43,7 +43,7 @@ pub fn main() { fn check_str_eq(a: ~str, b: ~str) { let mut i: int = 0; - for str::each(a) |ab| { + for a.bytes_iter().advance |ab| { debug!(i); debug!(ab); let bb: u8 = b[i];