From 1e8982bdb26208d9d9ed4cdcbcd21cc9ef35bd46 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 9 Jun 2013 23:10:50 +1000 Subject: [PATCH 01/21] std: replace str::each_split* with an iterator --- src/compiletest/header.rs | 4 +- src/compiletest/runtest.rs | 19 +- src/libextra/fileinput.rs | 5 +- src/libextra/getopts.rs | 10 +- src/libextra/net_ip.rs | 15 +- src/libextra/net_url.rs | 2 +- src/libextra/num/rational.rs | 15 +- src/libextra/terminfo/parser/compiled.rs | 6 +- src/libextra/terminfo/searcher.rs | 5 +- src/librustc/driver/driver.rs | 16 +- src/librustc/metadata/cstore.rs | 3 +- src/librusti/rusti.rc | 6 +- src/librustpkg/path_util.rs | 3 +- src/librustpkg/rustpkg.rc | 7 +- src/libstd/os.rs | 6 +- src/libstd/path.rs | 60 +-- src/libstd/str.rs | 586 +++++++---------------- src/libsyntax/parse/parser.rs | 11 +- src/test/bench/sudoku.rs | 5 +- 19 files changed, 269 insertions(+), 515 deletions(-) diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index b147dc806e211..782571fc6791e 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -141,8 +141,8 @@ fn parse_check_line(line: &str) -> Option<~str> { fn parse_exec_env(line: &str) -> Option<(~str, ~str)> { do parse_name_value_directive(line, ~"exec-env").map |nv| { // nv is either FOO or FOO=BAR - let mut strs = ~[]; - for str::each_splitn_char(*nv, '=', 1u) |s| { strs.push(s.to_owned()); } + let mut strs: ~[~str] = nv.splitn_iter('=', 1).transform(|s| s.to_owned()).collect(); + match strs.len() { 1u => (strs.pop(), ~""), 2u => { diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index b4a20886ad866..444f4c8d53908 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -278,7 +278,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { // check if each line in props.check_lines appears in the // output (in order) let mut i = 0u; - for str::each_line(ProcRes.stdout) |line| { + for ProcRes.stdout.line_iter().advance |line| { if check_lines[i].trim() == line.trim() { i += 1u; } @@ -308,7 +308,7 @@ fn check_error_patterns(props: &TestProps, let mut next_err_idx = 0u; let mut next_err_pat = &props.error_patterns[next_err_idx]; let mut done = false; - for str::each_line(ProcRes.stderr) |line| { + for ProcRes.stderr.line_iter().advance |line| { if str::contains(line, *next_err_pat) { debug!("found error pattern %s", *next_err_pat); next_err_idx += 1u; @@ -358,7 +358,7 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError], // filename:line1:col1: line2:col2: *warning:* msg // where line1:col1: is the starting point, line2:col2: // is the ending point, and * represents ANSI color codes. - for str::each_line(ProcRes.stderr) |line| { + for ProcRes.stderr.line_iter().advance |line| { let mut was_expected = false; for vec::eachi(expected_errors) |i, ee| { if !found_flags[i] { @@ -612,15 +612,11 @@ fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) -> } fn split_maybe_args(argstr: &Option<~str>) -> ~[~str] { - fn rm_whitespace(v: ~[~str]) -> ~[~str] { - v.filtered(|s| !str::is_whitespace(*s)) - } - match *argstr { Some(ref s) => { - let mut ss = ~[]; - for str::each_split_char(*s, ' ') |s| { ss.push(s.to_owned()) } - rm_whitespace(ss) + s.split_iter(' ') + .filter_map(|s| if s.is_whitespace() {None} else {Some(s.to_owned())}) + .collect() } None => ~[] } @@ -739,8 +735,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps, let cmdline = make_cmdline("", args.prog, args.args); // get bare program string - let mut tvec = ~[]; - for str::each_split_char(args.prog, '/') |ts| { tvec.push(ts.to_owned()) } + let tvec: ~[~str] = args.prog.split_iter('/').transform(|ts| ts.to_owned()).collect(); let prog_short = tvec.pop(); // copy to target diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs index 1608273271501..add857ca9ed07 100644 --- a/src/libextra/fileinput.rs +++ b/src/libextra/fileinput.rs @@ -416,7 +416,6 @@ mod test { use core::iterator::IteratorUtil; use core::io; - use core::str; use core::uint; use core::vec; @@ -527,9 +526,7 @@ mod test { } for input_vec_state(filenames) |line, state| { - let nums = do vec::build |p| { - for str::each_split_char(line, ' ') |s| { p(s.to_owned()); } - }; + let nums: ~[&str] = line.split_iter(' ').collect(); let file_num = uint::from_str(nums[0]).get(); let line_num = uint::from_str(nums[1]).get(); assert_eq!(line_num, state.line_num_file); diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 2bc0a8ef6b09f..af026473a1bf6 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -82,6 +82,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::cmp::Eq; use core::result::{Err, Ok}; use core::result; @@ -247,14 +248,13 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { let mut i_arg = None; if cur[1] == '-' as u8 { let tail = str::slice(cur, 2, curlen); - let mut tail_eq = ~[]; - for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) } + let tail_eq: ~[&str] = tail.split_iter('=').collect(); if tail_eq.len() <= 1 { names = ~[Long(tail.to_owned())]; } else { names = - ~[Long(copy tail_eq[0])]; - i_arg = Some(copy tail_eq[1]); + ~[Long(tail_eq[0].to_owned())]; + i_arg = Some(tail_eq[1].to_owned()); } } else { let mut j = 1; @@ -635,7 +635,7 @@ pub mod groups { // Normalize desc to contain words separated by one space character let mut desc_normalized_whitespace = ~""; - for str::each_word(desc) |word| { + for desc.word_iter().advance |word| { desc_normalized_whitespace.push_str(word); desc_normalized_whitespace.push_char(' '); } diff --git a/src/libextra/net_ip.rs b/src/libextra/net_ip.rs index ddbf09e40eb92..760fc7485e069 100644 --- a/src/libextra/net_ip.rs +++ b/src/libextra/net_ip.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::libc; use core::comm::{stream, SharedChan}; use core::ptr; @@ -158,9 +159,7 @@ pub mod v4 { use core::cast::transmute; use core::result; - use core::str; use core::uint; - use core::vec; /** * Convert a str to `ip_addr` @@ -199,14 +198,12 @@ pub mod v4 { } } pub fn parse_to_ipv4_rep(ip: &str) -> result::Result { - let mut parts = ~[]; - for str::each_split_char(ip, '.') |s| { parts.push(s.to_owned()) } - let parts = vec::map(parts, |s| { - match uint::from_str(*s) { - Some(n) if n <= 255 => n, - _ => 256 + let parts: ~[uint] = ip.split_iter('.').transform(|s| { + match uint::from_str(s) { + Some(n) if n <= 255 => n, + _ => 256 } - }); + }).collect(); if parts.len() != 4 { Err(fmt!("'%s' doesn't have 4 parts", ip)) } else if parts.contains(&256) { diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index f26019d928208..f7e86b00d2348 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -334,7 +334,7 @@ fn userinfo_to_str(userinfo: &UserInfo) -> ~str { fn query_from_str(rawquery: &str) -> Query { let mut query: Query = ~[]; if str::len(rawquery) != 0 { - for str::each_split_char(rawquery, '&') |p| { + for rawquery.split_iter('&').advance |p| { let (k, v) = split_char_first(p, '='); query.push((decode_component(k), decode_component(v))); }; diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs index 1a8ab75b3dd0d..08fbb8aacc930 100644 --- a/src/libextra/num/rational.rs +++ b/src/libextra/num/rational.rs @@ -12,11 +12,10 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::cmp; use core::from_str::FromStr; use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round}; -use core::str; -use core::vec; use super::bigint::BigInt; /// Represents the ratio between 2 numbers. @@ -252,11 +251,7 @@ impl FromStr for Ratio { /// Parses `numer/denom`. fn from_str(s: &str) -> Option> { - let split = vec::build(|push| { - for str::each_splitn_char(s, '/', 1) |s| { - push(s.to_owned()); - } - }); + let split: ~[&str] = s.splitn_iter('/', 1).collect(); if split.len() < 2 { return None; } do FromStr::from_str::(split[0]).chain |a| { do FromStr::from_str::(split[1]).chain |b| { @@ -269,11 +264,7 @@ impl FromStrRadix for Ratio { /// Parses `numer/denom` where the numbers are in base `radix`. fn from_str_radix(s: &str, radix: uint) -> Option> { - let split = vec::build(|push| { - for str::each_splitn_char(s, '/', 1) |s| { - push(s.to_owned()); - } - }); + let split: ~[&str] = s.splitn_iter('/', 1).collect(); if split.len() < 2 { None } else { do FromStrRadix::from_str_radix::(split[0], radix).chain |a| { diff --git a/src/libextra/terminfo/parser/compiled.rs b/src/libextra/terminfo/parser/compiled.rs index 61c68c27fe5dc..690596e6248e9 100644 --- a/src/libextra/terminfo/parser/compiled.rs +++ b/src/libextra/terminfo/parser/compiled.rs @@ -14,6 +14,7 @@ use core::prelude::*; use core::{vec, int, str}; use core::io::Reader; +use core::iterator::IteratorUtil; use core::hashmap::HashMap; use super::super::TermInfo; @@ -212,11 +213,8 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> { return Err(~"incompatible file: more string offsets than expected"); } - let mut term_names: ~[~str] = vec::with_capacity(2); let names_str = str::from_bytes(file.read_bytes(names_bytes as uint - 1)); // don't read NUL - for names_str.each_split_char('|') |s| { - term_names.push(s.to_owned()); - } + let term_names: ~[~str] = names_str.split_iter('|').transform(|s| s.to_owned()).collect(); file.read_byte(); // consume NUL diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs index d6577cf3b94db..d109bb12e0228 100644 --- a/src/libextra/terminfo/searcher.rs +++ b/src/libextra/terminfo/searcher.rs @@ -12,9 +12,10 @@ /// Does not support hashed database, only filesystem! use core::prelude::*; -use core::{os, str}; +use core::{os}; use core::os::getenv; use core::io::{file_reader, Reader}; +use core::iterator::IteratorUtil; use path = core::path::Path; /// Return path to database entry for `term` @@ -36,7 +37,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~path> { dirs_to_search.push(homedir.unwrap().push(".terminfo")); // ncurses compatability } match getenv("TERMINFO_DIRS") { - Some(dirs) => for str::each_split_char(dirs, ':') |i| { + Some(dirs) => for dirs.split_iter(':').advance |i| { if i == "" { dirs_to_search.push(path("/usr/share/terminfo")); } else { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 928f7d5a79179..d765bcff9e236 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -24,6 +24,7 @@ use middle; use util::common::time; use util::ppaux; +use core::iterator::IteratorUtil; use core::hashmap::HashMap; use core::int; use core::io; @@ -684,11 +685,7 @@ pub fn build_session_options(binary: @~str, let addl_lib_search_paths = getopts::opt_strs(matches, "L").map(|s| Path(*s)); let linker = getopts::opt_maybe_str(matches, "linker"); let linker_args = getopts::opt_strs(matches, "link-args").flat_map( |a| { - let mut args = ~[]; - for str::each_split_char(*a, ' ') |arg| { - args.push(str::to_owned(arg)); - } - args + a.split_iter(' ').transform(|arg| arg.to_owned()).collect() }); let cfg = parse_cfgspecs(getopts::opt_strs(matches, "cfg"), demitter); @@ -699,12 +696,9 @@ pub fn build_session_options(binary: @~str, let custom_passes = match getopts::opt_maybe_str(matches, "passes") { None => ~[], Some(s) => { - let mut o = ~[]; - for s.each_split(|c| c == ' ' || c == ',') |s| { - let s = s.trim().to_owned(); - o.push(s); - } - o + s.split_iter(|c: char| c == ' ' || c == ',').transform(|s| { + s.trim().to_owned() + }).collect() } }; diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 6cc01cb90b8be..f0cabe5045587 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -17,6 +17,7 @@ use core::prelude::*; use metadata::cstore; use metadata::decoder; +use core::iterator::IteratorUtil; use core::hashmap::HashMap; use core::vec; use extra; @@ -114,7 +115,7 @@ pub fn get_used_libraries(cstore: &CStore) -> ~[~str] { } pub fn add_used_link_args(cstore: &mut CStore, args: &str) { - for args.each_split_char(' ') |s| { + for args.split_iter(' ').advance |s| { cstore.used_link_args.push(s.to_owned()); } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 88482c94336da..6d4043bfc8999 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -339,9 +339,11 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, use_rl: bool) -> Option { if line.starts_with(":") { + // FIXME #5898: conflicts with Cell.take(), so can't be at the top level + use core::iterator::IteratorUtil; + let full = line.substr(1, line.len() - 1); - let mut split = ~[]; - for str::each_word(full) |word| { split.push(word.to_owned()) } + let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect(); let len = split.len(); if len > 0 { diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index af6b23ba75544..c039eeacbe47a 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -17,6 +17,7 @@ pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install}; use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; use core::os::mkdir_recursive; use core::os; +use core::iterator::IteratorUtil; /// Returns the value of RUST_PATH, as a list /// of Paths. In general this should be read from the @@ -166,7 +167,7 @@ fn library_in_workspace(full_name: &str, short_name: &str, where: Target, let f_name = match p_path.filename() { Some(s) => s, None => loop }; - for f_name.each_split_char('-') |piece| { + for f_name.split_iter('-').advance |piece| { debug!("a piece = %s", piece); if which == 0 && piece != lib_prefix { break; diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 37b8c2ad43384..2db51fe969fc4 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -29,6 +29,7 @@ extern mod syntax; use core::prelude::*; use core::*; +use core::iterator::IteratorUtil; pub use core::path::Path; use core::hashmap::HashMap; use rustc::driver::{driver, session}; @@ -161,10 +162,8 @@ impl<'self> PkgScript<'self> { exe.to_str(), root.to_str(), "configs"); let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]); // Run the configs() function to get the configs - let mut cfgs = ~[]; - for str::each_word(str::from_bytes(output.output)) |w| { - cfgs.push(w.to_owned()); - } + let cfgs = str::from_bytes_slice(output.output).word_iter() + .transform(|w| w.to_owned()).collect(); (cfgs, output.status) } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 6ce6d81bf2439..2069e61f11e64 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -30,6 +30,7 @@ use cast; use io; +use iterator::IteratorUtil; use libc; use libc::{c_char, c_void, c_int, size_t}; use libc::{mode_t, FILE}; @@ -224,12 +225,11 @@ pub fn env() -> ~[(~str,~str)] { fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] { let mut pairs = ~[]; for input.each |p| { - let mut vs = ~[]; - for str::each_splitn_char(*p, '=', 1) |s| { vs.push(s.to_owned()) } + let vs: ~[&str] = p.splitn_iter('=', 1).collect(); debug!("splitting: len: %u", vs.len()); assert_eq!(vs.len(), 2); - pairs.push((copy vs[0], copy vs[1])); + pairs.push((vs[0].to_owned(), vs[1].to_owned())); } pairs } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index a551b9bf3c0b3..b2f25d41157ba 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -18,6 +18,7 @@ Cross-platform file path handling use container::Container; use cmp::Eq; +use iterator::IteratorUtil; use libc; use option::{None, Option, Some}; use str; @@ -449,10 +450,9 @@ impl ToStr for PosixPath { // PosixPath and WindowsPath, most of their methods are common. impl GenericPath for PosixPath { fn from_str(s: &str) -> PosixPath { - let mut components = ~[]; - for str::each_split_nonempty(s, |c| c == '/') |s| { - components.push(s.to_owned()) - } + let components = s.split_iter('/') + .filter_map(|s| if s.is_empty() {None} else {Some(s.to_owned())}) + .collect(); let is_absolute = (s.len() != 0 && s[0] == '/' as u8); PosixPath { is_absolute: is_absolute, @@ -508,7 +508,7 @@ impl GenericPath for PosixPath { } fn with_filename(&self, f: &str) -> PosixPath { - assert!(! str::any(f, |c| windows::is_sep(c as u8))); + assert!(! str::any(f, |c| windows::is_sep(c))); self.dir_path().push(f) } @@ -569,11 +569,11 @@ impl GenericPath for PosixPath { fn push_many(&self, cs: &[~str]) -> PosixPath { let mut v = copy self.components; for cs.each |e| { - let mut ss = ~[]; - for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| { - ss.push(s.to_owned()) + for e.split_iter(windows::is_sep).advance |s| { + if !s.is_empty() { + v.push(s.to_owned()) + } } - v.push_all_move(ss); } PosixPath { is_absolute: self.is_absolute, @@ -583,11 +583,11 @@ impl GenericPath for PosixPath { fn push(&self, s: &str) -> PosixPath { let mut v = copy self.components; - let mut ss = ~[]; - for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| { - ss.push(s.to_owned()) + for s.split_iter(windows::is_sep).advance |s| { + if !s.is_empty() { + v.push(s.to_owned()) + } } - v.push_all_move(ss); PosixPath { components: v, ..copy *self } } @@ -661,11 +661,11 @@ impl GenericPath for WindowsPath { } } - let mut components = ~[]; - for str::each_split_nonempty(rest, |c| windows::is_sep(c as u8)) |s| { - components.push(s.to_owned()) - } - let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0])); + let components = rest.split_iter(windows::is_sep) + .filter_map(|s| if s.is_empty() {None} else {Some(s.to_owned())}) + .collect(); + + let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0] as char)); WindowsPath { host: host, device: device, @@ -722,7 +722,7 @@ impl GenericPath for WindowsPath { } fn with_filename(&self, f: &str) -> WindowsPath { - assert!(! str::any(f, |c| windows::is_sep(c as u8))); + assert!(! str::any(f, |c| windows::is_sep(c))); self.dir_path().push(f) } @@ -826,11 +826,11 @@ impl GenericPath for WindowsPath { fn push_many(&self, cs: &[~str]) -> WindowsPath { let mut v = copy self.components; for cs.each |e| { - let mut ss = ~[]; - for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| { - ss.push(s.to_owned()) + for e.split_iter(windows::is_sep).advance |s| { + if !s.is_empty() { + v.push(s.to_owned()) + } } - v.push_all_move(ss); } // tedious, but as-is, we can't use ..self WindowsPath { @@ -843,11 +843,11 @@ impl GenericPath for WindowsPath { fn push(&self, s: &str) -> WindowsPath { let mut v = copy self.components; - let mut ss = ~[]; - for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| { - ss.push(s.to_owned()) + for s.split_iter(windows::is_sep).advance |s| { + if !s.is_empty() { + v.push(s.to_owned()) + } } - v.push_all_move(ss); WindowsPath { components: v, ..copy *self } } @@ -905,8 +905,8 @@ pub mod windows { use option::{None, Option, Some}; #[inline(always)] - pub fn is_sep(u: u8) -> bool { - u == '/' as u8 || u == '\\' as u8 + pub fn is_sep(u: char) -> bool { + u == '/' || u == '\\' } pub fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> { @@ -915,7 +915,7 @@ pub mod windows { s[0] == s[1]) { let mut i = 2; while i < s.len() { - if is_sep(s[i]) { + if is_sep(s[i] as char) { let pre = s.slice(2, i).to_owned(); let rest = s.slice(i, s.len()).to_owned(); return Some((pre, rest)); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 2af300fc1b881..930026fa4f76f 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, IteratorUtil}; +use iterator::{Iterator, IteratorUtil, FilterIterator}; use libc; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; @@ -633,128 +633,92 @@ pub fn slice<'a>(s: &'a str, begin: uint, end: uint) -> &'a str { unsafe { raw::slice_bytes(s, begin, end) } } -/// Splits a string into substrings at each occurrence of a given character -pub fn each_split_char<'a>(s: &'a str, sep: char, - it: &fn(&'a str) -> bool) -> bool { - each_split_char_inner(s, sep, len(s), true, true, it) -} +/// An iterator over the substrings of a string, separated by `sep`. +pub struct StrCharSplitIterator<'self,Sep> { + priv string: &'self str, + priv position: uint, + priv sep: Sep, + /// The number of splits remaining + priv count: uint, + /// Whether an empty string at the end is allowed + priv allow_trailing_empty: bool, + priv finished: bool, + priv only_ascii: bool +} + +/// An iterator over the words of a string, separated by an sequence of whitespace +pub type WordIterator<'self> = + FilterIterator<'self, &'self str, + StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>; + +/// A separator for splitting a string character-wise +pub trait StrCharSplitSeparator { + /// Determine if the splitter should split at the given character + fn should_split(&self, char) -> bool; + /// Indicate if the splitter only uses ASCII characters, which + /// allows for a faster implementation. + fn only_ascii(&self) -> bool; +} +impl StrCharSplitSeparator for char { + #[inline(always)] + fn should_split(&self, c: char) -> bool { *self == c } -/// Like `each_split_char`, but a trailing empty string is omitted -pub fn each_split_char_no_trailing<'a>(s: &'a str, - sep: char, - it: &fn(&'a str) -> bool) -> bool { - each_split_char_inner(s, sep, len(s), true, false, it) + fn only_ascii(&self) -> bool { (*self as uint) < 128 } } +impl<'self> StrCharSplitSeparator for &'self fn(char) -> bool { + #[inline(always)] + fn should_split(&self, c: char) -> bool { (*self)(c) } -/** - * Splits a string into substrings at each occurrence of a given - * character up to 'count' times. - * - * The character must be a valid UTF-8/ASCII character - */ -pub fn each_splitn_char<'a>(s: &'a str, - sep: char, - count: uint, - it: &fn(&'a str) -> bool) -> bool { - each_split_char_inner(s, sep, count, true, true, it) + fn only_ascii(&self) -> bool { false } } +impl<'self> StrCharSplitSeparator for extern "Rust" fn(char) -> bool { + #[inline(always)] + fn should_split(&self, c: char) -> bool { (*self)(c) } -/// Like `each_split_char`, but omits empty strings -pub fn each_split_char_nonempty<'a>(s: &'a str, - sep: char, - it: &fn(&'a str) -> bool) -> bool { - each_split_char_inner(s, sep, len(s), false, false, it) + fn only_ascii(&self) -> bool { false } } -fn each_split_char_inner<'a>(s: &'a str, - sep: char, - count: uint, - allow_empty: bool, - allow_trailing_empty: bool, - it: &fn(&'a str) -> bool) -> bool { - if sep < 128u as char { - let (b, l) = (sep as u8, len(s)); - let mut done = 0u; - let mut (i, start) = (0u, 0u); - while i < l && done < count { - if s[i] == b { - if allow_empty || start < i { - if !it( unsafe{ raw::slice_bytes(s, start, i) } ) { - return false; - } - } - start = i + 1u; - done += 1u; - } - i += 1u; - } - // only slice a non-empty trailing substring - if allow_trailing_empty || start < l { - if !it( unsafe{ raw::slice_bytes(s, start, l) } ) { return false; } - } - return true; - } - return each_split_inner(s, |cur| cur == sep, count, - allow_empty, allow_trailing_empty, it) -} +impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { + fn next(&mut self) -> Option<&'self str> { + if self.finished { return None } -/// Splits a string into substrings using a character function -pub fn each_split<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) -> bool { - each_split_inner(s, sepfn, len(s), true, true, it) -} + let l = self.string.len(); + let start = self.position; -/// Like `each_split`, but a trailing empty string is omitted -pub fn each_split_no_trailing<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) -> bool { - each_split_inner(s, sepfn, len(s), true, false, it) -} + if self.only_ascii { + // this gives a *huge* speed up for splitting on ASCII + // characters (e.g. '\n' or ' ') + while self.position < l && self.count > 0 { + let byte = self.string[self.position]; -/** - * Splits a string into substrings using a character function, cutting at - * most `count` times. - */ -pub fn each_splitn<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - count: uint, - it: &fn(&'a str) -> bool) -> bool { - each_split_inner(s, sepfn, count, true, true, it) -} - -/// Like `each_split`, but omits empty strings -pub fn each_split_nonempty<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) -> bool { - each_split_inner(s, sepfn, len(s), false, false, it) -} - -fn each_split_inner<'a>(s: &'a str, - sepfn: &fn(cc: char) -> bool, - count: uint, - allow_empty: bool, - allow_trailing_empty: bool, - it: &fn(&'a str) -> bool) -> bool { - let l = len(s); - let mut (i, start, done) = (0u, 0u, 0u); - while i < l && done < count { - let CharRange {ch, next} = char_range_at(s, i); - if sepfn(ch) { - if allow_empty || start < i { - if !it( unsafe{ raw::slice_bytes(s, start, i) } ) { - return false; + if self.sep.should_split(byte as char) { + let slice = unsafe { raw::slice_bytes(self.string, start, self.position) }; + self.position += 1; + self.count -= 1; + return Some(slice); } + self.position += 1; + } + } else { + while self.position < l && self.count > 0 { + let CharRange {ch, next} = char_range_at(self.string, self.position); + + if self.sep.should_split(ch) { + let slice = unsafe { raw::slice_bytes(self.string, start, self.position) }; + self.position = next; + self.count -= 1; + return Some(slice); + } + self.position = next; } - start = next; - done += 1u; } - i = next; - } - if allow_trailing_empty || start < l { - if !it( unsafe{ raw::slice_bytes(s, start, l) } ) { return false; } + self.finished = true; + if self.allow_trailing_empty || start < l { + Some(unsafe { raw::slice_bytes(self.string, start, l) }) + } else { + None + } } - return true; } // See Issue #1932 for why this is a naive search @@ -875,19 +839,12 @@ pub fn levdistance(s: &str, t: &str) -> uint { return dcol[tlen]; } -/** - * Splits a string into substrings separated by LF ('\n'). - */ -pub fn each_line<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { - each_split_char_no_trailing(s, '\n', it) -} - /** * Splits a string into substrings separated by LF ('\n') * and/or CR LF ("\r\n") */ pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { - for each_line(s) |s| { + for s.line_iter().advance |s| { let l = s.len(); if l > 0u && s[l - 1u] == '\r' as u8 { if !it( unsafe { raw::slice_bytes(s, 0, l - 1) } ) { return false; } @@ -898,11 +855,6 @@ pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { return true; } -/// Splits a string into substrings separated by whitespace -pub fn each_word<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { - each_split_nonempty(s, char::is_whitespace, it) -} - /** Splits a string into substrings with possibly internal whitespace, * each of them at most `lim` bytes long. The substrings have leading and trailing * whitespace removed, and are only cut at whitespace boundaries. @@ -2216,7 +2168,7 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { * ~~~ {.rust} * let string = "a\nb\nc"; * let mut lines = ~[]; - * for each_line(string) |line| { lines.push(line) } + * for string.line_iter().advance |line| { lines.push(line) } * * assert!(subslice_offset(string, lines[0]) == 0); // &"a" * assert!(subslice_offset(string, lines[1]) == 2); // &"b" @@ -2523,6 +2475,18 @@ pub trait StrSlice<'self> { fn rev_iter(&self) -> StrCharRevIterator<'self>; fn bytes_iter(&self) -> StrBytesIterator<'self>; fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self>; + fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep>; + fn splitn_iter(&self, sep: Sep, count: uint) + -> StrCharSplitIterator<'self, Sep>; + fn split_options_iter(&self, sep: Sep, + count: uint, allow_trailing_empty: bool) + -> StrCharSplitIterator<'self, Sep>; + /// An iterator over the lines of a string (subsequences separated + /// by `\n`). + fn line_iter(&self) -> StrCharSplitIterator<'self, char>; + /// An iterator over the words of a string (subsequences separated + /// by any sequence of whitespace). + fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; fn is_whitespace(&self) -> bool; @@ -2530,8 +2494,6 @@ pub trait StrSlice<'self> { fn len(&self) -> uint; fn char_len(&self) -> uint; fn slice(&self, begin: uint, end: uint) -> &'self str; - fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool; - fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool; fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool; fn starts_with<'a>(&self, needle: &'a str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; @@ -2597,6 +2559,36 @@ impl<'self> StrSlice<'self> for &'self str { StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() } } + fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> { + self.split_options_iter(sep, self.len(), true) + } + + fn splitn_iter(&self, sep: Sep, count: uint) + -> StrCharSplitIterator<'self, Sep> { + self.split_options_iter(sep, count, true) + } + fn split_options_iter(&self, sep: Sep, + count: uint, allow_trailing_empty: bool) + -> StrCharSplitIterator<'self, Sep> { + let only_ascii = sep.only_ascii(); + StrCharSplitIterator { + string: *self, + position: 0, + sep: sep, + count: count, + allow_trailing_empty: allow_trailing_empty, + finished: false, + only_ascii: only_ascii + } + } + + fn line_iter(&self) -> StrCharSplitIterator<'self, char> { + self.split_options_iter('\n', self.len(), false) + } + fn word_iter(&self) -> WordIterator<'self> { + self.split_iter(char::is_whitespace).filter(|s| !s.is_empty()) + } + /// Returns true if one string ends with another #[inline] @@ -2637,18 +2629,6 @@ impl<'self> StrSlice<'self> for &'self str { fn slice(&self, begin: uint, end: uint) -> &'self str { slice(*self, begin, end) } - /// Splits a string into substrings using a character function - #[inline] - fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool { - each_split(*self, sepfn, it) - } - /** - * Splits a string into substrings at each occurrence of a given character - */ - #[inline] - fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool { - each_split_char(*self, sep, it) - } /** * Splits a string into a vector of the substrings separated by a given * string @@ -2904,131 +2884,6 @@ mod tests { let _cc3 = pop_char(&mut data); } - #[test] - fn test_split_char() { - fn t(s: &str, c: char, u: &[~str]) { - debug!("split_byte: %?", s); - let mut v = ~[]; - for each_split_char(s, c) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - t("abc.hello.there", '.', [~"abc", ~"hello", ~"there"]); - t(".hello.there", '.', [~"", ~"hello", ~"there"]); - t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there", ~""]); - - t("", 'z', [~""]); - t("z", 'z', [~"",~""]); - t("ok", 'z', [~"ok"]); - } - - #[test] - fn test_split_char_2() { - fn t(s: &str, c: char, u: &[~str]) { - debug!("split_byte: %?", s); - let mut v = ~[]; - for each_split_char(s, c) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - let data = "ประเทศไทย中华Việt Nam"; - t(data, 'V', [~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', [~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); - } - - #[test] - fn test_splitn_char() { - fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!("splitn_byte: %?", s); - let mut v = ~[]; - for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - debug!("comparing vs. %?", u); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - t("abc.hello.there", '.', 0u, [~"abc.hello.there"]); - t("abc.hello.there", '.', 1u, [~"abc", ~"hello.there"]); - t("abc.hello.there", '.', 2u, [~"abc", ~"hello", ~"there"]); - t("abc.hello.there", '.', 3u, [~"abc", ~"hello", ~"there"]); - t(".hello.there", '.', 0u, [~".hello.there"]); - t(".hello.there", '.', 1u, [~"", ~"hello.there"]); - t("...hello.there.", '.', 3u, [~"", ~"", ~"", ~"hello.there."]); - t("...hello.there.", '.', 5u, [~"", ~"", ~"", ~"hello", ~"there", ~""]); - - t("", 'z', 5u, [~""]); - t("z", 'z', 5u, [~"",~""]); - t("ok", 'z', 5u, [~"ok"]); - t("z", 'z', 0u, [~"z"]); - t("w.x.y", '.', 0u, [~"w.x.y"]); - t("w.x.y", '.', 1u, [~"w",~"x.y"]); - } - - #[test] - fn test_splitn_char_2() { - fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!("splitn_byte: %?", s); - let mut v = ~[]; - for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - debug!("comparing vs. %?", u); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - - t("ประเทศไทย中华Việt Nam", '华', 1u, [~"ประเทศไทย中", ~"Việt Nam"]); - t("zzXXXzYYYzWWWz", 'z', 3u, [~"", ~"", ~"XXX", ~"YYYzWWWz"]); - t("z", 'z', 5u, [~"",~""]); - t("", 'z', 5u, [~""]); - t("ok", 'z', 5u, [~"ok"]); - } - - #[test] - fn test_splitn_char_3() { - fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!("splitn_byte: %?", s); - let mut v = ~[]; - for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - debug!("comparing vs. %?", u); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - let data = "ประเทศไทย中华Việt Nam"; - t(data, 'V', 1u, [~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', 1u, [~"ประเ", ~"ศไทย中华Việt Nam"]); - } - - #[test] - fn test_split_char_no_trailing() { - fn t(s: &str, c: char, u: &[~str]) { - debug!("split_byte: %?", s); - let mut v = ~[]; - for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - t("abc.hello.there", '.', [~"abc", ~"hello", ~"there"]); - t(".hello.there", '.', [~"", ~"hello", ~"there"]); - t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there"]); - - t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there"]); - t("", 'z', []); - t("z", 'z', [~""]); - t("ok", 'z', [~"ok"]); - } - - #[test] - fn test_split_char_no_trailing_2() { - fn t(s: &str, c: char, u: &[~str]) { - debug!("split_byte: %?", s); - let mut v = ~[]; - for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) } - debug!("split_byte to: %?", v); - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - let data = "ประเทศไทย中华Việt Nam"; - t(data, 'V', [~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', [~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); - } - #[test] fn test_split_str() { fn t<'a>(s: &str, sep: &'a str, u: &[~str]) { @@ -3053,75 +2908,6 @@ mod tests { } - #[test] - fn test_split() { - fn t(s: &str, sepf: &fn(char) -> bool, u: &[~str]) { - let mut v = ~[]; - for each_split(s, sepf) |s| { v.push(s.to_owned()) } - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - - t("ประเทศไทย中华Việt Nam", |cc| cc == '华', [~"ประเทศไทย中", ~"Việt Nam"]); - t("zzXXXzYYYz", char::is_lowercase, [~"", ~"", ~"XXX", ~"YYY", ~""]); - t("zzXXXzYYYz", char::is_uppercase, [~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); - t("z", |cc| cc == 'z', [~"",~""]); - t("", |cc| cc == 'z', [~""]); - t("ok", |cc| cc == 'z', [~"ok"]); - } - - #[test] - fn test_split_no_trailing() { - fn t(s: &str, sepf: &fn(char) -> bool, u: &[~str]) { - let mut v = ~[]; - for each_split_no_trailing(s, sepf) |s| { v.push(s.to_owned()) } - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - - t("ประเทศไทย中华Việt Nam", |cc| cc == '华', [~"ประเทศไทย中", ~"Việt Nam"]); - t("zzXXXzYYYz", char::is_lowercase, [~"", ~"", ~"XXX", ~"YYY"]); - t("zzXXXzYYYz", char::is_uppercase, [~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); - t("z", |cc| cc == 'z', [~""]); - t("", |cc| cc == 'z', []); - t("ok", |cc| cc == 'z', [~"ok"]); - } - - #[test] - fn test_lines() { - let lf = "\nMary had a little lamb\nLittle lamb\n"; - let crlf = "\r\nMary had a little lamb\r\nLittle lamb\r\n"; - - fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) { - let mut v = ~[]; - for f(s) |s| { v.push(s.to_owned()) } - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - - t(lf, each_line, [~"", ~"Mary had a little lamb", ~"Little lamb"]); - t(lf, each_line_any, [~"", ~"Mary had a little lamb", ~"Little lamb"]); - t(crlf, each_line, [~"\r", ~"Mary had a little lamb\r", ~"Little lamb\r"]); - t(crlf, each_line_any, [~"", ~"Mary had a little lamb", ~"Little lamb"]); - t("", each_line, []); - t("", each_line_any, []); - t("\n", each_line, [~""]); - t("\n", each_line_any, [~""]); - t("banana", each_line, [~"banana"]); - t("banana", each_line_any, [~"banana"]); - } - - #[test] - fn test_words() { - fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) { - let mut v = ~[]; - for f(s) |s| { v.push(s.to_owned()) } - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - let data = "\nMary had a little lamb\nLittle lamb\n"; - - t(data, each_word, [~"Mary",~"had",~"a",~"little",~"lamb",~"Little",~"lamb"]); - t("ok", each_word, [~"ok"]); - t("", each_word, []); - } - #[test] fn test_split_within() { fn t(s: &str, i: uint, u: &[~str]) { @@ -3671,7 +3457,7 @@ mod tests { let string = "a\nb\nc"; let mut lines = ~[]; - for each_line(string) |line| { lines.push(line) } + for string.line_iter().advance |line| { lines.push(line) } assert_eq!(subslice_offset(string, lines[0]), 0); assert_eq!(subslice_offset(string, lines[1]), 2); assert_eq!(subslice_offset(string, lines[2]), 4); @@ -3730,78 +3516,6 @@ mod tests { assert!(!contains_char("", 'a')); } - #[test] - fn test_split_char_each() { - let data = "\nMary had a little lamb\nLittle lamb\n"; - - let mut ii = 0; - - for each_split_char(data, ' ') |xx| { - match ii { - 0 => assert!("\nMary" == xx), - 1 => assert!("had" == xx), - 2 => assert!("a" == xx), - 3 => assert!("little" == xx), - _ => () - } - ii += 1; - } - } - - #[test] - fn test_splitn_char_each() { - let data = "\nMary had a little lamb\nLittle lamb\n"; - - let mut ii = 0; - - for each_splitn_char(data, ' ', 2u) |xx| { - match ii { - 0 => assert!("\nMary" == xx), - 1 => assert!("had" == xx), - 2 => assert!("a little lamb\nLittle lamb\n" == xx), - _ => () - } - ii += 1; - } - } - - #[test] - fn test_words_each() { - let data = "\nMary had a little lamb\nLittle lamb\n"; - - let mut ii = 0; - - for each_word(data) |ww| { - match ii { - 0 => assert!("Mary" == ww), - 1 => assert!("had" == ww), - 2 => assert!("a" == ww), - 3 => assert!("little" == ww), - _ => () - } - ii += 1; - } - - each_word("", |_x| fail!()); // should not fail - } - - #[test] - fn test_lines_each () { - let lf = "\nMary had a little lamb\nLittle lamb\n"; - - let mut ii = 0; - - for each_line(lf) |x| { - match ii { - 0 => assert!("" == x), - 1 => assert!("Mary had a little lamb" == x), - 2 => assert!("Little lamb" == x), - _ => () - } - ii += 1; - } - } - #[test] fn test_map() { assert_eq!(~"", map("", |c| unsafe {libc::toupper(c as c_char)} as char)); @@ -4015,4 +3729,68 @@ mod tests { assert_eq!(b, v[pos]); } } + + #[test] + fn test_split_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: ~[&str] = data.split_iter(' ').collect(); + assert_eq!(split, ~["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + let split: ~[&str] = data.split_iter(|c: char| c == ' ').collect(); + assert_eq!(split, ~["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + // Unicode + let split: ~[&str] = data.split_iter('ä').collect(); + assert_eq!(split, ~["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + + let split: ~[&str] = data.split_iter(|c: char| c == 'ä').collect(); + assert_eq!(split, ~["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + } + #[test] + fn test_splitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: ~[&str] = data.splitn_iter(' ', 3).collect(); + assert_eq!(split, ~["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + let split: ~[&str] = data.splitn_iter(|c: char| c == ' ', 3).collect(); + assert_eq!(split, ~["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + // Unicode + let split: ~[&str] = data.splitn_iter('ä', 3).collect(); + assert_eq!(split, ~["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + + let split: ~[&str] = data.splitn_iter(|c: char| c == 'ä', 3).collect(); + assert_eq!(split, ~["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + } + + #[test] + fn test_split_char_iterator_no_trailing() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: ~[&str] = data.split_options_iter('\n', 1000, true).collect(); + assert_eq!(split, ~["", "Märy häd ä little lämb", "Little lämb", ""]); + + let split: ~[&str] = data.split_options_iter('\n', 1000, false).collect(); + assert_eq!(split, ~["", "Märy häd ä little lämb", "Little lämb"]); + } + + #[test] + fn test_word_iter() { + let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; + let words: ~[&str] = data.word_iter().collect(); + assert_eq!(words, ~["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) + } + + #[test] + fn test_line_iter() { + let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; + let lines: ~[&str] = data.line_iter().collect(); + assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]); + + let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n + let lines: ~[&str] = data.line_iter().collect(); + assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]); + } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 59db35201f100..3ff894c267b8f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -92,6 +92,7 @@ use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; use opt_vec; use opt_vec::OptVec; +use core::iterator::IteratorUtil; use core::either::Either; use core::either; use core::hashmap::HashSet; @@ -3981,17 +3982,15 @@ impl Parser { token::LIT_STR(s) => { self.bump(); let the_string = ident_to_str(&s); - let mut words = ~[]; - for str::each_word(*the_string) |s| { words.push(s) } let mut abis = AbiSet::empty(); - for words.each |word| { - match abi::lookup(*word) { + for the_string.word_iter().advance |word| { + match abi::lookup(word) { Some(abi) => { if abis.contains(abi) { self.span_err( *self.span, fmt!("ABI `%s` appears twice", - *word)); + word)); } else { abis.add(abi); } @@ -4006,7 +4005,7 @@ impl Parser { str::connect_slices( abi::all_names(), ", "), - *word)); + word)); } } } diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 3bf08cfb934f8..d05edef25a6e2 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -14,6 +14,7 @@ extern mod extra; use std::io::{ReaderUtil, WriterUtil}; use std::io; +use std::iterator::IteratorUtil; use std::os; use std::str; use std::u8; @@ -73,8 +74,8 @@ impl Sudoku { let mut g = vec::from_fn(10u, { |_i| ~[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8] }); while !reader.eof() { let line = reader.read_line(); - let mut comps = ~[]; - for str::each_split_char(line.trim(), ',') |s| { comps.push(s.to_owned()) } + let comps: ~[&str] = line.trim().split_iter(',').collect(); + if comps.len() == 3u { let row = uint::from_str(comps[0]).get() as u8; let col = uint::from_str(comps[1]).get() as u8; From b29cd22bce6325a60788ab84f989bd2e82fcaaf4 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 00:34:23 +1000 Subject: [PATCH 02/21] std: replace str::all/any fns and methods with iterators --- src/compiletest/header.rs | 1 + src/compiletest/runtest.rs | 2 +- src/libextra/json.rs | 2 +- src/libextra/semver.rs | 3 +- src/librustdoc/unindent_pass.rs | 2 +- src/libstd/path.rs | 4 +-- src/libstd/run.rs | 2 +- src/libstd/str.rs | 52 ++------------------------------- src/libstd/str/ascii.rs | 4 +-- src/libsyntax/parse/lexer.rs | 3 +- 10 files changed, 15 insertions(+), 60 deletions(-) diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 782571fc6791e..153a8de8029fa 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -13,6 +13,7 @@ use core::prelude::*; use common::config; use common; +use core::iterator::IteratorUtil; use core::io; use core::os; use core::str; diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 444f4c8d53908..6812f6e445561 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -735,7 +735,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps, let cmdline = make_cmdline("", args.prog, args.args); // get bare program string - let tvec: ~[~str] = args.prog.split_iter('/').transform(|ts| ts.to_owned()).collect(); + let mut tvec: ~[~str] = args.prog.split_iter('/').transform(|ts| ts.to_owned()).collect(); let prog_short = tvec.pop(); // copy to target diff --git a/src/libextra/json.rs b/src/libextra/json.rs index fc1597ffed445..30a2b5f862768 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -567,7 +567,7 @@ impl Parser { } fn parse_ident(&mut self, ident: &str, value: Json) -> Result { - if str::all(ident, |c| c == self.next_char()) { + if ident.iter().all(|c| c == self.next_char()) { self.bump(); Ok(value) } else { diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs index 494f0c8ea815f..36ebd10ae17b7 100644 --- a/src/libextra/semver.rs +++ b/src/libextra/semver.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::char; use core::cmp; use core::io::{ReaderUtil}; @@ -168,7 +169,7 @@ fn take_num(rdr: @io::Reader, ch: char) -> (uint, char) { fn take_ident(rdr: @io::Reader, ch: char) -> (Identifier, char) { let (s,ch) = take_nonempty_prefix(rdr, ch, char::is_alphanumeric); - if s.all(char::is_digit) { + if s.iter().all(char::is_digit) { match uint::from_str(s) { None => { bad_parse::cond.raise(()); (Numeric(0), ch) }, Some(i) => (Numeric(i), ch) diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index b6753f385dfc1..6bb5b2e0cfcc8 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -63,7 +63,7 @@ fn unindent(s: &str) -> ~str { } else { saw_first_line = true; let mut spaces = 0; - do str::all(*line) |char| { + do line.iter().all |char| { // Only comparing against space because I wouldn't // know what to do with mixed whitespace chars if char == ' ' { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index b2f25d41157ba..eb78120c6bed3 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -508,7 +508,7 @@ impl GenericPath for PosixPath { } fn with_filename(&self, f: &str) -> PosixPath { - assert!(! str::any(f, |c| windows::is_sep(c))); + assert!(! f.iter().all(windows::is_sep)); self.dir_path().push(f) } @@ -722,7 +722,7 @@ impl GenericPath for WindowsPath { } fn with_filename(&self, f: &str) -> WindowsPath { - assert!(! str::any(f, |c| windows::is_sep(c))); + assert!(! f.iter().all(windows::is_sep)); self.dir_path().push(f) } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 3b17067feba7f..29598bc48fa41 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -588,7 +588,7 @@ pub fn make_command_line(prog: &str, args: &[~str]) -> ~str { return cmd; fn append_arg(cmd: &mut ~str, arg: &str) { - let quote = arg.any(|c| c == ' ' || c == '\t'); + let quote = arg.iter().any(|c| c == ' ' || c == '\t'); if quote { cmd.push_char('"'); } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 930026fa4f76f..09ea6a5dfa9b2 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1175,22 +1175,6 @@ impl<'self> Equiv<~str> for &'self str { Section: Iterating through strings */ -/** - * Return true if a predicate matches all characters or if the string - * contains no characters - */ -pub fn all(s: &str, it: &fn(char) -> bool) -> bool { - all_between(s, 0u, len(s), it) -} - -/** - * Return true if a predicate matches any character (and false if it - * matches none or there are no characters) - */ -pub fn any(ss: &str, pred: &fn(char) -> bool) -> bool { - !all(ss, |cc| !pred(cc)) -} - /// Apply a function to each character pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { let mut result = ~""; @@ -1675,7 +1659,7 @@ pub fn is_empty(s: &str) -> bool { len(s) == 0u } * Whitespace characters are determined by `char::is_whitespace` */ pub fn is_whitespace(s: &str) -> bool { - return all(s, char::is_whitespace); + s.iter().all(char::is_whitespace) } /** @@ -1684,7 +1668,7 @@ pub fn is_whitespace(s: &str) -> bool { * Alphanumeric characters are determined by `char::is_alphanumeric` */ fn is_alphanumeric(s: &str) -> bool { - return all(s, char::is_alphanumeric); + s.iter().all(char::is_alphanumeric) } /// Returns the string length/size in bytes not counting the null terminator @@ -2467,8 +2451,6 @@ pub mod traits {} #[allow(missing_doc)] pub trait StrSlice<'self> { - fn all(&self, it: &fn(char) -> bool) -> bool; - fn any(&self, it: &fn(char) -> bool) -> bool; fn contains<'a>(&self, needle: &'a str) -> bool; fn contains_char(&self, needle: char) -> bool; fn iter(&self) -> StrCharIterator<'self>; @@ -2514,18 +2496,6 @@ pub trait StrSlice<'self> { /// Extension methods for strings impl<'self> StrSlice<'self> for &'self str { - /** - * Return true if a predicate matches all characters or if the string - * contains no characters - */ - #[inline] - fn all(&self, it: &fn(char) -> bool) -> bool { all(*self, it) } - /** - * Return true if a predicate matches any character (and false if it - * matches none or there are no characters) - */ - #[inline] - fn any(&self, it: &fn(char) -> bool) -> bool { any(*self, it) } /// Returns true if one string contains another #[inline] fn contains<'a>(&self, needle: &'a str) -> bool { @@ -3522,24 +3492,6 @@ mod tests { assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); } - #[test] - fn test_all() { - assert_eq!(true, all("", char::is_uppercase)); - assert_eq!(false, all("ymca", char::is_uppercase)); - assert_eq!(true, all("YMCA", char::is_uppercase)); - assert_eq!(false, all("yMCA", char::is_uppercase)); - assert_eq!(false, all("YMCy", char::is_uppercase)); - } - - #[test] - fn test_any() { - assert_eq!(false, any("", char::is_uppercase)); - assert_eq!(false, any("ymca", char::is_uppercase)); - assert_eq!(true, any("YMCA", char::is_uppercase)); - assert_eq!(true, any("yMCA", char::is_uppercase)); - assert_eq!(true, any("Ymcy", char::is_uppercase)); - } - #[test] fn test_chars() { let ss = ~"ศไทย中华Việt Nam"; diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index e288d605714f4..a4a1b7a171d33 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -226,8 +226,8 @@ mod tests { assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); - assert!(str::all("banana", |c| c.is_ascii())); - assert!(! str::all("ประเทศไทย中华Việt Nam", |c| c.is_ascii())); + assert!("banana".iter().all(|c| c.is_ascii())); + assert!(!"ประเทศไทย中华Việt Nam".iter().all(|c| c.is_ascii())); } #[test] diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 8ee0a976c8b9c..f615f1321df9f 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -19,6 +19,7 @@ use ext::tt::transcribe::{dup_tt_reader}; use parse::token; use parse::token::{str_to_ident}; +use core::iterator::IteratorUtil; use core::char; use core::either; use core::str; @@ -245,7 +246,7 @@ fn consume_whitespace_and_comments(rdr: @mut StringReader) pub fn is_line_non_doc_comment(s: &str) -> bool { let s = s.trim_right(); - s.len() > 3 && s.all(|ch| ch == '/') + s.len() > 3 && s.iter().all(|ch| ch == '/') } // PRECONDITION: rdr.curr is not whitespace From c32fb53cf9ae20a657d17bd8e2f0b36863096583 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 00:44:58 +1000 Subject: [PATCH 03/21] std: remove str::{len, slice, is_empty} in favour of methods. --- doc/rust.md | 6 +- src/compiletest/errors.rs | 8 +- src/compiletest/header.rs | 4 +- src/libextra/getopts.rs | 2 +- src/libextra/net_tcp.rs | 2 +- src/libextra/net_url.rs | 50 ++--- src/libextra/rope.rs | 14 +- src/libextra/sha1.rs | 3 +- src/libextra/time.rs | 6 +- src/libfuzzer/fuzzer.rc | 5 +- src/librustc/back/link.rs | 2 +- src/librustc/metadata/filesearch.rs | 2 +- src/librustc/middle/lint.rs | 4 +- src/librustc/middle/resolve.rs | 4 +- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 4 +- src/librustc/util/ppaux.rs | 2 +- src/librustdoc/desc_to_brief_pass.rs | 6 +- src/librustdoc/sectionalize_pass.rs | 2 +- src/librustdoc/unindent_pass.rs | 4 +- src/libstd/io.rs | 2 +- src/libstd/os.rs | 13 +- src/libstd/str.rs | 196 ++++++++---------- src/libstd/unstable/extfmt.rs | 2 +- src/libsyntax/codemap.rs | 6 +- src/libsyntax/diagnostic.rs | 7 +- src/libsyntax/parse/comments.rs | 4 +- src/libsyntax/parse/lexer.rs | 6 +- src/libsyntax/print/pprust.rs | 2 +- src/test/bench/shootout-fasta.rs | 10 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/compile-fail/die-not-static.rs | 2 +- src/test/run-fail/task-spawn-barefn.rs | 2 +- src/test/run-pass/string-self-append.rs | 4 +- src/test/run-pass/utf8_chars.rs | 2 +- 35 files changed, 185 insertions(+), 207 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 592bdcf3a3dc0..6d586c9b201c5 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -803,7 +803,7 @@ An example of `use` declarations: ~~~~ use std::float::sin; -use std::str::{slice, contains}; +use std::str::{from_chars, contains}; use std::option::Some; fn main() { @@ -814,8 +814,8 @@ fn main() { info!(Some(1.0)); // Equivalent to - // 'info!(std::str::contains(std::str::slice("foo", 0, 1), "oo"));' - info!(contains(slice("foo", 0, 1), "oo")); + // 'info!(std::str::contains(std::str::from_chars(&['f','o','o']), "oo"));' + info!(contains(from_chars(&['f','o','o']), "oo")); } ~~~~ diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 728548caf77c1..575df0268d6cb 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -33,13 +33,13 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { let mut idx; match str::find_str(line, error_tag) { None => return ~[], - Some(nn) => { idx = (nn as uint) + str::len(error_tag); } + Some(nn) => { idx = (nn as uint) + error_tag.len(); } } // "//~^^^ kind msg" denotes a message expected // three lines above current line: let mut adjust_line = 0u; - let len = str::len(line); + let len = line.len(); while idx < len && line[idx] == ('^' as u8) { adjust_line += 1u; idx += 1u; @@ -52,12 +52,12 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use // to_ascii_consume and to_str_consume to not do a unnecessary copy. - let kind = str::slice(line, start_kind, idx); + let kind = line.slice(start_kind, idx); let kind = kind.to_ascii().to_lower().to_str_ascii(); // Extract msg: while idx < len && line[idx] == (' ' as u8) { idx += 1u; } - let msg = str::slice(line, idx, len).to_owned(); + let msg = line.slice(idx, len).to_owned(); debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 153a8de8029fa..c61adff006303 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -177,8 +177,8 @@ fn parse_name_value_directive(line: &str, let keycolon = directive + ":"; match str::find_str(line, keycolon) { Some(colon) => { - let value = str::slice(line, colon + str::len(keycolon), - str::len(line)).to_owned(); + let value = line.slice(colon + keycolon.len(), + line.len()).to_owned(); debug!("%s: %s", directive, value); Some(value) } diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index af026473a1bf6..111de53052cd6 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -247,7 +247,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { let mut names; let mut i_arg = None; if cur[1] == '-' as u8 { - let tail = str::slice(cur, 2, curlen); + let tail = cur.slice(2, curlen); let tail_eq: ~[&str] = tail.split_iter('=').collect(); if tail_eq.len() <= 1 { names = ~[Long(tail.to_owned())]; diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs index 87ebfdfb7976c..9026dc25b2d93 100644 --- a/src/libextra/net_tcp.rs +++ b/src/libextra/net_tcp.rs @@ -1809,7 +1809,7 @@ mod test { } fn buf_write(w: &W, val: &str) { - debug!("BUF_WRITE: val len %?", str::len(val)); + debug!("BUF_WRITE: val len %?", val.len()); do str::byte_slice(val) |b_slice| { debug!("BUF_WRITE: b_slice len %?", b_slice.len()); diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index f7e86b00d2348..6fd6fa3acd91b 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -291,7 +291,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> { fn split_char_first(s: &str, c: char) -> (~str, ~str) { - let len = str::len(s); + let len = s.len(); let mut index = len; let mut mat = 0; do io::with_str_reader(s) |rdr| { @@ -307,16 +307,16 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) { } } if index+mat == len { - return (str::slice(s, 0, index).to_owned(), ~""); + return (s.slice(0, index).to_owned(), ~""); } else { - return (str::slice(s, 0, index).to_owned(), - str::slice(s, index + mat, str::len(s)).to_owned()); + return (s.slice(0, index).to_owned(), + s.slice(index + mat, s.len()).to_owned()); } } fn userinfo_from_str(uinfo: &str) -> UserInfo { let (user, p) = split_char_first(uinfo, ':'); - let pass = if str::len(p) == 0 { + let pass = if p.is_empty() { None } else { Some(p) @@ -333,7 +333,7 @@ fn userinfo_to_str(userinfo: &UserInfo) -> ~str { fn query_from_str(rawquery: &str) -> Query { let mut query: Query = ~[]; - if str::len(rawquery) != 0 { + if !rawquery.is_empty() { for rawquery.split_iter('&').advance |p| { let (k, v) = split_char_first(p, '='); query.push((decode_component(k), decode_component(v))); @@ -373,7 +373,7 @@ pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> { return Err(~"url: Scheme cannot be empty."); } else { return Ok((rawurl.slice(0,i).to_owned(), - rawurl.slice(i+1,str::len(rawurl)).to_owned())); + rawurl.slice(i+1,rawurl.len()).to_owned())); } } _ => { @@ -475,7 +475,7 @@ fn get_authority(rawurl: &str) -> } Ip6Host => { if colon_count > 7 { - host = str::slice(rawurl, begin, i).to_owned(); + host = rawurl.slice(begin, i).to_owned(); pos = i; st = InPort; } @@ -492,13 +492,13 @@ fn get_authority(rawurl: &str) -> colon_count = 0; // reset count match st { Start => { - let user = str::slice(rawurl, begin, i).to_owned(); + let user = rawurl.slice(begin, i).to_owned(); userinfo = Some(UserInfo::new(user, None)); st = InHost; } PassHostPort => { - let user = str::slice(rawurl, begin, pos).to_owned(); - let pass = str::slice(rawurl, pos+1, i).to_owned(); + let user = rawurl.slice(begin, pos).to_owned(); + let pass = rawurl.slice(pos+1, i).to_owned(); userinfo = Some(UserInfo::new(user, Some(pass))); st = InHost; } @@ -529,31 +529,31 @@ fn get_authority(rawurl: &str) -> match st { Start => { if host_is_end_plus_one() { - host = str::slice(rawurl, begin, end+1).to_owned(); + host = rawurl.slice(begin, end+1).to_owned(); } else { - host = str::slice(rawurl, begin, end).to_owned(); + host = rawurl.slice(begin, end).to_owned(); } } PassHostPort | Ip6Port => { if in != Digit { return Err(~"Non-digit characters in port."); } - host = str::slice(rawurl, begin, pos).to_owned(); - port = Some(str::slice(rawurl, pos+1, end).to_owned()); + host = rawurl.slice(begin, pos).to_owned(); + port = Some(rawurl.slice(pos+1, end).to_owned()); } Ip6Host | InHost => { - host = str::slice(rawurl, begin, end).to_owned(); + host = rawurl.slice(begin, end).to_owned(); } InPort => { if in != Digit { return Err(~"Non-digit characters in port."); } - port = Some(str::slice(rawurl, pos+1, end).to_owned()); + port = Some(rawurl.slice(pos+1, end).to_owned()); } } let rest = if host_is_end_plus_one() { ~"" } - else { str::slice(rawurl, end, len).to_owned() }; + else { rawurl.slice(end, len).to_owned() }; return Ok((userinfo, host, port, rest)); } @@ -561,7 +561,7 @@ fn get_authority(rawurl: &str) -> // returns the path and unparsed part of url, or an error fn get_path(rawurl: &str, authority: bool) -> Result<(~str, ~str), ~str> { - let len = str::len(rawurl); + let len = rawurl.len(); let mut end = len; for rawurl.iter().enumerate().advance |(i,c)| { match c { @@ -585,8 +585,8 @@ fn get_path(rawurl: &str, authority: bool) -> } } - return Ok((decode_component(str::slice(rawurl, 0, end)), - str::slice(rawurl, end, len).to_owned())); + return Ok((decode_component(rawurl.slice(0, end)), + rawurl.slice(end, len).to_owned())); } // returns the parsed query and the fragment, if present @@ -594,16 +594,16 @@ fn get_query_fragment(rawurl: &str) -> Result<(Query, Option<~str>), ~str> { if !str::starts_with(rawurl, "?") { if str::starts_with(rawurl, "#") { - let f = decode_component(str::slice(rawurl, + let f = decode_component(rawurl.slice( 1, - str::len(rawurl))); + rawurl.len())); return Ok((~[], Some(f))); } else { return Ok((~[], None)); } } - let (q, r) = split_char_first(str::slice(rawurl, 1, rawurl.len()), '#'); - let f = if str::len(r) != 0 { + let (q, r) = split_char_first(rawurl.slice(1, rawurl.len()), '#'); + let f = if r.len() != 0 { Some(decode_component(r)) } else { None }; return Ok((query_from_str(q), f)); } diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 413a498a20ec5..1b58aa68f776f 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -71,7 +71,7 @@ pub fn empty() -> Rope { * * the function runs in linear time. */ pub fn of_str(str: @~str) -> Rope { - return of_substr(str, 0u, str::len(*str)); + return of_substr(str, 0u, str.len()); } /** @@ -98,7 +98,7 @@ pub fn of_str(str: @~str) -> Rope { */ pub fn of_substr(str: @~str, byte_offset: uint, byte_len: uint) -> Rope { if byte_len == 0u { return node::Empty; } - if byte_offset + byte_len > str::len(*str) { fail!(); } + if byte_offset + byte_len > str.len() { fail!(); } return node::Content(node::of_substr(str, byte_offset, byte_len)); } @@ -657,7 +657,7 @@ pub mod node { * the length of `str`. */ pub fn of_str(str: @~str) -> @Node { - return of_substr(str, 0u, str::len(*str)); + return of_substr(str, 0u, str.len()); } /** @@ -705,7 +705,7 @@ pub mod node { */ pub fn of_substr_unsafer(str: @~str, byte_start: uint, byte_len: uint, char_len: uint) -> @Node { - assert!((byte_start + byte_len <= str::len(*str))); + assert!((byte_start + byte_len <= str.len())); let candidate = @Leaf(Leaf { byte_offset: byte_start, byte_len: byte_len, @@ -1292,9 +1292,7 @@ mod tests { node::Leaf(x) => { str::push_str( str, - str::slice( - *x.content, x.byte_offset, - x.byte_offset + x.byte_len)); + x.content.slice(x.byte_offset, x.byte_offset + x.byte_len)); } node::Concat(ref x) => { aux(str, x.left); @@ -1340,7 +1338,7 @@ mod tests { assert!(rope_to_string(r) == *sample); let mut string_iter = 0u; - let string_len = str::len(*sample); + let string_len = sample.len(); let mut rope_iter = iterator::char::start(r); let mut equal = true; while equal { diff --git a/src/libextra/sha1.rs b/src/libextra/sha1.rs index 3ad2e727a5d17..658621e25bdf1 100644 --- a/src/libextra/sha1.rs +++ b/src/libextra/sha1.rs @@ -281,7 +281,6 @@ pub fn sha1() -> @Sha1 { mod tests { use sha1; - use core::str; use core::vec; #[test] @@ -396,7 +395,7 @@ mod tests { // Test that it works when accepting the message in pieces for tests.each |t| { - let len = str::len(t.input); + let len = t.input.len(); let mut left = len; while left > 0u { let take = (left + 1u) / 2u; diff --git a/src/libextra/time.rs b/src/libextra/time.rs index e1c78f729a4a5..f545b28c5072b 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -279,7 +279,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { match strs[i] { // can't use let due to stage0 bugs (ref needle, value) => { if match_str(ss, pos, *needle) { - return Some((value, pos + str::len(*needle))); + return Some((value, pos + needle.len())); } } } @@ -598,7 +598,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { // It's odd, but to maintain compatibility with c's // strptime we ignore the timezone. let mut pos = pos; - let len = str::len(s); + let len = s.len(); while pos < len { let range = str::char_range_at(s, pos); pos = range.next; @@ -651,7 +651,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { tm_nsec: 0_i32, }; let mut pos = 0u; - let len = str::len(s); + let len = s.len(); let mut result = Err(~"Invalid time"); while !rdr.eof() && pos < len { diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index 4e285e686df52..bd72f0891ddfb 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -376,7 +376,7 @@ pub fn check_variants_T(crate: @ast::crate, pub fn last_part(filename: ~str) -> ~str { let ix = str::rfind_char(filename, '/').get(); - str::slice(filename, ix + 1u, str::len(filename) - 3u).to_owned() + filename.slice(ix + 1u, filename.len() - 3u).to_owned() } pub enum happiness { @@ -434,7 +434,7 @@ pub fn check_running(exe_filename: &Path) -> happiness { "/Users/jruderman/scripts/timed_run_rust_program.py", [exe_filename.to_str()]); let comb = str::from_bytes(p.output) + "\n" + str::from_bytes(p.error); - if str::len(comb) > 1u { + if comb.len() > 1u { error!("comb comb comb: %?", comb); } @@ -712,4 +712,3 @@ pub mod core { pub use std::cmp; pub use std::sys; } - diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 29e7ba0e62f7d..fa9e2c9a72413 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -686,7 +686,7 @@ pub fn mangle(sess: Session, ss: path) -> ~str { for ss.each |s| { match *s { path_name(s) | path_mod(s) => { let sani = sanitize(*sess.str_of(s)); - n += fmt!("%u%s", str::len(sani), sani); + n += fmt!("%u%s", sani.len(), sani); } } } n += "E"; // End name-sequence. diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index f83d33dcb3c06..6314cb6269768 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -186,7 +186,7 @@ fn get_rustpkg_lib_path_nearest() -> Result { // On Unix should be "lib", on windows "bin" pub fn libdir() -> ~str { let libdir = env!("CFG_LIBDIR"); - if str::is_empty(libdir) { + if libdir.is_empty() { fail!("rustc compiled without CFG_LIBDIR environment variable"); } libdir.to_owned() diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 703516251dcdc..74e001f4e1356 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -849,14 +849,14 @@ fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) { fn ident_without_trailing_underscores<'r>(ident: &'r str) -> &'r str { match str::rfind(ident, |c| c != '_') { - Some(idx) => str::slice(ident, 0, idx + 1), + Some(idx) => ident.slice(0, idx + 1), None => ident, // all underscores } } fn ident_without_leading_underscores<'r>(ident: &'r str) -> &'r str { match str::find(ident, |c| c != '_') { - Some(idx) => str::slice(ident, idx, ident.len()), + Some(idx) => ident.slice(idx, ident.len()), None => ident // all underscores } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 2d2eeff199fc5..25736afd38a0d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2575,7 +2575,7 @@ impl Resolver { if "???" == module_name { let span = span { lo: span.lo, - hi: span.lo + BytePos(str::len(*segment_name)), + hi: span.lo + BytePos(segment_name.len()), expn_info: span.expn_info, }; self.session.span_err(span, @@ -4830,7 +4830,7 @@ impl Resolver { if values.len() > 0 && values[smallest] != uint::max_value && - values[smallest] < str::len(name) + 2 && + values[smallest] < name.len() + 2 && values[smallest] <= max_distance && maybes[smallest] != name.to_owned() { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 78aca4c831f7c..03ae32cf0a6cb 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1221,7 +1221,7 @@ pub fn C_estr_slice(cx: @CrateContext, s: @~str) -> ValueRef { pub fn C_postr(s: &str) -> ValueRef { unsafe { return do str::as_c_str(s) |buf| { - llvm::LLVMConstString(buf, str::len(s) as c_uint, False) + llvm::LLVMConstString(buf, s.len() as c_uint, False) }; } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 5f475f1bb9d82..bc863fb363fe9 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -245,8 +245,8 @@ fn get_cache(cx: @CrateContext) -> metadata_cache { fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { (if str::starts_with(full_path, work_dir) { - str::slice(full_path, str::len(work_dir) + 1u, - str::len(full_path)).to_owned() + full_path.slice(work_dir.len() + 1u, + full_path.len()).to_owned() } else { full_path.to_owned() }, work_dir.to_owned()) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d4f1e42d5ff80..c72bf5c7f0b21 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -485,7 +485,7 @@ pub fn parameterized(cx: ctxt, pub fn ty_to_short_str(cx: ctxt, typ: t) -> ~str { let mut s = encoder::encoded_ty(cx, typ); - if str::len(s) >= 32u { s = str::slice(s, 0u, 32u).to_owned(); } + if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); } return s; } diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 24ade927be247..f66012696ae6b 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -94,7 +94,7 @@ fn parse_desc(desc: ~str) -> Option<~str> { match first_sentence(copy desc) { Some(first_sentence) => { - if str::len(first_sentence) <= max_brief_len { + if first_sentence.len() <= max_brief_len { Some(first_sentence) } else { None @@ -133,7 +133,7 @@ fn first_sentence_(s: &str) -> ~str { }; match idx { Some(idx) if idx > 2u => { - str::to_owned(str::slice(s, 0, idx - 1)) + str::to_owned(s.slice(0, idx - 1)) } _ => { if str::ends_with(s, ".") { @@ -165,7 +165,7 @@ pub fn paragraphs(s: &str) -> ~[~str] { whitespace_lines = 0; - accum = if str::is_empty(accum) { + accum = if accum.is_empty() { copy *line } else { accum + "\n" + *line diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 75f8e22f67e13..61a8d11af7f7b 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -154,7 +154,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { fn parse_header(line: ~str) -> Option<~str> { if str::starts_with(line, "# ") { - Some(str::slice(line, 2u, str::len(line)).to_owned()) + Some(line.slice(2u, line.len()).to_owned()) } else { None } diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index 6bb5b2e0cfcc8..ba6f7184f6895 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -83,8 +83,8 @@ fn unindent(s: &str) -> ~str { if str::is_whitespace(*line) { copy *line } else { - assert!(str::len(*line) >= min_indent); - str::slice(*line, min_indent, str::len(*line)).to_owned() + assert!(line.len() >= min_indent); + line.slice(min_indent, line.len()).to_owned() } }; str::connect(unindented, "\n") diff --git a/src/libstd/io.rs b/src/libstd/io.rs index e3977ca00674b..8ec3a4cdd8115 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -748,7 +748,7 @@ impl ReaderUtil for T { if self.eof() && line.is_empty() { break; } // trim the \n, so that each_line is consistent with read_line - let n = str::len(line); + let n = line.len(); if line[n-1] == '\n' as u8 { unsafe { str::raw::set_len(&mut line, n-1); } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 2069e61f11e64..ab8965a679691 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -525,7 +525,7 @@ pub fn self_exe_path() -> Option { */ pub fn homedir() -> Option { return match getenv("HOME") { - Some(ref p) => if !str::is_empty(*p) { + Some(ref p) => if !p.is_empty() { Some(Path(*p)) } else { secondary() @@ -541,7 +541,7 @@ pub fn homedir() -> Option { #[cfg(windows)] fn secondary() -> Option { do getenv(~"USERPROFILE").chain |p| { - if !str::is_empty(p) { + if !p.is_empty() { Some(Path(p)) } else { None @@ -566,7 +566,7 @@ pub fn tmpdir() -> Path { fn getenv_nonempty(v: &str) -> Option { match getenv(v) { Some(x) => - if str::is_empty(x) { + if x.is_empty() { None } else { Some(Path(x)) @@ -1449,6 +1449,7 @@ mod tests { use rand; use run; use str; + use str::StrSlice; use vec; use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; @@ -1606,7 +1607,7 @@ mod tests { #[test] fn tmpdir() { - assert!(!str::is_empty(os::tmpdir().to_str())); + assert!(!os::tmpdir().to_str().is_empty()); } // Issue #712 @@ -1671,7 +1672,7 @@ mod tests { unsafe { let tempdir = getcwd(); // would like to use $TMPDIR, // doesn't seem to work on Linux - assert!((str::len(tempdir.to_str()) > 0u)); + assert!((tempdir.to_str().len() > 0u)); let in = tempdir.push("in.txt"); let out = tempdir.push("out.txt"); @@ -1686,7 +1687,7 @@ mod tests { let mut buf = str::to_bytes(s) + [0 as u8]; do vec::as_mut_buf(buf) |b, _len| { assert!((libc::fwrite(b as *c_void, 1u as size_t, - (str::len(s) + 1u) as size_t, ostream) + (s.len() + 1u) as size_t, ostream) == buf.len() as size_t)) } assert_eq!(libc::fclose(ostream), (0u as c_int)); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 09ea6a5dfa9b2..b44e79f7d03be 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -110,7 +110,7 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { /// Copy a slice into a new unique str #[inline(always)] pub fn to_owned(s: &str) -> ~str { - unsafe { raw::slice_bytes_owned(s, 0, len(s)) } + unsafe { raw::slice_bytes_owned(s, 0, s.len()) } } impl ToStr for ~str { @@ -148,7 +148,7 @@ pub fn push_char(s: &mut ~str, ch: char) { else if code < max_four_b { 4u } else if code < max_five_b { 5u } else { 6u }; - let len = len(*s); + let len = s.len(); let new_len = len + nb; reserve_at_least(&mut *s, new_len); let off = len; @@ -453,7 +453,7 @@ Section: Adding to and removing from a string * If the string does not contain any characters */ pub fn pop_char(s: &mut ~str) -> char { - let end = len(*s); + let end = s.len(); assert!(end > 0u); let CharRange {ch, next} = char_range_at_reverse(*s, end); unsafe { raw::set_len(s, next); } @@ -469,7 +469,7 @@ pub fn pop_char(s: &mut ~str) -> char { */ pub fn shift_char(s: &mut ~str) -> char { let CharRange {ch, next} = char_range_at(*s, 0u); - *s = unsafe { raw::slice_bytes_owned(*s, next, len(*s)) }; + *s = unsafe { raw::slice_bytes_owned(*s, next, s.len()) }; return ch; } @@ -485,7 +485,7 @@ pub fn shift_char(s: &mut ~str) -> char { #[inline] pub fn slice_shift_char<'a>(s: &'a str) -> (char, &'a str) { let CharRange {ch, next} = char_range_at(s, 0u); - let next_s = unsafe { raw::slice_bytes(s, next, len(s)) }; + let next_s = unsafe { raw::slice_bytes(s, next, s.len()) }; return (ch, next_s); } @@ -554,7 +554,7 @@ pub fn trim_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { pub fn trim_left<'a>(s: &'a str) -> &'a str { match find(s, |c| !char::is_whitespace(c)) { None => "", - Some(first) => unsafe { raw::slice_bytes(s, first, len(s)) } + Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) } } } @@ -584,7 +584,7 @@ Section: Transforming strings pub fn to_bytes(s: &str) -> ~[u8] { unsafe { let mut v: ~[u8] = ::cast::transmute(to_owned(s)); - vec::raw::set_len(&mut v, len(s)); + vec::raw::set_len(&mut v, s.len()); v } } @@ -618,19 +618,7 @@ pub fn to_chars(s: &str) -> ~[char] { * `begin`. */ pub fn substr<'a>(s: &'a str, begin: uint, n: uint) -> &'a str { - slice(s, begin, begin + count_bytes(s, begin, n)) -} - -/** - * Returns a slice of the given string from the byte range [`begin`..`end`) - * - * Fails when `begin` and `end` do not point to valid characters or beyond - * the last character of the string - */ -pub fn slice<'a>(s: &'a str, begin: uint, end: uint) -> &'a str { - assert!(is_char_boundary(s, begin)); - assert!(is_char_boundary(s, end)); - unsafe { raw::slice_bytes(s, begin, end) } + s.slice(begin, begin + count_bytes(s, begin, n)) } /// An iterator over the substrings of a string, separated by `sep`. @@ -724,7 +712,7 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte // See Issue #1932 for why this is a naive search fn iter_matches<'a,'b>(s: &'a str, sep: &'b str, f: &fn(uint, uint) -> bool) -> bool { - let (sep_len, l) = (len(sep), len(s)); + let (sep_len, l) = (sep.len(), s.len()); assert!(sep_len > 0u); let mut (i, match_start, match_i) = (0u, 0u, 0u); @@ -759,7 +747,7 @@ fn iter_between_matches<'a,'b>(s: &'a str, if !f(last_end, from) { return false; } last_end = to; } - return f(last_end, len(s)); + return f(last_end, s.len()); } /** @@ -889,7 +877,7 @@ pub fn each_split_within<'a>(ss: &'a str, let mut state = A; let mut cont = true; - let slice: &fn() = || { cont = it(slice(ss, slice_start, last_end)) }; + let slice: &fn() = || { cont = it(ss.slice(slice_start, last_end)) }; let machine: &fn((uint, char)) -> bool = |(i, c)| { let whitespace = if char::is_whitespace(c) { Ws } else { Cr }; @@ -902,7 +890,7 @@ pub fn each_split_within<'a>(ss: &'a str, (B, Cr, UnderLim) => { B } (B, Cr, OverLim) if (i - last_start + 1) > lim => fail!("word starting with %? longer than limit!", - self::slice(ss, last_start, i + 1)), + ss.slice(last_start, i + 1)), (B, Cr, OverLim) => { slice(); slice_start = last_start; B } (B, Ws, UnderLim) => { last_end = i; C } (B, Ws, OverLim) => { last_end = i; slice(); A } @@ -1178,7 +1166,7 @@ Section: Iterating through strings /// Apply a function to each character pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { let mut result = ~""; - reserve(&mut result, len(ss)); + reserve(&mut result, ss.len()); for ss.iter().advance |cc| { str::push_char(&mut result, ff(cc)); } @@ -1203,7 +1191,7 @@ Section: Searching * or `none` if there is no match */ pub fn find_char(s: &str, c: char) -> Option { - find_char_between(s, c, 0u, len(s)) + find_char_between(s, c, 0u, s.len()) } /** @@ -1223,11 +1211,11 @@ pub fn find_char(s: &str, c: char) -> Option { * * # Failure * - * `start` must be less than or equal to `len(s)`. `start` must be the + * `start` must be less than or equal to `s.len()`. `start` must be the * index of a character boundary, as defined by `is_char_boundary`. */ pub fn find_char_from(s: &str, c: char, start: uint) -> Option { - find_char_between(s, c, start, len(s)) + find_char_between(s, c, start, s.len()) } /** @@ -1248,14 +1236,14 @@ pub fn find_char_from(s: &str, c: char, start: uint) -> Option { * # Failure * * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `len(s)`. `start` must be the index of a character boundary, + * or equal to `s.len()`. `start` must be the index of a character boundary, * as defined by `is_char_boundary`. */ pub fn find_char_between(s: &str, c: char, start: uint, end: uint) -> Option { if c < 128u as char { assert!(start <= end); - assert!(end <= len(s)); + assert!(end <= s.len()); let mut i = start; let b = c as u8; while i < end { @@ -1282,7 +1270,7 @@ pub fn find_char_between(s: &str, c: char, start: uint, end: uint) * or `none` if there is no match */ pub fn rfind_char(s: &str, c: char) -> Option { - rfind_char_between(s, c, len(s), 0u) + rfind_char_between(s, c, s.len(), 0u) } /** @@ -1302,7 +1290,7 @@ pub fn rfind_char(s: &str, c: char) -> Option { * * # Failure * - * `start` must be less than or equal to `len(s)`. `start` must be + * `start` must be less than or equal to `s.len()`. `start` must be * the index of a character boundary, as defined by `is_char_boundary`. */ pub fn rfind_char_from(s: &str, c: char, start: uint) -> Option { @@ -1327,13 +1315,13 @@ pub fn rfind_char_from(s: &str, c: char, start: uint) -> Option { * # Failure * * `end` must be less than or equal to `start` and `start` must be less than - * or equal to `len(s)`. `start` must be the index of a character boundary, + * or equal to `s.len()`. `start` must be the index of a character boundary, * as defined by `is_char_boundary`. */ pub fn rfind_char_between(s: &str, c: char, start: uint, end: uint) -> Option { if c < 128u as char { assert!(start >= end); - assert!(start <= len(s)); + assert!(start <= s.len()); let mut i = start; let b = c as u8; while i > end { @@ -1361,7 +1349,7 @@ pub fn rfind_char_between(s: &str, c: char, start: uint, end: uint) -> Option bool) -> Option { - find_between(s, 0u, len(s), f) + find_between(s, 0u, s.len(), f) } /** @@ -1381,12 +1369,12 @@ pub fn find(s: &str, f: &fn(char) -> bool) -> Option { * * # Failure * - * `start` must be less than or equal to `len(s)`. `start` must be the + * `start` must be less than or equal to `s.len()`. `start` must be the * index of a character boundary, as defined by `is_char_boundary`. */ pub fn find_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option { - find_between(s, start, len(s), f) + find_between(s, start, s.len(), f) } /** @@ -1408,12 +1396,12 @@ pub fn find_from(s: &str, start: uint, f: &fn(char) * # Failure * * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `len(s)`. `start` must be the index of a character + * or equal to `s.len()`. `start` must be the index of a character * boundary, as defined by `is_char_boundary`. */ pub fn find_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option { assert!(start <= end); - assert!(end <= len(s)); + assert!(end <= s.len()); assert!(is_char_boundary(s, start)); let mut i = start; while i < end { @@ -1439,7 +1427,7 @@ pub fn find_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Op * or `none` if there is no match */ pub fn rfind(s: &str, f: &fn(char) -> bool) -> Option { - rfind_between(s, len(s), 0u, f) + rfind_between(s, s.len(), 0u, f) } /** @@ -1459,7 +1447,7 @@ pub fn rfind(s: &str, f: &fn(char) -> bool) -> Option { * * # Failure * - * `start` must be less than or equal to `len(s)', `start` must be the + * `start` must be less than or equal to `s.len()', `start` must be the * index of a character boundary, as defined by `is_char_boundary` */ pub fn rfind_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option { @@ -1485,12 +1473,12 @@ pub fn rfind_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option { * # Failure * * `end` must be less than or equal to `start` and `start` must be less - * than or equal to `len(s)`. `start` must be the index of a character + * than or equal to `s.len()`. `start` must be the index of a character * boundary, as defined by `is_char_boundary` */ pub fn rfind_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option { assert!(start >= end); - assert!(start <= len(s)); + assert!(start <= s.len()); assert!(is_char_boundary(s, start)); let mut i = start; while i > end { @@ -1522,7 +1510,7 @@ fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { * or `none` if there is no match */ pub fn find_str<'a,'b>(haystack: &'a str, needle: &'b str) -> Option { - find_str_between(haystack, needle, 0u, len(haystack)) + find_str_between(haystack, needle, 0u, haystack.len()) } /** @@ -1542,13 +1530,13 @@ pub fn find_str<'a,'b>(haystack: &'a str, needle: &'b str) -> Option { * * # Failure * - * `start` must be less than or equal to `len(s)` + * `start` must be less than or equal to `s.len()` */ pub fn find_str_from<'a,'b>(haystack: &'a str, needle: &'b str, start: uint) -> Option { - find_str_between(haystack, needle, start, len(haystack)) + find_str_between(haystack, needle, start, haystack.len()) } /** @@ -1569,7 +1557,7 @@ pub fn find_str_from<'a,'b>(haystack: &'a str, * # Failure * * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `len(s)`. + * or equal to `s.len()`. */ pub fn find_str_between<'a,'b>(haystack: &'a str, needle: &'b str, @@ -1577,8 +1565,8 @@ pub fn find_str_between<'a,'b>(haystack: &'a str, end:uint) -> Option { // See Issue #1932 for why this is a naive search - assert!(end <= len(haystack)); - let needle_len = len(needle); + assert!(end <= haystack.len()); + let needle_len = needle.len(); if needle_len == 0u { return Some(start); } if needle_len > end { return None; } @@ -1624,7 +1612,7 @@ pub fn contains_char(haystack: &str, needle: char) -> bool { * * needle - The string to look for */ pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let (haystack_len, needle_len) = (len(haystack), len(needle)); + let (haystack_len, needle_len) = (haystack.len(), needle.len()); if needle_len == 0u { true } else if needle_len > haystack_len { false } else { match_at(haystack, needle, 0u) } @@ -1639,7 +1627,7 @@ pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { * * needle - The string to look for */ pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let (haystack_len, needle_len) = (len(haystack), len(needle)); + let (haystack_len, needle_len) = (haystack.len(), needle.len()); if needle_len == 0u { true } else if needle_len > haystack_len { false } else { match_at(haystack, needle, haystack_len - needle_len) } @@ -1649,10 +1637,6 @@ pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { Section: String properties */ -/// Returns true if the string has length 0 -#[inline(always)] -pub fn is_empty(s: &str) -> bool { len(s) == 0u } - /** * Returns true if the string contains only whitespace * @@ -1671,15 +1655,9 @@ fn is_alphanumeric(s: &str) -> bool { s.iter().all(char::is_alphanumeric) } -/// Returns the string length/size in bytes not counting the null terminator -#[inline(always)] -pub fn len(s: &str) -> uint { - do as_buf(s) |_p, n| { n - 1u } -} - /// Returns the number of characters that a string holds #[inline(always)] -pub fn char_len(s: &str) -> uint { count_chars(s, 0u, len(s)) } +pub fn char_len(s: &str) -> uint { count_chars(s, 0u, s.len()) } /* Section: Misc @@ -1828,7 +1806,7 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { assert!(is_char_boundary(s, start)); let mut (end, cnt) = (start, n); - let l = len(s); + let l = s.len(); while cnt > 0u { assert!(end < l); let next = char_range_at(s, end).next; @@ -1856,7 +1834,7 @@ pub fn utf8_char_width(b: u8) -> uint { * character sequence. */ pub fn is_char_boundary(s: &str, index: uint) -> bool { - if index == len(s) { return true; } + if index == s.len() { return true; } let b = s[index]; return b < 128u8 || b >= 192u8; } @@ -1873,7 +1851,7 @@ pub fn is_char_boundary(s: &str, index: uint) -> bool { * ~~~ {.rust} * let s = "中华Việt Nam"; * let i = 0u; - * while i < str::len(s) { + * while i < s.len() { * let CharRange {ch, next} = str::char_range_at(s, i); * std::io::println(fmt!("%u: %c",i,ch)); * i = next; @@ -2242,7 +2220,7 @@ pub fn capacity(s: &const ~str) -> uint { /// Escape each char in `s` with char::escape_default. pub fn escape_default(s: &str) -> ~str { let mut out: ~str = ~""; - reserve_at_least(&mut out, str::len(s)); + reserve_at_least(&mut out, s.len()); for s.iter().advance |c| { push_str(&mut out, char::escape_default(c)); } @@ -2252,7 +2230,7 @@ pub fn escape_default(s: &str) -> ~str { /// Escape each char in `s` with char::escape_unicode. pub fn escape_unicode(s: &str) -> ~str { let mut out: ~str = ~""; - reserve_at_least(&mut out, str::len(s)); + reserve_at_least(&mut out, s.len()); for s.iter().advance |c| { push_str(&mut out, char::escape_unicode(c)); } @@ -2265,7 +2243,7 @@ pub mod raw { use libc; use ptr; use str::raw; - use str::{as_buf, is_utf8, len, reserve_at_least}; + use str::{as_buf, is_utf8, reserve_at_least}; use vec; /// Create a Rust string from a null-terminated *u8 buffer @@ -2394,7 +2372,7 @@ pub mod raw { /// Removes the last byte from a string and returns it. (Not UTF-8 safe). pub unsafe fn pop_byte(s: &mut ~str) -> u8 { - let len = len(*s); + let len = s.len(); assert!((len > 0u)); let b = s[len - 1u]; set_len(s, len - 1u); @@ -2403,7 +2381,7 @@ pub mod raw { /// Removes the first byte from a string and returns it. (Not UTF-8 safe). pub unsafe fn shift_byte(s: &mut ~str) -> u8 { - let len = len(*s); + let len = s.len(); assert!((len > 0u)); let b = s[0]; *s = raw::slice_bytes_owned(*s, 1u, len); @@ -2567,7 +2545,7 @@ impl<'self> StrSlice<'self> for &'self str { } /// Returns true if the string has length 0 #[inline] - fn is_empty(&self) -> bool { is_empty(*self) } + fn is_empty(&self) -> bool { self.len() == 0 } /** * Returns true if the string contains only whitespace * @@ -2584,7 +2562,9 @@ impl<'self> StrSlice<'self> for &'self str { fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } /// Returns the size in bytes not counting the null terminator #[inline(always)] - fn len(&self) -> uint { len(*self) } + fn len(&self) -> uint { + do as_buf(*self) |_p, n| { n - 1u } + } /// Returns the number of characters that a string holds #[inline] fn char_len(&self) -> uint { char_len(*self) } @@ -2597,7 +2577,9 @@ impl<'self> StrSlice<'self> for &'self str { */ #[inline] fn slice(&self, begin: uint, end: uint) -> &'self str { - slice(*self, begin, end) + assert!(is_char_boundary(*self, begin)); + assert!(is_char_boundary(*self, end)); + unsafe { raw::slice_bytes(*self, begin, end) } } /** * Splits a string into a vector of the substrings separated by a given @@ -2788,8 +2770,8 @@ mod tests { #[test] fn test_eq_slice() { - assert!((eq_slice(slice("foobar", 0, 3), "foo"))); - assert!((eq_slice(slice("barfoo", 3, 6), "foo"))); + assert!((eq_slice("foobar".slice(0, 3), "foo"))); + assert!((eq_slice("barfoo".slice(3, 6), "foo"))); assert!((!eq_slice("foo1", "foo2"))); } @@ -2803,13 +2785,13 @@ mod tests { #[test] fn test_len() { - assert_eq!(len(""), 0u); - assert_eq!(len("hello world"), 11u); - assert_eq!(len("\x63"), 1u); - assert_eq!(len("\xa2"), 2u); - assert_eq!(len("\u03c0"), 2u); - assert_eq!(len("\u2620"), 3u); - assert_eq!(len("\U0001d11e"), 4u); + assert_eq!("".len(), 0u); + assert_eq!("hello world".len(), 11u); + assert_eq!("\x63".len(), 1u); + assert_eq!("\xa2".len(), 2u); + assert_eq!("\u03c0".len(), 2u); + assert_eq!("\u2620".len(), 3u); + assert_eq!("\U0001d11e".len(), 4u); assert_eq!(char_len(""), 0u); assert_eq!(char_len("hello world"), 11u); @@ -2937,7 +2919,7 @@ mod tests { #[test] fn test_substr() { fn t(a: &str, b: &str, start: int) { - assert_eq!(substr(a, start as uint, len(b)), b); + assert_eq!(substr(a, start as uint, b.len()), b); } t("hello", "llo", 2); t("hello", "el", 1); @@ -3044,8 +3026,8 @@ mod tests { #[test] fn test_is_empty() { - assert!((is_empty(""))); - assert!((!is_empty("a"))); + assert!("".is_empty()); + assert!(!"a".is_empty()); } #[test] @@ -3101,16 +3083,16 @@ mod tests { #[test] fn test_slice() { - assert_eq!("ab", slice("abc", 0, 2)); - assert_eq!("bc", slice("abc", 1, 3)); - assert_eq!("", slice("abc", 1, 1)); - assert_eq!("\u65e5", slice("\u65e5\u672c", 0, 3)); + assert_eq!("ab", "abc".slice(0, 2)); + assert_eq!("bc", "abc".slice(1, 3)); + assert_eq!("", "abc".slice(1, 1)); + assert_eq!("\u65e5", "\u65e5\u672c".slice(0, 3)); let data = "ประเทศไทย中华"; - assert_eq!("ป", slice(data, 0, 3)); - assert_eq!("ร", slice(data, 3, 6)); - assert_eq!("", slice(data, 3, 3)); - assert_eq!("华", slice(data, 30, 33)); + assert_eq!("ป", data.slice(0, 3)); + assert_eq!("ร", data.slice(3, 6)); + assert_eq!("", data.slice(3, 3)); + assert_eq!("华", data.slice(30, 33)); fn a_million_letter_X() -> ~str { let mut i = 0; @@ -3129,23 +3111,23 @@ mod tests { } let letters = a_million_letter_X(); assert!(half_a_million_letter_X() == - slice(letters, 0u, 3u * 500000u).to_owned()); + letters.slice(0u, 3u * 500000u).to_owned()); } #[test] fn test_slice_2() { let ss = "中华Việt Nam"; - assert_eq!("华", slice(ss, 3u, 6u)); - assert_eq!("Việt Nam", slice(ss, 6u, 16u)); + assert_eq!("华", ss.slice(3u, 6u)); + assert_eq!("Việt Nam", ss.slice(6u, 16u)); - assert_eq!("ab", slice("abc", 0u, 2u)); - assert_eq!("bc", slice("abc", 1u, 3u)); - assert_eq!("", slice("abc", 1u, 1u)); + assert_eq!("ab", "abc".slice(0u, 2u)); + assert_eq!("bc", "abc".slice(1u, 3u)); + assert_eq!("", "abc".slice(1u, 1u)); - assert_eq!("中", slice(ss, 0u, 3u)); - assert_eq!("华V", slice(ss, 3u, 7u)); - assert_eq!("", slice(ss, 3u, 3u)); + assert_eq!("中", ss.slice(0u, 3u)); + assert_eq!("华V", ss.slice(3u, 7u)); + assert_eq!("", ss.slice(3u, 3u)); /*0: 中 3: 华 6: V @@ -3162,7 +3144,7 @@ mod tests { #[should_fail] #[ignore(cfg(windows))] fn test_slice_fail() { - slice("中华Việt Nam", 0u, 2u); + "中华Việt Nam".slice(0u, 2u); } #[test] @@ -3420,8 +3402,8 @@ mod tests { #[test] fn test_subslice_offset() { let a = "kernelsprite"; - let b = slice(a, 7, len(a)); - let c = slice(a, 0, len(a) - 6); + let b = a.slice(7, a.len()); + let c = a.slice(0, a.len() - 6); assert_eq!(subslice_offset(a, b), 7); assert_eq!(subslice_offset(a, c), 0); @@ -3448,7 +3430,7 @@ mod tests { let v: ~[u8] = to_bytes(s1); let s2: ~str = from_bytes(v); let mut i: uint = 0u; - let n1: uint = len(s1); + let n1: uint = s1.len(); let n2: uint = v.len(); assert_eq!(n1, n2); while i < n1 { @@ -3601,7 +3583,7 @@ mod tests { #[test] fn test_to_managed() { assert_eq!("abc".to_managed(), @"abc"); - assert_eq!(slice("abcdef", 1, 5).to_managed(), @"bcde"); + assert_eq!("abcdef".slice(1, 5).to_managed(), @"bcde"); } #[test] diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index 07bcf6d953c3a..9b74119b08cb5 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -547,7 +547,7 @@ pub mod rt { let unpadded = match cv.precision { CountImplied => s, CountIs(max) => if (max as uint) < str::char_len(s) { - str::slice(s, 0, max as uint) + s.slice(0, max as uint) } else { s } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 5f8d6e73cefab..52f6e458db3e1 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -290,9 +290,9 @@ impl FileMap { let begin = begin.to_uint(); let end = match str::find_char_from(*self.src, '\n', begin) { Some(e) => e, - None => str::len(*self.src) + None => self.src.len() }; - str::slice(*self.src, begin, end).to_owned() + self.src.slice(begin, end).to_owned() } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { @@ -418,7 +418,7 @@ impl CodeMap { let begin = self.lookup_byte_offset(sp.lo); let end = self.lookup_byte_offset(sp.hi); assert_eq!(begin.fm.start_pos, end.fm.start_pos); - return str::slice(*begin.fm.src, + return begin.fm.src.slice( begin.pos.to_uint(), end.pos.to_uint()).to_owned(); } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index fa4a74b895454..58b01fe78e7b8 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -14,7 +14,6 @@ use codemap::{Pos, span}; use codemap; use core::io; -use core::str; use core::uint; use core::vec; use extra::term; @@ -259,7 +258,7 @@ fn highlight_lines(cm: @codemap::CodeMap, if elided { let last_line = display_lines[display_lines.len() - 1u]; let s = fmt!("%s:%u ", fm.name, last_line + 1u); - let mut indent = str::len(s); + let mut indent = s.len(); let mut out = ~""; while indent > 0u { out += " "; indent -= 1u; } out += "...\n"; @@ -277,11 +276,11 @@ fn highlight_lines(cm: @codemap::CodeMap, while num > 0u { num /= 10u; digits += 1u; } // indent past |name:## | and the 0-offset column location - let left = str::len(fm.name) + digits + lo.col.to_uint() + 3u; + let left = fm.name.len() + digits + lo.col.to_uint() + 3u; let mut s = ~""; // Skip is the number of characters we need to skip because they are // part of the 'filename:line ' part of the previous line. - let skip = str::len(fm.name) + digits + 3u; + let skip = fm.name.len() + digits + 3u; for skip.times() { s += " "; } diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 57df0fe6f8632..a715ede766401 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -215,7 +215,7 @@ fn trim_whitespace_prefix_and_push_line(lines: &mut ~[~str], let col = col.to_uint(); let s1 = if all_whitespace(s, 0, uint::min(len, col)) { if col < len { - str::slice(s, col, len).to_owned() + s.slice(col, len).to_owned() } else { ~"" } } else { s }; debug!("pushing line: %s", s1); @@ -277,7 +277,7 @@ fn read_block_comment(rdr: @mut StringReader, } } } - if str::len(curr_line) != 0 { + if curr_line.len() != 0 { trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col); } } diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index f615f1321df9f..04635fdf4e9bf 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -366,7 +366,7 @@ fn scan_exponent(rdr: @mut StringReader) -> Option<~str> { bump(rdr); } let exponent = scan_digits(rdr, 10u); - if str::len(exponent) > 0u { + if exponent.len() > 0u { return Some(rslt + exponent); } else { rdr.fatal(~"scan_exponent: bad fp literal"); } } else { return None::<~str>; } @@ -434,7 +434,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { tp = if signed { either::Left(ast::ty_i64) } else { either::Right(ast::ty_u64) }; } - if str::len(num_str) == 0u { + if num_str.len() == 0u { rdr.fatal(~"no valid digits found for number"); } let parsed = match u64::from_str_radix(num_str, base as uint) { @@ -499,7 +499,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { } return token::LIT_FLOAT_UNSUFFIXED(str_to_ident(num_str)); } else { - if str::len(num_str) == 0u { + if num_str.len() == 0u { rdr.fatal(~"no valid digits found for number"); } let parsed = match u64::from_str_radix(num_str, base as uint) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5c81d406cd200..10fd46ea4b628 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -249,7 +249,7 @@ pub fn head(s: @ps, w: &str) { // outer-box is consistent cbox(s, indent_unit); // head-box is inconsistent - ibox(s, str::len(w) + 1); + ibox(s, w.len() + 1); // keyword that starts the head if !w.is_empty() { word_nbsp(s, w); diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 9f125a48de956..c497a30ec5f66 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -81,27 +81,27 @@ fn make_random_fasta(wr: @io::Writer, for uint::range(0u, n as uint) |_i| { str::push_char(&mut op, select_random(myrandom_next(rng, 100u32), copy genelist)); - if str::len(op) >= LINE_LENGTH() { + if op.len() >= LINE_LENGTH() { wr.write_line(op); op = ~""; } } - if str::len(op) > 0u { wr.write_line(op); } + if op.len() > 0u { wr.write_line(op); } } fn make_repeat_fasta(wr: @io::Writer, id: ~str, desc: ~str, s: ~str, n: int) { unsafe { wr.write_line(~">" + id + " " + desc); let mut op: ~str = ~""; - let sl: uint = str::len(s); + let sl: uint = s.len(); for uint::range(0u, n as uint) |i| { str::raw::push_byte(&mut op, s[i % sl]); - if str::len(op) >= LINE_LENGTH() { + if op.len() >= LINE_LENGTH() { wr.write_line(op); op = ~""; } } - if str::len(op) > 0u { wr.write_line(op); } + if op.len() > 0u { wr.write_line(op); } } } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index e403ba6e73dec..ef32b0bb2dc9b 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -191,7 +191,7 @@ fn main() { while !rdr.eof() { let line: ~str = rdr.read_line(); - if str::len(line) == 0u { loop; } + if line.len() == 0u { loop; } match (line[0] as char, proc_mode) { diff --git a/src/test/compile-fail/die-not-static.rs b/src/test/compile-fail/die-not-static.rs index c7f5e27181837..40a4232717db2 100644 --- a/src/test/compile-fail/die-not-static.rs +++ b/src/test/compile-fail/die-not-static.rs @@ -2,7 +2,7 @@ use std::str; fn main() { let v = ~"test"; - let sslice = str::slice(v, 0, v.len()); + let sslice = v.slice(0, v.len()); //~^ ERROR borrowed value does not live long enough fail!(sslice); } diff --git a/src/test/run-fail/task-spawn-barefn.rs b/src/test/run-fail/task-spawn-barefn.rs index 2456f968c3c10..6e1af6ff7e095 100644 --- a/src/test/run-fail/task-spawn-barefn.rs +++ b/src/test/run-fail/task-spawn-barefn.rs @@ -20,5 +20,5 @@ fn main() { } fn startfn() { - assert!(str::is_empty(~"Ensure that the child task runs by failing")); + assert!("Ensure that the child task runs by failing".is_empty()); } diff --git a/src/test/run-pass/string-self-append.rs b/src/test/run-pass/string-self-append.rs index f02600bb137c0..e01b2a42f6139 100644 --- a/src/test/run-pass/string-self-append.rs +++ b/src/test/run-pass/string-self-append.rs @@ -18,8 +18,8 @@ pub fn main() { let mut i = 20; let mut expected_len = 1u; while i > 0 { - error!(str::len(a)); - assert_eq!(str::len(a), expected_len); + error!(a.len()); + assert_eq!(a.len(), expected_len); a = a + a; // FIXME(#3387)---can't write a += a i -= 1; expected_len *= 2u; diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 0069165aed4ef..011fb4435c3e8 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -18,7 +18,7 @@ pub fn main() { let chs: ~[char] = ~['e', 'é', '€', 0x10000 as char]; let s: ~str = str::from_chars(chs); - assert!(str::len(s) == 10u); + assert!(s.len() == 10u); assert!(str::char_len(s) == 4u); assert!(str::to_chars(s).len() == 4u); assert!(str::from_chars(str::to_chars(s)) == s); From ee41ad4168a0e9316d8621ad5ceda2208c553f76 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 10:01:10 +1000 Subject: [PATCH 04/21] std: fix compile & test --- src/librustpkg/version.rs | 10 ++++------ src/libstd/run.rs | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index 92906f5af543d..c966ede3cdf09 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -15,6 +15,7 @@ extern mod std; use extra::semver; use core::prelude::*; +use core::iterator::IteratorUtil; use core::{char, os, result, run, str}; use package_path::RemotePath; use extra::tempfile::mkdtemp; @@ -112,7 +113,7 @@ pub fn try_getting_version(remote_path: &RemotePath) -> Option { ~"tag", ~"-l"]); let output_text = str::from_bytes(outp.output); debug!("Full output: ( %s ) [%?]", output_text, outp.status); - for output_text.each_split_char('\n') |l| { + for output_text.line_iter().advance |l| { debug!("A line of output: %s", l); if !l.is_whitespace() { output = Some(l); @@ -162,11 +163,8 @@ fn try_parsing_version(s: &str) -> Option { /// Just an approximation fn is_url_like(p: &RemotePath) -> bool { - let mut n = 0; - for p.to_str().each_split_char('/') |_| { - n += 1; - } - n > 2 + let str = p.to_str(); + str.split_iter('/').count() > 2 } /// If s is of the form foo#bar, where bar is a valid version diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 29598bc48fa41..41bc573f10d3f 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -12,6 +12,7 @@ #[allow(missing_doc)]; +use iterator::IteratorUtil; use cast; use comm::{stream, SharedChan, GenericChan, GenericPort}; use int; From 76fc9be5a1634c8b7ebf766f51ad594d9012fe9c Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 12:46:35 +1000 Subject: [PATCH 05/21] std: convert each_split_str to an iterator --- src/librustc/middle/resolve.rs | 5 +- src/libstd/str.rs | 226 ++++++++++++++++----------------- 2 files changed, 114 insertions(+), 117 deletions(-) diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 25736afd38a0d..ffa3c815b289d 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -40,7 +40,7 @@ use syntax::visit::{visit_foreign_item, visit_item}; use syntax::visit::{visit_mod, visit_ty, vt}; use syntax::opt_vec::OptVec; -use core::str::each_split_str; +use core::iterator::IteratorUtil; use core::str; use core::uint; use core::vec; @@ -1737,8 +1737,7 @@ impl Resolver { entry: %s (%?)", path_string, def_like); - let mut pieces = ~[]; - for each_split_str(path_string, "::") |s| { pieces.push(s.to_owned()) } + let mut pieces: ~[&str] = path_string.split_str_iter("::").collect(); let final_ident_str = pieces.pop(); let final_ident = self.session.ident_of(final_ident_str); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index b44e79f7d03be..46bf0b08c1039 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -667,6 +667,7 @@ impl<'self> StrCharSplitSeparator for extern "Rust" fn(char) -> bool { } impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { + #[inline] fn next(&mut self) -> Option<&'self str> { if self.finished { return None } @@ -709,88 +710,69 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte } } -// See Issue #1932 for why this is a naive search -fn iter_matches<'a,'b>(s: &'a str, sep: &'b str, - f: &fn(uint, uint) -> bool) -> bool { - let (sep_len, l) = (sep.len(), s.len()); - assert!(sep_len > 0u); - let mut (i, match_start, match_i) = (0u, 0u, 0u); +/// An iterator over the start and end indicies of the matches of a +/// substring within a larger string +pub struct StrMatchesIndexIterator<'self> { + priv haystack: &'self str, + priv needle: &'self str, + priv position: uint, +} - while i < l { - if s[i] == sep[match_i] { - if match_i == 0u { match_start = i; } - match_i += 1u; - // Found a match - if match_i == sep_len { - if !f(match_start, i + 1u) { return false; } - match_i = 0u; - } - i += 1u; - } else { - // Failed match, backtrack - if match_i > 0u { - match_i = 0u; - i = match_start + 1u; +/// An iterator over the substrings of a string separated by a given +/// search string +pub struct StrStrSplitIterator<'self> { + priv it: StrMatchesIndexIterator<'self>, + priv last_end: uint, + priv finished: bool +} + +impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> { + #[inline] + fn next(&mut self) -> Option<(uint, uint)> { + // See Issue #1932 for why this is a naive search + let (h_len, n_len) = (self.haystack.len(), self.needle.len()); + let mut (match_start, match_i) = (0, 0); + + while self.position < h_len { + if self.haystack[self.position] == self.needle[match_i] { + if match_i == 0 { match_start = self.position; } + match_i += 1; + self.position += 1; + + if match_i == n_len { + // found a match! + return Some((match_start, self.position)); + } } else { - i += 1u; + // failed match, backtrack + if match_i > 0 { + match_i = 0; + self.position = match_start; + } + self.position += 1; } } + None } - return true; -} - -fn iter_between_matches<'a,'b>(s: &'a str, - sep: &'b str, - f: &fn(uint, uint) -> bool) -> bool { - let mut last_end = 0u; - for iter_matches(s, sep) |from, to| { - if !f(last_end, from) { return false; } - last_end = to; - } - return f(last_end, s.len()); } -/** - * Splits a string into a vector of the substrings separated by a given string - * - * # Example - * - * ~~~ {.rust} - * let mut v = ~[]; - * for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); } - * assert!(v == ["", "XXX", "YYY", ""]); - * ~~~ - */ -pub fn each_split_str<'a,'b>(s: &'a str, - sep: &'b str, - it: &fn(&'a str) -> bool) -> bool { - for iter_between_matches(s, sep) |from, to| { - if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; } - } - return true; -} +impl<'self> Iterator<&'self str> for StrStrSplitIterator<'self> { + #[inline] + fn next(&mut self) -> Option<&'self str> { + if self.finished { return None; } -/** - * Splits the string `s` based on `sep`, yielding all splits to the iterator - * function provide - * - * # Example - * - * ~~~ {.rust} - * let mut v = ~[]; - * for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); } - * assert!(v == ["XXX", "YYY"]); - * ~~~ - */ -pub fn each_split_str_nonempty<'a,'b>(s: &'a str, - sep: &'b str, - it: &fn(&'a str) -> bool) -> bool { - for iter_between_matches(s, sep) |from, to| { - if to > from { - if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; } + match self.it.next() { + Some((from, to)) => { + let ret = Some(self.it.haystack.slice(self.last_end, from)); + self.last_end = to; + ret + } + None => { + self.finished = true; + Some(self.it.haystack.slice(self.last_end, self.it.haystack.len())) + } } } - return true; } /// Levenshtein Distance between two strings @@ -929,15 +911,13 @@ pub fn each_split_within<'a>(ss: &'a str, * The original string with all occurances of `from` replaced with `to` */ pub fn replace(s: &str, from: &str, to: &str) -> ~str { - let mut (result, first) = (~"", true); - for iter_between_matches(s, from) |start, end| { - if first { - first = false; - } else { - push_str(&mut result, to); - } - push_str(&mut result, unsafe{raw::slice_bytes(s, start, end)}); + let mut (result, last_end) = (~"", 0); + for s.matches_index_iter(from).advance |(start, end)| { + result.push_str(unsafe{raw::slice_bytes(s, last_end, start)}); + result.push_str(to); + last_end = end; } + result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())}); result } @@ -2441,6 +2421,20 @@ pub trait StrSlice<'self> { fn split_options_iter(&self, sep: Sep, count: uint, allow_trailing_empty: bool) -> StrCharSplitIterator<'self, Sep>; + /// An iterator over the start and end indices of each match of + /// `sep` within `self`. + fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>; + /** + * An iterator over the substrings of `self` separated by `sep`. + * + * # Example + * + * ~~~ {.rust} + * let v: ~[&str] = ".XXX.YYY.".split_str_iter(".").collect() + * assert_eq!(v, ["", "XXX", "YYY", ""]); + * ~~~ + */ + fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>; /// An iterator over the lines of a string (subsequences separated /// by `\n`). fn line_iter(&self) -> StrCharSplitIterator<'self, char>; @@ -2454,7 +2448,6 @@ pub trait StrSlice<'self> { fn len(&self) -> uint; fn char_len(&self) -> uint; fn slice(&self, begin: uint, end: uint) -> &'self str; - fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool; fn starts_with<'a>(&self, needle: &'a str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; fn escape_default(&self) -> ~str; @@ -2529,6 +2522,21 @@ impl<'self> StrSlice<'self> for &'self str { only_ascii: only_ascii } } + fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self> { + assert!(!sep.is_empty()) + StrMatchesIndexIterator { + haystack: *self, + needle: sep, + position: 0 + } + } + fn split_str_iter(&self, sep: &'self str) -> StrStrSplitIterator<'self> { + StrStrSplitIterator { + it: self.matches_index_iter(sep), + last_end: 0, + finished: false + } + } fn line_iter(&self) -> StrCharSplitIterator<'self, char> { self.split_options_iter('\n', self.len(), false) @@ -2581,15 +2589,6 @@ impl<'self> StrSlice<'self> for &'self str { assert!(is_char_boundary(*self, end)); unsafe { raw::slice_bytes(*self, begin, end) } } - /** - * Splits a string into a vector of the substrings separated by a given - * string - */ - #[inline] - fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool { - each_split_str(*self, sep, it) - } - /// Returns true if one string starts with another #[inline] fn starts_with<'a>(&self, needle: &'a str) -> bool { starts_with(*self, needle) @@ -2836,30 +2835,6 @@ mod tests { let _cc3 = pop_char(&mut data); } - #[test] - fn test_split_str() { - fn t<'a>(s: &str, sep: &'a str, u: &[~str]) { - let mut v = ~[]; - for each_split_str(s, sep) |s| { v.push(s.to_owned()) } - assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); - } - t("--1233345--", "12345", [~"--1233345--"]); - t("abc::hello::there", "::", [~"abc", ~"hello", ~"there"]); - t("::hello::there", "::", [~"", ~"hello", ~"there"]); - t("hello::there::", "::", [~"hello", ~"there", ~""]); - t("::hello::there::", "::", [~"", ~"hello", ~"there", ~""]); - t("ประเทศไทย中华Việt Nam", "中华", [~"ประเทศไทย", ~"Việt Nam"]); - t("zzXXXzzYYYzz", "zz", [~"", ~"XXX", ~"YYY", ~""]); - t("zzXXXzYYYz", "XXX", [~"zz", ~"zYYYz"]); - t(".XXX.YYY.", ".", [~"", ~"XXX", ~"YYY", ~""]); - t("", ".", [~""]); - t("zz", "zz", [~"",~""]); - t("ok", "z", [~"ok"]); - t("zzz", "zz", [~"",~"z"]); - t("zzzzz", "zz", [~"",~"",~"z"]); - } - - #[test] fn test_split_within() { fn t(s: &str, i: uint, u: &[~str]) { @@ -3727,4 +3702,27 @@ mod tests { let lines: ~[&str] = data.line_iter().collect(); assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]); } + + + #[test] + fn test_split_str_iterator() { + fn t<'a>(s: &str, sep: &'a str, u: ~[&str]) { + let v: ~[&str] = s.split_str_iter(sep).collect(); + assert_eq!(v, u); + } + t("--1233345--", "12345", ~["--1233345--"]); + t("abc::hello::there", "::", ~["abc", "hello", "there"]); + t("::hello::there", "::", ~["", "hello", "there"]); + t("hello::there::", "::", ~["hello", "there", ""]); + t("::hello::there::", "::", ~["", "hello", "there", ""]); + t("ประเทศไทย中华Việt Nam", "中华", ~["ประเทศไทย", "Việt Nam"]); + t("zzXXXzzYYYzz", "zz", ~["", "XXX", "YYY", ""]); + t("zzXXXzYYYz", "XXX", ~["zz", "zYYYz"]); + t(".XXX.YYY.", ".", ~["", "XXX", "YYY", ""]); + t("", ".", ~[""]); + t("zz", "zz", ~["",""]); + t("ok", "z", ~["ok"]); + t("zzz", "zz", ~["","z"]); + t("zzzzz", "zz", ~["","","z"]); + } } From 0cfc08d81e7cc664330ce9d38a874c14a4ae51bf Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 13:09:51 +1000 Subject: [PATCH 06/21] std: convert character-based str::find_* to methods. Add .slice_{to,from} methods. --- src/compiletest/runtest.rs | 2 +- src/libfuzzer/fuzzer.rc | 2 +- src/librustc/middle/lint.rs | 17 +- src/librustc/middle/resolve.rs | 2 +- src/librustdoc/desc_to_brief_pass.rs | 14 +- src/librustpkg/version.rs | 2 +- src/libstd/path.rs | 16 +- src/libstd/str.rs | 497 ++++++++------------------- src/libsyntax/codemap.rs | 11 +- 9 files changed, 158 insertions(+), 405 deletions(-) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 6812f6e445561..8f493fa2d064d 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -417,7 +417,7 @@ fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool { if *idx >= haystack.len() { return false; } - let opt = str::find_char_from(haystack, needle, *idx); + let opt = haystack.slice_from(*idx).find(needle); if opt.is_none() { return false; } diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index bd72f0891ddfb..95aea33d31a90 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -375,7 +375,7 @@ pub fn check_variants_T(crate: @ast::crate, } pub fn last_part(filename: ~str) -> ~str { - let ix = str::rfind_char(filename, '/').get(); + let ix = filename.rfind('/').get(); filename.slice(ix + 1u, filename.len() - 3u).to_owned() } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 74e001f4e1356..7462067162dc7 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -841,26 +841,11 @@ fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) { fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool { let ident = cx.sess.str_of(ident); assert!(!ident.is_empty()); - let ident = ident_without_trailing_underscores(*ident); - let ident = ident_without_leading_underscores(ident); + let ident = ident.trim_chars(&['_']); char::is_uppercase(str::char_at(ident, 0)) && !ident.contains_char('_') } - fn ident_without_trailing_underscores<'r>(ident: &'r str) -> &'r str { - match str::rfind(ident, |c| c != '_') { - Some(idx) => ident.slice(0, idx + 1), - None => ident, // all underscores - } - } - - fn ident_without_leading_underscores<'r>(ident: &'r str) -> &'r str { - match str::find(ident, |c| c != '_') { - Some(idx) => ident.slice(idx, ident.len()), - None => ident // all underscores - } - } - fn check_case(cx: &Context, ident: ast::ident, span: span) { if !is_camel_case(cx.tcx, ident) { cx.span_lint(non_camel_case_types, span, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index ffa3c815b289d..dd70c2bfb563f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2681,7 +2681,7 @@ impl Resolver { match module_prefix_result { Failed => { let mpath = self.idents_to_str(module_path); - match str::rfind(self.idents_to_str(module_path), |c| { c == ':' }) { + match self.idents_to_str(module_path).rfind(':') { Some(idx) => { self.session.span_err(span, fmt!("unresolved import: could not find `%s` \ in `%s`", str::substr(mpath, idx, diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index f66012696ae6b..0f4ade0551de7 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -118,19 +118,17 @@ fn first_sentence_(s: &str) -> ~str { let mut dotcount = 0; // The index of the character following a single dot. This allows // Things like [0..1) to appear in the brief description - let idx = do str::find(s) |ch| { + let idx = s.find(|ch: char| { if ch == '.' { dotcount += 1; false + } else if dotcount == 1 { + true } else { - if dotcount == 1 { - true - } else { - dotcount = 0; - false - } + dotcount = 0; + false } - }; + }); match idx { Some(idx) if idx > 2u => { str::to_owned(s.slice(0, idx - 1)) diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index c966ede3cdf09..b38f440a941f3 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -175,7 +175,7 @@ pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> { if { let mut i: uint = 0; for str::to_chars(s).each |&c| { if c == '#' { i += 1; } }; i > 1 } { return None; } - match str::rfind_char(s, '#') { + match s.rfind('#') { Some(i) => { debug!("in %s, i = %?", s, i); let path = s.slice(0, i); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index eb78120c6bed3..4df07830b2386 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -479,8 +479,8 @@ impl GenericPath for PosixPath { match self.filename() { None => None, Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) => Some(f.slice(0, p).to_owned()), + match f.rfind('.') { + Some(p) => Some(f.slice_to(p).to_owned()), None => Some(copy *f), } } @@ -491,8 +491,8 @@ impl GenericPath for PosixPath { match self.filename() { None => None, Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), + match f.rfind('.') { + Some(p) if p < f.len() => Some(f.slice_from(p).to_owned()), _ => None, } } @@ -693,8 +693,8 @@ impl GenericPath for WindowsPath { match self.filename() { None => None, Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) => Some(f.slice(0, p).to_owned()), + match f.rfind('.') { + Some(p) => Some(f.slice_to(p).to_owned()), None => Some(copy *f), } } @@ -705,8 +705,8 @@ impl GenericPath for WindowsPath { match self.filename() { None => None, Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), + match f.rfind('.') { + Some(p) if p < f.len() => Some(f.slice_from(p).to_owned()), _ => None, } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 46bf0b08c1039..a7f152a27e592 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -21,6 +21,7 @@ use at_vec; use cast::transmute; use cast; use char; +use char::Char; use clone::Clone; use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use container::Container; @@ -510,7 +511,7 @@ pub fn unshift_char(s: &mut ~str, ch: char) { pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { if chars_to_trim.is_empty() { return s; } - match find(s, |c| !chars_to_trim.contains(&c)) { + match s.find(|c| !chars_to_trim.contains(&c)) { None => "", Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) } } @@ -528,7 +529,7 @@ pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { pub fn trim_right_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { if chars_to_trim.is_empty() { return s; } - match rfind(s, |c| !chars_to_trim.contains(&c)) { + match s.rfind(|c| !chars_to_trim.contains(&c)) { None => "", Some(last) => { let next = char_range_at(s, last).next; @@ -552,7 +553,7 @@ pub fn trim_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { /// Returns a string with leading whitespace removed pub fn trim_left<'a>(s: &'a str) -> &'a str { - match find(s, |c| !char::is_whitespace(c)) { + match s.find(|c| !char::is_whitespace(c)) { None => "", Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) } } @@ -560,7 +561,7 @@ pub fn trim_left<'a>(s: &'a str) -> &'a str { /// Returns a string with trailing whitespace removed pub fn trim_right<'a>(s: &'a str) -> &'a str { - match rfind(s, |c| !char::is_whitespace(c)) { + match s.rfind(|c| !char::is_whitespace(c)) { None => "", Some(last) => { let next = char_range_at(s, last).next; @@ -621,6 +622,34 @@ pub fn substr<'a>(s: &'a str, begin: uint, n: uint) -> &'a str { s.slice(begin, begin + count_bytes(s, begin, n)) } +/// Something that can be used to compare against a character +pub trait CharEq { + /// Determine if the splitter should split at the given character + fn matches(&self, char) -> bool; + /// Indicate if this is only concerned about ASCII characters, + /// which can allow for a faster implementation. + fn only_ascii(&self) -> bool; +} +impl CharEq for char { + #[inline(always)] + fn matches(&self, c: char) -> bool { *self == c } + + fn only_ascii(&self) -> bool { (*self as uint) < 128 } +} +impl<'self> CharEq for &'self fn(char) -> bool { + #[inline(always)] + fn matches(&self, c: char) -> bool { (*self)(c) } + + fn only_ascii(&self) -> bool { false } +} +impl CharEq for extern "Rust" fn(char) -> bool { + #[inline(always)] + fn matches(&self, c: char) -> bool { (*self)(c) } + + fn only_ascii(&self) -> bool { false } +} + + /// An iterator over the substrings of a string, separated by `sep`. pub struct StrCharSplitIterator<'self,Sep> { priv string: &'self str, @@ -639,34 +668,7 @@ pub type WordIterator<'self> = FilterIterator<'self, &'self str, StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>; -/// A separator for splitting a string character-wise -pub trait StrCharSplitSeparator { - /// Determine if the splitter should split at the given character - fn should_split(&self, char) -> bool; - /// Indicate if the splitter only uses ASCII characters, which - /// allows for a faster implementation. - fn only_ascii(&self) -> bool; -} -impl StrCharSplitSeparator for char { - #[inline(always)] - fn should_split(&self, c: char) -> bool { *self == c } - - fn only_ascii(&self) -> bool { (*self as uint) < 128 } -} -impl<'self> StrCharSplitSeparator for &'self fn(char) -> bool { - #[inline(always)] - fn should_split(&self, c: char) -> bool { (*self)(c) } - - fn only_ascii(&self) -> bool { false } -} -impl<'self> StrCharSplitSeparator for extern "Rust" fn(char) -> bool { - #[inline(always)] - fn should_split(&self, c: char) -> bool { (*self)(c) } - - fn only_ascii(&self) -> bool { false } -} - -impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { +impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { #[inline] fn next(&mut self) -> Option<&'self str> { if self.finished { return None } @@ -680,7 +682,7 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte while self.position < l && self.count > 0 { let byte = self.string[self.position]; - if self.sep.should_split(byte as char) { + if self.sep.matches(byte as char) { let slice = unsafe { raw::slice_bytes(self.string, start, self.position) }; self.position += 1; self.count -= 1; @@ -692,7 +694,7 @@ impl<'self, Sep: StrCharSplitSeparator> Iterator<&'self str> for StrCharSplitIte while self.position < l && self.count > 0 { let CharRange {ch, next} = char_range_at(self.string, self.position); - if self.sep.should_split(ch) { + if self.sep.matches(ch) { let slice = unsafe { raw::slice_bytes(self.string, start, self.position) }; self.position = next; self.count -= 1; @@ -1157,318 +1159,6 @@ pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { Section: Searching */ -/** - * Returns the byte index of the first matching character - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - */ -pub fn find_char(s: &str, c: char) -> Option { - find_char_between(s, c, 0u, s.len()) -} - -/** - * Returns the byte index of the first matching character beginning - * from a given byte offset - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * * `start` - The byte index to begin searching at, inclusive - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `s.len()`. `start` must be the - * index of a character boundary, as defined by `is_char_boundary`. - */ -pub fn find_char_from(s: &str, c: char, start: uint) -> Option { - find_char_between(s, c, start, s.len()) -} - -/** - * Returns the byte index of the first matching character within a given range - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * * `start` - The byte index to begin searching at, inclusive - * * `end` - The byte index to end searching at, exclusive - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `s.len()`. `start` must be the index of a character boundary, - * as defined by `is_char_boundary`. - */ -pub fn find_char_between(s: &str, c: char, start: uint, end: uint) - -> Option { - if c < 128u as char { - assert!(start <= end); - assert!(end <= s.len()); - let mut i = start; - let b = c as u8; - while i < end { - if s[i] == b { return Some(i); } - i += 1u; - } - return None; - } else { - find_between(s, start, end, |x| x == c) - } -} - -/** - * Returns the byte index of the last matching character - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - */ -pub fn rfind_char(s: &str, c: char) -> Option { - rfind_char_between(s, c, s.len(), 0u) -} - -/** - * Returns the byte index of the last matching character beginning - * from a given byte offset - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * * `start` - The byte index to begin searching at, exclusive - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `s.len()`. `start` must be - * the index of a character boundary, as defined by `is_char_boundary`. - */ -pub fn rfind_char_from(s: &str, c: char, start: uint) -> Option { - rfind_char_between(s, c, start, 0u) -} - -/** - * Returns the byte index of the last matching character within a given range - * - * # Arguments - * - * * `s` - The string to search - * * `c` - The character to search for - * * `start` - The byte index to begin searching at, exclusive - * * `end` - The byte index to end searching at, inclusive - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - * - * # Failure - * - * `end` must be less than or equal to `start` and `start` must be less than - * or equal to `s.len()`. `start` must be the index of a character boundary, - * as defined by `is_char_boundary`. - */ -pub fn rfind_char_between(s: &str, c: char, start: uint, end: uint) -> Option { - if c < 128u as char { - assert!(start >= end); - assert!(start <= s.len()); - let mut i = start; - let b = c as u8; - while i > end { - i -= 1u; - if s[i] == b { return Some(i); } - } - return None; - } else { - rfind_between(s, start, end, |x| x == c) - } -} - -/** - * Returns the byte index of the first character that satisfies - * the given predicate - * - * # Arguments - * - * * `s` - The string to search - * * `f` - The predicate to satisfy - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - */ -pub fn find(s: &str, f: &fn(char) -> bool) -> Option { - find_between(s, 0u, s.len(), f) -} - -/** - * Returns the byte index of the first character that satisfies - * the given predicate, beginning from a given byte offset - * - * # Arguments - * - * * `s` - The string to search - * * `start` - The byte index to begin searching at, inclusive - * * `f` - The predicate to satisfy - * - * # Return value - * - * An `option` containing the byte index of the first matching charactor - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `s.len()`. `start` must be the - * index of a character boundary, as defined by `is_char_boundary`. - */ -pub fn find_from(s: &str, start: uint, f: &fn(char) - -> bool) -> Option { - find_between(s, start, s.len(), f) -} - -/** - * Returns the byte index of the first character that satisfies - * the given predicate, within a given range - * - * # Arguments - * - * * `s` - The string to search - * * `start` - The byte index to begin searching at, inclusive - * * `end` - The byte index to end searching at, exclusive - * * `f` - The predicate to satisfy - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `s.len()`. `start` must be the index of a character - * boundary, as defined by `is_char_boundary`. - */ -pub fn find_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option { - assert!(start <= end); - assert!(end <= s.len()); - assert!(is_char_boundary(s, start)); - let mut i = start; - while i < end { - let CharRange {ch, next} = char_range_at(s, i); - if f(ch) { return Some(i); } - i = next; - } - return None; -} - -/** - * Returns the byte index of the last character that satisfies - * the given predicate - * - * # Arguments - * - * * `s` - The string to search - * * `f` - The predicate to satisfy - * - * # Return value - * - * An option containing the byte index of the last matching character - * or `none` if there is no match - */ -pub fn rfind(s: &str, f: &fn(char) -> bool) -> Option { - rfind_between(s, s.len(), 0u, f) -} - -/** - * Returns the byte index of the last character that satisfies - * the given predicate, beginning from a given byte offset - * - * # Arguments - * - * * `s` - The string to search - * * `start` - The byte index to begin searching at, exclusive - * * `f` - The predicate to satisfy - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `s.len()', `start` must be the - * index of a character boundary, as defined by `is_char_boundary` - */ -pub fn rfind_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option { - rfind_between(s, start, 0u, f) -} - -/** - * Returns the byte index of the last character that satisfies - * the given predicate, within a given range - * - * # Arguments - * - * * `s` - The string to search - * * `start` - The byte index to begin searching at, exclusive - * * `end` - The byte index to end searching at, inclusive - * * `f` - The predicate to satisfy - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - * - * # Failure - * - * `end` must be less than or equal to `start` and `start` must be less - * than or equal to `s.len()`. `start` must be the index of a character - * boundary, as defined by `is_char_boundary` - */ -pub fn rfind_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option { - assert!(start >= end); - assert!(start <= s.len()); - assert!(is_char_boundary(s, start)); - let mut i = start; - while i > end { - let CharRange {ch, next: prev} = char_range_at_reverse(s, i); - if f(ch) { return Some(prev); } - i = prev; - } - return None; -} - // Utility used by various searching functions fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { let mut i = at; @@ -1580,7 +1270,7 @@ pub fn contains<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { * * needle - The char to look for */ pub fn contains_char(haystack: &str, needle: char) -> bool { - find_char(haystack, needle).is_some() + haystack.find(needle).is_some() } /** @@ -2415,11 +2105,9 @@ pub trait StrSlice<'self> { fn rev_iter(&self) -> StrCharRevIterator<'self>; fn bytes_iter(&self) -> StrBytesIterator<'self>; fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self>; - fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep>; - fn splitn_iter(&self, sep: Sep, count: uint) - -> StrCharSplitIterator<'self, Sep>; - fn split_options_iter(&self, sep: Sep, - count: uint, allow_trailing_empty: bool) + fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep>; + fn splitn_iter(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep>; + fn split_options_iter(&self, sep: Sep, count: uint, allow_trailing_empty: bool) -> StrCharSplitIterator<'self, Sep>; /// An iterator over the start and end indices of each match of /// `sep` within `self`. @@ -2448,6 +2136,8 @@ pub trait StrSlice<'self> { fn len(&self) -> uint; fn char_len(&self) -> uint; fn slice(&self, begin: uint, end: uint) -> &'self str; + fn slice_from(&self, begin: uint) -> &'self str; + fn slice_to(&self, end: uint) -> &'self str; fn starts_with<'a>(&self, needle: &'a str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; fn escape_default(&self) -> ~str; @@ -2463,6 +2153,9 @@ pub trait StrSlice<'self> { fn char_at(&self, i: uint) -> char; fn char_at_reverse(&self, i: uint) -> char; fn to_bytes(&self) -> ~[u8]; + + fn find(&self, search: C) -> Option; + fn rfind(&self, search: C) -> Option; } /// Extension methods for strings @@ -2500,16 +2193,14 @@ impl<'self> StrSlice<'self> for &'self str { StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() } } - fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> { + fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> { self.split_options_iter(sep, self.len(), true) } - fn splitn_iter(&self, sep: Sep, count: uint) - -> StrCharSplitIterator<'self, Sep> { + fn splitn_iter(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep> { self.split_options_iter(sep, count, true) } - fn split_options_iter(&self, sep: Sep, - count: uint, allow_trailing_empty: bool) + fn split_options_iter(&self, sep: Sep, count: uint, allow_trailing_empty: bool) -> StrCharSplitIterator<'self, Sep> { let only_ascii = sep.only_ascii(); StrCharSplitIterator { @@ -2590,6 +2281,14 @@ impl<'self> StrSlice<'self> for &'self str { unsafe { raw::slice_bytes(*self, begin, end) } } #[inline] + fn slice_from(&self, begin: uint) -> &'self str { + self.slice(begin, self.len()) + } + #[inline] + fn slice_to(&self, end: uint) -> &'self str { + self.slice(0, end) + } + #[inline] fn starts_with<'a>(&self, needle: &'a str) -> bool { starts_with(*self, needle) } @@ -2654,6 +2353,54 @@ impl<'self> StrSlice<'self> for &'self str { } fn to_bytes(&self) -> ~[u8] { to_bytes(*self) } + + /** + * Returns the byte index of the first character of `self` that matches `search` + * + * # Return value + * + * `Some` containing the byte index of the last matching character + * or `None` if there is no match + */ + fn find(&self, search: C) -> Option { + if search.only_ascii() { + for self.bytes_iter().enumerate().advance |(i, b)| { + if search.matches(b as char) { return Some(i) } + } + } else { + let mut index = 0; + for self.iter().advance |c| { + if search.matches(c) { return Some(index); } + index += c.len_utf8_bytes(); + } + } + + None + } + /** + * Returns the byte index of the last character of `self` that matches `search` + * + * # Return value + * + * `Some` containing the byte index of the last matching character + * or `None` if there is no match + */ + fn rfind(&self, search: C) -> Option { + let mut index = self.len(); + if search.only_ascii() { + for self.bytes_rev_iter().advance |b| { + index -= 1; + if search.matches(b as char) { return Some(index); } + } + } else { + for self.rev_iter().advance |c| { + index -= c.len_utf8_bytes(); + if search.matches(c) { return Some(index); } + } + } + + None + } } #[allow(missing_doc)] @@ -2803,12 +2550,23 @@ mod tests { } #[test] - fn test_rfind_char() { - assert_eq!(rfind_char("hello", 'l'), Some(3u)); - assert_eq!(rfind_char("hello", 'o'), Some(4u)); - assert_eq!(rfind_char("hello", 'h'), Some(0u)); - assert!(rfind_char("hello", 'z').is_none()); - assert_eq!(rfind_char("ประเทศไทย中华Việt Nam", '华'), Some(30u)); + fn test_find() { + assert_eq!("hello".find('l'), Some(2u)); + assert_eq!("hello".find(|c:char| c == 'o'), Some(4u)); + assert!("hello".find('x').is_none()); + assert!("hello".find(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30u)); + assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30u)); + } + + #[test] + fn test_rfind() { + assert_eq!("hello".rfind('l'), Some(3u)); + assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4u)); + assert!("hello".rfind('x').is_none()); + assert!("hello".rfind(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30u)); + assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30u)); } #[test] @@ -3122,6 +2880,19 @@ mod tests { "中华Việt Nam".slice(0u, 2u); } + #[test] + fn test_slice_from() { + assert_eq!("abcd".slice_from(0), "abcd"); + assert_eq!("abcd".slice_from(2), "cd"); + assert_eq!("abcd".slice_from(4), ""); + } + #[test] + fn test_slice_to() { + assert_eq!("abcd".slice_to(0), ""); + assert_eq!("abcd".slice_to(2), "ab"); + assert_eq!("abcd".slice_to(4), "abcd"); + } + #[test] fn test_trim_left_chars() { assert!(trim_left_chars(" *** foo *** ", []) == " *** foo *** "); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 52f6e458db3e1..68403b2c60859 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -24,7 +24,6 @@ source code snippets, etc. use core::prelude::*; use core::cmp; -use core::str; use core::to_bytes; use core::uint; use extra::serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -288,11 +287,11 @@ impl FileMap { pub fn get_line(&self, line: int) -> ~str { let begin: BytePos = self.lines[line] - self.start_pos; let begin = begin.to_uint(); - let end = match str::find_char_from(*self.src, '\n', begin) { - Some(e) => e, - None => self.src.len() - }; - self.src.slice(begin, end).to_owned() + let slice = self.src.slice_from(begin); + match slice.find('\n') { + Some(e) => slice.slice_to(e).to_owned(), + None => slice.to_owned() + } } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { From 7281fb948a48f56e06f9a324d52e70e056071005 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 16:17:10 +1000 Subject: [PATCH 07/21] std: replace str::{any,all}_between with the iterator equivalent. --- src/libextra/rope.rs | 5 ++- src/libstd/str.rs | 60 ------------------------------------ src/libsyntax/parse/lexer.rs | 2 +- 3 files changed, 3 insertions(+), 64 deletions(-) diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 1b58aa68f776f..9ae8c47ae3c68 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -37,6 +37,7 @@ use core::prelude::*; +use core::iterator::IteratorUtil; use core::str; use core::uint; use core::vec; @@ -1079,9 +1080,7 @@ pub mod node { pub fn loop_chars(node: @Node, it: &fn(c: char) -> bool) -> bool { return loop_leaves(node,|leaf| { - str::all_between(*leaf.content, - leaf.byte_offset, - leaf.byte_len, it) + leaf.content.slice(leaf.byte_offset, leaf.byte_len).iter().all(it) }); } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index a7f152a27e592..e68b79575e0dd 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1623,66 +1623,6 @@ pub fn char_at_reverse(s: &str, i: uint) -> char { char_range_at_reverse(s, i).ch } -/** - * Loop through a substring, char by char - * - * # Safety note - * - * * This function does not check whether the substring is valid. - * * This function fails if `start` or `end` do not - * represent valid positions inside `s` - * - * # Arguments - * - * * s - A string to traverse. It may be empty. - * * start - The byte offset at which to start in the string. - * * end - The end of the range to traverse - * * it - A block to execute with each consecutive character of `s`. - * Return `true` to continue, `false` to stop. - * - * # Return value - * - * `true` If execution proceeded correctly, `false` if it was interrupted, - * that is if `it` returned `false` at any point. - */ -pub fn all_between(s: &str, start: uint, end: uint, - it: &fn(char) -> bool) -> bool { - assert!(is_char_boundary(s, start)); - let mut i = start; - while i < end { - let CharRange {ch, next} = char_range_at(s, i); - if !it(ch) { return false; } - i = next; - } - return true; -} - -/** - * Loop through a substring, char by char - * - * # Safety note - * - * * This function does not check whether the substring is valid. - * * This function fails if `start` or `end` do not - * represent valid positions inside `s` - * - * # Arguments - * - * * s - A string to traverse. It may be empty. - * * start - The byte offset at which to start in the string. - * * end - The end of the range to traverse - * * it - A block to execute with each consecutive character of `s`. - * Return `true` to continue, `false` to stop. - * - * # Return value - * - * `true` if `it` returns `true` for any character - */ -pub fn any_between(s: &str, start: uint, end: uint, - it: &fn(char) -> bool) -> bool { - !all_between(s, start, end, |c| !it(c)) -} - // UTF-8 tags and ranges static tag_cont_u8: u8 = 128u8; static tag_cont: uint = 128u; diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 04635fdf4e9bf..2dc8008f8ec53 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -307,7 +307,7 @@ fn consume_any_line_comment(rdr: @mut StringReader) pub fn is_block_non_doc_comment(s: &str) -> bool { assert!(s.len() >= 1u); - str::all_between(s, 1u, s.len() - 1u, |ch| ch == '*') + s.slice(1u, s.len() - 1u).iter().all(|ch| ch == '*') } // might return a sugared-doc-attr From 017450a6111a430eca86caf4ee6021ed654b552f Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 16:23:05 +1000 Subject: [PATCH 08/21] std: replace str::find_str* with a method --- src/compiletest/errors.rs | 2 +- src/compiletest/header.rs | 2 +- src/libextra/test.rs | 4 +- src/librustdoc/markdown_pass.rs | 8 +- src/libstd/str.rs | 159 +++++------------- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/run-pass/option-ext.rs | 2 +- 7 files changed, 54 insertions(+), 125 deletions(-) diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 575df0268d6cb..f524f1424b4f5 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -31,7 +31,7 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] { fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] { let error_tag = ~"//~"; let mut idx; - match str::find_str(line, error_tag) { + match line.find_str(error_tag) { None => return ~[], Some(nn) => { idx = (nn as uint) + error_tag.len(); } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index c61adff006303..0adcb924a4992 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -175,7 +175,7 @@ fn parse_name_directive(line: &str, directive: &str) -> bool { fn parse_name_value_directive(line: &str, directive: ~str) -> Option<~str> { let keycolon = directive + ":"; - match str::find_str(line, keycolon) { + match line.find_str(keycolon) { Some(colon) => { let value = line.slice(colon + keycolon.len(), line.len()).to_owned(); diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 6a9751b66e01e..36d91382fb286 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -407,8 +407,8 @@ fn should_sort_failures_before_printing_them() { print_failures(st); }; - let apos = str::find_str(s, "a").get(); - let bpos = str::find_str(s, "b").get(); + let apos = s.find_str("a").get(); + let bpos = s.find_str("b").get(); assert!(apos < bpos); } diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 7d41b899bc3d5..6b13c1fe1f65a 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -633,10 +633,10 @@ mod test { fn d() { }" ); - let idx_a = str::find_str(markdown, "# Module `a`").get(); - let idx_b = str::find_str(markdown, "## Function `b`").get(); - let idx_c = str::find_str(markdown, "# Module `c`").get(); - let idx_d = str::find_str(markdown, "## Function `d`").get(); + let idx_a = markdown.find_str("# Module `a`").get(); + let idx_b = markdown.find_str("## Function `b`").get(); + let idx_c = markdown.find_str("# Module `c`").get(); + let idx_d = markdown.find_str("## Function `d`").get(); assert!(idx_b < idx_d); assert!(idx_d < idx_a); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index e68b79575e0dd..98b210dd5a912 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1166,88 +1166,6 @@ fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { return true; } -/** - * Returns the byte index of the first matching substring - * - * # Arguments - * - * * `haystack` - The string to search - * * `needle` - The string to search for - * - * # Return value - * - * An `option` containing the byte index of the first matching substring - * or `none` if there is no match - */ -pub fn find_str<'a,'b>(haystack: &'a str, needle: &'b str) -> Option { - find_str_between(haystack, needle, 0u, haystack.len()) -} - -/** - * Returns the byte index of the first matching substring beginning - * from a given byte offset - * - * # Arguments - * - * * `haystack` - The string to search - * * `needle` - The string to search for - * * `start` - The byte index to begin searching at, inclusive - * - * # Return value - * - * An `option` containing the byte index of the last matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `s.len()` - */ -pub fn find_str_from<'a,'b>(haystack: &'a str, - needle: &'b str, - start: uint) - -> Option { - find_str_between(haystack, needle, start, haystack.len()) -} - -/** - * Returns the byte index of the first matching substring within a given range - * - * # Arguments - * - * * `haystack` - The string to search - * * `needle` - The string to search for - * * `start` - The byte index to begin searching at, inclusive - * * `end` - The byte index to end searching at, exclusive - * - * # Return value - * - * An `option` containing the byte index of the first matching character - * or `none` if there is no match - * - * # Failure - * - * `start` must be less than or equal to `end` and `end` must be less than - * or equal to `s.len()`. - */ -pub fn find_str_between<'a,'b>(haystack: &'a str, - needle: &'b str, - start: uint, - end:uint) - -> Option { - // See Issue #1932 for why this is a naive search - assert!(end <= haystack.len()); - let needle_len = needle.len(); - if needle_len == 0u { return Some(start); } - if needle_len > end { return None; } - - let mut i = start; - let e = end - needle_len; - while i <= e { - if match_at(haystack, needle, i) { return Some(i); } - i += 1u; - } - return None; -} /** * Returns true if one string contains another @@ -1258,7 +1176,7 @@ pub fn find_str_between<'a,'b>(haystack: &'a str, * * needle - The string to look for */ pub fn contains<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - find_str(haystack, needle).is_some() + haystack.find_str(needle).is_some() } /** @@ -2096,6 +2014,7 @@ pub trait StrSlice<'self> { fn find(&self, search: C) -> Option; fn rfind(&self, search: C) -> Option; + fn find_str(&self, &str) -> Option; } /// Extension methods for strings @@ -2341,6 +2260,28 @@ impl<'self> StrSlice<'self> for &'self str { None } + + /** + * Returns the byte index of the first matching substring + * + * # Arguments + * + * * `needle` - The string to search for + * + * # Return value + * + * `Some` containing the byte index of the first matching substring + * or `None` if there is no match + */ + fn find_str(&self, needle: &str) -> Option { + if needle.is_empty() { + Some(0) + } else { + self.matches_index_iter(needle) + .next() + .map_consume(|(start, _end)| start) + } + } } #[allow(missing_doc)] @@ -2550,43 +2491,31 @@ mod tests { #[test] fn test_find_str() { // byte positions - assert!(find_str("banana", "apple pie").is_none()); - assert_eq!(find_str("", ""), Some(0u)); - - let data = "ประเทศไทย中华Việt Nam"; - assert_eq!(find_str(data, ""), Some(0u)); - assert_eq!(find_str(data, "ประเ"), Some( 0u)); - assert_eq!(find_str(data, "ะเ"), Some( 6u)); - assert_eq!(find_str(data, "中华"), Some(27u)); - assert!(find_str(data, "ไท华").is_none()); - } - - #[test] - fn test_find_str_between() { - // byte positions - assert_eq!(find_str_between("", "", 0u, 0u), Some(0u)); + assert_eq!("".find_str(""), Some(0u)); + assert!("banana".find_str("apple pie").is_none()); let data = "abcabc"; - assert_eq!(find_str_between(data, "ab", 0u, 6u), Some(0u)); - assert_eq!(find_str_between(data, "ab", 2u, 6u), Some(3u)); - assert!(find_str_between(data, "ab", 2u, 4u).is_none()); + assert_eq!(data.slice(0u, 6u).find_str("ab"), Some(0u)); + assert_eq!(data.slice(2u, 6u).find_str("ab"), Some(3u)); + assert!(data.slice(2u, 4u).find_str("ab").is_none()); let mut data = ~"ประเทศไทย中华Việt Nam"; data = data + data; - assert_eq!(find_str_between(data, "", 0u, 43u), Some(0u)); - assert_eq!(find_str_between(data, "", 6u, 43u), Some(6u)); - - assert_eq!(find_str_between(data, "ประ", 0u, 43u), Some( 0u)); - assert_eq!(find_str_between(data, "ทศไ", 0u, 43u), Some(12u)); - assert_eq!(find_str_between(data, "ย中", 0u, 43u), Some(24u)); - assert_eq!(find_str_between(data, "iệt", 0u, 43u), Some(34u)); - assert_eq!(find_str_between(data, "Nam", 0u, 43u), Some(40u)); - - assert_eq!(find_str_between(data, "ประ", 43u, 86u), Some(43u)); - assert_eq!(find_str_between(data, "ทศไ", 43u, 86u), Some(55u)); - assert_eq!(find_str_between(data, "ย中", 43u, 86u), Some(67u)); - assert_eq!(find_str_between(data, "iệt", 43u, 86u), Some(77u)); - assert_eq!(find_str_between(data, "Nam", 43u, 86u), Some(83u)); + assert!(data.find_str("ไท华").is_none()); + assert_eq!(data.slice(0u, 43u).find_str(""), Some(0u)); + assert_eq!(data.slice(6u, 43u).find_str(""), Some(6u - 6u)); + + assert_eq!(data.slice(0u, 43u).find_str("ประ"), Some( 0u)); + assert_eq!(data.slice(0u, 43u).find_str("ทศไ"), Some(12u)); + assert_eq!(data.slice(0u, 43u).find_str("ย中"), Some(24u)); + assert_eq!(data.slice(0u, 43u).find_str("iệt"), Some(34u)); + assert_eq!(data.slice(0u, 43u).find_str("Nam"), Some(40u)); + + assert_eq!(data.slice(43u, 86u).find_str("ประ"), Some(43u - 43u)); + assert_eq!(data.slice(43u, 86u).find_str("ทศไ"), Some(55u - 43u)); + assert_eq!(data.slice(43u, 86u).find_str("ย中"), Some(67u - 43u)); + assert_eq!(data.slice(43u, 86u).find_str("iệt"), Some(77u - 43u)); + assert_eq!(data.slice(43u, 86u).find_str("Nam"), Some(83u - 43u)); } #[test] diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index ef32b0bb2dc9b..9ba9b9759fd11 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -197,7 +197,7 @@ fn main() { // start processing if this is the one ('>', false) => { - match str::find_str_from(line, ~"THREE", 1u) { + match line.slice_from(1).find_str(~"THREE") { option::Some(_) => { proc_mode = true; } option::None => { } } diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 7355bde61f3a6..f37f40935abe7 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -12,7 +12,7 @@ use std::str; pub fn main() { let thing = ~"{{ f }}"; - let f = str::find_str(thing, ~"{{"); + let f = thing.find_str(~"{{"); if f.is_none() { println(~"None!"); From a64e886e3c1dd38473fd7711933557f1b97a9036 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 17:32:36 +1000 Subject: [PATCH 09/21] std: remove str::contains in favour of the method --- doc/rust.md | 11 +--- src/compiletest/header.rs | 2 +- src/compiletest/runtest.rs | 8 +-- src/libextra/net_tcp.rs | 8 +-- src/libextra/test.rs | 2 +- src/libextra/uv_ll.rs | 6 +- src/libfuzzer/fuzzer.rc | 2 +- src/librustc/driver/driver.rs | 30 +++++----- src/librustc/middle/resolve.rs | 2 +- src/librustdoc/markdown_pass.rs | 86 ++++++++++++++--------------- src/librustdoc/sectionalize_pass.rs | 16 ++---- src/libstd/str.rs | 66 +++++++++------------- 12 files changed, 104 insertions(+), 135 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 6d586c9b201c5..0a33eb6ab2a53 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -802,20 +802,15 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: ~~~~ -use std::float::sin; -use std::str::{from_chars, contains}; +use std::float::{sin, pow}; use std::option::Some; fn main() { - // Equivalent to 'info!(std::float::sin(1.0));' - info!(sin(1.0)); + // Equivalent to 'info!(std::float::pow(std::float::sin(1.0), 2.0));' + info!(pow(sin(1.0), 2.0)); // Equivalent to 'info!(std::option::Some(1.0));' info!(Some(1.0)); - - // Equivalent to - // 'info!(std::str::contains(std::str::from_chars(&['f','o','o']), "oo"));' - info!(contains(from_chars(&['f','o','o']), "oo")); } ~~~~ diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 0adcb924a4992..d8562d725a709 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -169,7 +169,7 @@ fn parse_pp_exact(line: &str, testfile: &Path) -> Option { } fn parse_name_directive(line: &str, directive: &str) -> bool { - str::contains(line, directive) + line.contains(directive) } fn parse_name_value_directive(line: &str, diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 8f493fa2d064d..d87101ffb8542 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -309,7 +309,7 @@ fn check_error_patterns(props: &TestProps, let mut next_err_pat = &props.error_patterns[next_err_idx]; let mut done = false; for ProcRes.stderr.line_iter().advance |line| { - if str::contains(line, *next_err_pat) { + if line.contains(*next_err_pat) { debug!("found error pattern %s", *next_err_pat); next_err_idx += 1u; if next_err_idx == props.error_patterns.len() { @@ -365,8 +365,8 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError], debug!("prefix=%s ee.kind=%s ee.msg=%s line=%s", prefixes[i], ee.kind, ee.msg, line); if (str::starts_with(line, prefixes[i]) && - str::contains(line, ee.kind) && - str::contains(line, ee.msg)) { + line.contains(ee.kind) && + line.contains(ee.msg)) { found_flags[i] = true; was_expected = true; break; @@ -375,7 +375,7 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError], } // ignore this msg which gets printed at the end - if str::contains(line, "aborting due to") { + if line.contains("aborting due to") { was_expected = true; } diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs index 9026dc25b2d93..3ea085f5e86f1 100644 --- a/src/libextra/net_tcp.rs +++ b/src/libextra/net_tcp.rs @@ -1597,8 +1597,8 @@ mod test { expected_req, actual_req); debug!("RESP: expected: '%s' actual: '%s'", expected_resp, actual_resp); - assert!(str::contains(actual_req, expected_req)); - assert!(str::contains(actual_resp, expected_resp)); + assert!(actual_req.contains(expected_req)); + assert!(actual_resp.contains(expected_resp)); } pub fn impl_gl_tcp_ipv4_get_peer_addr() { let hl_loop = &uv::global_loop::get(); @@ -1765,8 +1765,8 @@ mod test { expected_req, actual_req); debug!("RESP: expected: '%s' actual: '%s'", expected_resp, actual_resp); - assert!(str::contains(actual_req, expected_req)); - assert!(str::contains(actual_resp, expected_resp)); + assert!(actual_req.contains(expected_req)); + assert!(actual_resp.contains(expected_resp)); } pub fn impl_tcp_socket_impl_reader_handles_eof() { diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 36d91382fb286..406dfb086eace 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -514,7 +514,7 @@ pub fn filter_tests( fn filter_fn(test: TestDescAndFn, filter_str: &str) -> Option { - if str::contains(test.desc.name.to_str(), filter_str) { + if test.desc.name.to_str().contains(filter_str) { return option::Some(test); } else { return option::None; } } diff --git a/src/libextra/uv_ll.rs b/src/libextra/uv_ll.rs index 17f1cd499b08a..187960b91016a 100644 --- a/src/libextra/uv_ll.rs +++ b/src/libextra/uv_ll.rs @@ -1480,7 +1480,7 @@ mod test { let server_kill_msg = copy (*client_data).server_kill_msg; let write_req = (*client_data).server_write_req; - if str::contains(request_str, server_kill_msg) { + if request_str.contains(server_kill_msg) { debug!(~"SERVER: client req contains kill_msg!"); debug!(~"SERVER: sending response to client"); read_stop(client_stream_ptr); @@ -1753,8 +1753,8 @@ mod test { let msg_from_client = server_port.recv(); let msg_from_server = client_port.recv(); - assert!(str::contains(msg_from_client, kill_server_msg)); - assert!(str::contains(msg_from_server, server_resp_msg)); + assert!(msg_from_client.contains(kill_server_msg)); + assert!(msg_from_server.contains(server_resp_msg)); } // FIXME don't run on fbsd or linux 32 bit(#2064) diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index 95aea33d31a90..416fabb6d8f67 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -57,7 +57,7 @@ pub fn write_file(filename: &Path, content: &str) { } pub fn contains(haystack: &str, needle: &str) -> bool { - str::contains(haystack, needle) + haystack.contains(needle) } pub fn find_rust_files(files: &mut ~[Path], path: &Path) { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index d765bcff9e236..5af47880c3043 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -465,33 +465,33 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input, } pub fn get_os(triple: &str) -> Option { - if str::contains(triple, "win32") || - str::contains(triple, "mingw32") { + if triple.contains("win32") || + triple.contains("mingw32") { Some(session::os_win32) - } else if str::contains(triple, "darwin") { + } else if triple.contains("darwin") { Some(session::os_macos) - } else if str::contains(triple, "android") { + } else if triple.contains("android") { Some(session::os_android) - } else if str::contains(triple, "linux") { + } else if triple.contains("linux") { Some(session::os_linux) - } else if str::contains(triple, "freebsd") { + } else if triple.contains("freebsd") { Some(session::os_freebsd) } else { None } } pub fn get_arch(triple: &str) -> Option { - if str::contains(triple, "i386") || - str::contains(triple, "i486") || - str::contains(triple, "i586") || - str::contains(triple, "i686") || - str::contains(triple, "i786") { + if triple.contains("i386") || + triple.contains("i486") || + triple.contains("i586") || + triple.contains("i686") || + triple.contains("i786") { Some(abi::X86) - } else if str::contains(triple, "x86_64") { + } else if triple.contains("x86_64") { Some(abi::X86_64) - } else if str::contains(triple, "arm") || - str::contains(triple, "xscale") { + } else if triple.contains("arm") || + triple.contains("xscale") { Some(abi::Arm) - } else if str::contains(triple, "mips") { + } else if triple.contains("mips") { Some(abi::Mips) } else { None } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index dd70c2bfb563f..0f3a6c7629f1b 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -3099,7 +3099,7 @@ impl Resolver { let import_count = imports.len(); if index != import_count { let sn = self.session.codemap.span_to_snippet(imports[index].span); - if str::contains(sn, "::") { + if sn.contains("::") { self.session.span_err(imports[index].span, "unresolved import"); } else { let err = fmt!("unresolved import (maybe you meant `%s::*`?)", diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 6b13c1fe1f65a..976344a1825cb 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -607,13 +607,13 @@ mod test { #[test] fn write_markdown_should_write_mod_headers() { let markdown = render(~"mod moo { }"); - assert!(str::contains(markdown, "# Module `moo`")); + assert!(markdown.contains("# Module `moo`")); } #[test] fn should_leave_blank_line_after_header() { let markdown = render(~"mod morp { }"); - assert!(str::contains(markdown, "Module `morp`\n\n")); + assert!(markdown.contains("Module `morp`\n\n")); } #[test] @@ -669,10 +669,10 @@ mod test { let (page, markdown) = po.recv(); match page { doc::CratePage(_) => { - assert!(str::contains(markdown, "% Crate core")); + assert!(markdown.contains("% Crate core")); } doc::ItemPage(_) => { - assert!(str::contains(markdown, "% Module a")); + assert!(markdown.contains("% Module a")); } } } @@ -681,7 +681,7 @@ mod test { #[test] fn should_write_full_path_to_mod() { let markdown = render(~"mod a { mod b { mod c { } } }"); - assert!(str::contains(markdown, "# Module `a::b::c`")); + assert!(markdown.contains("# Module `a::b::c`")); } #[test] @@ -692,21 +692,20 @@ mod test { Body\"]\ mod a { }"); - assert!(str::contains(markdown, "#### Header\n\nBody\n\n")); + assert!(markdown.contains("#### Header\n\nBody\n\n")); } #[test] fn should_write_crate_description() { let markdown = render(~"#[doc = \"this is the crate\"];"); - assert!(str::contains(markdown, "this is the crate")); + assert!(markdown.contains("this is the crate")); } #[test] fn should_write_index() { let markdown = render(~"mod a { } mod b { }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n* [Module `a`](#module-a)\n\ * [Module `b`](#module-b)\n\n" )); @@ -715,20 +714,19 @@ mod test { #[test] fn should_write_index_brief() { let markdown = render(~"#[doc = \"test\"] mod a { }"); - assert!(str::contains(markdown, "(#module-a) - test\n")); + assert!(markdown.contains("(#module-a) - test\n")); } #[test] fn should_not_write_index_if_no_entries() { let markdown = render(~""); - assert!(!str::contains(markdown, "\n\n\n")); + assert!(!markdown.contains("\n\n\n")); } #[test] fn should_write_index_for_foreign_mods() { let markdown = render(~"extern { fn a(); }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n* [Function `a`](#function-a)\n\n" )); } @@ -737,32 +735,32 @@ mod test { fn should_write_foreign_fns() { let markdown = render( ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, "test")); + assert!(markdown.contains("test")); } #[test] fn should_write_foreign_fn_headers() { let markdown = render( ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, "## Function `a`")); + assert!(markdown.contains("## Function `a`")); } #[test] fn write_markdown_should_write_function_header() { let markdown = render(~"fn func() { }"); - assert!(str::contains(markdown, "## Function `func`")); + assert!(markdown.contains("## Function `func`")); } #[test] fn should_write_the_function_signature() { let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, "\n fn a()\n")); + assert!(markdown.contains("\n fn a()\n")); } #[test] fn should_insert_blank_line_after_fn_signature() { let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, "fn a()\n\n")); + assert!(markdown.contains("fn a()\n\n")); } #[test] @@ -783,19 +781,19 @@ mod test { ] }; let markdown = write_markdown_str(doc); - assert!(str::contains(markdown, " line 1\n line 2")); + assert!(markdown.contains(" line 1\n line 2")); } #[test] fn should_leave_blank_line_between_fn_header_and_sig() { let markdown = render(~"fn a() { }"); - assert!(str::contains(markdown, "Function `a`\n\n fn a()")); + assert!(markdown.contains("Function `a`\n\n fn a()")); } #[test] fn should_write_const_header() { let markdown = render(~"static a: bool = true;"); - assert!(str::contains(markdown, "## Const `a`\n\n")); + assert!(markdown.contains("## Const `a`\n\n")); } #[test] @@ -803,19 +801,19 @@ mod test { let markdown = render( ~"#[doc = \"b\"]\ static a: bool = true;"); - assert!(str::contains(markdown, "\n\nb\n\n")); + assert!(markdown.contains("\n\nb\n\n")); } #[test] fn should_write_enum_header() { let markdown = render(~"enum a { b }"); - assert!(str::contains(markdown, "## Enum `a`\n\n")); + assert!(markdown.contains("## Enum `a`\n\n")); } #[test] fn should_write_enum_description() { let markdown = render(~"#[doc = \"b\"] enum a { b }"); - assert!(str::contains(markdown, "\n\nb\n\n")); + assert!(markdown.contains("\n\nb\n\n")); } #[test] @@ -824,8 +822,7 @@ mod test { ~"enum a { \ #[doc = \"test\"] b, \ #[doc = \"test\"] c }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n#### Variants\n\ \n\ \n* `b` - test\ @@ -836,8 +833,7 @@ mod test { #[test] fn should_write_variant_list_without_descs() { let markdown = render(~"enum a { b, c }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n#### Variants\n\ \n\ \n* `b`\ @@ -849,8 +845,7 @@ mod test { fn should_write_variant_list_with_indent() { let markdown = render( ~"enum a { #[doc = \"line 1\\n\\nline 2\"] b, c }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n#### Variants\n\ \n\ \n* `b` - line 1\ @@ -863,8 +858,7 @@ mod test { #[test] fn should_write_variant_list_with_signatures() { let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }"); - assert!(str::contains( - markdown, + assert!(markdown.contains( "\n\n#### Variants\n\ \n\ \n* `b(int)`\ @@ -875,43 +869,43 @@ mod test { #[test] fn should_write_trait_header() { let markdown = render(~"trait i { fn a(); }"); - assert!(str::contains(markdown, "## Trait `i`")); + assert!(markdown.contains("## Trait `i`")); } #[test] fn should_write_trait_desc() { let markdown = render(~"#[doc = \"desc\"] trait i { fn a(); }"); - assert!(str::contains(markdown, "desc")); + assert!(markdown.contains("desc")); } #[test] fn should_write_trait_method_header() { let markdown = render(~"trait i { fn a(); }"); - assert!(str::contains(markdown, "### Method `a`")); + assert!(markdown.contains("### Method `a`")); } #[test] fn should_write_trait_method_signature() { let markdown = render(~"trait i { fn a(&self); }"); - assert!(str::contains(markdown, "\n fn a(&self)")); + assert!(markdown.contains("\n fn a(&self)")); } #[test] fn should_write_impl_header() { let markdown = render(~"impl int { fn a() { } }"); - assert!(str::contains(markdown, "## Implementation for `int`")); + assert!(markdown.contains("## Implementation for `int`")); } #[test] fn should_write_impl_header_with_bounds() { let markdown = render(~"impl int { }"); - assert!(str::contains(markdown, "## Implementation for `int` where ``")); + assert!(markdown.contains("## Implementation for `int` where ``")); } #[test] fn should_write_impl_header_with_trait() { let markdown = render(~"impl j for int { fn a() { } }"); - assert!(str::contains(markdown, + assert!(markdown.contains( "## Implementation of `j` for `int`")); } @@ -919,45 +913,45 @@ mod test { fn should_write_impl_desc() { let markdown = render( ~"#[doc = \"desc\"] impl int { fn a() { } }"); - assert!(str::contains(markdown, "desc")); + assert!(markdown.contains("desc")); } #[test] fn should_write_impl_method_header() { let markdown = render( ~"impl int { fn a() { } }"); - assert!(str::contains(markdown, "### Method `a`")); + assert!(markdown.contains("### Method `a`")); } #[test] fn should_write_impl_method_signature() { let markdown = render( ~"impl int { fn a(&mut self) { } }"); - assert!(str::contains(markdown, "\n fn a(&mut self)")); + assert!(markdown.contains("\n fn a(&mut self)")); } #[test] fn should_write_type_header() { let markdown = render(~"type t = int;"); - assert!(str::contains(markdown, "## Type `t`")); + assert!(markdown.contains("## Type `t`")); } #[test] fn should_write_type_desc() { let markdown = render( ~"#[doc = \"desc\"] type t = int;"); - assert!(str::contains(markdown, "\n\ndesc\n\n")); + assert!(markdown.contains("\n\ndesc\n\n")); } #[test] fn should_write_type_signature() { let markdown = render(~"type t = int;"); - assert!(str::contains(markdown, "\n\n type t = int\n\n")); + assert!(markdown.contains("\n\n type t = int\n\n")); } #[test] fn should_put_struct_header() { let markdown = render(~"struct S { field: () }"); - assert!(str::contains(markdown, "## Struct `S`\n\n")); + assert!(markdown.contains("## Struct `S`\n\n")); } } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 61a8d11af7f7b..ddc1b7dfe21e8 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -191,9 +191,7 @@ mod test { Body\"]\ mod a { }"); - assert!(str::contains( - doc.cratemod().mods()[0].item.sections[0].header, - "Header")); + assert!(doc.cratemod().mods()[0].item.sections[0].header.contains("Header")); } #[test] @@ -204,9 +202,7 @@ mod test { Body\"]\ mod a { }"); - assert!(str::contains( - doc.cratemod().mods()[0].item.sections[0].body, - "Body")); + assert!(doc.cratemod().mods()[0].item.sections[0].body.contains("Body")); } #[test] @@ -229,12 +225,8 @@ mod test { Body\"]\ mod a { }"); - assert!(!str::contains( - doc.cratemod().mods()[0].desc().get(), - "Header")); - assert!(!str::contains( - doc.cratemod().mods()[0].desc().get(), - "Body")); + assert!(!doc.cratemod().mods()[0].desc().get().contains("Header")); + assert!(!doc.cratemod().mods()[0].desc().get().contains("Body")); } #[test] diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 98b210dd5a912..7ae59e524a0ce 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1167,30 +1167,6 @@ fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { } -/** - * Returns true if one string contains another - * - * # Arguments - * - * * haystack - The string to look in - * * needle - The string to look for - */ -pub fn contains<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - haystack.find_str(needle).is_some() -} - -/** - * Returns true if a string contains a char. - * - * # Arguments - * - * * haystack - The string to look in - * * needle - The char to look for - */ -pub fn contains_char(haystack: &str, needle: char) -> bool { - haystack.find(needle).is_some() -} - /** * Returns true if one string starts with another * @@ -2019,15 +1995,27 @@ pub trait StrSlice<'self> { /// Extension methods for strings impl<'self> StrSlice<'self> for &'self str { - /// Returns true if one string contains another + /** + * Returns true if one string contains another + * + * # Arguments + * + * * needle - The string to look for + */ #[inline] fn contains<'a>(&self, needle: &'a str) -> bool { - contains(*self, needle) + self.find_str(needle).is_some() } - /// Returns true if a string contains a char + /** + * Returns true if a string contains a char. + * + * # Arguments + * + * * needle - The char to look for + */ #[inline] fn contains_char(&self, needle: char) -> bool { - contains_char(*self, needle) + self.find(needle).is_some() } #[inline] @@ -3060,19 +3048,19 @@ mod tests { #[test] fn test_contains() { - assert!(contains("abcde", "bcd")); - assert!(contains("abcde", "abcd")); - assert!(contains("abcde", "bcde")); - assert!(contains("abcde", "")); - assert!(contains("", "")); - assert!(!contains("abcde", "def")); - assert!(!contains("", "a")); + assert!("abcde".contains("bcd")); + assert!("abcde".contains("abcd")); + assert!("abcde".contains("bcde")); + assert!("abcde".contains("")); + assert!("".contains("")); + assert!(!"abcde".contains("def")); + assert!(!"".contains("a")); let data = ~"ประเทศไทย中华Việt Nam"; - assert!(contains(data, "ประเ")); - assert!(contains(data, "ะเ")); - assert!(contains(data, "中华")); - assert!(!contains(data, "ไท华")); + assert!(data.contains("ประเ")); + assert!(data.contains("ะเ")); + assert!(data.contains("中华")); + assert!(!data.contains("ไท华")); } #[test] From 1553874149c3c37b94d75e9122092b131ba74c77 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 17:42:24 +1000 Subject: [PATCH 10/21] std: convert str::reserve* to methods, and methodise str::push_*. --- src/libextra/base64.rs | 26 +- src/libextra/json.rs | 22 +- src/libextra/net_url.rs | 26 +- src/libextra/rope.rs | 4 +- src/libextra/semver.rs | 2 +- src/libextra/time.rs | 2 +- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/borrowck/mod.rs | 18 +- src/librustc/middle/dataflow.rs | 6 +- src/libstd/str.rs | 332 +++++++++++++------------ src/libstd/unstable/lang.rs | 6 +- src/libsyntax/ext/fmt.rs | 3 + src/libsyntax/parse/comments.rs | 6 +- src/libsyntax/parse/lexer.rs | 29 +-- src/test/bench/shootout-fasta.rs | 2 +- src/test/run-pass/issue-4241.rs | 6 +- src/test/run-pass/move-out-of-field.rs | 2 +- src/test/run-pass/utf8_chars.rs | 2 +- 18 files changed, 248 insertions(+), 248 deletions(-) diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index b8f3a267d2d24..62d4a32b8e239 100644 --- a/src/libextra/base64.rs +++ b/src/libextra/base64.rs @@ -49,7 +49,7 @@ impl<'self> ToBase64 for &'self [u8] { fn to_base64(&self) -> ~str { let mut s = ~""; let len = self.len(); - str::reserve(&mut s, ((len + 3u) / 4u) * 3u); + s.reserve(((len + 3u) / 4u) * 3u); let mut i = 0u; @@ -59,10 +59,10 @@ impl<'self> ToBase64 for &'self [u8] { (self[i + 2u] as uint); // This 24-bit number gets separated into four 6-bit numbers. - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); - str::push_char(&mut s, CHARS[n & 63u]); + s.push_char(CHARS[(n >> 18u) & 63u]); + s.push_char(CHARS[(n >> 12u) & 63u]); + s.push_char(CHARS[(n >> 6u) & 63u]); + s.push_char(CHARS[n & 63u]); i += 3u; } @@ -73,18 +73,18 @@ impl<'self> ToBase64 for &'self [u8] { 0 => (), 1 => { let n = (self[i] as uint) << 16u; - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, '='); - str::push_char(&mut s, '='); + s.push_char(CHARS[(n >> 18u) & 63u]); + s.push_char(CHARS[(n >> 12u) & 63u]); + s.push_char('='); + s.push_char('='); } 2 => { let n = (self[i] as uint) << 16u | (self[i + 1u] as uint) << 8u; - str::push_char(&mut s, CHARS[(n >> 18u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 12u) & 63u]); - str::push_char(&mut s, CHARS[(n >> 6u) & 63u]); - str::push_char(&mut s, '='); + s.push_char(CHARS[(n >> 18u) & 63u]); + s.push_char(CHARS[(n >> 12u) & 63u]); + s.push_char(CHARS[(n >> 6u) & 63u]); + s.push_char('='); } _ => fail!("Algebra is broken, please alert the math police") } diff --git a/src/libextra/json.rs b/src/libextra/json.rs index 30a2b5f862768..1e9ec48aff32d 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -79,7 +79,7 @@ fn escape_str(s: &str) -> ~str { fn spaces(n: uint) -> ~str { let mut ss = ~""; - for n.times { str::push_str(&mut ss, " "); } + for n.times { ss.push_str(" "); } return ss; } @@ -712,14 +712,14 @@ impl Parser { if (escape) { match self.ch { - '"' => str::push_char(&mut res, '"'), - '\\' => str::push_char(&mut res, '\\'), - '/' => str::push_char(&mut res, '/'), - 'b' => str::push_char(&mut res, '\x08'), - 'f' => str::push_char(&mut res, '\x0c'), - 'n' => str::push_char(&mut res, '\n'), - 'r' => str::push_char(&mut res, '\r'), - 't' => str::push_char(&mut res, '\t'), + '"' => res.push_char('"'), + '\\' => res.push_char('\\'), + '/' => res.push_char('/'), + 'b' => res.push_char('\x08'), + 'f' => res.push_char('\x0c'), + 'n' => res.push_char('\n'), + 'r' => res.push_char('\r'), + 't' => res.push_char('\t'), 'u' => { // Parse \u1234. let mut i = 0u; @@ -748,7 +748,7 @@ impl Parser { ~"invalid \\u escape (not four digits)"); } - str::push_char(&mut res, n as char); + res.push_char(n as char); } _ => return self.error(~"invalid escape") } @@ -760,7 +760,7 @@ impl Parser { self.bump(); return Ok(res); } - str::push_char(&mut res, self.ch); + res.push_char(self.ch); } } diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 6fd6fa3acd91b..30d55721efb76 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -81,7 +81,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { 'a' .. 'z' | '0' .. '9' | '-' | '.' | '_' | '~' => { - str::push_char(&mut out, ch); + out.push_char(ch); } _ => { if full_url { @@ -92,7 +92,7 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { // sub-delims: '!' | '$' | '&' | '"' | '(' | ')' | '*' | '+' | ',' | ';' | '=' => { - str::push_char(&mut out, ch); + out.push_char(ch); } _ => out += fmt!("%%%X", ch as uint) @@ -148,18 +148,18 @@ fn decode_inner(s: &str, full_url: bool) -> ~str { // sub-delims: '!' | '$' | '&' | '"' | '(' | ')' | '*' | '+' | ',' | ';' | '=' => { - str::push_char(&mut out, '%'); - str::push_char(&mut out, bytes[0u] as char); - str::push_char(&mut out, bytes[1u] as char); + out.push_char('%'); + out.push_char(bytes[0u] as char); + out.push_char(bytes[1u] as char); } - ch => str::push_char(&mut out, ch) + ch => out.push_char(ch) } } else { - str::push_char(&mut out, ch); + out.push_char(ch); } } - ch => str::push_char(&mut out, ch) + ch => out.push_char(ch) } } @@ -191,9 +191,9 @@ fn encode_plus(s: &str) -> ~str { let ch = rdr.read_byte() as char; match ch { 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => { - str::push_char(&mut out, ch); + out.push_char(ch); } - ' ' => str::push_char(&mut out, '+'), + ' ' => out.push_char('+'), _ => out += fmt!("%%%X", ch as uint) } } @@ -216,7 +216,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str { if first { first = false; } else { - str::push_char(&mut out, '&'); + out.push_char('&'); first = false; } @@ -267,9 +267,9 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> { }; if parsing_key { - str::push_char(&mut key, ch) + key.push_char(ch) } else { - str::push_char(&mut value, ch) + value.push_char(ch) } } } diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 9ae8c47ae3c68..de78e0a6eebda 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -1289,9 +1289,7 @@ mod tests { fn aux(str: &mut ~str, node: @node::Node) { match (*node) { node::Leaf(x) => { - str::push_str( - str, - x.content.slice(x.byte_offset, x.byte_offset + x.byte_len)); + str.push_str(x.content.slice(x.byte_offset, x.byte_offset + x.byte_len)); } node::Concat(ref x) => { aux(str, x.left); diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs index 36ebd10ae17b7..dad080752388e 100644 --- a/src/libextra/semver.rs +++ b/src/libextra/semver.rs @@ -149,7 +149,7 @@ fn take_nonempty_prefix(rdr: @io::Reader, let mut buf = ~""; let mut ch = ch; while pred(ch) { - str::push_char(&mut buf, ch); + buf.push_char(ch); ch = rdr.read_char(); } if buf.is_empty() { diff --git a/src/libextra/time.rs b/src/libextra/time.rs index f545b28c5072b..fea5cb560acaf 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -851,7 +851,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str { while !rdr.eof() { match rdr.read_char() { '%' => buf += parse_type(rdr.read_char(), tm), - ch => str::push_char(&mut buf, ch) + ch => buf.push_char(ch) } } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 32a2bf22f2705..18946ee2d790e 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -980,7 +980,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder { fn type_string(doc: ebml::Doc) -> ~str { let mut str = ~""; for uint::range(doc.start, doc.end) |i| { - str::push_char(&mut str, doc.data[i] as char); + str.push_char(doc.data[i] as char); } str } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index fa3bae3f5ac92..b0b9c9f7efb62 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -694,9 +694,9 @@ impl BorrowckCtxt { out: &mut ~str) { match *loan_path { LpExtend(_, _, LpDeref) => { - str::push_char(out, '('); + out.push_char('('); self.append_loan_path_to_str(loan_path, out); - str::push_char(out, ')'); + out.push_char(')'); } LpExtend(_, _, LpInterior(_)) | LpVar(_) => { @@ -712,7 +712,7 @@ impl BorrowckCtxt { LpVar(id) => { match self.tcx.items.find(&id) { Some(&ast_map::node_local(ref ident)) => { - str::push_str(out, *token::ident_to_str(ident)); + out.push_str(*token::ident_to_str(ident)); } r => { self.tcx.sess.bug( @@ -726,23 +726,23 @@ impl BorrowckCtxt { self.append_loan_path_to_str_from_interior(lp_base, out); match fname { mc::NamedField(ref fname) => { - str::push_char(out, '.'); - str::push_str(out, *token::ident_to_str(fname)); + out.push_char('.'); + out.push_str(*token::ident_to_str(fname)); } mc::PositionalField(idx) => { - str::push_char(out, '#'); // invent a notation here - str::push_str(out, idx.to_str()); + out.push_char('#'); // invent a notation here + out.push_str(idx.to_str()); } } } LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => { self.append_loan_path_to_str_from_interior(lp_base, out); - str::push_str(out, "[]"); + out.push_str("[]"); } LpExtend(lp_base, _, LpDeref) => { - str::push_char(out, '*'); + out.push_char('*'); self.append_loan_path_to_str(lp_base, out); } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 1f9fff14ba209..e2d88e3c76812 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -947,13 +947,13 @@ fn bits_to_str(words: &[uint]) -> ~str { for words.each |&word| { let mut v = word; for uint::range(0, uint::bytes) |_| { - str::push_char(&mut result, sep); - str::push_str(&mut result, fmt!("%02x", v & 0xFF)); + result.push_char(sep); + result.push_str(fmt!("%02x", v & 0xFF)); v >>= 8; sep = '-'; } } - str::push_char(&mut result, ']'); + result.push_char(']'); return result; } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 7ae59e524a0ce..5455edc25863c 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -139,121 +139,35 @@ pub fn from_byte(b: u8) -> ~str { unsafe { ::cast::transmute(~[b, 0u8]) } } -/// Appends a character at the end of a string -pub fn push_char(s: &mut ~str, ch: char) { - unsafe { - let code = ch as uint; - let nb = if code < max_one_b { 1u } - else if code < max_two_b { 2u } - else if code < max_three_b { 3u } - else if code < max_four_b { 4u } - else if code < max_five_b { 5u } - else { 6u }; - let len = s.len(); - let new_len = len + nb; - reserve_at_least(&mut *s, new_len); - let off = len; - do as_buf(*s) |buf, _len| { - let buf: *mut u8 = ::cast::transmute(buf); - match nb { - 1u => { - *ptr::mut_offset(buf, off) = code as u8; - } - 2u => { - *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8; - } - 3u => { - *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8; - } - 4u => { - *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8; - } - 5u => { - *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8; - } - 6u => { - *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8; - *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8; - } - _ => {} - } - } - raw::set_len(s, new_len); - } -} - /// Convert a char to a string pub fn from_char(ch: char) -> ~str { let mut buf = ~""; - push_char(&mut buf, ch); + buf.push_char(ch); buf } /// Convert a vector of chars to a string pub fn from_chars(chs: &[char]) -> ~str { let mut buf = ~""; - reserve(&mut buf, chs.len()); + buf.reserve(chs.len()); for chs.each |ch| { - push_char(&mut buf, *ch); + buf.push_char(*ch) } buf } -/// Appends a string slice to the back of a string, without overallocating -#[inline(always)] -pub fn push_str_no_overallocate(lhs: &mut ~str, rhs: &str) { - unsafe { - let llen = lhs.len(); - let rlen = rhs.len(); - reserve(&mut *lhs, llen + rlen); - do as_buf(*lhs) |lbuf, _llen| { - do as_buf(rhs) |rbuf, _rlen| { - let dst = ptr::offset(lbuf, llen); - let dst = ::cast::transmute_mut_unsafe(dst); - ptr::copy_memory(dst, rbuf, rlen); - } - } - raw::set_len(lhs, llen + rlen); - } -} - -/// Appends a string slice to the back of a string -#[inline(always)] +/// A function version of the `.push_str`, required for `fmt!` during +/// the bootstrap. Use `lhs.push_str(rhs)` instead of this. +#[doc="hidden"] pub fn push_str(lhs: &mut ~str, rhs: &str) { - unsafe { - let llen = lhs.len(); - let rlen = rhs.len(); - reserve_at_least(&mut *lhs, llen + rlen); - do as_buf(*lhs) |lbuf, _llen| { - do as_buf(rhs) |rbuf, _rlen| { - let dst = ptr::offset(lbuf, llen); - let dst = ::cast::transmute_mut_unsafe(dst); - ptr::copy_memory(dst, rbuf, rlen); - } - } - raw::set_len(lhs, llen + rlen); - } + lhs.push_str(rhs) } /// Concatenate two strings together #[inline(always)] pub fn append(lhs: ~str, rhs: &str) -> ~str { let mut v = lhs; - push_str_no_overallocate(&mut v, rhs); + v.push_str_no_overallocate(rhs); v } @@ -286,7 +200,7 @@ impl<'self> StrVector for &'self [~str] { } let mut s = ~""; - reserve(&mut s, len); + s.reserve(len); unsafe { do as_buf(s) |buf, _| { @@ -319,7 +233,7 @@ impl<'self> StrVector for &'self [~str] { let mut s = ~""; let mut first = true; - reserve(&mut s, len); + s.reserve(len); unsafe { do as_buf(s) |buf, _| { @@ -358,7 +272,7 @@ impl<'self> StrVector for &'self [&'self str] { } let mut s = ~""; - reserve(&mut s, len); + s.reserve(len); unsafe { do as_buf(s) |buf, _| { @@ -391,7 +305,7 @@ impl<'self> StrVector for &'self [&'self str] { let mut s = ~""; let mut first = true; - reserve(&mut s, len); + s.reserve(len); unsafe { do as_buf(s) |buf, _| { @@ -425,7 +339,7 @@ pub fn repeat(ss: &str, nn: uint) -> ~str { let mut ret = ~""; // ignore the NULL terminator let len = len - 1; - reserve(&mut ret, nn * len); + ret.reserve(nn * len); unsafe { do as_buf(ret) |rbuf, _len| { @@ -1148,9 +1062,9 @@ Section: Iterating through strings /// Apply a function to each character pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { let mut result = ~""; - reserve(&mut result, ss.len()); + result.reserve(ss.len()); for ss.iter().advance |cc| { - str::push_char(&mut result, ff(cc)); + result.push_char(ff(cc)); } result } @@ -1325,8 +1239,8 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) { */ pub fn from_utf16(v: &[u16]) -> ~str { let mut buf = ~""; - reserve(&mut buf, v.len()); - utf16_chars(v, |ch| push_char(&mut buf, ch)); + buf.reserve(v.len()); + utf16_chars(v, |ch| buf.push_char(ch)); buf } @@ -1336,7 +1250,7 @@ pub fn from_utf16(v: &[u16]) -> ~str { */ pub fn with_capacity(capacity: uint) -> ~str { let mut buf = ~""; - reserve(&mut buf, capacity); + buf.reserve(capacity); buf } @@ -1660,54 +1574,6 @@ pub fn subslice_offset(outer: &str, inner: &str) -> uint { } } -/** - * Reserves capacity for exactly `n` bytes in the given string, not including - * the null terminator. - * - * Assuming single-byte characters, the resulting string will be large - * enough to hold a string of length `n`. To account for the null terminator, - * the underlying buffer will have the size `n` + 1. - * - * If the capacity for `s` is already equal to or greater than the requested - * capacity, then no action is taken. - * - * # Arguments - * - * * s - A string - * * n - The number of bytes to reserve space for - */ -#[inline(always)] -pub fn reserve(s: &mut ~str, n: uint) { - unsafe { - let v: *mut ~[u8] = cast::transmute(s); - vec::reserve(&mut *v, n + 1); - } -} - -/** - * Reserves capacity for at least `n` bytes in the given string, not including - * the null terminator. - * - * Assuming single-byte characters, the resulting string will be large - * enough to hold a string of length `n`. To account for the null terminator, - * the underlying buffer will have the size `n` + 1. - * - * This function will over-allocate in order to amortize the allocation costs - * in scenarios where the caller may need to repeatedly reserve additional - * space. - * - * If the capacity for `s` is already equal to or greater than the requested - * capacity, then no action is taken. - * - * # Arguments - * - * * s - A string - * * n - The number of bytes to reserve space for - */ -#[inline(always)] -pub fn reserve_at_least(s: &mut ~str, n: uint) { - reserve(s, uint::next_power_of_two(n + 1u) - 1u) -} /** * Returns the number of single-byte characters the string can hold without @@ -1724,9 +1590,9 @@ pub fn capacity(s: &const ~str) -> uint { /// Escape each char in `s` with char::escape_default. pub fn escape_default(s: &str) -> ~str { let mut out: ~str = ~""; - reserve_at_least(&mut out, s.len()); + out.reserve_at_least(s.len()); for s.iter().advance |c| { - push_str(&mut out, char::escape_default(c)); + out.push_str(char::escape_default(c)); } out } @@ -1734,9 +1600,9 @@ pub fn escape_default(s: &str) -> ~str { /// Escape each char in `s` with char::escape_unicode. pub fn escape_unicode(s: &str) -> ~str { let mut out: ~str = ~""; - reserve_at_least(&mut out, s.len()); + out.reserve_at_least(s.len()); for s.iter().advance |c| { - push_str(&mut out, char::escape_unicode(c)); + out.push_str(char::escape_unicode(c)); } out } @@ -1747,7 +1613,7 @@ pub mod raw { use libc; use ptr; use str::raw; - use str::{as_buf, is_utf8, reserve_at_least}; + use str::{as_buf, is_utf8}; use vec; /// Create a Rust string from a null-terminated *u8 buffer @@ -1859,7 +1725,7 @@ pub mod raw { /// Appends a byte to a string. (Not UTF-8 safe). pub unsafe fn push_byte(s: &mut ~str, b: u8) { let new_len = s.len() + 1; - reserve_at_least(&mut *s, new_len); + s.reserve_at_least(new_len); do as_buf(*s) |buf, len| { let buf: *mut u8 = ::cast::transmute(buf); *ptr::mut_offset(buf, len) = b; @@ -1870,7 +1736,7 @@ pub mod raw { /// Appends a vector of bytes to a string. (Not UTF-8 safe). unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) { let new_len = s.len() + bytes.len(); - reserve_at_least(&mut *s, new_len); + s.reserve_at_least(new_len); for bytes.each |byte| { push_byte(&mut *s, *byte); } } @@ -2274,18 +2140,154 @@ impl<'self> StrSlice<'self> for &'self str { #[allow(missing_doc)] pub trait OwnedStr { - fn push_str(&mut self, v: &str); + fn push_str_no_overallocate(&mut self, rhs: &str); + fn push_str(&mut self, rhs: &str); fn push_char(&mut self, c: char); + fn reserve(&mut self, n: uint); + fn reserve_at_least(&mut self, n: uint); } impl OwnedStr for ~str { + /// Appends a string slice to the back of a string, without overallocating + #[inline(always)] + fn push_str_no_overallocate(&mut self, rhs: &str) { + unsafe { + let llen = self.len(); + let rlen = rhs.len(); + self.reserve(llen + rlen); + do as_buf(*self) |lbuf, _llen| { + do as_buf(rhs) |rbuf, _rlen| { + let dst = ptr::offset(lbuf, llen); + let dst = ::cast::transmute_mut_unsafe(dst); + ptr::copy_memory(dst, rbuf, rlen); + } + } + raw::set_len(self, llen + rlen); + } + } + + /// Appends a string slice to the back of a string #[inline] - fn push_str(&mut self, v: &str) { - push_str(self, v); + fn push_str(&mut self, rhs: &str) { + unsafe { + let llen = self.len(); + let rlen = rhs.len(); + self.reserve_at_least(llen + rlen); + do as_buf(*self) |lbuf, _llen| { + do as_buf(rhs) |rbuf, _rlen| { + let dst = ptr::offset(lbuf, llen); + let dst = ::cast::transmute_mut_unsafe(dst); + ptr::copy_memory(dst, rbuf, rlen); + } + } + raw::set_len(self, llen + rlen); + } } + /// Appends a character to the back of a string #[inline] fn push_char(&mut self, c: char) { - push_char(self, c); + unsafe { + let code = c as uint; + let nb = if code < max_one_b { 1u } + else if code < max_two_b { 2u } + else if code < max_three_b { 3u } + else if code < max_four_b { 4u } + else if code < max_five_b { 5u } + else { 6u }; + let len = self.len(); + let new_len = len + nb; + self.reserve_at_least(new_len); + let off = len; + do as_buf(*self) |buf, _len| { + let buf: *mut u8 = ::cast::transmute(buf); + match nb { + 1u => { + *ptr::mut_offset(buf, off) = code as u8; + } + 2u => { + *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8; + } + 3u => { + *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8; + } + 4u => { + *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8; + } + 5u => { + *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8; + } + 6u => { + *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8; + } + _ => {} + } + } + raw::set_len(self, new_len); + } + } + + /** + * Reserves capacity for exactly `n` bytes in the given string, not including + * the null terminator. + * + * Assuming single-byte characters, the resulting string will be large + * enough to hold a string of length `n`. To account for the null terminator, + * the underlying buffer will have the size `n` + 1. + * + * If the capacity for `s` is already equal to or greater than the requested + * capacity, then no action is taken. + * + * # Arguments + * + * * s - A string + * * n - The number of bytes to reserve space for + */ + #[inline(always)] + pub fn reserve(&mut self, n: uint) { + unsafe { + let v: *mut ~[u8] = cast::transmute(self); + vec::reserve(&mut *v, n + 1); + } + } + + /** + * Reserves capacity for at least `n` bytes in the given string, not including + * the null terminator. + * + * Assuming single-byte characters, the resulting string will be large + * enough to hold a string of length `n`. To account for the null terminator, + * the underlying buffer will have the size `n` + 1. + * + * This function will over-allocate in order to amortize the allocation costs + * in scenarios where the caller may need to repeatedly reserve additional + * space. + * + * If the capacity for `s` is already equal to or greater than the requested + * capacity, then no action is taken. + * + * # Arguments + * + * * s - A string + * * n - The number of bytes to reserve space for + */ + #[inline(always)] + fn reserve_at_least(&mut self, n: uint) { + self.reserve(uint::next_power_of_two(n + 1u) - 1u) } } @@ -2582,13 +2584,13 @@ mod tests { fn a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; - while i < 100000 { push_str(&mut rs, "aaaaaaaaaa"); i += 1; } + while i < 100000 { rs.push_str("aaaaaaaaaa"); i += 1; } rs } fn half_a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; - while i < 100000 { push_str(&mut rs, "aaaaa"); i += 1; } + while i < 100000 { rs.push_str("aaaaa"); i += 1; } rs } let letters = a_million_letter_a(); diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index cd3e0cf303e1d..e75cf2c01c675 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -136,10 +136,10 @@ unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { let mut sep = " at "; for borrow_list.rev_iter().advance |entry| { if entry.box == box { - str::push_str(&mut msg, sep); + msg.push_str(sep); let filename = str::raw::from_c_str(entry.file); - str::push_str(&mut msg, filename); - str::push_str(&mut msg, fmt!(":%u", entry.line as uint)); + msg.push_str(filename); + msg.push_str(fmt!(":%u", entry.line as uint)); sep = " and at "; } } diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 6d0c499f2c823..b2ec3684b70e0 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -276,6 +276,9 @@ fn pieces_to_expr(cx: @ExtCtxt, sp: span, stms.push(cx.stmt_let(fmt_sp, npieces > 1, ident, cx.expr_str_uniq(fmt_sp, s))); } else { + // we call the push_str function because the + // bootstrap doesnt't seem to work if we call the + // method. let args = ~[cx.expr_mut_addr_of(fmt_sp, buf()), cx.expr_str(fmt_sp, s)]; let call = cx.expr_call_global(fmt_sp, ~[core_ident, diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index a715ede766401..89fd5c3762a3b 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -125,7 +125,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { fn read_to_eol(rdr: @mut StringReader) -> ~str { let mut val = ~""; while rdr.curr != '\n' && !is_eof(rdr) { - str::push_char(&mut val, rdr.curr); + val.push_char(rdr.curr); bump(rdr); } if rdr.curr == '\n' { bump(rdr); } @@ -237,7 +237,7 @@ fn read_block_comment(rdr: @mut StringReader, // doc-comments are not really comments, they are attributes if rdr.curr == '*' || rdr.curr == '!' { while !(rdr.curr == '*' && nextch(rdr) == '/') && !is_eof(rdr) { - str::push_char(&mut curr_line, rdr.curr); + curr_line.push_char(rdr.curr); bump(rdr); } if !is_eof(rdr) { @@ -261,7 +261,7 @@ fn read_block_comment(rdr: @mut StringReader, curr_line = ~""; bump(rdr); } else { - str::push_char(&mut curr_line, rdr.curr); + curr_line.push_char(rdr.curr); if rdr.curr == '/' && nextch(rdr) == '*' { bump(rdr); bump(rdr); diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 2dc8008f8ec53..809a222352fb8 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -358,11 +358,11 @@ fn scan_exponent(rdr: @mut StringReader) -> Option<~str> { let mut c = rdr.curr; let mut rslt = ~""; if c == 'e' || c == 'E' { - str::push_char(&mut rslt, c); + rslt.push_char(c); bump(rdr); c = rdr.curr; if c == '-' || c == '+' { - str::push_char(&mut rslt, c); + rslt.push_char(c); bump(rdr); } let exponent = scan_digits(rdr, 10u); @@ -379,7 +379,7 @@ fn scan_digits(rdr: @mut StringReader, radix: uint) -> ~str { if c == '_' { bump(rdr); loop; } match char::to_digit(c, radix) { Some(_) => { - str::push_char(&mut rslt, c); + rslt.push_char(c); bump(rdr); } _ => return rslt @@ -721,31 +721,28 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token { let escaped = rdr.curr; bump(rdr); match escaped { - 'n' => str::push_char(&mut accum_str, '\n'), - 'r' => str::push_char(&mut accum_str, '\r'), - 't' => str::push_char(&mut accum_str, '\t'), - '\\' => str::push_char(&mut accum_str, '\\'), - '\'' => str::push_char(&mut accum_str, '\''), - '"' => str::push_char(&mut accum_str, '"'), + 'n' => accum_str.push_char('\n'), + 'r' => accum_str.push_char('\r'), + 't' => accum_str.push_char('\t'), + '\\' => accum_str.push_char('\\'), + '\'' => accum_str.push_char('\''), + '"' => accum_str.push_char('"'), '\n' => consume_whitespace(rdr), 'x' => { - str::push_char(&mut accum_str, - scan_numeric_escape(rdr, 2u)); + accum_str.push_char(scan_numeric_escape(rdr, 2u)); } 'u' => { - str::push_char(&mut accum_str, - scan_numeric_escape(rdr, 4u)); + accum_str.push_char(scan_numeric_escape(rdr, 4u)); } 'U' => { - str::push_char(&mut accum_str, - scan_numeric_escape(rdr, 8u)); + accum_str.push_char(scan_numeric_escape(rdr, 8u)); } c2 => { rdr.fatal(fmt!("unknown string escape: %d", c2 as int)); } } } - _ => str::push_char(&mut accum_str, ch) + _ => accum_str.push_char(ch) } } bump(rdr); diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index c497a30ec5f66..5c77e698bec8b 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -79,7 +79,7 @@ fn make_random_fasta(wr: @io::Writer, }; let mut op: ~str = ~""; for uint::range(0u, n as uint) |_i| { - str::push_char(&mut op, select_random(myrandom_next(rng, 100u32), + op.push_char(select_random(myrandom_next(rng, 100u32), copy genelist)); if op.len() >= LINE_LENGTH() { wr.write_line(op); diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index 4aa604160d933..972b9c7a52533 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -95,10 +95,10 @@ priv fn parse_response(io: @io::Reader) -> Result { priv fn cmd_to_str(cmd: ~[~str]) -> ~str { let mut res = ~"*"; - str::push_str(&mut res, cmd.len().to_str()); - str::push_str(&mut res, "\r\n"); + res.push_str(cmd.len().to_str()); + res.push_str("\r\n"); for cmd.each |s| { - str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n", + res.push_str(str::concat(~[~"$", s.len().to_str(), ~"\r\n", copy *s, ~"\r\n"])); } res diff --git a/src/test/run-pass/move-out-of-field.rs b/src/test/run-pass/move-out-of-field.rs index b6485348a5184..a3c2872803adc 100644 --- a/src/test/run-pass/move-out-of-field.rs +++ b/src/test/run-pass/move-out-of-field.rs @@ -6,7 +6,7 @@ struct StringBuffer { impl StringBuffer { pub fn append(&mut self, v: &str) { - str::push_str(&mut self.s, v); + self.s.push_str(v); } } diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 011fb4435c3e8..94990d649d82f 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -33,7 +33,7 @@ pub fn main() { let mut stack = ~"a×c€"; assert_eq!(str::pop_char(&mut stack), '€'); assert_eq!(str::pop_char(&mut stack), 'c'); - str::push_char(&mut stack, 'u'); + stack.push_char('u'); assert!(stack == ~"a×u"); assert_eq!(str::shift_char(&mut stack), 'a'); assert_eq!(str::shift_char(&mut stack), '×'); From f632f466148c7e5571393bb2a24cd628703a60fa Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 21:03:16 +1000 Subject: [PATCH 11/21] std: convert str::trim* to methods. --- src/libextra/num/bigint.rs | 2 +- src/librustdoc/markdown_index_pass.rs | 2 +- src/librustdoc/text_pass.rs | 2 +- src/librusti/rusti.rc | 2 +- src/libstd/str.rs | 200 ++++++++++++-------------- 5 files changed, 94 insertions(+), 114 deletions(-) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 1411079d52f0d..0294b595cfd93 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -524,7 +524,7 @@ impl ToStrRadix for BigUint { let s = uint::to_str_radix(*n as uint, radix); str::from_chars(vec::from_elem(l - s.len(), '0')) + s })); - str::trim_left_chars(s, ['0']).to_owned() + s.trim_left_chars(['0']).to_owned() } } } diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 87a73f5c9d3e0..36eb5e77ad651 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -152,7 +152,7 @@ pub fn pandoc_header_id(header: &str) -> ~str { // Collapse sequences of whitespace to a single dash // XXX: Hacky implementation here that only covers // one or two spaces. - let s = str::trim(s); + let s = s.trim(); let s = str::replace(s, " ", "-"); let s = str::replace(s, " ", "-"); return s; diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 96a67ea324356..1f7a71e0fd896 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -157,7 +157,7 @@ mod test { let doc = (attr_pass::mk_pass().f)(srv.clone(), doc); let doc = (desc_to_brief_pass::mk_pass().f)(srv.clone(), doc); let doc = (sectionalize_pass::mk_pass().f)(srv.clone(), doc); - (mk_pass(~"", |s| str::trim(s).to_owned() ).f)(srv.clone(), doc) + (mk_pass(~"", |s| s.trim().to_owned() ).f)(srv.clone(), doc) } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 6d4043bfc8999..17caaf6bf7d24 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -318,7 +318,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, match get_line(use_rl, "rusti| ") { None => fail!("unterminated multiline command :{ .. :}"), Some(line) => { - if str::trim(line) == ":}" { + if line.trim() == ":}" { end_multiline = true; } else { multiline_cmd += line + "\n"; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 5455edc25863c..605a11032a109 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -413,80 +413,6 @@ pub fn unshift_char(s: &mut ~str, ch: char) { *s = new_str; } -/** - * Returns a string with leading `chars_to_trim` removed. - * - * # Arguments - * - * * s - A string - * * chars_to_trim - A vector of chars - * - */ -pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { - if chars_to_trim.is_empty() { return s; } - - match s.find(|c| !chars_to_trim.contains(&c)) { - None => "", - Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) } - } -} - -/** - * Returns a string with trailing `chars_to_trim` removed. - * - * # Arguments - * - * * s - A string - * * chars_to_trim - A vector of chars - * - */ -pub fn trim_right_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { - if chars_to_trim.is_empty() { return s; } - - match s.rfind(|c| !chars_to_trim.contains(&c)) { - None => "", - Some(last) => { - let next = char_range_at(s, last).next; - unsafe { raw::slice_bytes(s, 0u, next) } - } - } -} - -/** - * Returns a string with leading and trailing `chars_to_trim` removed. - * - * # Arguments - * - * * s - A string - * * chars_to_trim - A vector of chars - * - */ -pub fn trim_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str { - trim_left_chars(trim_right_chars(s, chars_to_trim), chars_to_trim) -} - -/// Returns a string with leading whitespace removed -pub fn trim_left<'a>(s: &'a str) -> &'a str { - match s.find(|c| !char::is_whitespace(c)) { - None => "", - Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) } - } -} - -/// Returns a string with trailing whitespace removed -pub fn trim_right<'a>(s: &'a str) -> &'a str { - match s.rfind(|c| !char::is_whitespace(c)) { - None => "", - Some(last) => { - let next = char_range_at(s, last).next; - unsafe { raw::slice_bytes(s, 0u, next) } - } - } -} - -/// Returns a string with leading and trailing whitespace removed -pub fn trim<'a>(s: &'a str) -> &'a str { trim_left(trim_right(s)) } - /* Section: Transforming strings */ @@ -2024,25 +1950,79 @@ impl<'self> StrSlice<'self> for &'self str { /// Returns a string with leading and trailing whitespace removed #[inline] - fn trim(&self) -> &'self str { trim(*self) } + fn trim(&self) -> &'self str { + self.trim_left().trim_right() + } /// Returns a string with leading whitespace removed #[inline] - fn trim_left(&self) -> &'self str { trim_left(*self) } + fn trim_left(&self) -> &'self str { + match self.find(|c| !char::is_whitespace(c)) { + None => "", + Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) } + } + } /// Returns a string with trailing whitespace removed #[inline] - fn trim_right(&self) -> &'self str { trim_right(*self) } + fn trim_right(&self) -> &'self str { + match self.rfind(|c| !char::is_whitespace(c)) { + None => "", + Some(last) => { + let next = char_range_at(*self, last).next; + unsafe { raw::slice_bytes(*self, 0u, next) } + } + } + } + /** + * Returns a string with leading and trailing `chars_to_trim` removed. + * + * # Arguments + * + * * chars_to_trim - A vector of chars + * + */ #[inline] fn trim_chars(&self, chars_to_trim: &[char]) -> &'self str { - trim_chars(*self, chars_to_trim) + self.trim_left_chars(chars_to_trim).trim_right_chars(chars_to_trim) } + /** + * Returns a string with leading `chars_to_trim` removed. + * + * # Arguments + * + * * s - A string + * * chars_to_trim - A vector of chars + * + */ #[inline] fn trim_left_chars(&self, chars_to_trim: &[char]) -> &'self str { - trim_left_chars(*self, chars_to_trim) + if chars_to_trim.is_empty() { return *self; } + + match self.find(|c| !chars_to_trim.contains(&c)) { + None => "", + Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) } + } } + /** + * Returns a string with trailing `chars_to_trim` removed. + * + * # Arguments + * + * * s - A string + * * chars_to_trim - A vector of chars + * + */ #[inline] fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str { - trim_right_chars(*self, chars_to_trim) + if chars_to_trim.is_empty() { return *self; } + + match self.rfind(|c| !chars_to_trim.contains(&c)) { + None => "", + Some(last) => { + let next = char_range_at(self, last).next; + unsafe { raw::slice_bytes(self, 0u, next) } + } + } } @@ -2754,56 +2734,56 @@ mod tests { #[test] fn test_trim_left_chars() { - assert!(trim_left_chars(" *** foo *** ", []) == " *** foo *** "); - assert!(trim_left_chars(" *** foo *** ", ['*', ' ']) == "foo *** "); - assert_eq!(trim_left_chars(" *** *** ", ['*', ' ']), ""); - assert!(trim_left_chars("foo *** ", ['*', ' ']) == "foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars([]), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_left_chars(['*', ' ']), "foo *** "); + assert_eq!(" *** *** ".trim_left_chars(['*', ' ']), ""); + assert_eq!("foo *** ".trim_left_chars(['*', ' ']), "foo *** "); } #[test] fn test_trim_right_chars() { - assert!(trim_right_chars(" *** foo *** ", []) == " *** foo *** "); - assert!(trim_right_chars(" *** foo *** ", ['*', ' ']) == " *** foo"); - assert_eq!(trim_right_chars(" *** *** ", ['*', ' ']), ""); - assert!(trim_right_chars(" *** foo", ['*', ' ']) == " *** foo"); + assert_eq!(" *** foo *** ".trim_right_chars([]), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_right_chars(['*', ' ']), " *** foo"); + assert_eq!(" *** *** ".trim_right_chars(['*', ' ']), ""); + assert_eq!(" *** foo".trim_right_chars(['*', ' ']), " *** foo"); } #[test] fn test_trim_chars() { - assert_eq!(trim_chars(" *** foo *** ", []), " *** foo *** "); - assert_eq!(trim_chars(" *** foo *** ", ['*', ' ']), "foo"); - assert_eq!(trim_chars(" *** *** ", ['*', ' ']), ""); - assert_eq!(trim_chars("foo", ['*', ' ']), "foo"); + assert_eq!(" *** foo *** ".trim_chars([]), " *** foo *** "); + assert_eq!(" *** foo *** ".trim_chars(['*', ' ']), "foo"); + assert_eq!(" *** *** ".trim_chars(['*', ' ']), ""); + assert_eq!("foo".trim_chars(['*', ' ']), "foo"); } #[test] fn test_trim_left() { - assert_eq!(trim_left(""), ""); - assert_eq!(trim_left("a"), "a"); - assert_eq!(trim_left(" "), ""); - assert_eq!(trim_left(" blah"), "blah"); - assert_eq!(trim_left(" \u3000 wut"), "wut"); - assert_eq!(trim_left("hey "), "hey "); + assert_eq!("".trim_left(), ""); + assert_eq!("a".trim_left(), "a"); + assert_eq!(" ".trim_left(), ""); + assert_eq!(" blah".trim_left(), "blah"); + assert_eq!(" \u3000 wut".trim_left(), "wut"); + assert_eq!("hey ".trim_left(), "hey "); } #[test] fn test_trim_right() { - assert_eq!(trim_right(""), ""); - assert_eq!(trim_right("a"), "a"); - assert_eq!(trim_right(" "), ""); - assert_eq!(trim_right("blah "), "blah"); - assert_eq!(trim_right("wut \u3000 "), "wut"); - assert_eq!(trim_right(" hey"), " hey"); + assert_eq!("".trim_right(), ""); + assert_eq!("a".trim_right(), "a"); + assert_eq!(" ".trim_right(), ""); + assert_eq!("blah ".trim_right(), "blah"); + assert_eq!("wut \u3000 ".trim_right(), "wut"); + assert_eq!(" hey".trim_right(), " hey"); } #[test] fn test_trim() { - assert_eq!(trim(""), ""); - assert_eq!(trim("a"), "a"); - assert_eq!(trim(" "), ""); - assert_eq!(trim(" blah "), "blah"); - assert_eq!(trim("\nwut \u3000 "), "wut"); - assert_eq!(trim(" hey dude "), "hey dude"); + assert_eq!("".trim(), ""); + assert_eq!("a".trim(), "a"); + assert_eq!(" ".trim(), ""); + assert_eq!(" blah ".trim(), "blah"); + assert_eq!("\nwut \u3000 ".trim(), "wut"); + assert_eq!(" hey dude ".trim(), "hey dude"); } #[test] From ec5a028adac360537c8f37a669eda522bd8c9b6b Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 21:46:36 +1000 Subject: [PATCH 12/21] std: convert str::char_at* to methods. --- src/compiletest/runtest.rs | 6 +- src/libextra/getopts.rs | 8 +- src/libextra/rope.rs | 7 +- src/libextra/time.rs | 10 +- src/librustc/middle/lint.rs | 2 +- src/libstd/io.rs | 2 +- src/libstd/str.rs | 255 ++++++++++++++++---------------- src/libsyntax/parse/lexer.rs | 4 +- src/test/run-pass/utf8_chars.rs | 4 +- 9 files changed, 146 insertions(+), 152 deletions(-) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index d87101ffb8542..c9e44a7916034 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -429,7 +429,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut uint) -> bool { if *idx >= haystack.len() { return false; } - let range = str::char_range_at(haystack, *idx); + let range = haystack.char_range_at(*idx); if range.ch != needle { return false; } @@ -440,7 +440,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut uint) -> bool { fn scan_integer(haystack: &str, idx: &mut uint) -> bool { let mut i = *idx; while i < haystack.len() { - let range = str::char_range_at(haystack, i); + let range = haystack.char_range_at(i); if range.ch < '0' || '9' < range.ch { break; } @@ -460,7 +460,7 @@ fn scan_string(haystack: &str, needle: &str, idx: &mut uint) -> bool { if haystack_i >= haystack.len() { return false; } - let range = str::char_range_at(haystack, haystack_i); + let range = haystack.char_range_at(haystack_i); haystack_i = range.next; if !scan_char(needle, range.ch, &mut needle_i) { return false; diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 111de53052cd6..76e921f02f9e6 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -112,7 +112,7 @@ pub struct Opt { fn mkname(nm: &str) -> Name { if nm.len() == 1u { - Short(str::char_at(nm, 0u)) + Short(nm.char_at(0u)) } else { Long(nm.to_owned()) } @@ -261,7 +261,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { let mut last_valid_opt_id = None; names = ~[]; while j < curlen { - let range = str::char_range_at(cur, j); + let range = cur.char_range_at(j); let opt = Short(range.ch); /* In a series of potential options (eg. -aheJ), if we @@ -565,11 +565,11 @@ pub mod groups { hasarg: hasarg, occur: occur}], - (1,0) => ~[Opt {name: Short(str::char_at(short_name, 0)), + (1,0) => ~[Opt {name: Short(short_name.char_at(0)), hasarg: hasarg, occur: occur}], - (1,_) => ~[Opt {name: Short(str::char_at(short_name, 0)), + (1,_) => ~[Opt {name: Short(short_name.char_at(0)), hasarg: hasarg, occur: occur}, Opt {name: Long((long_name)), diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index de78e0a6eebda..80d80fa0ade3e 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -1132,7 +1132,7 @@ pub mod node { pub fn char_at(mut node: @Node, mut pos: uint) -> char { loop { match *node { - Leaf(x) => return str::char_at(*x.content, pos), + Leaf(x) => return x.content.char_at(pos), Concat(Concat {left, right, _}) => { let left_len = char_len(left); node = if left_len > pos { left } @@ -1257,8 +1257,7 @@ pub mod node { return None } else { let range = - str::char_range_at(*aleaf.content, - (*it).leaf_byte_pos + aleaf.byte_offset); + aleaf.content.char_range_at((*it).leaf_byte_pos + aleaf.byte_offset); let ch = range.ch; let next = range.next; (*it).leaf_byte_pos = next - aleaf.byte_offset; @@ -1345,7 +1344,7 @@ mod tests { equal = false; } break; } Some(c) => { - let range = str::char_range_at(*sample, string_iter); + let range = sample.char_range_at(string_iter); string_iter = range.next; if range.ch != c { equal = false; break; } } diff --git a/src/libextra/time.rs b/src/libextra/time.rs index fea5cb560acaf..caaa2994405e0 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -296,7 +296,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut i = 0u; while i < digits { - let range = str::char_range_at(ss, pos); + let range = ss.char_range_at(pos); pos = range.next; match range.ch { @@ -323,7 +323,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } fn parse_char(s: &str, pos: uint, c: char) -> Result { - let range = str::char_range_at(s, pos); + let range = s.char_range_at(pos); if c == range.ch { Ok(range.next) @@ -600,7 +600,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut pos = pos; let len = s.len(); while pos < len { - let range = str::char_range_at(s, pos); + let range = s.char_range_at(pos); pos = range.next; if range.ch == ' ' { break; } } @@ -609,7 +609,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } } 'z' => { - let range = str::char_range_at(s, pos); + let range = s.char_range_at(pos); if range.ch == '+' || range.ch == '-' { match match_digits(s, range.next, 4u, false) { @@ -655,7 +655,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut result = Err(~"Invalid time"); while !rdr.eof() && pos < len { - let range = str::char_range_at(s, pos); + let range = s.char_range_at(pos); let ch = range.ch; let next = range.next; diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 7462067162dc7..92147bf4e0f72 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -842,7 +842,7 @@ fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) { let ident = cx.sess.str_of(ident); assert!(!ident.is_empty()); let ident = ident.trim_chars(&['_']); - char::is_uppercase(str::char_at(ident, 0)) && + char::is_uppercase(ident.char_at(0)) && !ident.contains_char('_') } diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 8ec3a4cdd8115..7f3af79e27c76 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -672,7 +672,7 @@ impl ReaderUtil for T { val <<= 6; val += (next & 63) as uint; } - // See str::char_at + // See str::StrSlice::char_at val += ((b0 << ((w + 1) as u8)) as uint) << (w - 1) * 6 - w - 1u; chars.push(val as char); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 605a11032a109..25d9a63b479ec 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -370,7 +370,7 @@ Section: Adding to and removing from a string pub fn pop_char(s: &mut ~str) -> char { let end = s.len(); assert!(end > 0u); - let CharRange {ch, next} = char_range_at_reverse(*s, end); + let CharRange {ch, next} = s.char_range_at_reverse(end); unsafe { raw::set_len(s, next); } return ch; } @@ -383,7 +383,7 @@ pub fn pop_char(s: &mut ~str) -> char { * If the string does not contain any characters */ pub fn shift_char(s: &mut ~str) -> char { - let CharRange {ch, next} = char_range_at(*s, 0u); + let CharRange {ch, next} = s.char_range_at(0u); *s = unsafe { raw::slice_bytes_owned(*s, next, s.len()) }; return ch; } @@ -399,7 +399,7 @@ pub fn shift_char(s: &mut ~str) -> char { */ #[inline] pub fn slice_shift_char<'a>(s: &'a str) -> (char, &'a str) { - let CharRange {ch, next} = char_range_at(s, 0u); + let CharRange {ch, next} = s.char_range_at(0u); let next_s = unsafe { raw::slice_bytes(s, next, s.len()) }; return (ch, next_s); } @@ -532,7 +532,7 @@ impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Se } } else { while self.position < l && self.count > 0 { - let CharRange {ch, next} = char_range_at(self.string, self.position); + let CharRange {ch, next} = self.string.char_range_at(self.position); if self.sep.matches(ch) { let slice = unsafe { raw::slice_bytes(self.string, start, self.position) }; @@ -1198,7 +1198,7 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { assert!(is_char_boundary(s, end)); let mut (i, len) = (start, 0u); while i < end { - let next = char_range_at(s, i).next; + let next = s.char_range_at(i).next; len += 1u; i = next; } @@ -1213,7 +1213,7 @@ pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { let l = s.len(); while cnt > 0u { assert!(end < l); - let next = char_range_at(s, end).next; + let next = s.char_range_at(end).next; cnt -= 1u; end = next; } @@ -1233,130 +1233,12 @@ pub fn utf8_char_width(b: u8) -> uint { return 6u; } -/** - * Returns false if the index points into the middle of a multi-byte - * character sequence. - */ -pub fn is_char_boundary(s: &str, index: uint) -> bool { - if index == s.len() { return true; } - let b = s[index]; - return b < 128u8 || b >= 192u8; -} - -/** - * Pluck a character out of a string and return the index of the next - * character. - * - * This function can be used to iterate over the unicode characters of a - * string. - * - * # Example - * - * ~~~ {.rust} - * let s = "中华Việt Nam"; - * let i = 0u; - * while i < s.len() { - * let CharRange {ch, next} = str::char_range_at(s, i); - * std::io::println(fmt!("%u: %c",i,ch)); - * i = next; - * } - * ~~~ - * - * # Example output - * - * ~~~ - * 0: 中 - * 3: 华 - * 6: V - * 7: i - * 8: ệ - * 11: t - * 12: - * 13: N - * 14: a - * 15: m - * ~~~ - * - * # Arguments - * - * * s - The string - * * i - The byte offset of the char to extract - * - * # Return value - * - * A record {ch: char, next: uint} containing the char value and the byte - * index of the next unicode character. - * - * # Failure - * - * If `i` is greater than or equal to the length of the string. - * If `i` is not the index of the beginning of a valid UTF-8 character. - */ -pub fn char_range_at(s: &str, i: uint) -> CharRange { - let b0 = s[i]; - let w = utf8_char_width(b0); - assert!((w != 0u)); - if w == 1u { return CharRange {ch: b0 as char, next: i + 1u}; } - let mut val = 0u; - let end = i + w; - let mut i = i + 1u; - while i < end { - let byte = s[i]; - assert_eq!(byte & 192u8, tag_cont_u8); - val <<= 6u; - val += (byte & 63u8) as uint; - i += 1u; - } - // Clunky way to get the right bits from the first byte. Uses two shifts, - // the first to clip off the marker bits at the left of the byte, and then - // a second (as uint) to get it to the right position. - val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u); - return CharRange {ch: val as char, next: i}; -} - -/// Plucks the character starting at the `i`th byte of a string -pub fn char_at(s: &str, i: uint) -> char { - return char_range_at(s, i).ch; -} - #[allow(missing_doc)] pub struct CharRange { ch: char, next: uint } -/** - * Given a byte position and a str, return the previous char and its position. - * - * This function can be used to iterate over a unicode string in reverse. - * - * Returns 0 for next index if called on start index 0. - */ -pub fn char_range_at_reverse(ss: &str, start: uint) -> CharRange { - let mut prev = start; - - // while there is a previous byte == 10...... - while prev > 0u && ss[prev - 1u] & 192u8 == tag_cont_u8 { - prev -= 1u; - } - - // now refer to the initial byte of previous char - if prev > 0u { - prev -= 1u; - } else { - prev = 0u; - } - - - let ch = char_at(ss, prev); - return CharRange {ch:ch, next:prev}; -} - -/// Plucks the character ending at the `i`th byte of a string -pub fn char_at_reverse(s: &str, i: uint) -> char { - char_range_at_reverse(s, i).ch -} - // UTF-8 tags and ranges static tag_cont_u8: u8 = 128u8; static tag_cont: uint = 128u; @@ -1776,7 +1658,10 @@ pub trait StrSlice<'self> { fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str; fn to_owned(&self) -> ~str; fn to_managed(&self) -> @str; + fn is_char_boundary(s: &str, index: uint) -> bool; + fn char_range_at(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; + fn char_range_at_reverse(&self, start: uint) -> CharRange; fn char_at_reverse(&self, i: uint) -> char; fn to_bytes(&self) -> ~[u8]; @@ -1967,7 +1852,7 @@ impl<'self> StrSlice<'self> for &'self str { match self.rfind(|c| !char::is_whitespace(c)) { None => "", Some(last) => { - let next = char_range_at(*self, last).next; + let next = self.char_range_at(last).next; unsafe { raw::slice_bytes(*self, 0u, next) } } } @@ -2019,8 +1904,8 @@ impl<'self> StrSlice<'self> for &'self str { match self.rfind(|c| !chars_to_trim.contains(&c)) { None => "", Some(last) => { - let next = char_range_at(self, last).next; - unsafe { raw::slice_bytes(self, 0u, next) } + let next = self.char_range_at(last).next; + unsafe { raw::slice_bytes(*self, 0u, next) } } } } @@ -2037,12 +1922,122 @@ impl<'self> StrSlice<'self> for &'self str { unsafe { ::cast::transmute(v) } } + /** + * Returns false if the index points into the middle of a multi-byte + * character sequence. + */ + fn is_char_boundary(&self, index: uint) -> bool { + if index == self.len() { return true; } + let b = self[index]; + return b < 128u8 || b >= 192u8; + } + + /** + * Pluck a character out of a string and return the index of the next + * character. + * + * This function can be used to iterate over the unicode characters of a + * string. + * + * # Example + * + * ~~~ {.rust} + * let s = "中华Việt Nam"; + * let i = 0u; + * while i < s.len() { + * let CharRange {ch, next} = s.char_range_at(i); + * std::io::println(fmt!("%u: %c",i,ch)); + * i = next; + * } + * ~~~ + * + * # Example output + * + * ~~~ + * 0: 中 + * 3: 华 + * 6: V + * 7: i + * 8: ệ + * 11: t + * 12: + * 13: N + * 14: a + * 15: m + * ~~~ + * + * # Arguments + * + * * s - The string + * * i - The byte offset of the char to extract + * + * # Return value + * + * A record {ch: char, next: uint} containing the char value and the byte + * index of the next unicode character. + * + * # Failure + * + * If `i` is greater than or equal to the length of the string. + * If `i` is not the index of the beginning of a valid UTF-8 character. + */ + fn char_range_at(&self, i: uint) -> CharRange { + let b0 = self[i]; + let w = utf8_char_width(b0); + assert!((w != 0u)); + if w == 1u { return CharRange {ch: b0 as char, next: i + 1u}; } + let mut val = 0u; + let end = i + w; + let mut i = i + 1u; + while i < end { + let byte = self[i]; + assert_eq!(byte & 192u8, tag_cont_u8); + val <<= 6u; + val += (byte & 63u8) as uint; + i += 1u; + } + // Clunky way to get the right bits from the first byte. Uses two shifts, + // the first to clip off the marker bits at the left of the byte, and then + // a second (as uint) to get it to the right position. + val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u); + return CharRange {ch: val as char, next: i}; + } + + /// Plucks the character starting at the `i`th byte of a string #[inline] - fn char_at(&self, i: uint) -> char { char_at(*self, i) } + fn char_at(&self, i: uint) -> char { self.char_range_at(i).ch } + + /** + * Given a byte position and a str, return the previous char and its position. + * + * This function can be used to iterate over a unicode string in reverse. + * + * Returns 0 for next index if called on start index 0. + */ + fn char_range_at_reverse(&self, start: uint) -> CharRange { + let mut prev = start; + + // while there is a previous byte == 10...... + while prev > 0u && self[prev - 1u] & 192u8 == tag_cont_u8 { + prev -= 1u; + } + + // now refer to the initial byte of previous char + if prev > 0u { + prev -= 1u; + } else { + prev = 0u; + } + + + let ch = self.char_at(prev); + return CharRange {ch:ch, next:prev}; + } + /// Plucks the character ending at the `i`th byte of a string #[inline] fn char_at_reverse(&self, i: uint) -> char { - char_at_reverse(*self, i) + self.char_range_at_reverse(i).ch } fn to_bytes(&self) -> ~[u8] { to_bytes(*self) } @@ -3182,7 +3177,7 @@ mod tests { #[test] fn test_char_range_at_reverse_underflow() { - assert_eq!(char_range_at_reverse("abc", 0).next, 0); + assert_eq!("abc".char_range_at_reverse(0).next, 0); } #[test] diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 809a222352fb8..5f9bc4ca6f610 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -180,7 +180,7 @@ pub fn bump(rdr: &mut StringReader) { if current_byte_offset < (*rdr.src).len() { assert!(rdr.curr != -1 as char); let last_char = rdr.curr; - let next = str::char_range_at(*rdr.src, current_byte_offset); + let next = rdr.src.char_range_at(current_byte_offset); let byte_offset_diff = next.next - current_byte_offset; rdr.pos = rdr.pos + BytePos(byte_offset_diff); rdr.curr = next.ch; @@ -204,7 +204,7 @@ pub fn is_eof(rdr: @mut StringReader) -> bool { pub fn nextch(rdr: @mut StringReader) -> char { let offset = byte_offset(rdr, rdr.pos).to_uint(); if offset < (*rdr.src).len() { - return str::char_at(*rdr.src, offset); + return rdr.src.char_at(offset); } else { return -1 as char; } } diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 94990d649d82f..b7ce617fe5044 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -22,8 +22,8 @@ pub fn main() { assert!(str::char_len(s) == 4u); assert!(str::to_chars(s).len() == 4u); assert!(str::from_chars(str::to_chars(s)) == s); - assert!(str::char_at(s, 0u) == 'e'); - assert!(str::char_at(s, 1u) == 'é'); + assert!(s.char_at(0u) == 'e'); + assert!(s.char_at(1u) == 'é'); assert!((str::is_utf8(str::to_bytes(s)))); assert!((!str::is_utf8(~[0x80_u8]))); From ead4468249f57ca530cddf347f15c1f348c1c325 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 23:01:45 +1000 Subject: [PATCH 13/21] std: fix tests --- src/libstd/str.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 25d9a63b479ec..98ac71bc018dd 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1194,8 +1194,8 @@ pub fn with_capacity(capacity: uint) -> ~str { * The number of Unicode characters in `s` between the given indices. */ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { - assert!(is_char_boundary(s, start)); - assert!(is_char_boundary(s, end)); + assert!(s.is_char_boundary(start)); + assert!(s.is_char_boundary(end)); let mut (i, len) = (start, 0u); while i < end { let next = s.char_range_at(i).next; @@ -1208,7 +1208,7 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { /// Counts the number of bytes taken by the first `n` chars in `s` /// starting from `start`. pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { - assert!(is_char_boundary(s, start)); + assert!(s.is_char_boundary(start)); let mut (end, cnt) = (start, n); let l = s.len(); while cnt > 0u { @@ -1658,7 +1658,7 @@ pub trait StrSlice<'self> { fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str; fn to_owned(&self) -> ~str; fn to_managed(&self) -> @str; - fn is_char_boundary(s: &str, index: uint) -> bool; + fn is_char_boundary(&self, index: uint) -> bool; fn char_range_at(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; fn char_range_at_reverse(&self, start: uint) -> CharRange; @@ -1800,8 +1800,8 @@ impl<'self> StrSlice<'self> for &'self str { */ #[inline] fn slice(&self, begin: uint, end: uint) -> &'self str { - assert!(is_char_boundary(*self, begin)); - assert!(is_char_boundary(*self, end)); + assert!(self.is_char_boundary(begin)); + assert!(self.is_char_boundary(end)); unsafe { raw::slice_bytes(*self, begin, end) } } #[inline] @@ -2284,7 +2284,7 @@ impl<'self> Iterator for StrCharIterator<'self> { #[inline] fn next(&mut self) -> Option { if self.index < self.string.len() { - let CharRange {ch, next} = char_range_at(self.string, self.index); + let CharRange {ch, next} = self.string.char_range_at(self.index); self.index = next; Some(ch) } else { @@ -2303,7 +2303,7 @@ 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); + let CharRange {ch, next} = self.string.char_range_at_reverse(self.index); self.index = next; Some(ch) } else { @@ -2461,7 +2461,7 @@ mod tests { let data = "abcabc"; assert_eq!(data.slice(0u, 6u).find_str("ab"), Some(0u)); - assert_eq!(data.slice(2u, 6u).find_str("ab"), Some(3u)); + assert_eq!(data.slice(2u, 6u).find_str("ab"), Some(3u - 2u)); assert!(data.slice(2u, 4u).find_str("ab").is_none()); let mut data = ~"ประเทศไทย中华Việt Nam"; @@ -3042,10 +3042,10 @@ mod tests { #[test] fn test_contains_char() { - assert!(contains_char("abc", 'b')); - assert!(contains_char("a", 'a')); - assert!(!contains_char("abc", 'd')); - assert!(!contains_char("", 'a')); + assert!("abc".contains_char('b')); + assert!("a".contains_char('a')); + assert!(!"abc".contains_char('d')); + assert!(!"".contains_char('a')); } #[test] From 5a711ea7c317ea90f03d5118dbb2e19e1622bc29 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 23:15:01 +1000 Subject: [PATCH 14/21] clean-up unused import warnings --- src/libextra/arc.rs | 1 - src/libextra/rope.rs | 1 - src/librustc/middle/astencode.rs | 1 - src/librustc/middle/borrowck/mod.rs | 1 - src/librustc/middle/dataflow.rs | 1 - src/librustc/middle/freevars.rs | 1 - src/librustc/middle/trans/common.rs | 1 - src/libstd/str.rs | 1 - src/libsyntax/parse/lexer.rs | 3 +-- src/libsyntax/print/pprust.rs | 1 - 10 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index a59f59deee3c6..1b6b656e398a4 100644 --- a/src/libextra/arc.rs +++ b/src/libextra/arc.rs @@ -46,7 +46,6 @@ use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars}; use core::cast; use core::unstable::sync::UnsafeAtomicRcBox; -use core::ptr; use core::task; use core::borrow; diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 80d80fa0ade3e..24cbf1b3f4aa8 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -38,7 +38,6 @@ use core::prelude::*; use core::iterator::IteratorUtil; -use core::str; use core::uint; use core::vec; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 18946ee2d790e..79f5b7984b6a4 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -26,7 +26,6 @@ use middle; use util::ppaux::ty_to_str; use core::at_vec; -use core::str; use core::uint; use extra::ebml::reader; use extra::ebml; diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index b0b9c9f7efb62..da3c5e43606fe 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -25,7 +25,6 @@ use core::hashmap::{HashSet, HashMap}; use core::io; use core::ops::{BitOr, BitAnd}; use core::result::{Result}; -use core::str; use syntax::ast; use syntax::ast_map; use syntax::visit; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index e2d88e3c76812..c528bad0b070b 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -21,7 +21,6 @@ use core::prelude::*; use core::iterator::IteratorUtil; use core::cast; use core::io; -use core::str; use core::uint; use core::vec; use syntax::ast; diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index abce35bebffb4..2907e53cd4c2f 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -17,7 +17,6 @@ use middle::resolve; use middle::ty; use core::hashmap::HashMap; -use core::vec; use syntax::codemap::span; use syntax::{ast, ast_util, visit}; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 03ae32cf0a6cb..a3491114bd32d 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -44,7 +44,6 @@ use core::cast; use core::hash; use core::hashmap::{HashMap, HashSet}; use core::libc::{c_uint, c_longlong, c_ulonglong}; -use core::ptr; use core::str; use core::to_bytes; use core::vec::raw::to_ptr; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 98ac71bc018dd..4766504813dee 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -32,7 +32,6 @@ use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; use ptr; use ptr::RawPtr; -use str; use to_str::ToStr; use uint; use vec; diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 5f9bc4ca6f610..002a6caf85c5f 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -22,7 +22,6 @@ use parse::token::{str_to_ident}; use core::iterator::IteratorUtil; use core::char; use core::either; -use core::str; use core::u64; pub use ext::tt::transcribe::{TtReader, new_tt_reader}; @@ -548,7 +547,7 @@ fn ident_continue(c: char) -> bool { // EFFECT: advances the input past that token // EFFECT: updates the interner fn next_token_inner(rdr: @mut StringReader) -> token::Token { - let mut c = rdr.curr; + let c = rdr.curr; if ident_start(c) { let start = rdr.last_pos; while ident_continue(rdr.curr) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 10fd46ea4b628..2157fec835eaf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -34,7 +34,6 @@ use core::io; use core::str; use core::u64; use core::uint; -use core::vec; // The @ps is stored here to prevent recursive type. pub enum ann_node<'self> { From ccd0ac59e9a918f3c2a174e31213286dc6867d37 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 23:25:25 +1000 Subject: [PATCH 15/21] std: remove str::{connect,concat}*. --- src/compiletest/runtest.rs | 6 +++--- src/libextra/getopts.rs | 4 ++-- src/libextra/net_url.rs | 2 +- src/libextra/num/bigint.rs | 4 ++-- src/libextra/semver.rs | 4 ++-- src/librustc/back/link.rs | 6 +++--- src/librustc/driver/driver.rs | 4 ++-- src/librustc/middle/trans/asm.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/build.rs | 2 +- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/infer/test.rs | 2 +- src/librustc/middle/typeck/infer/to_str.rs | 2 +- src/librustc/util/common.rs | 2 +- src/librustc/util/ppaux.rs | 14 +++++++------- src/librustdoc/attr_parser.rs | 2 +- src/librustdoc/markdown_pass.rs | 6 +++--- src/librustdoc/markdown_writer.rs | 4 ++-- src/librustdoc/unindent_pass.rs | 2 +- src/librusti/rusti.rc | 2 +- src/librustpkg/util.rs | 4 ++-- src/libstd/path.rs | 6 +++--- src/libstd/str.rs | 17 ----------------- src/libsyntax/abi.rs | 3 +-- src/libsyntax/ast_map.rs | 2 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/ext/asm.rs | 2 +- src/libsyntax/ext/pipes/liveness.rs | 2 +- src/libsyntax/ext/pipes/pipec.rs | 10 ++++------ src/libsyntax/ext/quote.rs | 4 ++-- src/libsyntax/ext/source_util.rs | 4 +--- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/parse/comments.rs | 2 +- src/libsyntax/parse/parser.rs | 4 +--- src/test/run-pass/issue-3563-3.rs | 2 +- src/test/run-pass/issue-4241.rs | 4 ++-- src/test/run-pass/trait-to-str.rs | 2 +- 38 files changed, 62 insertions(+), 86 deletions(-) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index c9e44a7916034..16190f69549cd 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -244,7 +244,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { None => copy *config }; let config = &mut config; - let cmds = str::connect(props.debugger_cmds, "\n"); + let cmds = props.debugger_cmds.connect("\n"); let check_lines = copy props.check_lines; // compile test file (it shoud have 'compile-flags:-g' in the header) @@ -645,13 +645,13 @@ fn program_output(config: &config, testfile: &Path, lib_path: &str, prog: ~str, #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn make_cmdline(_libpath: &str, prog: &str, args: &[~str]) -> ~str { - fmt!("%s %s", prog, str::connect(args, " ")) + fmt!("%s %s", prog, args.connect(" ")) } #[cfg(target_os = "win32")] fn make_cmdline(libpath: &str, prog: &str, args: &[~str]) -> ~str { fmt!("%s %s %s", lib_path_cmd_prefix(libpath), prog, - str::connect(args, " ")) + args.connect(" ")) } // Build the LD_LIBRARY_PATH variable as it would be seen on the command line diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 76e921f02f9e6..44b5659008355 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -648,14 +648,14 @@ pub mod groups { // FIXME: #5516 // wrapped description - row += str::connect(desc_rows, desc_sep); + row += desc_rows.connect(desc_sep); row }); return str::to_owned(brief) + "\n\nOptions:\n" + - str::connect(rows, "\n") + + rows.connect("\n") + "\n\n"; } } // end groups module diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 30d55721efb76..46e76a7a39913 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -354,7 +354,7 @@ pub fn query_to_str(query: &Query) -> ~str { } } } - return str::connect(strvec, "&"); + return strvec.connect("&"); } // returns the scheme and the rest of the url, or a parsing error diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 0294b595cfd93..c6e7592a314e1 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -520,10 +520,10 @@ impl ToStrRadix for BigUint { fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str { if v.is_empty() { return ~"0" } - let s = str::concat(vec::reversed(v).map(|n| { + let s = vec::reversed(v).map(|n| { let s = uint::to_str_radix(*n as uint, radix); str::from_chars(vec::from_elem(l - s.len(), '0')) + s - })); + }).concat(); s.trim_left_chars(['0']).to_owned() } } diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs index dad080752388e..c7d2010e609da 100644 --- a/src/libextra/semver.rs +++ b/src/libextra/semver.rs @@ -81,12 +81,12 @@ impl ToStr for Version { let s = if self.pre.is_empty() { s } else { - s + "-" + str::connect(self.pre.map(|i| i.to_str()), ".") + s + "-" + self.pre.map(|i| i.to_str()).connect(".") }; if self.build.is_empty() { s } else { - s + "+" + str::connect(self.build.map(|i| i.to_str()), ".") + s + "+" + self.build.map(|i| i.to_str()).connect(".") } } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index fa9e2c9a72413..496c1f88a6c8a 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -394,7 +394,7 @@ pub mod write { sess.err(fmt!("building with `%s` failed with code %d", cc_prog, prog.status)); sess.note(fmt!("%s arguments: %s", - cc_prog, str::connect(cc_args, " "))); + cc_prog, cc_args.connect(" "))); sess.note(str::from_bytes(prog.error + prog.output)); sess.abort_if_errors(); } @@ -809,14 +809,14 @@ pub fn link_binary(sess: Session, debug!("output: %s", output.to_str()); let cc_args = link_args(sess, obj_filename, out_filename, lm); - debug!("%s link args: %s", cc_prog, str::connect(cc_args, " ")); + debug!("%s link args: %s", cc_prog, cc_args.connect(" ")); // We run 'cc' here let prog = run::process_output(cc_prog, cc_args); if 0 != prog.status { sess.err(fmt!("linking with `%s` failed with code %d", cc_prog, prog.status)); sess.note(fmt!("%s arguments: %s", - cc_prog, str::connect(cc_args, " "))); + cc_prog, cc_args.connect(" "))); sess.note(str::from_bytes(prog.error + prog.output)); sess.abort_if_errors(); } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 5af47880c3043..ef5670da45587 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -328,8 +328,8 @@ pub fn compile_rest(sess: Session, let outputs = outputs.get_ref(); if (sess.opts.debugging_opts & session::print_link_args) != 0 { - io::println(str::connect(link::link_args(sess, - &outputs.obj_filename, &outputs.out_filename, link_meta), " ")); + io::println(link::link_args(sess, &outputs.obj_filename, + &outputs.out_filename, link_meta).connect(" ")); } // NB: Android hack diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index ac92ea7596399..833146a935e8f 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -87,7 +87,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block { revoke_clean(bcx, *c); } - let mut constraints = str::connect(constraints, ","); + let mut constraints = constraints.connect(","); let mut clobbers = getClobbers(); if *ia.clobbers != ~"" && clobbers != ~"" { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f368255030bd2..b913a1b499617 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1995,7 +1995,7 @@ pub fn trans_enum_variant(ccx: @CrateContext, debug!("trans_enum_variant: name=%s tps=%s repr=%? enum_ty=%s", unsafe { str::raw::from_c_str(llvm::LLVMGetValueName(llfndecl)) }, - ~"[" + str::connect(ty_param_substs.map(|&t| ty_to_str(ccx.tcx, t)), ", ") + "]", + ~"[" + ty_param_substs.map(|&t| ty_to_str(ccx.tcx.connect(t)), ", ") + "]", repr, ty_to_str(ccx.tcx, enum_ty)); adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 3b26a2cbf2246..8406444bd097e 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -192,7 +192,7 @@ pub fn Invoke(cx: block, terminate(cx, "Invoke"); debug!("Invoke(%s with arguments (%s))", val_str(cx.ccx().tn, Fn), - str::connect(vec::map(Args, |a| val_str(cx.ccx().tn, + vec::map(Args.connect(|a| val_str(cx.ccx().tn, *a).to_owned()), ", ")); unsafe { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index a3491114bd32d..b29972f039b19 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -1483,7 +1483,7 @@ pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] { if !params.all(|t| !ty::type_needs_infer(*t)) { bcx.sess().bug( fmt!("Type parameters for node %d include inference types: %s", - id, str::connect(params.map(|t| bcx.ty_to_str(*t)), ","))); + id, params.map(|t| bcx.ty_to_str(*t)).connect(","))); } match bcx.fcx.param_substs { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 9eb5f8159545e..30dd677396b17 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1879,7 +1879,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } else { "s" }, - str::connect(missing_fields, ", "))); + missing_fields.connect(", "))); } } diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index e6e6753255e74..0db9d16adf3c0 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -100,7 +100,7 @@ impl Env { return match search_mod(self, &self.crate.node.module, 0, names) { Some(id) => id, None => { - fail!("No item found: `%s`", str::connect(names, "::")); + fail!("No item found: `%s`", names.connect("::")); } }; diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index ef3b837e98a16..d6623f06c3d33 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -35,7 +35,7 @@ impl InferStr for ty::t { impl InferStr for FnSig { fn inf_str(&self, cx: &InferCtxt) -> ~str { fmt!("(%s) -> %s", - str::connect(self.inputs.map(|a| a.inf_str(cx)), ", "), + self.inputs.map(|a| a.inf_str(cx)).connect(", "), self.output.inf_str(cx)) } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index a44c409aa33b5..8d0cba0e8b712 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -111,7 +111,7 @@ pub fn local_rhs_span(l: @ast::local, def: span) -> span { pub fn pluralize(n: uint, s: ~str) -> ~str { if n == 1 { s } - else { str::concat([s, ~"s"]) } + else { fmt!("%ss", s) } } // A set of node IDs (used to keep track of which node IDs are for statements) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c72bf5c7f0b21..b5e6e7e119488 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -281,7 +281,7 @@ pub fn vstore_ty_to_str(cx: ctxt, mt: &mt, vs: ty::vstore) -> ~str { pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str { let tstrs = ts.map(|t| ty_to_str(cx, *t)); - fmt!("(%s)", str::connect(tstrs, ", ")) + fmt!("(%s)", tstrs.connect(", ")) } pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str { @@ -369,7 +369,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) { s.push_char('('); let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a)); - s.push_str(str::connect(strs, ", ")); + s.push_str(strs.connect(", ")); s.push_char(')'); if ty::get(sig.output).sty != ty_nil { s.push_str(" -> "); @@ -420,7 +420,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_type => ~"type", ty_tup(ref elems) => { let strs = elems.map(|elem| ty_to_str(cx, *elem)); - ~"(" + str::connect(strs, ",") + ")" + ~"(" + strs.connect(",") + ")" } ty_closure(ref f) => { closure_to_str(cx, f) @@ -477,7 +477,7 @@ pub fn parameterized(cx: ctxt, if tps.len() > 0u { let strs = vec::map(tps, |t| ty_to_str(cx, *t)); - fmt!("%s%s<%s>", base, r_str, str::connect(strs, ",")) + fmt!("%s%s<%s>", base, r_str, strs.connect(",")) } else { fmt!("%s%s", base, r_str) } @@ -515,7 +515,7 @@ impl Repr for ~T { */ fn repr_vec(tcx: ctxt, v: &[T]) -> ~str { - fmt!("[%s]", str::connect(v.map(|t| t.repr(tcx)), ",")) + fmt!("[%s]", v.map(|t| t.repr(tcx)).connect(",")) } impl<'self, T:Repr> Repr for &'self [T] { @@ -569,7 +569,7 @@ impl Repr for ty::ParamBounds { for self.trait_bounds.each |t| { res.push(t.repr(tcx)); } - str::connect(res, "+") + res.connect("+") } } @@ -787,7 +787,7 @@ impl UserString for ty::BuiltinBounds { for self.each |bb| { result.push(bb.user_string(tcx)); } - str::connect(result, "+") + result.connect("+") } } } diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs index d2d9ec7d79bd8..47c54ee8e8f45 100644 --- a/src/librustdoc/attr_parser.rs +++ b/src/librustdoc/attr_parser.rs @@ -53,7 +53,7 @@ pub fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> { if doc_strs.is_empty() { None } else { - Some(str::connect(doc_strs, "\n")) + Some(doc_strs.connect("\n")) } } diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 976344a1825cb..b6917f527a1ff 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -173,7 +173,7 @@ pub fn header_kind(doc: doc::ItemTag) -> ~str { } pub fn header_name(doc: doc::ItemTag) -> ~str { - let fullpath = str::connect(doc.path() + [doc.name()], "::"); + let fullpath = (doc.path() + [doc.name()]).connect("::"); match &doc { &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => { fullpath @@ -414,7 +414,7 @@ fn code_block_indent(s: ~str) -> ~str { for str::each_line_any(s) |line| { indented.push(fmt!(" %s", line)); } - str::connect(indented, "\n") + indented.connect("\n") } fn write_const( @@ -476,7 +476,7 @@ fn list_item_indent(item: &str) -> ~str { // separate markdown elements within `*` lists must be indented by four // spaces, or they will escape the list context. indenting everything // seems fine though. - str::connect_slices(indented, "\n ") + indented.connect("\n ") } fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) { diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index 7bcfa1acdfad2..353152763267c 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -107,7 +107,7 @@ fn pandoc_writer( use core::io::WriterUtil; debug!("pandoc cmd: %s", pandoc_cmd); - debug!("pandoc args: %s", str::connect(pandoc_args, " ")); + debug!("pandoc args: %s", pandoc_args.connect(" ")); let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new()); @@ -164,7 +164,7 @@ pub fn make_filename( } } doc::ItemPage(doc) => { - str::connect(doc.path() + [doc.name()], "_") + (doc.path() + [doc.name()]).connect("_") } } }; diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index ba6f7184f6895..23a4b9c7ba4b7 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -87,7 +87,7 @@ fn unindent(s: &str) -> ~str { line.slice(min_indent, line.len()).to_owned() } }; - str::connect(unindented, "\n") + unindented.connect("\n") } else { s.to_str() } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 17caaf6bf7d24..9cb98dd8c2d83 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -308,7 +308,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, println("no crates loaded"); } else { println(fmt!("crates loaded: %s", - str::connect(loaded_crates, ", "))); + loaded_crates.connect(", "))); } } ~"{" => { diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 10d2d139a145b..75e2c3fd46454 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -207,8 +207,8 @@ pub fn compile_input(ctxt: &Ctx, let binary = @(copy os::args()[0]); - debug!("flags: %s", str::connect(flags, " ")); - debug!("cfgs: %s", str::connect(cfgs, " ")); + debug!("flags: %s", flags.connect(" ")); + debug!("cfgs: %s", cfgs.connect(" ")); debug!("compile_input's sysroot = %?", ctxt.sysroot_opt); let crate_type = match what { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 4df07830b2386..d62fc8c2cbafd 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -22,7 +22,7 @@ use iterator::IteratorUtil; use libc; use option::{None, Option, Some}; use str; -use str::StrSlice; +use str::{StrSlice, StrVector}; use to_str::ToStr; use ascii::{AsciiCast, AsciiStr}; use old_iter::BaseIter; @@ -442,7 +442,7 @@ impl ToStr for PosixPath { if self.is_absolute { s += "/"; } - s + str::connect(self.components, "/") + s + self.components.connect("/") } } @@ -629,7 +629,7 @@ impl ToStr for WindowsPath { if self.is_absolute { s += "\\"; } - s + str::connect(self.components, "\\") + s + self.components.connect("\\") } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 4766504813dee..c820f64549010 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -170,18 +170,6 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str { v } -/// Concatenate a vector of strings -pub fn concat(v: &[~str]) -> ~str { v.concat() } - -/// Concatenate a vector of strings -pub fn concat_slices(v: &[&str]) -> ~str { v.concat() } - -/// Concatenate a vector of strings, placing a given separator between each -pub fn connect(v: &[~str], sep: &str) -> ~str { v.connect(sep) } - -/// Concatenate a vector of strings, placing a given separator between each -pub fn connect_slices(v: &[&str], sep: &str) -> ~str { v.connect(sep) } - #[allow(missing_doc)] pub trait StrVector { pub fn concat(&self) -> ~str; @@ -2495,7 +2483,6 @@ mod tests { #[test] fn test_concat() { fn t(v: &[~str], s: &str) { - assert_eq!(concat(v), s.to_str()); assert_eq!(v.concat(), s.to_str()); } t([~"you", ~"know", ~"I'm", ~"no", ~"good"], "youknowI'mnogood"); @@ -2507,7 +2494,6 @@ mod tests { #[test] fn test_connect() { fn t(v: &[~str], sep: &str, s: &str) { - assert_eq!(connect(v, sep), s.to_str()); assert_eq!(v.connect(sep), s.to_str()); } t([~"you", ~"know", ~"I'm", ~"no", ~"good"], @@ -2520,7 +2506,6 @@ mod tests { #[test] fn test_concat_slices() { fn t(v: &[&str], s: &str) { - assert_eq!(concat_slices(v), s.to_str()); assert_eq!(v.concat(), s.to_str()); } t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood"); @@ -2532,7 +2517,6 @@ mod tests { #[test] fn test_connect_slices() { fn t(v: &[&str], sep: &str, s: &str) { - assert_eq!(connect_slices(v, sep), s.to_str()); assert_eq!(v.connect(sep), s.to_str()); } t(["you", "know", "I'm", "no", "good"], @@ -3307,7 +3291,6 @@ mod tests { assert_eq!(lines, ~["", "Märy häd ä little lämb", "", "Little lämb"]); } - #[test] fn test_split_str_iterator() { fn t<'a>(s: &str, sep: &'a str, u: ~[&str]) { diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 75439dfaa786c..53729dbd1157d 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -10,7 +10,6 @@ use core::prelude::*; -use core::str; use core::to_bytes; #[deriving(Eq)] @@ -267,7 +266,7 @@ impl ToStr for AbiSet { for self.each |abi| { strs.push(abi.data().name); } - fmt!("\"%s\"", str::connect_slices(strs, " ")) + fmt!("\"%s\"", strs.connect(" ")) } } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index fecded5e87b21..8a379a6213aac 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -62,7 +62,7 @@ pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner) path_name(s) => copy *itr.get(s.name) } }; - str::connect(strs, sep) + strs.connect(sep) } pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index b040397de720d..db7c29edab068 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -28,7 +28,7 @@ use core::to_bytes; pub fn path_name_i(idents: &[ident]) -> ~str { // FIXME: Bad copies (#2543 -- same for everything else that says "bad") - str::connect(idents.map(|i| copy *token::interner_get(i.name)), "::") + idents.map(|i| copy *token::interner_get(i.name)).connect("::") } pub fn path_to_ident(p: @Path) -> ident { copy *p.idents.last() } diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 7f8f2be6f6e1e..14cbd170c4822 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -120,7 +120,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) clobs.push(clob); } - cons = str::connect(clobs, ","); + cons = clobs.connect(","); } Options => { let option = p.parse_str(); diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index 43bcb68b8e08f..cb7386b988003 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -88,7 +88,7 @@ pub fn analyze(proto: @mut protocol_, _cx: @ExtCtxt) { } if self_live.len() > 0 { - let states = str::connect(self_live.map(|s| copy s.name), " "); + let states = self_live.map(|s| copy s.name).connect(" "); debug!("protocol %s is unbounded due to loops involving: %s", copy proto.name, states); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index a5725613d5898..304c496bbf4d8 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -24,7 +24,6 @@ use opt_vec; use opt_vec::OptVec; use core::iterator::IteratorUtil; -use core::str; use core::vec; pub trait gen_send { @@ -100,9 +99,9 @@ impl gen_send for message { } body += fmt!("let message = %s(%s);\n", name, - str::connect(vec::append_one( - arg_names.map(|x| cx.str_of(*x)), - ~"s"), ", ")); + vec::append_one( + arg_names.map(|x| cx.str_of(*x)), + ~"s").connect(", ")); if !try { body += fmt!("::std::pipes::send(pipe, message);\n"); @@ -155,8 +154,7 @@ impl gen_send for message { ~"" } else { - ~"(" + str::connect(arg_names.map(|x| copy *x), - ", ") + ")" + ~"(" + arg_names.map(|x| copy *x).connect(", ") + ")" }; let mut body = ~"{ "; diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 09c9dd922c7af..2c6f40091ac9f 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -92,7 +92,7 @@ pub mod rt { impl<'self> ToSource for &'self [@ast::item] { fn to_source(&self) -> ~str { - str::connect(self.map(|i| i.to_source()), "\n\n") + self.map(|i| i.to_source()).connect("\n\n") } } @@ -104,7 +104,7 @@ pub mod rt { impl<'self> ToSource for &'self [@ast::Ty] { fn to_source(&self) -> ~str { - str::connect(self.map(|i| i.to_source()), ", ") + self.map(|i| i.to_source()).connect(", ") } } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 4d1e9a31821d1..79018ebd1eadc 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -23,7 +23,6 @@ use print::pprust; use core::io; use core::result; -use core::str; use core::vec; // These macros all relate to the file system; they either return @@ -74,8 +73,7 @@ pub fn expand_mod(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::check_zero_tts(cx, sp, tts, "module_path!"); base::MRExpr(cx.expr_str(sp, - str::connect(cx.mod_path().map( - |x| cx.str_of(*x)), "::"))) + cx.mod_path().map(|x| cx.str_of(*x)).connect("::"))) } // include! : parse the given file as an expr diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index a6ec91f899ca8..0c9ca98fb9d3f 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -371,7 +371,7 @@ pub fn parse( } else { if (bb_eis.len() > 0u && next_eis.len() > 0u) || bb_eis.len() > 1u { - let nts = str::connect(vec::map(bb_eis, |ei| { + let nts = vec::map(bb_eis.connect(|ei| { match ei.elts[ei.idx].node { match_nonterminal(ref bind,ref name,_) => { fmt!("%s ('%s')", *ident_to_str(name), diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 89fd5c3762a3b..a6933c1648313 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -116,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { let lines = block_trim(lines, ~"\t ", None); let lines = block_trim(lines, ~"*", Some(1u)); let lines = block_trim(lines, ~"\t ", None); - return str::connect(lines, "\n"); + return lines.connect("\n"); } fail!("not a doc-comment: %s", comment); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ff894c267b8f..03b4c0c5ca1c2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4002,9 +4002,7 @@ impl Parser { fmt!("illegal ABI: \ expected one of [%s], \ found `%s`", - str::connect_slices( - abi::all_names(), - ", "), + abi::all_names().connect(", "), word)); } } diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index 10d448b7952f8..368725607160d 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -120,7 +120,7 @@ impl ToStr for AsciiArt { let lines = do self.lines.map |line| {str::from_chars(*line)}; // Concatenate the lines together using a new-line. - str::connect(lines, "\n") + lines.connect("\n") } } diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index 972b9c7a52533..23e5f3945b12d 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -98,8 +98,8 @@ priv fn cmd_to_str(cmd: ~[~str]) -> ~str { res.push_str(cmd.len().to_str()); res.push_str("\r\n"); for cmd.each |s| { - res.push_str(str::concat(~[~"$", s.len().to_str(), ~"\r\n", - copy *s, ~"\r\n"])); + res.push_str([~"$", s.len().to_str(), ~"\r\n", + copy *s, ~"\r\n"].concat())); } res } diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index 9b94b78512594..bc167e5124fdb 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -26,7 +26,7 @@ impl to_str for int { impl to_str for ~[T] { fn to_str(&self) -> ~str { - ~"[" + str::connect(vec::map(*self, |e| e.to_str() ), ", ") + "]" + ~"[" + self.map(|e| e.to_str()).connect(", ") + "]" } } From 8c59d920a12fe40398a0033438ff426bb3387fd0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 10 Jun 2013 23:57:41 +1000 Subject: [PATCH 16/21] std: basic documentation for the new str methods --- src/libstd/str.rs | 88 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 20 deletions(-) diff --git a/src/libstd/str.rs b/src/libstd/str.rs index c820f64549010..a7fe102738d39 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -155,9 +155,7 @@ pub fn from_chars(chs: &[char]) -> ~str { buf } -/// A function version of the `.push_str`, required for `fmt!` during -/// the bootstrap. Use `lhs.push_str(rhs)` instead of this. -#[doc="hidden"] +#[doc(hidden)] pub fn push_str(lhs: &mut ~str, rhs: &str) { lhs.push_str(rhs) } @@ -1604,25 +1602,9 @@ pub trait StrSlice<'self> { fn splitn_iter(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep>; fn split_options_iter(&self, sep: Sep, count: uint, allow_trailing_empty: bool) -> StrCharSplitIterator<'self, Sep>; - /// An iterator over the start and end indices of each match of - /// `sep` within `self`. fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>; - /** - * An iterator over the substrings of `self` separated by `sep`. - * - * # Example - * - * ~~~ {.rust} - * let v: ~[&str] = ".XXX.YYY.".split_str_iter(".").collect() - * assert_eq!(v, ["", "XXX", "YYY", ""]); - * ~~~ - */ fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>; - /// An iterator over the lines of a string (subsequences separated - /// by `\n`). fn line_iter(&self) -> StrCharSplitIterator<'self, char>; - /// An iterator over the words of a string (subsequences separated - /// by any sequence of whitespace). fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; @@ -1681,7 +1663,15 @@ impl<'self> StrSlice<'self> for &'self str { fn contains_char(&self, needle: char) -> bool { self.find(needle).is_some() } - + /// An iterator over the characters of `self`. Note, this iterates + /// over unicode code-points, not unicode graphemes. + /// + /// # Example + /// + /// ~~~ {.rust} + /// let v: ~[char] = "abc åäö".iter().collect(); + /// assert_eq!(v, ~['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); + /// ~~~ #[inline] fn iter(&self) -> StrCharIterator<'self> { StrCharIterator { @@ -1689,6 +1679,7 @@ impl<'self> StrSlice<'self> for &'self str { string: *self } } + /// An iterator over the characters of `self`, in reverse order. #[inline] fn rev_iter(&self) -> StrCharRevIterator<'self> { StrCharRevIterator { @@ -1697,20 +1688,47 @@ impl<'self> StrSlice<'self> for &'self str { } } + /// An iterator over the bytes of `self` + #[inline] fn bytes_iter(&self) -> StrBytesIterator<'self> { StrBytesIterator { it: as_bytes_slice(*self).iter() } } + /// An iterator over the bytes of `self`, in reverse order + #[inline] fn bytes_rev_iter(&self) -> StrBytesRevIterator<'self> { StrBytesRevIterator { it: as_bytes_slice(*self).rev_iter() } } + /// An iterator over substrings of `self`, separated by characters + /// matched by `sep`. + /// + /// # Example + /// + /// ~~~ {.rust} + /// let v: ~[&str] = "Mary had a little lamb".split_iter(' ').collect(); + /// assert_eq!(v, ~["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: ~[&str] = "abc1def2ghi".split_iter(|c: char| c.is_digit()).collect(); + /// assert_eq!(v, ~["abc", "def", "ghi"]); + /// ~~~ + #[inline] fn split_iter(&self, sep: Sep) -> StrCharSplitIterator<'self, Sep> { self.split_options_iter(sep, self.len(), true) } + /// An iterator over substrings of `self`, separated by characters + /// matched by `sep`, restricted to splitting at most `count` + /// times. + #[inline] fn splitn_iter(&self, sep: Sep, count: uint) -> StrCharSplitIterator<'self, Sep> { self.split_options_iter(sep, count, true) } + + /// An iterator over substrings of `self`, separated by characters + /// matched by `sep`, splitting at most `count` times, and + /// possibly not including the trailing empty substring, if it + /// exists. + #[inline] fn split_options_iter(&self, sep: Sep, count: uint, allow_trailing_empty: bool) -> StrCharSplitIterator<'self, Sep> { let only_ascii = sep.only_ascii(); @@ -1724,6 +1742,9 @@ impl<'self> StrSlice<'self> for &'self str { only_ascii: only_ascii } } + /// An iterator over the start and end indices of each match of + /// `sep` within `self`. + #[inline] fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self> { assert!(!sep.is_empty()) StrMatchesIndexIterator { @@ -1732,6 +1753,17 @@ impl<'self> StrSlice<'self> for &'self str { position: 0 } } + /** + * An iterator over the substrings of `self` separated by `sep`. + * + * # Example + * + * ~~~ {.rust} + * let v: ~[&str] = "abcXXXabcYYYabc".split_str_iter("abc").collect() + * assert_eq!(v, ["", "XXX", "YYY", ""]); + * ~~~ + */ + #[inline] fn split_str_iter(&self, sep: &'self str) -> StrStrSplitIterator<'self> { StrStrSplitIterator { it: self.matches_index_iter(sep), @@ -1740,9 +1772,15 @@ impl<'self> StrSlice<'self> for &'self str { } } + /// An iterator over the lines of a string (subsequences separated + /// by `\n`). + #[inline] fn line_iter(&self) -> StrCharSplitIterator<'self, char> { self.split_options_iter('\n', self.len(), false) } + /// An iterator over the words of a string (subsequences separated + /// by any sequence of whitespace). + #[inline] fn word_iter(&self) -> WordIterator<'self> { self.split_iter(char::is_whitespace).filter(|s| !s.is_empty()) } @@ -1791,14 +1829,24 @@ impl<'self> StrSlice<'self> for &'self str { assert!(self.is_char_boundary(end)); unsafe { raw::slice_bytes(*self, begin, end) } } + /// Returns a slice of the string from `begin` to its end. + /// + /// Fails when `begin` does not point to a valid character, or is + /// out of bounds. #[inline] fn slice_from(&self, begin: uint) -> &'self str { self.slice(begin, self.len()) } + /// Returns a slice of the string from the beginning to byte + /// `end`. + /// + /// Fails when `end` does not point to a valid character, or is + /// out of bounds. #[inline] fn slice_to(&self, end: uint) -> &'self str { self.slice(0, end) } + /// Checks if `needle` is a prefix of the string. #[inline] fn starts_with<'a>(&self, needle: &'a str) -> bool { starts_with(*self, needle) From ebefe425b962d3914cc523d7f539fdb2244cec06 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 00:49:19 +1000 Subject: [PATCH 17/21] std: remove str::to_chars --- src/librustpkg/version.rs | 5 ++--- src/libstd/str.rs | 5 ----- src/test/run-pass/utf8_chars.rs | 6 ++++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index b38f440a941f3..434583eb79eda 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -143,8 +143,7 @@ fn try_parsing_version(s: &str) -> Option { let s = s.trim(); debug!("Attempting to parse: %s", s); let mut parse_state = Start; - // I gave up on using external iterators (tjc) - for str::to_chars(s).each() |&c| { + for s.iter().advance |&c| { if char::is_digit(c) { parse_state = SawDigit; } @@ -172,7 +171,7 @@ fn is_url_like(p: &RemotePath) -> bool { /// Otherwise, return None. pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> { // reject strings with multiple '#'s - if { let mut i: uint = 0; for str::to_chars(s).each |&c| { if c == '#' { i += 1; } }; i > 1 } { + if s.splitn_iter('#', 2).count() > 1 { return None; } match s.rfind('#') { diff --git a/src/libstd/str.rs b/src/libstd/str.rs index a7fe102738d39..8967b447fd7f9 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -432,11 +432,6 @@ 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] { - s.iter().collect() -} - /** * Take a substring of another. * diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index b7ce617fe5044..d3bfd9b0164d5 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -10,6 +10,7 @@ extern mod extra; +use std::iterator::IteratorUtil; use std::str; use std::vec; @@ -17,11 +18,12 @@ pub fn main() { // Chars of 1, 2, 3, and 4 bytes let chs: ~[char] = ~['e', 'é', '€', 0x10000 as char]; let s: ~str = str::from_chars(chs); + let schs: ~[char] = s.iter().collect(); assert!(s.len() == 10u); assert!(str::char_len(s) == 4u); - assert!(str::to_chars(s).len() == 4u); - assert!(str::from_chars(str::to_chars(s)) == s); + assert!(schs.len() == 4u); + assert!(str::from_chars(schs) == s); assert!(s.char_at(0u) == 'e'); assert!(s.char_at(1u) == 'é'); From 248b6e38b533d43b8b4adaf6d47efc62fe82ef2a Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 00:52:43 +1000 Subject: [PATCH 18/21] std: replace str::substr with the method. --- src/libextra/rope.rs | 6 +++--- src/librustc/middle/resolve.rs | 6 +++--- src/libstd/str.rs | 16 +++------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 24cbf1b3f4aa8..f23a4433289e0 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -83,9 +83,9 @@ pub fn of_str(str: @~str) -> Rope { * * # Return value * - * A rope representing the same string as `str::substr(str, byte_offset, - * byte_len)`. Depending on `byte_len`, this rope may be empty, flat or - * complex. + * A rope representing the same string as `str.substr(byte_offset, + * byte_len)`. Depending on `byte_len`, this rope may be empty, flat + * or complex. * * # Performance note * diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 0f3a6c7629f1b..96838c32266a8 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -2684,11 +2684,11 @@ impl Resolver { match self.idents_to_str(module_path).rfind(':') { Some(idx) => { self.session.span_err(span, fmt!("unresolved import: could not find `%s` \ - in `%s`", str::substr(mpath, idx, - mpath.len() - idx), + in `%s`", mpath.substr(idx, + mpath.len() - idx), // idx - 1 to account for the extra // colon - str::substr(mpath, 0, idx - 1))); + mpath.substr(0, idx - 1))); }, None => (), }; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 8967b447fd7f9..f525c34cc4721 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -432,16 +432,6 @@ pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] { } } -/** - * Take a substring of another. - * - * Returns a slice pointing at `n` characters starting from byte offset - * `begin`. - */ -pub fn substr<'a>(s: &'a str, begin: uint, n: uint) -> &'a str { - s.slice(begin, begin + count_bytes(s, begin, n)) -} - /// Something that can be used to compare against a character pub trait CharEq { /// Determine if the splitter should split at the given character @@ -1854,7 +1844,7 @@ impl<'self> StrSlice<'self> for &'self str { */ #[inline] fn substr(&self, begin: uint, n: uint) -> &'self str { - substr(*self, begin, n) + s.slice(begin, begin + count_bytes(s, begin, n)) } /// Escape each char in `s` with char::escape_default. #[inline] @@ -2516,11 +2506,11 @@ mod tests { #[test] fn test_substr() { fn t(a: &str, b: &str, start: int) { - assert_eq!(substr(a, start as uint, b.len()), b); + assert_eq!(a.substr(start as uint, b.len()), b); } t("hello", "llo", 2); t("hello", "el", 1); - assert_eq!("ะเทศไท", substr("ประเทศไทย中华Việt Nam", 6u, 6u)); + assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".substr(6u, 6u)); } #[test] From 838191c40bc0411853d2b0d7e98326d08a5060e0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 01:03:16 +1000 Subject: [PATCH 19/21] std: replace str::{starts,ends}_with with the method. --- src/compiletest/compiletest.rc | 4 +- src/compiletest/header.rs | 2 +- src/compiletest/procsrv.rs | 2 +- src/compiletest/runtest.rs | 2 +- src/libextra/net_url.rs | 8 +-- src/libextra/tempfile.rs | 2 +- src/librustc/back/rpath.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustdoc/desc_to_brief_pass.rs | 2 +- src/librustdoc/sectionalize_pass.rs | 2 +- src/libstd/io.rs | 4 +- src/libstd/str.rs | 74 +++++++++----------------- 12 files changed, 40 insertions(+), 66 deletions(-) diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 7a0622d059d0c..e832534b227a9 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -231,11 +231,11 @@ pub fn is_test(config: &config, testfile: &Path) -> bool { let mut valid = false; for valid_extensions.each |ext| { - if str::ends_with(name, *ext) { valid = true; } + if name.ends_with(*ext) { valid = true; } } for invalid_prefixes.each |pre| { - if str::starts_with(name, *pre) { valid = false; } + if name.starts_with(*pre) { valid = false; } } return valid; diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index d8562d725a709..87f5f4bd3fae1 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -112,7 +112,7 @@ fn iter_header(testfile: &Path, it: &fn(~str) -> bool) -> bool { // Assume that any directives will be found before the first // module or function. This doesn't seem to be an optimization // with a warm page cache. Maybe with a cold one. - if str::starts_with(ln, "fn") || str::starts_with(ln, "mod") { + if ln.starts_with("fn") || ln.starts_with("mod") { return false; } else { if !(it(ln)) { return false; } } } diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index f86ab2c909313..87188100f4c52 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -28,7 +28,7 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] { if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) } else { (k,v) } }; - if str::ends_with(prog, "rustc.exe") { + if prog.ends_with("rustc.exe") { env.push((~"RUST_THREADS", ~"1")); } return env; diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 16190f69549cd..7159e51e3b6f3 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -364,7 +364,7 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError], if !found_flags[i] { debug!("prefix=%s ee.kind=%s ee.msg=%s line=%s", prefixes[i], ee.kind, ee.msg, line); - if (str::starts_with(line, prefixes[i]) && + if (line.starts_with(prefixes[i]) && line.contains(ee.kind) && line.contains(ee.msg)) { found_flags[i] = true; diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index 46e76a7a39913..c85a866a04a66 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -394,7 +394,7 @@ enum Input { // returns userinfo, host, port, and unparsed part, or an error fn get_authority(rawurl: &str) -> Result<(Option, ~str, Option<~str>, ~str), ~str> { - if !str::starts_with(rawurl, "//") { + if !raw_url.starts_with("//") { // there is no authority. return Ok((None, ~"", None, rawurl.to_str())); } @@ -579,7 +579,7 @@ fn get_path(rawurl: &str, authority: bool) -> } if authority { - if end != 0 && !str::starts_with(rawurl, "/") { + if end != 0 && !rawurl.starts_with("/") { return Err(~"Non-empty path must begin with\ '/' in presence of authority."); } @@ -592,8 +592,8 @@ fn get_path(rawurl: &str, authority: bool) -> // returns the parsed query and the fragment, if present fn get_query_fragment(rawurl: &str) -> Result<(Query, Option<~str>), ~str> { - if !str::starts_with(rawurl, "?") { - if str::starts_with(rawurl, "#") { + if !rawurl.starts_with("?") { + if rawurl.starts_with("#") { let f = decode_component(rawurl.slice( 1, rawurl.len())); diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs index 98c5783807239..c239e65e2d9a9 100644 --- a/src/libextra/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -42,7 +42,7 @@ mod tests { fn test_mkdtemp() { let p = mkdtemp(&Path("."), "foobar").unwrap(); os::remove_dir(&p); - assert!(str::ends_with(p.to_str(), "foobar")); + assert!(p.to_str().ends_with("foobar")); } // Ideally these would be in core::os but then core would need diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index a84cb2cdbe10e..5e5e0067afa41 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -240,7 +240,7 @@ mod test { debug!("test_prefix_path: %s vs. %s", res.to_str(), d.to_str()); - assert!(str::ends_with(res.to_str(), d.to_str())); + assert!(res.to_str().ends_with(d.to_str())); } #[test] diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index bc863fb363fe9..ce93cad73b6f3 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -244,7 +244,7 @@ fn get_cache(cx: @CrateContext) -> metadata_cache { } fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { - (if str::starts_with(full_path, work_dir) { + (if full_path.starts_with(work_dir) { full_path.slice(work_dir.len() + 1u, full_path.len()).to_owned() } else { diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 0f4ade0551de7..13ad47e34b8aa 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -134,7 +134,7 @@ fn first_sentence_(s: &str) -> ~str { str::to_owned(s.slice(0, idx - 1)) } _ => { - if str::ends_with(s, ".") { + if s.ends_with(".") { str::to_owned(s) } else { str::to_owned(s) diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index ddc1b7dfe21e8..8716f823848e2 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -153,7 +153,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { } fn parse_header(line: ~str) -> Option<~str> { - if str::starts_with(line, "# ") { + if line.starts_with("# ") { Some(line.slice(2u, line.len()).to_owned()) } else { None diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 7f3af79e27c76..409882c5cfe5a 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1979,7 +1979,7 @@ mod tests { fn file_writer_bad_name() { match io::file_writer(&Path("?/?"), []) { result::Err(e) => { - assert!(str::starts_with(e, "error opening")); + assert!(e.starts_with("error opening")); } result::Ok(_) => fail!() } @@ -1989,7 +1989,7 @@ mod tests { fn buffered_file_writer_bad_name() { match io::buffered_file_writer(&Path("?/?")) { result::Err(e) => { - assert!(str::starts_with(e, "error opening")); + assert!(e.starts_with("error opening")); } result::Ok(_) => fail!() } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index f525c34cc4721..03169a167b312 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -977,36 +977,6 @@ fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { } -/** - * Returns true if one string starts with another - * - * # Arguments - * - * * haystack - The string to look in - * * needle - The string to look for - */ -pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let (haystack_len, needle_len) = (haystack.len(), needle.len()); - if needle_len == 0u { true } - else if needle_len > haystack_len { false } - else { match_at(haystack, needle, 0u) } -} - -/** - * Returns true if one string ends with another - * - * # Arguments - * - * * haystack - The string to look in - * * needle - The string to look for - */ -pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let (haystack_len, needle_len) = (haystack.len(), needle.len()); - if needle_len == 0u { true } - else if needle_len > haystack_len { false } - else { match_at(haystack, needle, haystack_len - needle_len) } -} - /* Section: String properties */ @@ -1600,7 +1570,7 @@ pub trait StrSlice<'self> { fn slice(&self, begin: uint, end: uint) -> &'self str; fn slice_from(&self, begin: uint) -> &'self str; fn slice_to(&self, end: uint) -> &'self str; - fn starts_with<'a>(&self, needle: &'a str) -> bool; + fn starts_with(&self, needle: &str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; fn escape_default(&self) -> ~str; fn escape_unicode(&self) -> ~str; @@ -1770,12 +1740,6 @@ impl<'self> StrSlice<'self> for &'self str { self.split_iter(char::is_whitespace).filter(|s| !s.is_empty()) } - - /// Returns true if one string ends with another - #[inline] - fn ends_with(&self, needle: &str) -> bool { - ends_with(*self, needle) - } /// Returns true if the string has length 0 #[inline] fn is_empty(&self) -> bool { self.len() == 0 } @@ -1831,11 +1795,21 @@ impl<'self> StrSlice<'self> for &'self str { fn slice_to(&self, end: uint) -> &'self str { self.slice(0, end) } - /// Checks if `needle` is a prefix of the string. - #[inline] + /// Returns true if `needle` is a prefix of the string. fn starts_with<'a>(&self, needle: &'a str) -> bool { - starts_with(*self, needle) + let (self_len, needle_len) = (self.len(), needle.len()); + if needle_len == 0u { true } + else if needle_len > self_len { false } + else { match_at(*self, needle, 0u) } } + /// Returns true if `needle` is a suffix of the string. + pub fn ends_with(&self, needle: &str) -> bool { + let (self_len, needle_len) = (self.len(), needle.len()); + if needle_len == 0u { true } + else if needle_len > self_len { false } + else { match_at(*self, needle, self_len - needle_len) } + } + /** * Take a substring of another. * @@ -2591,20 +2565,20 @@ mod tests { #[test] fn test_starts_with() { - assert!((starts_with("", ""))); - assert!((starts_with("abc", ""))); - assert!((starts_with("abc", "a"))); - assert!((!starts_with("a", "abc"))); - assert!((!starts_with("", "abc"))); + assert!(("".starts_with(""))); + assert!(("abc".starts_with(""))); + assert!(("abc".starts_with("a"))); + assert!((!"a".starts_with("abc"))); + assert!((!"".starts_with("abc"))); } #[test] fn test_ends_with() { - assert!((ends_with("", ""))); - assert!((ends_with("abc", ""))); - assert!((ends_with("abc", "c"))); - assert!((!ends_with("a", "abc"))); - assert!((!ends_with("", "abc"))); + assert!(("".ends_with(""))); + assert!(("abc".ends_with(""))); + assert!(("abc".ends_with("c"))); + assert!((!"a".ends_with("abc"))); + assert!((!"".ends_with("abc"))); } #[test] From 2fa83c05035855f4b8f9a8b671d8d7cd69b60f8b Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 01:07:52 +1000 Subject: [PATCH 20/21] std: replace str::is_{alphanumeric,whitespace} with the methods. --- src/librustdoc/desc_to_brief_pass.rs | 2 +- src/librustdoc/unindent_pass.rs | 6 +++--- src/libstd/str.rs | 32 ++++++---------------------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 13ad47e34b8aa..f018a237b7e29 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -151,7 +151,7 @@ pub fn paragraphs(s: &str) -> ~[~str] { let paras = do lines.iter().fold(~[]) |paras, line| { let mut res = paras; - if str::is_whitespace(*line) { + if line.is_whitespace() { whitespace_lines += 1; } else { if whitespace_lines > 0 { diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index 23a4b9c7ba4b7..beb246857be72 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -46,7 +46,7 @@ fn unindent(s: &str) -> ~str { let ignore_previous_indents = saw_first_line && !saw_second_line && - !str::is_whitespace(*line); + !line.is_whitespace(); let min_indent = if ignore_previous_indents { uint::max_value @@ -58,7 +58,7 @@ fn unindent(s: &str) -> ~str { saw_second_line = true; } - if str::is_whitespace(*line) { + if line.is_whitespace() { min_indent } else { saw_first_line = true; @@ -80,7 +80,7 @@ fn unindent(s: &str) -> ~str { if !lines.is_empty() { let unindented = ~[lines.head().trim().to_owned()] + do lines.tail().map |line| { - if str::is_whitespace(*line) { + if line.is_whitespace() { copy *line } else { assert!(line.len() >= min_indent); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 03169a167b312..e581eff83ad83 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -981,24 +981,6 @@ fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool { Section: String properties */ -/** - * Returns true if the string contains only whitespace - * - * Whitespace characters are determined by `char::is_whitespace` - */ -pub fn is_whitespace(s: &str) -> bool { - s.iter().all(char::is_whitespace) -} - -/** - * Returns true if the string contains only alphanumerics - * - * Alphanumeric characters are determined by `char::is_alphanumeric` - */ -fn is_alphanumeric(s: &str) -> bool { - s.iter().all(char::is_alphanumeric) -} - /// Returns the number of characters that a string holds #[inline(always)] pub fn char_len(s: &str) -> uint { count_chars(s, 0u, s.len()) } @@ -1749,14 +1731,14 @@ impl<'self> StrSlice<'self> for &'self str { * Whitespace characters are determined by `char::is_whitespace` */ #[inline] - fn is_whitespace(&self) -> bool { is_whitespace(*self) } + fn is_whitespace(&self) -> bool { self.iter().all(char::is_whitespace) } /** * Returns true if the string contains only alphanumerics * * Alphanumeric characters are determined by `char::is_alphanumeric` */ #[inline] - fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } + fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) } /// Returns the size in bytes not counting the null terminator #[inline(always)] fn len(&self) -> uint { @@ -2773,11 +2755,11 @@ mod tests { #[test] fn test_is_whitespace() { - assert!(is_whitespace("")); - assert!(is_whitespace(" ")); - assert!(is_whitespace("\u2009")); // Thin space - assert!(is_whitespace(" \n\t ")); - assert!(!is_whitespace(" _ ")); + assert!("".is_whitespace()); + assert!(" ".is_whitespace()); + assert!("\u2009".is_whitespace()); // Thin space + assert!(" \n\t ".is_whitespace()); + assert!(!" _ ".is_whitespace()); } #[test] From e8782eeb6327eb79b132cc3f71bfaf55310dde00 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 02:34:14 +1000 Subject: [PATCH 21/21] fix tests, remove some warnings --- doc/rust.md | 12 ++++++------ src/compiletest/errors.rs | 1 - src/compiletest/header.rs | 1 - src/libextra/net_url.rs | 3 +-- src/libextra/rope.rs | 3 +-- src/libextra/semver.rs | 1 - src/libfuzzer/fuzzer.rc | 1 - src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/build.rs | 4 +--- src/librustc/middle/typeck/check/mod.rs | 1 - src/librustc/middle/typeck/infer/to_str.rs | 1 - src/librustc/util/common.rs | 1 - src/librustpkg/version.rs | 4 ++-- src/libstd/io.rs | 1 - src/libstd/str.rs | 11 +---------- src/libstd/str/ascii.rs | 1 - src/libsyntax/ast_map.rs | 1 - src/libsyntax/ast_util.rs | 1 - src/libsyntax/ext/asm.rs | 1 - src/libsyntax/ext/pipes/liveness.rs | 1 - src/libsyntax/ext/tt/macro_parser.rs | 5 ++--- src/test/run-pass/trait-to-str.rs | 5 +++-- 22 files changed, 18 insertions(+), 44 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 0a33eb6ab2a53..3c0828def154a 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -802,15 +802,15 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: ~~~~ -use std::float::{sin, pow}; -use std::option::Some; +use std::float::sin; +use std::option::{Some, None}; fn main() { - // Equivalent to 'info!(std::float::pow(std::float::sin(1.0), 2.0));' - info!(pow(sin(1.0), 2.0)); + // Equivalent to 'info!(std::float::sin(1.0));' + info!(sin(1.0)); - // Equivalent to 'info!(std::option::Some(1.0));' - info!(Some(1.0)); + // Equivalent to 'info!(~[std::option::Some(1.0), std::option::None]);' + info!(~[Some(1.0), None]); } ~~~~ diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index f524f1424b4f5..cdc0defcbcab0 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -11,7 +11,6 @@ use core::prelude::*; use core::io; -use core::str; pub struct ExpectedError { line: uint, kind: ~str, msg: ~str } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 87f5f4bd3fae1..2888d4223b714 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -16,7 +16,6 @@ use common; use core::iterator::IteratorUtil; use core::io; use core::os; -use core::str; pub struct TestProps { // Lines that should be expected, in order, on standard out diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs index c85a866a04a66..83cda31c68089 100644 --- a/src/libextra/net_url.rs +++ b/src/libextra/net_url.rs @@ -19,7 +19,6 @@ use core::cmp::Eq; use core::io::{Reader, ReaderUtil}; use core::io; use core::hashmap::HashMap; -use core::str; use core::to_bytes; use core::uint; @@ -394,7 +393,7 @@ enum Input { // returns userinfo, host, port, and unparsed part, or an error fn get_authority(rawurl: &str) -> Result<(Option, ~str, Option<~str>, ~str), ~str> { - if !raw_url.starts_with("//") { + if !rawurl.starts_with("//") { // there is no authority. return Ok((None, ~"", None, rawurl.to_str())); } diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index f23a4433289e0..de54964142349 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -40,6 +40,7 @@ use core::prelude::*; use core::iterator::IteratorUtil; use core::uint; use core::vec; +use core::str; /// The type of ropes. pub type Rope = node::Root; @@ -1187,8 +1188,6 @@ pub mod node { pub mod char_iterator { use core::prelude::*; - use core::str; - use rope::node::{Leaf, Node}; use rope::node::leaf_iterator; diff --git a/src/libextra/semver.rs b/src/libextra/semver.rs index c7d2010e609da..3ab8bb1f60bc2 100644 --- a/src/libextra/semver.rs +++ b/src/libextra/semver.rs @@ -20,7 +20,6 @@ use core::cmp; use core::io::{ReaderUtil}; use core::io; use core::option::{Option, Some, None}; -use core::str; use core::to_str::ToStr; use core::uint; diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index 416fabb6d8f67..dbeea417a3dd9 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -37,7 +37,6 @@ use std::result; use std::run; use std::str; use std::uint; -use std::vec; use syntax::diagnostic; use syntax::parse::token::ident_interner; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b913a1b499617..8e015d9a677e1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1995,7 +1995,7 @@ pub fn trans_enum_variant(ccx: @CrateContext, debug!("trans_enum_variant: name=%s tps=%s repr=%? enum_ty=%s", unsafe { str::raw::from_c_str(llvm::LLVMGetValueName(llfndecl)) }, - ~"[" + ty_param_substs.map(|&t| ty_to_str(ccx.tcx.connect(t)), ", ") + "]", + ~"[" + ty_param_substs.map(|&t| ty_to_str(ccx.tcx, t)).connect(", ") + "]", repr, ty_to_str(ccx.tcx, enum_ty)); adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 8406444bd097e..8b2814875046a 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -192,9 +192,7 @@ pub fn Invoke(cx: block, terminate(cx, "Invoke"); debug!("Invoke(%s with arguments (%s))", val_str(cx.ccx().tn, Fn), - vec::map(Args.connect(|a| val_str(cx.ccx().tn, - *a).to_owned()), - ", ")); + Args.map(|a| val_str(cx.ccx().tn, *a).to_owned()).connect(", ")); unsafe { count_insn(cx, "invoke"); llvm::LLVMBuildInvoke(B(cx), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 30dd677396b17..b12b1499759f9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -115,7 +115,6 @@ use core::iterator::IteratorUtil; use core::cast::transmute; use core::hashmap::HashMap; use core::result; -use core::str; use core::util::replace; use core::vec; use extra::list::Nil; diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index d6623f06c3d33..364d8b2d052c3 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -18,7 +18,6 @@ use middle::typeck::infer::InferCtxt; use middle::typeck::infer::unify::{Redirect, Root, VarValue}; use util::ppaux::{mt_to_str, ty_to_str, trait_ref_to_str}; -use core::str; use core::uint; use syntax::ast; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 8d0cba0e8b712..9556fd3e2574d 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -16,7 +16,6 @@ use syntax::visit; use core::hashmap::HashSet; use core::io; -use core::str; use extra; pub fn time(do_it: bool, what: ~str, thunk: &fn() -> T) -> T { diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index 434583eb79eda..0900d93e498f3 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -143,7 +143,7 @@ fn try_parsing_version(s: &str) -> Option { let s = s.trim(); debug!("Attempting to parse: %s", s); let mut parse_state = Start; - for s.iter().advance |&c| { + for s.iter().advance |c| { if char::is_digit(c) { parse_state = SawDigit; } @@ -171,7 +171,7 @@ fn is_url_like(p: &RemotePath) -> bool { /// Otherwise, return None. pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> { // reject strings with multiple '#'s - if s.splitn_iter('#', 2).count() > 1 { + if s.splitn_iter('#', 2).count() > 2 { return None; } match s.rfind('#') { diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 409882c5cfe5a..58711360c3564 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1836,7 +1836,6 @@ mod tests { use io; use path::Path; use result; - use str; use u64; use vec; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index e581eff83ad83..8cd69f32e4969 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1800,7 +1800,7 @@ impl<'self> StrSlice<'self> for &'self str { */ #[inline] fn substr(&self, begin: uint, n: uint) -> &'self str { - s.slice(begin, begin + count_bytes(s, begin, n)) + self.slice(begin, begin + count_bytes(*self, begin, n)) } /// Escape each char in `s` with char::escape_default. #[inline] @@ -2318,7 +2318,6 @@ impl<'self> Iterator for StrBytesRevIterator<'self> { mod tests { use iterator::IteratorUtil; use container::Container; - use char; use option::Some; use libc::c_char; use libc; @@ -3026,14 +3025,6 @@ mod tests { assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); } - #[test] - fn test_chars() { - let ss = ~"ศไทย中华Việt Nam"; - assert!(~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a', - 'm'] - == to_chars(ss)); - } - #[test] fn test_utf16() { let pairs = diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index a4a1b7a171d33..618d5095777a9 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -202,7 +202,6 @@ impl ToStrConsume for ~[Ascii] { #[cfg(test)] mod tests { use super::*; - use str; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 8a379a6213aac..2e60f7d02dfbc 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -24,7 +24,6 @@ use syntax::parse::token::special_idents; use core::cmp; use core::hashmap::HashMap; -use core::str; use core::vec; pub enum path_elt { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index db7c29edab068..3d6269942fd5b 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -23,7 +23,6 @@ use visit; use core::hashmap::HashMap; use core::int; use core::option; -use core::str; use core::to_bytes; pub fn path_name_i(idents: &[ident]) -> ~str { diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 14cbd170c4822..d3efd07aa045d 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -21,7 +21,6 @@ use ext::base::*; use parse; use parse::token; -use core::str; use core::vec; enum State { diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index cb7386b988003..1076c5d0b98f5 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -42,7 +42,6 @@ use core::prelude::*; use ext::base::ExtCtxt; use ext::pipes::proto::{protocol_}; -use core::str; use extra::bitv::Bitv; pub fn analyze(proto: @mut protocol_, _cx: @ExtCtxt) { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 0c9ca98fb9d3f..e5a77cc21fb8d 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -24,7 +24,6 @@ use parse::token; use core::iterator::IteratorUtil; use core::hashmap::HashMap; -use core::str; use core::uint; use core::vec; @@ -371,14 +370,14 @@ pub fn parse( } else { if (bb_eis.len() > 0u && next_eis.len() > 0u) || bb_eis.len() > 1u { - let nts = vec::map(bb_eis.connect(|ei| { + let nts = bb_eis.map(|ei| { match ei.elts[ei.idx].node { match_nonterminal(ref bind,ref name,_) => { fmt!("%s ('%s')", *ident_to_str(name), *ident_to_str(bind)) } _ => fail!() - } }), " or "); + } }).connect(" or "); return error(sp, fmt!( "Local ambiguity: multiple parsing options: \ built-in NTs %s or %u other options.", diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index bc167e5124fdb..4029bd18338c3 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -14,7 +14,8 @@ extern mod std; -use std::{str, int, vec}; +use std::str::StrVector; +use std::{int, vec}; trait to_str { fn to_str(&self) -> ~str; @@ -26,7 +27,7 @@ impl to_str for int { impl to_str for ~[T] { fn to_str(&self) -> ~str { - ~"[" + self.map(|e| e.to_str()).connect(", ") + "]" + ~"[" + vec::map(*self, |e| e.to_str()).connect(", ") + "]" } }