diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 891935dcadd..e0ceb79a37d 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -24,7 +24,6 @@ use util::logv; use core::io; use core::os; -use core::str; use core::uint; use core::vec; diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index f4754b3e4cb..5bf4dd517a5 100644 --- a/src/libextra/base64.rs +++ b/src/libextra/base64.rs @@ -229,8 +229,6 @@ impl<'self> FromBase64 for &'self str { #[cfg(test)] mod tests { - use core::str; - #[test] fn test_to_base64() { assert_eq!("".to_base64(), ~""); diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs index 12539cd4759..fed73256c00 100644 --- a/src/libextra/rope.rs +++ b/src/libextra/rope.rs @@ -1271,7 +1271,6 @@ mod tests { use rope::*; - use core::str; use core::uint; use core::vec; diff --git a/src/libextra/sha1.rs b/src/libextra/sha1.rs index 0c35630345b..7c4b3f4ce39 100644 --- a/src/libextra/sha1.rs +++ b/src/libextra/sha1.rs @@ -24,7 +24,6 @@ use core::prelude::*; -use core::str; use core::uint; use core::vec; @@ -279,8 +278,6 @@ pub fn sha1() -> @Sha1 { mod tests { use sha1; - use core::vec; - #[test] fn test() { struct Test { diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs index dae9113b3a9..972bccde18a 100644 --- a/src/libextra/smallintmap.rs +++ b/src/libextra/smallintmap.rs @@ -294,11 +294,6 @@ mod tests { use super::SmallIntMap; - use core::local_data; - use core::rand; - use core::uint; - use core::vec; - #[test] fn test_find_mut() { let mut m = SmallIntMap::new(); diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs index 0189e0db6d4..b88fd374da2 100644 --- a/src/libextra/sort.rs +++ b/src/libextra/sort.rs @@ -751,7 +751,6 @@ fn shift_vec(dest: &mut [T], mod test_qsort3 { use sort::*; - use core::vec; fn check_sort(v1: &mut [int], v2: &mut [int]) { let len = v1.len(); @@ -861,8 +860,6 @@ mod tests { use sort::*; - use core::vec; - fn check_sort(v1: &[int], v2: &[int]) { let len = v1.len(); pub fn le(a: &int, b: &int) -> bool { *a <= *b } diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs index 4af47fa806f..3a1de5de01d 100644 --- a/src/libextra/stats.rs +++ b/src/libextra/stats.rs @@ -12,7 +12,6 @@ use core::prelude::*; -use core::vec; use core::f64; use core::cmp; use core::num; diff --git a/src/libextra/std.rc b/src/libextra/std.rc index 83c0bb516b4..93759bea35f 100644 --- a/src/libextra/std.rc +++ b/src/libextra/std.rc @@ -37,6 +37,7 @@ not required in or otherwise suitable for the core library. extern mod core(name = "std", vers = "0.7-pre"); +#[cfg(stage0)] use core::{str, unstable}; use core::str::{StrSlice, OwnedStr}; diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs index c239e65e2d9..39dcee5eff3 100644 --- a/src/libextra/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -36,7 +36,6 @@ mod tests { use tempfile::mkdtemp; use core::os; - use core::str; #[test] fn test_mkdtemp() { diff --git a/src/libextra/terminfo/parser/compiled.rs b/src/libextra/terminfo/parser/compiled.rs index 81b6083db01..66649c62fca 100644 --- a/src/libextra/terminfo/parser/compiled.rs +++ b/src/libextra/terminfo/parser/compiled.rs @@ -313,7 +313,6 @@ pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> { #[cfg(test)] mod test { use super::*; - use p = core::path::Path; #[test] fn test_veclens() { diff --git a/src/libextra/test.rs b/src/libextra/test.rs index a465cef09e6..72837cb4ae1 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -26,7 +26,6 @@ use core::either; use core::io; use core::option; use core::result; -use core::str; use core::task; use core::to_str::ToStr; use core::uint; @@ -542,7 +541,7 @@ pub fn filter_tests( // Sort the tests alphabetically fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool { - str::le(t1.desc.name.to_str(), t2.desc.name.to_str()) + t1.desc.name.to_str() < t2.desc.name.to_str() } sort::quick_sort(filtered, lteq); diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index f98758f64af..e37ce7c71ef 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -710,7 +710,6 @@ mod test_treemap { use core::rand::RngUtil; use core::rand; - use core::str; use core::vec; #[test] diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 85fc0575170..33f578d335b 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -199,9 +199,6 @@ pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { mod test { use core::prelude::*; - use core::os; - use core::str; - // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then // these redundant #[cfg(test)] blocks can be removed #[cfg(test)] diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index e11367a7a7d..925b1f506d7 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -15,7 +15,6 @@ use cstore = metadata::cstore; use driver::session::Session; use e = metadata::encoder; use metadata::decoder; -use metadata::encoder; use metadata::tydecode; use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter}; use metadata::tyencode; diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 2803608567d..3e656b3e594 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -4845,7 +4845,7 @@ impl Resolver { let mut smallest = 0; for maybes.eachi |i, &other| { - values[i] = str::levdistance(name, other); + values[i] = name.lev_distance(other); if values[i] <= values[smallest] { smallest = i; diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 9ae241c7030..5481ed9a7fd 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -47,7 +47,6 @@ use core::container::Map; use core::libc::c_ulonglong; use core::option::{Option, Some, None}; -use core::str; use core::vec; use lib::llvm::{ValueRef, TypeRef, True, IntEQ, IntNE}; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e2073d21fe3..ffc54bbed35 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -71,7 +71,6 @@ use core::libc::c_uint; use core::str; use core::uint; use core::vec; -use core::local_data; use extra::time; use syntax::ast::ident; use syntax::ast_map::{path, path_elt_to_str, path_name}; @@ -3120,4 +3119,3 @@ pub fn trans_crate(sess: session::Session, return (llcx, llmod, link_meta); } - diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index 9d8f750a350..3775aafb569 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -32,8 +32,6 @@ use syntax::ast; use syntax::ast_map; use syntax; -#[cfg(test)] use core::vec; - pub struct Ctxt { ast: @ast::crate, ast_map: ast_map::map diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 51fea9b46b3..dbaa5e8532c 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -24,7 +24,6 @@ use fold::Fold; use fold; use pass::Pass; -use core::str; use core::util; pub fn mk_pass() -> Pass { @@ -129,25 +128,21 @@ fn first_sentence_(s: &str) -> ~str { } }); match idx { - Some(idx) if idx > 2u => { - str::to_owned(s.slice(0, idx - 1)) - } + Some(idx) if idx > 2u => s.slice(0, idx - 1).to_owned(), _ => { if s.ends_with(".") { - str::to_owned(s) + s.to_owned() } else { - str::to_owned(s) + s.to_owned() } } } } pub fn paragraphs(s: &str) -> ~[~str] { - let mut lines = ~[]; - for str::each_line_any(s) |line| { lines.push(line.to_owned()); } let mut whitespace_lines = 0; let mut accum = ~""; - let paras = do lines.iter().fold(~[]) |paras, line| { + let paras = do s.any_line_iter().fold(~[]) |paras, line| { let mut res = paras; if line.is_whitespace() { @@ -163,9 +158,9 @@ pub fn paragraphs(s: &str) -> ~[~str] { whitespace_lines = 0; accum = if accum.is_empty() { - copy *line + line.to_owned() } else { - accum + "\n" + *line + fmt!("%s\n%s", accum, line) } } diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index f4b6ae8fb32..f8c49f544bc 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -285,8 +285,6 @@ mod test { use extract::{extract, from_srv}; use parse; - use core::vec; - fn mk_doc(source: @str) -> doc::Doc { let ast = parse::from_str(source); extract(ast, ~"") diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 17db7c24a7c..075b64a674c 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -466,10 +466,7 @@ fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) { } fn list_item_indent(item: &str) -> ~str { - let mut indented = ~[]; - for str::each_line_any(item) |line| { - indented.push(line); - } + let indented = item.any_line_iter().collect::<~[&str]>(); // separate markdown elements within `*` lists must be indented by four // spaces, or they will escape the list context. indenting everything @@ -539,8 +536,6 @@ mod test { use tystr_pass; use unindent_pass; - use core::str; - fn render(source: ~str) -> ~str { let (srv, doc) = create_doc_srv(source); let markdown = write_markdown_str_srv(srv, doc); diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index bb5d71e8db1..584e6ccc887 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -157,7 +157,6 @@ mod test { use doc; use extract; use page_pass::run; - use core::vec; fn mk_doc_( output_style: config::OutputStyle, diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index 8a90d3f74d3..484eb8c7980 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -77,8 +77,6 @@ mod test { #[test] fn should_prune_hidden_items() { - use core::vec; - let doc = mk_doc(~"#[doc(hidden)] mod a { }"); assert!(doc.cratemod().mods().is_empty()) } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index e861939c2dd..741da3e265e 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -162,7 +162,6 @@ mod test { use extract; use tystr_pass; use prune_private_pass::run; - use core::vec; fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 8716f823848..ba433bf479d 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -19,7 +19,7 @@ use fold::Fold; use fold; use pass::Pass; -use core::str; +use core::iterator::IteratorUtil; pub fn mk_pass() -> Pass { Pass { @@ -104,21 +104,19 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { if desc.is_none() { return (None, ~[]); } - let mut lines = ~[]; - for str::each_line_any(*desc.get_ref()) |line| { lines.push(line.to_owned()); } let mut new_desc = None::<~str>; let mut current_section = None; let mut sections = ~[]; - for lines.each |line| { - match parse_header(copy *line) { + for desc.get_ref().any_line_iter().advance |line| { + match parse_header(line) { Some(header) => { if current_section.is_some() { - sections += [copy *current_section.get_ref()]; + sections.push(copy *current_section.get_ref()); } current_section = Some(doc::Section { - header: header, + header: header.to_owned(), body: ~"" }); } @@ -126,17 +124,17 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { match copy current_section { Some(section) => { current_section = Some(doc::Section { - body: section.body + "\n" + *line, + body: fmt!("%s\n%s", section.body, line), .. section }); } None => { new_desc = match copy new_desc { Some(desc) => { - Some(desc + "\n" + *line) + Some(fmt!("%s\n%s", desc, line)) } None => { - Some(copy *line) + Some(line.to_owned()) } }; } @@ -146,15 +144,15 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { } if current_section.is_some() { - sections += [current_section.get()]; + sections.push(current_section.unwrap()); } (new_desc, sections) } -fn parse_header(line: ~str) -> Option<~str> { +fn parse_header<'a>(line: &'a str) -> Option<&'a str> { if line.starts_with("# ") { - Some(line.slice(2u, line.len()).to_owned()) + Some(line.slice_from(2)) } else { None } @@ -172,9 +170,6 @@ mod test { use extract; use sectionalize_pass::run; - use core::str; - use core::vec; - fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 1f7a71e0fd8..6db582a60e9 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -149,8 +149,6 @@ mod test { use sectionalize_pass; use text_pass::mk_pass; - use core::str; - fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index caf0e5376d1..2bcf04c0262 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -21,7 +21,6 @@ middle of a line, and each of the following lines is indented. use core::prelude::*; -use core::str; use core::uint; use pass::Pass; use text_pass; @@ -31,8 +30,7 @@ pub fn mk_pass() -> Pass { } fn unindent(s: &str) -> ~str { - let mut lines = ~[]; - for str::each_line_any(s) |line| { lines.push(line.to_owned()); } + let lines = s.any_line_iter().collect::<~[&str]>(); let mut saw_first_line = false; let mut saw_second_line = false; let min_indent = do lines.iter().fold(uint::max_value) @@ -76,19 +74,20 @@ fn unindent(s: &str) -> ~str { } }; - if !lines.is_empty() { - let unindented = ~[lines.head().trim().to_owned()] - + do lines.tail().map |line| { - if line.is_whitespace() { - copy *line - } else { - assert!(line.len() >= min_indent); - line.slice(min_indent, line.len()).to_owned() - } - }; - unindented.connect("\n") - } else { - s.to_str() + match lines { + [head, .. tail] => { + let mut unindented = ~[ head.trim() ]; + unindented.push_all(do tail.map |&line| { + if line.is_whitespace() { + line + } else { + assert!(line.len() >= min_indent); + line.slice_from(min_indent) + } + }); + unindented.connect("\n") + } + [] => s.to_owned() } } diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 06ec6769385..0af6ed724e1 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -370,7 +370,7 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, if arg.ends_with(".rs") || arg.ends_with(".rc") { (arg.slice_to(arg.len() - 3).to_owned(), copy *arg) } else { - (copy *arg, arg + ".rs") + (copy *arg, *arg + ".rs") }; match compile_crate(filename, copy repl.binary) { Some(_) => loaded_crates.push(crate), diff --git a/src/libstd/os.rs b/src/libstd/os.rs index fffcb34dc09..e48dc723c47 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -144,7 +144,7 @@ pub mod win32 { } pub fn as_utf16_p(s: &str, f: &fn(*u16) -> T) -> T { - let mut t = str::to_utf16(s); + let mut t = s.to_utf16(); // Null terminate before passing on. t += [0u16]; vec::as_imm_buf(t, |buf, _len| f(buf)) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 400657d0c25..9c4e8f08358 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -515,7 +515,7 @@ impl GenericPath for PosixPath { fn with_filestem(&self, s: &str) -> PosixPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -657,7 +657,7 @@ impl GenericPath for WindowsPath { (None, None) => { host = None; device = None; - rest = str::to_owned(s); + rest = s.to_owned(); } } @@ -729,7 +729,7 @@ impl GenericPath for WindowsPath { fn with_filestem(&self, s: &str) -> WindowsPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -947,7 +947,6 @@ pub mod windows { mod tests { use option::{None, Some}; use path::{PosixPath, WindowsPath, windows}; - use str; #[test] fn test_double_slash_collapsing() { @@ -984,7 +983,7 @@ mod tests { fn test_posix_paths() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1042,7 +1041,7 @@ mod tests { fn test_normalize() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1105,7 +1104,7 @@ mod tests { fn test_windows_paths() { fn t(wp: &WindowsPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 1086fcaa75c..21f747317f4 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -23,10 +23,9 @@ use cast; use char; use char::Char; use clone::Clone; -use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use container::Container; use iter::Times; -use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator}; +use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator, MapIterator}; use libc; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; @@ -37,8 +36,6 @@ use uint; use vec; use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector}; -#[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq}; - /* Section: Conditions */ @@ -291,6 +288,10 @@ pub type WordIterator<'self> = FilterIterator<'self, &'self str, StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>; +/// An iterator over the lines of a string, separated by either `\n` or (`\r\n`). +pub type AnyLineIterator<'self> = + MapIterator<'self, &'self str, &'self str, StrCharSplitIterator<'self, char>>; + impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { #[inline] fn next(&mut self) -> Option<&'self str> { @@ -400,56 +401,6 @@ impl<'self> Iterator<&'self str> for StrStrSplitIterator<'self> { } } -/// Levenshtein Distance between two strings -pub fn levdistance(s: &str, t: &str) -> uint { - - let slen = s.len(); - let tlen = t.len(); - - if slen == 0 { return tlen; } - if tlen == 0 { return slen; } - - let mut dcol = vec::from_fn(tlen + 1, |x| x); - - for s.iter().enumerate().advance |(i, sc)| { - - let mut current = i; - dcol[0] = current + 1; - - for t.iter().enumerate().advance |(j, tc)| { - - let next = dcol[j + 1]; - - if sc == tc { - dcol[j + 1] = current; - } else { - dcol[j + 1] = ::cmp::min(current, next); - dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; - } - - current = next; - } - } - - return dcol[tlen]; -} - -/** - * 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 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; } - } else { - if !it( s ) { return false; } - } - } - return true; -} - /** 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. @@ -576,196 +527,6 @@ pub fn eq(a: &~str, b: &~str) -> bool { eq_slice(*a, *b) } -#[inline] -fn cmp(a: &str, b: &str) -> Ordering { - let low = uint::min(a.len(), b.len()); - - for uint::range(0, low) |idx| { - match a[idx].cmp(&b[idx]) { - Greater => return Greater, - Less => return Less, - Equal => () - } - } - - a.len().cmp(&b.len()) -} - -#[cfg(not(test))] -impl<'self> TotalOrd for &'self str { - #[inline] - fn cmp(&self, other: & &'self str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for ~str { - #[inline] - fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for @str { - #[inline] - fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) } -} - -/// Bytewise slice less than -#[inline] -fn lt(a: &str, b: &str) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - let end = uint::min(a_len, b_len); - - let mut i = 0; - while i < end { - let (c_a, c_b) = (a[i], b[i]); - if c_a < c_b { return true; } - if c_a > c_b { return false; } - i += 1; - } - - return a_len < b_len; -} - -/// Bytewise less than or equal -#[inline] -pub fn le(a: &str, b: &str) -> bool { - !lt(b, a) -} - -/// Bytewise greater than or equal -#[inline] -fn ge(a: &str, b: &str) -> bool { - !lt(a, b) -} - -/// Bytewise greater than -#[inline] -fn gt(a: &str, b: &str) -> bool { - !le(a, b) -} - -#[cfg(not(test))] -impl<'self> Eq for &'self str { - #[inline(always)] - fn eq(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for ~str { - #[inline(always)] - fn eq(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for @str { - #[inline(always)] - fn eq(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl<'self> TotalEq for &'self str { - #[inline(always)] - fn equals(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for ~str { - #[inline(always)] - fn equals(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for @str { - #[inline(always)] - fn equals(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl Ord for ~str { - #[inline(always)] - fn lt(&self, other: &~str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &~str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &~str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &~str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self> Ord for &'self str { - #[inline(always)] - fn lt(&self, other: & &'self str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: & &'self str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: & &'self str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: & &'self str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl Ord for @str { - #[inline(always)] - fn lt(&self, other: &@str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &@str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &@str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv for &'self str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} -#[cfg(not(test))] -impl<'self, S: Str> Equiv for @str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv for ~str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - - -/* -Section: Iterating through strings -*/ - -/// Apply a function to each character -pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { - let mut result = ~""; - result.reserve(ss.len()); - for ss.iter().advance |cc| { - result.push_char(ff(cc)); - } - result -} - /* Section: Searching */ @@ -820,30 +581,6 @@ pub fn is_utf16(v: &[u16]) -> bool { return true; } -/// Converts to a vector of `u16` encoded as UTF-16 -pub fn to_utf16(s: &str) -> ~[u16] { - let mut u = ~[]; - for s.iter().advance |ch| { - // Arithmetic with u32 literals is easier on the eyes than chars. - let mut ch = ch as u32; - - if (ch & 0xFFFF_u32) == ch { - // The BMP falls through (assuming non-surrogate, as it - // should) - assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); - u.push(ch as u16) - } else { - // Supplementary planes break into surrogates. - assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); - ch -= 0x1_0000_u32; - let w1 = 0xD800_u16 | ((ch >> 10) as u16); - let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all([w1, w2]) - } - } - u -} - /// Iterates over the utf-16 characters in the specified slice, yielding each /// decoded unicode character to the function provided. /// @@ -989,40 +726,6 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { } } -/** - * Returns the byte offset of an inner slice relative to an enclosing outer slice - * - * # Example - * - * ~~~ {.rust} - * let string = "a\nb\nc"; - * let mut lines = ~[]; - * 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" - * assert!(subslice_offset(string, lines[2]) == 4); // &"c" - * ~~~ - */ -#[inline(always)] -pub fn subslice_offset(outer: &str, inner: &str) -> uint { - do as_buf(outer) |a, a_len| { - do as_buf(inner) |b, b_len| { - let a_start: uint; - let a_end: uint; - let b_start: uint; - let b_end: uint; - unsafe { - a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); - b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); - } - assert!(a_start <= b_start); - assert!(b_end <= a_end); - b_start - a_start - } - } -} - /// Unsafe operations pub mod raw { use cast; @@ -1207,12 +910,138 @@ pub mod raw { #[cfg(not(test))] pub mod traits { use ops::Add; - impl<'self> Add<&'self str,~str> for ~str { + use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq}; + use super::{Str, eq_slice}; + + impl<'self> Add<&'self str,~str> for &'self str { #[inline(always)] fn add(&self, rhs: & &'self str) -> ~str { - self.append((*rhs)) + let mut ret = self.to_owned(); + ret.push_str(*rhs); + ret } } + + impl<'self> TotalOrd for &'self str { + #[inline] + fn cmp(&self, other: & &'self str) -> Ordering { + for self.bytes_iter().zip(other.bytes_iter()).advance |(s_b, o_b)| { + match s_b.cmp(&o_b) { + Greater => return Greater, + Less => return Less, + Equal => () + } + } + + self.len().cmp(&other.len()) + } + } + + impl TotalOrd for ~str { + #[inline] + fn cmp(&self, other: &~str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl TotalOrd for @str { + #[inline] + fn cmp(&self, other: &@str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl<'self> Eq for &'self str { + #[inline(always)] + fn eq(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + #[inline(always)] + fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } + } + + impl Eq for ~str { + #[inline(always)] + fn eq(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + #[inline(always)] + fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } + } + + impl Eq for @str { + #[inline(always)] + fn eq(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) + } + #[inline(always)] + fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } + } + + impl<'self> TotalEq for &'self str { + #[inline(always)] + fn equals(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for ~str { + #[inline(always)] + fn equals(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for @str { + #[inline(always)] + fn equals(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl<'self> Ord for &'self str { + #[inline(always)] + fn lt(&self, other: & &'self str) -> bool { self.cmp(other) == Less } + #[inline(always)] + fn le(&self, other: & &'self str) -> bool { self.cmp(other) != Greater } + #[inline(always)] + fn ge(&self, other: & &'self str) -> bool { self.cmp(other) != Less } + #[inline(always)] + fn gt(&self, other: & &'self str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for ~str { + #[inline(always)] + fn lt(&self, other: &~str) -> bool { self.cmp(other) == Less } + #[inline(always)] + fn le(&self, other: &~str) -> bool { self.cmp(other) != Greater } + #[inline(always)] + fn ge(&self, other: &~str) -> bool { self.cmp(other) != Less } + #[inline(always)] + fn gt(&self, other: &~str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for @str { + #[inline(always)] + fn lt(&self, other: &@str) -> bool { self.cmp(other) == Less } + #[inline(always)] + fn le(&self, other: &@str) -> bool { self.cmp(other) != Greater } + #[inline(always)] + fn ge(&self, other: &@str) -> bool { self.cmp(other) != Less } + #[inline(always)] + fn gt(&self, other: &@str) -> bool { self.cmp(other) == Greater } + } + + impl<'self, S: Str> Equiv for &'self str { + #[inline(always)] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv for @str { + #[inline(always)] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv for ~str { + #[inline(always)] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } } #[cfg(test)] @@ -1256,6 +1085,7 @@ pub trait StrSlice<'self> { fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>; fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>; fn line_iter(&self) -> StrCharSplitIterator<'self, char>; + fn any_line_iter(&self) -> AnyLineIterator<'self>; fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; @@ -1282,6 +1112,7 @@ pub trait StrSlice<'self> { fn replace(&self, from: &str, to: &str) -> ~str; fn to_owned(&self) -> ~str; fn to_managed(&self) -> @str; + fn to_utf16(&self) -> ~[u16]; fn is_char_boundary(&self, index: uint) -> bool; fn char_range_at(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; @@ -1296,6 +1127,12 @@ pub trait StrSlice<'self> { fn repeat(&self, nn: uint) -> ~str; fn slice_shift_char(&self) -> (char, &'self str); + + fn map_chars(&self, ff: &fn(char) -> char) -> ~str; + + fn lev_distance(&self, t: &str) -> uint; + + fn subslice_offset(&self, inner: &str) -> uint; } /// Extension methods for strings @@ -1437,6 +1274,17 @@ impl<'self> StrSlice<'self> for &'self str { fn line_iter(&self) -> StrCharSplitIterator<'self, char> { self.split_options_iter('\n', self.len(), false) } + + /// An iterator over the lines of a string, separated by either + /// `\n` or (`\r\n`). + fn any_line_iter(&self) -> AnyLineIterator<'self> { + do self.line_iter().transform |line| { + let l = line.len(); + if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) } + else { line } + } + } + /// An iterator over the words of a string (subsequences separated /// by any sequence of whitespace). #[inline] @@ -1586,7 +1434,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar") * assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar") * assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar") @@ -1605,7 +1453,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11") * assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12") * assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123") @@ -1627,7 +1475,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar") * assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar") * assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar") @@ -1679,6 +1527,30 @@ impl<'self> StrSlice<'self> for &'self str { unsafe { ::cast::transmute(v) } } + /// Converts to a vector of `u16` encoded as UTF-16. + fn to_utf16(&self) -> ~[u16] { + let mut u = ~[]; + for self.iter().advance |ch| { + // Arithmetic with u32 literals is easier on the eyes than chars. + let mut ch = ch as u32; + + if (ch & 0xFFFF_u32) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); + u.push(ch as u16) + } else { + // Supplementary planes break into surrogates. + assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); + ch -= 0x1_0000_u32; + let w1 = 0xD800_u16 | ((ch >> 10) as u16); + let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + u.push_all([w1, w2]) + } + } + u + } + /** * Returns false if the index points into the middle of a multi-byte * character sequence. @@ -1921,6 +1793,85 @@ impl<'self> StrSlice<'self> for &'self str { } + /// Apply a function to each character. + fn map_chars(&self, ff: &fn(char) -> char) -> ~str { + let mut result = with_capacity(self.len()); + for self.iter().advance |cc| { + result.push_char(ff(cc)); + } + result + } + + /// Levenshtein Distance between two strings. + fn lev_distance(&self, t: &str) -> uint { + let slen = self.len(); + let tlen = t.len(); + + if slen == 0 { return tlen; } + if tlen == 0 { return slen; } + + let mut dcol = vec::from_fn(tlen + 1, |x| x); + + for self.iter().enumerate().advance |(i, sc)| { + + let mut current = i; + dcol[0] = current + 1; + + for t.iter().enumerate().advance |(j, tc)| { + + let next = dcol[j + 1]; + + if sc == tc { + dcol[j + 1] = current; + } else { + dcol[j + 1] = ::cmp::min(current, next); + dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; + } + + current = next; + } + } + + return dcol[tlen]; + } + + + /** + * Returns the byte offset of an inner slice relative to an enclosing outer slice. + * + * Fails if `inner` is not a direct slice contained within self. + * + * # Example + * + * ~~~ {.rust} + * let string = "a\nb\nc"; + * let mut lines = ~[]; + * for string.line_iter().advance |line| { lines.push(line) } + * + * assert!(string.subslice_offset(lines[0]) == 0); // &"a" + * assert!(string.subslice_offset(lines[1]) == 2); // &"b" + * assert!(string.subslice_offset(lines[2]) == 4); // &"c" + * ~~~ + */ + #[inline(always)] + fn subslice_offset(&self, inner: &str) -> uint { + do as_buf(*self) |a, a_len| { + do as_buf(inner) |b, b_len| { + let a_start: uint; + let a_end: uint; + let b_start: uint; + let b_end: uint; + unsafe { + a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); + b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); + } + assert!(a_start <= b_start); + assert!(b_end <= a_end); + b_start - a_start + } + } + } + } #[allow(missing_doc)] @@ -2280,10 +2231,10 @@ mod tests { #[test] fn test_le() { - assert!((le(&"", &""))); - assert!((le(&"", &"foo"))); - assert!((le(&"foo", &"foo"))); - assert!((!eq(&~"foo", &~"bar"))); + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != ~"bar"); } #[test] @@ -3003,15 +2954,15 @@ mod tests { let a = "kernelsprite"; 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); + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); let string = "a\nb\nc"; let mut lines = ~[]; 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); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); } #[test] @@ -3019,7 +2970,7 @@ mod tests { fn test_subslice_offset_2() { let a = "alchemiter"; let b = "cruxtruder"; - subslice_offset(a, b); + a.subslice_offset(b); } #[test] @@ -3069,8 +3020,8 @@ mod tests { #[test] fn test_map() { - assert_eq!(~"", map("", |c| unsafe {libc::toupper(c as c_char)} as char)); - assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"", "".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"YMCA", "ymca".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); } #[test] @@ -3114,10 +3065,10 @@ mod tests { for pairs.each |p| { let (s, u) = copy *p; - assert!(to_utf16(s) == u); + assert!(s.to_utf16() == u); assert!(from_utf16(u) == s); - assert!(from_utf16(to_utf16(s)) == s); - assert!(to_utf16(from_utf16(u)) == u); + assert!(from_utf16(s.to_utf16()) == s); + assert!(from_utf16(u).to_utf16() == u); } } @@ -3188,6 +3139,24 @@ mod tests { assert_eq!("abc".char_range_at_reverse(0).next, 0); } + #[test] + fn test_add() { + macro_rules! t ( + ($s1:expr, $s2:expr, $e:expr) => { + assert_eq!($s1 + $s2, $e); + assert_eq!($s1.to_owned() + $s2, $e); + assert_eq!($s1.to_managed() + $s2, $e); + } + ); + + t!("foo", "bar", ~"foobar"); + t!("foo", @"bar", ~"foobar"); + t!("foo", ~"bar", ~"foobar"); + t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam"); + } + #[test] fn test_iterator() { use iterator::*; diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 25166eca7bb..44e480dc7df 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -39,8 +39,6 @@ pub mod rt { use parse; use print::pprust; - use core::str; - pub use ast::*; pub use parse::token::*; pub use parse::new_parser_from_tts; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 035675e523e..c1bf979cd31 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -969,7 +969,7 @@ mod test { // change every identifier to "zz" pub fn to_zz() -> @fn(ast::ident)->ast::ident { let zz_id = token::str_to_ident("zz"); - |id| {zz_id} + |_id| {zz_id} } // maybe add to expand.rs... diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index b7bb1b3bc53..40352f890f4 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -89,12 +89,11 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { } return do lines.map |line| { - let mut chars = ~[]; - for line.iter().advance |c| { chars.push(c) } + let chars = line.iter().collect::<~[char]>(); if i > chars.len() { ~"" } else { - str::from_chars(chars.slice(i, chars.len()).to_owned()) + str::from_chars(chars.slice(i, chars.len())) } }; } @@ -103,14 +102,13 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { // FIXME #5475: // return comment.slice(3u, comment.len()).trim().to_owned(); let r = comment.slice(3u, comment.len()); return r.trim().to_owned(); - } if comment.starts_with("/*") { - let mut lines = ~[]; - for str::each_line_any(comment.slice(3u, comment.len() - 2u)) |line| { - lines.push(line.to_owned()) - } + let lines = comment.slice(3u, comment.len() - 2u) + .any_line_iter() + .transform(|s| s.to_owned()) + .collect::<~[~str]>(); let lines = vertical_trim(lines); let lines = block_trim(lines, ~"\t ", None); let lines = block_trim(lines, ~"*", Some(1u));