std: replace the str::each* fns/methods with byte iterators

This commit is contained in:
Huon Wilson 2013-06-09 00:38:58 +10:00
parent 4b806b4d06
commit 00f5916809
6 changed files with 79 additions and 161 deletions

View File

@ -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;
}

View File

@ -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]);
}
}
}

View File

@ -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())
}
}

View File

@ -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));
}
}

View File

@ -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)); }

View File

@ -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];