From 4b806b4d06a6b82771657f9b79728d3fba84ebed Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sat, 8 Jun 2013 22:04:46 +1000 Subject: [PATCH] std: remove each_char* fns and methods from str, replaced by iterators. --- src/compiletest/runtest.rs | 3 +- src/libextra/fileinput.rs | 3 +- src/libextra/json.rs | 6 +- src/libextra/net_url.rs | 7 +- src/librustc/back/link.rs | 3 +- src/libstd/rand.rs | 3 +- src/libstd/repr.rs | 3 +- src/libstd/str.rs | 193 ++++++++++---------------------- src/libsyntax/parse/comments.rs | 5 +- src/test/run-pass/issue-2904.rs | 3 +- 10 files changed, 80 insertions(+), 149 deletions(-) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index c174057aaaa..1015373d7ce 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -22,6 +22,7 @@ use procsrv; use util; use util::logv; +use core::iterator::IteratorUtil; use core::io; use core::os; use core::str; @@ -780,7 +781,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps, Some(~"")); let mut exitcode : int = 0; - for str::each_char(exitcode_out) |c| { + for exitcode_out.iter().advance |c| { if !c.is_digit() { break; } exitcode = exitcode * 10 + match c { '0' .. '9' => c as int - ('0' as int), diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs index 3afa9b51c59..16082732715 100644 --- a/src/libextra/fileinput.rs +++ b/src/libextra/fileinput.rs @@ -414,6 +414,7 @@ mod test { use super::{FileInput, pathify, input_vec, input_vec_state}; + use core::iterator::IteratorUtil; use core::io; use core::str; use core::uint; @@ -455,7 +456,7 @@ mod test { let fi = FileInput::from_vec(copy filenames); - for "012".each_chari |line, c| { + for "012".iter().enumerate().advance |(line, c)| { assert_eq!(fi.read_byte(), c as int); assert_eq!(fi.state().line_num, line); assert_eq!(fi.state().line_num_file, 0); diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 22abe0edbb9..fc1597ffed4 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -18,6 +18,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::char; use core::float; use core::hashmap::HashMap; @@ -58,7 +59,7 @@ pub struct Error { fn escape_str(s: &str) -> ~str { let mut escaped = ~"\""; - for str::each_char(s) |c| { + for s.iter().advance |c| { match c { '"' => escaped += "\\\"", '\\' => escaped += "\\\\", @@ -913,7 +914,8 @@ impl serialize::Decoder for Decoder { fn read_char(&mut self) -> char { let mut v = ~[]; - for str::each_char(self.read_str()) |c| { v.push(c) } + let s = self.read_str(); + for s.iter().advance |c| { v.push(c) } if v.len() != 1 { fail!("string must have one character") } v[0] } diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 08540775864..f26019d9282 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::cmp::Eq; use core::io::{Reader, ReaderUtil}; use core::io; @@ -358,7 +359,7 @@ pub fn query_to_str(query: &Query) -> ~str { // returns the scheme and the rest of the url, or a parsing error pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> { - for str::each_chari(rawurl) |i,c| { + for rawurl.iter().enumerate().advance |(i,c)| { match c { 'A' .. 'Z' | 'a' .. 'z' => loop, '0' .. '9' | '+' | '-' | '.' => { @@ -418,7 +419,7 @@ fn get_authority(rawurl: &str) -> let mut colon_count = 0; let mut (pos, begin, end) = (0, 2, len); - for str::each_chari(rawurl) |i,c| { + for rawurl.iter().enumerate().advance |(i,c)| { if i < 2 { loop; } // ignore the leading // // deal with input class first @@ -562,7 +563,7 @@ fn get_path(rawurl: &str, authority: bool) -> Result<(~str, ~str), ~str> { let len = str::len(rawurl); let mut end = len; - for str::each_chari(rawurl) |i,c| { + for rawurl.iter().enumerate().advance |(i,c)| { match c { 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '&' |'\'' | '(' | ')' | '.' | '@' | ':' | '%' | '/' | '+' | '!' | '*' | ',' | ';' | '=' diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 3c10324fd3d..29e7ba0e62f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -22,6 +22,7 @@ use middle::trans::common::CrateContext; use middle::ty; use util::ppaux; +use core::iterator::IteratorUtil; use core::char; use core::hash::Streaming; use core::hash; @@ -636,7 +637,7 @@ pub fn get_symbol_hash(ccx: @CrateContext, t: ty::t) -> @str { // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $ pub fn sanitize(s: &str) -> ~str { let mut result = ~""; - for str::each_char(s) |c| { + for s.iter().advance |c| { match c { // Escape these with $ sequences '@' => result += "$SP$", diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index b763c1c2d76..7946f7e4f13 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -43,6 +43,7 @@ fn main () { use cast; use cmp; use int; +use iterator::IteratorUtil; use local_data; use prelude::*; use str; @@ -479,7 +480,7 @@ impl RngUtil for R { fn gen_char_from(&mut self, chars: &str) -> char { assert!(!chars.is_empty()); let mut cs = ~[]; - for str::each_char(chars) |c| { cs.push(c) } + for chars.iter().advance |c| { cs.push(c) } self.choose(cs) } diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 14bec48782f..46f69d020d1 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -22,6 +22,7 @@ use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use intrinsic::Opaque; use io::{Writer, WriterUtil}; +use iterator::IteratorUtil; use libc::c_void; use managed; use ptr; @@ -209,7 +210,7 @@ impl ReprVisitor { pub fn write_escaped_slice(&self, slice: &str) { self.writer.write_char('"'); - for slice.each_char |ch| { + for slice.iter().advance |ch| { self.writer.write_escaped_char(ch); } self.writer.write_char('"'); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index d0345a3953e..739825ff0c5 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -25,7 +25,7 @@ use clone::Clone; use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use container::Container; use iter::Times; -use iterator::Iterator; +use iterator::{Iterator, IteratorUtil}; use libc; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; @@ -608,11 +608,7 @@ pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] { /// Convert a string to a unique vector of characters pub fn to_chars(s: &str) -> ~[char] { - let mut buf = ~[]; - for each_char(s) |c| { - buf.push(c); - } - buf + s.iter().collect() } /** @@ -856,12 +852,12 @@ pub fn levdistance(s: &str, t: &str) -> uint { let mut dcol = vec::from_fn(tlen + 1, |x| x); - for s.each_chari |i, sc| { + for s.iter().enumerate().advance |(i, sc)| { let mut current = i; dcol[0] = current + 1; - for t.each_chari |j, tc| { + for t.iter().enumerate().advance |(j, tc)| { let next = dcol[j + 1]; @@ -943,7 +939,7 @@ pub fn each_split_within<'a>(ss: &'a str, let mut cont = true; let slice: &fn() = || { cont = it(slice(ss, slice_start, last_end)) }; - let machine: &fn(uint, char) -> bool = |i, c| { + let machine: &fn((uint, char)) -> bool = |(i, c)| { let whitespace = if char::is_whitespace(c) { Ws } else { Cr }; let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim }; @@ -968,12 +964,12 @@ pub fn each_split_within<'a>(ss: &'a str, cont }; - str::each_chari(ss, machine); + ss.iter().enumerate().advance(machine); // Let the automaton 'run out' by supplying trailing whitespace let mut fake_i = ss.len(); while cont && match state { B | C => true, A => false } { - machine(fake_i, ' '); + machine((fake_i, ' ')); fake_i += 1; } return cont; @@ -1247,7 +1243,7 @@ pub fn any(ss: &str, pred: &fn(char) -> bool) -> bool { pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { let mut result = ~""; reserve(&mut result, len(ss)); - for ss.each_char |cc| { + for ss.iter().advance |cc| { str::push_char(&mut result, ff(cc)); } result @@ -1289,55 +1285,6 @@ pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) -> bool { return true; } -/// Iterate over each char of a string, without allocating -#[inline(always)] -pub fn each_char(s: &str, it: &fn(char) -> bool) -> bool { - let mut i = 0; - let len = len(s); - while i < len { - let CharRange {ch, next} = char_range_at(s, i); - if !it(ch) { return false; } - i = next; - } - return true; -} - -/// Iterates over the chars in a string, with indices -#[inline(always)] -pub fn each_chari(s: &str, it: &fn(uint, char) -> bool) -> bool { - let mut pos = 0; - let mut ch_pos = 0u; - let len = s.len(); - while pos < len { - let CharRange {ch, next} = char_range_at(s, pos); - pos = next; - if !it(ch_pos, ch) { return false; } - ch_pos += 1u; - } - return true; -} - -/// Iterates over the chars in a string in reverse -#[inline(always)] -pub fn each_char_reverse(s: &str, it: &fn(char) -> bool) -> bool { - each_chari_reverse(s, |_, c| it(c)) -} - -/// Iterates over the chars in a string in reverse, with indices -#[inline(always)] -pub fn each_chari_reverse(s: &str, it: &fn(uint, char) -> bool) -> bool { - let mut pos = s.len(); - let mut ch_pos = s.char_len(); - while pos > 0 { - let CharRange {ch, next} = char_range_at_reverse(s, pos); - pos = next; - ch_pos -= 1; - - if !it(ch_pos, ch) { return false; } - } - return true; -} - /* Section: Searching */ @@ -1880,7 +1827,7 @@ pub fn is_utf16(v: &[u16]) -> bool { /// Converts to a vector of `u16` encoded as UTF-16 pub fn to_utf16(s: &str) -> ~[u16] { let mut u = ~[]; - for s.each_char |ch| { + for s.iter().advance |ch| { // Arithmetic with u32 literals is easier on the eyes than chars. let mut ch = ch as u32; @@ -2396,7 +2343,7 @@ pub fn capacity(s: &const ~str) -> uint { pub fn escape_default(s: &str) -> ~str { let mut out: ~str = ~""; reserve_at_least(&mut out, str::len(s)); - for s.each_char |c| { + for s.iter().advance |c| { push_str(&mut out, char::escape_default(c)); } out @@ -2406,7 +2353,7 @@ pub fn escape_default(s: &str) -> ~str { pub fn escape_unicode(s: &str) -> ~str { let mut out: ~str = ~""; reserve_at_least(&mut out, str::len(s)); - for s.each_char |c| { + for s.iter().advance |c| { push_str(&mut out, char::escape_unicode(c)); } out @@ -2608,15 +2555,12 @@ pub trait StrSlice<'self> { fn any(&self, it: &fn(char) -> bool) -> bool; fn contains<'a>(&self, needle: &'a str) -> bool; fn contains_char(&self, needle: char) -> bool; - fn char_iter(&self) -> StrCharIterator<'self>; + 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 each_char(&self, it: &fn(char) -> bool) -> bool; - fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool; - fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool; - fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; fn is_whitespace(&self) -> bool; @@ -2670,12 +2614,19 @@ impl<'self> StrSlice<'self> for &'self str { } #[inline] - fn char_iter(&self) -> StrCharIterator<'self> { + fn iter(&self) -> StrCharIterator<'self> { StrCharIterator { index: 0, string: *self } } + #[inline] + fn rev_iter(&self) -> StrCharRevIterator<'self> { + StrCharRevIterator { + index: self.len(), + string: *self + } + } /// Iterate over the bytes in a string #[inline] @@ -2691,25 +2642,6 @@ impl<'self> StrSlice<'self> for &'self str { fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool { eachi_reverse(*self, it) } - /// Iterate over the chars in a string - #[inline] - fn each_char(&self, it: &fn(char) -> bool) -> bool { each_char(*self, it) } - /// Iterate over the chars in a string, with indices - #[inline] - fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool { - each_chari(*self, it) - } - /// Iterate over the chars in a string in reverse - #[inline] - fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool { - each_char_reverse(*self, it) - } - /// Iterate over the chars in a string in reverse, with indices from the - /// end - #[inline] - fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool { - each_chari_reverse(*self, it) - } /// Returns true if one string ends with another #[inline] fn ends_with(&self, needle: &str) -> bool { @@ -2880,6 +2812,25 @@ impl<'self> Iterator for StrCharIterator<'self> { } } } +/// External iterator for a string's characters in reverse order. Use +/// with the `std::iterator` module. +pub struct StrCharRevIterator<'self> { + priv index: uint, + priv string: &'self str, +} + +impl<'self> Iterator for StrCharRevIterator<'self> { + #[inline] + fn next(&mut self) -> Option { + if self.index > 0 { + let CharRange {ch, next} = char_range_at_reverse(self.string, self.index); + self.index = next; + Some(ch) + } else { + None + } + } +} #[cfg(test)] mod tests { @@ -4067,52 +4018,6 @@ mod tests { } } - #[test] - fn test_each_char() { - let s = ~"ศไทย中华Việt Nam"; - let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = 0; - for s.each_char |ch| { - assert_eq!(ch, v[pos]); - pos += 1; - } - } - - #[test] - fn test_each_chari() { - let s = ~"ศไทย中华Việt Nam"; - let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = 0; - for s.each_chari |i, ch| { - assert_eq!(pos, i); - assert_eq!(ch, v[pos]); - pos += 1; - } - } - - #[test] - fn test_each_char_reverse() { - let s = ~"ศไทย中华Việt Nam"; - let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = v.len(); - for s.each_char_reverse |ch| { - pos -= 1; - assert_eq!(ch, v[pos]); - } - } - - #[test] - fn test_each_chari_reverse() { - let s = ~"ศไทย中华Việt Nam"; - let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = v.len(); - for s.each_chari_reverse |i, ch| { - pos -= 1; - assert_eq!(pos, i); - assert_eq!(ch, v[pos]); - } - } - #[test] fn test_escape_unicode() { assert_eq!(escape_unicode("abc"), ~"\\x61\\x62\\x63"); @@ -4168,7 +4073,23 @@ mod tests { let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; let mut pos = 0; - let mut it = s.char_iter(); + let mut it = s.iter(); + + for it.advance |c| { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); + } + + #[test] + fn test_rev_iterator() { + use iterator::*; + let s = ~"ศไทย中华Việt Nam"; + let v = ~['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; + + let mut pos = 0; + let mut it = s.rev_iter(); for it.advance |c| { assert_eq!(c, v[pos]); diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 54fba29a19a..22b9e7d6c5e 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -21,6 +21,7 @@ use parse::token; use parse::token::{get_ident_interner}; use parse; +use core::iterator::IteratorUtil; use core::io; use core::str; use core::uint; @@ -78,7 +79,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { if line.trim().is_empty() { loop; } - for line.each_chari |j, c| { + for line.iter().enumerate().advance |(j, c)| { if j >= i { break; } @@ -91,7 +92,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { return do lines.map |line| { let mut chars = ~[]; - for str::each_char(*line) |c| { chars.push(c) } + for line.iter().advance |c| { chars.push(c) } if i > chars.len() { ~"" } else { diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 7670a7eee7c..fcebb528c10 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -14,6 +14,7 @@ extern mod extra; +use std::iterator::IteratorUtil; use std::io::ReaderUtil; use std::io; use std::str; @@ -67,7 +68,7 @@ fn read_board_grid(in: rdr) -> ~[~[square]] { let mut grid = ~[]; for in.each_line |line| { let mut row = ~[]; - for str::each_char(line) |c| { + for line.iter().advance |c| { row.push(square_from_char(c)) } grid.push(row)