std::ascii: Provide a copyless [Ascii] -> str method.

This renames to_str_ascii to as_str_ascii and makes it non-copying,
which is possible now that strings no longer have a hidden extra
byte/null terminator.

Fixes #6120.
This commit is contained in:
Huon Wilson 2013-11-07 18:59:40 +11:00
parent 7fc689305c
commit b95a8c63fd
5 changed files with 24 additions and 33 deletions

View File

@ -52,10 +52,8 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[ExpectedError] {
let start_kind = idx;
while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
// 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 = line.slice(start_kind, idx);
let kind = kind.to_ascii().to_lower().to_str_ascii();
let kind = kind.to_ascii().to_lower().into_str();
// Extract msg:
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }

View File

@ -887,12 +887,8 @@ mod tests {
// tjc: funny that we have to use parens
fn ile(x: &(&'static str), y: &(&'static str)) -> bool
{
// FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
// to_ascii_move and to_str_move to not do a unnecessary clone.
// (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on
// Ascii)
let x = x.to_ascii().to_lower().to_str_ascii();
let y = y.to_ascii().to_lower().to_str_ascii();
let x = x.to_ascii().to_lower().into_str();
let y = y.to_ascii().to_lower().into_str();
x <= y
}

View File

@ -669,10 +669,8 @@ pub fn build_session_options(binary: @str,
for level in lint_levels.iter() {
let level_name = lint::level_to_str(*level);
// FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
// to_ascii_move and to_str_move to not do a unnecessary copy.
let level_short = level_name.slice_chars(0, 1);
let level_short = level_short.to_ascii().to_upper().to_str_ascii();
let level_short = level_short.to_ascii().to_upper().into_str();
let flags = vec::append(matches.opt_strs(level_short),
matches.opt_strs(level_name));
for lint_name in flags.iter() {

View File

@ -17,7 +17,7 @@ use str::OwnedStr;
use container::Container;
use cast;
use iter::Iterator;
use vec::{CopyableVector, ImmutableVector, MutableVector};
use vec::{ImmutableVector, MutableVector};
use to_bytes::IterBytes;
use option::{Some, None};
@ -154,10 +154,10 @@ impl AsciiCast<Ascii> for char {
/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
/// Take ownership and cast to an ascii vector without trailing zero element.
/// Take ownership and cast to an ascii vector.
fn into_ascii(self) -> ~[Ascii];
/// Take ownership and cast to an ascii vector without trailing zero element.
/// Take ownership and cast to an ascii vector.
/// Does not perform validation checks.
unsafe fn into_ascii_nocheck(self) -> ~[Ascii];
}
@ -188,10 +188,11 @@ impl OwnedAsciiCast for ~str {
}
}
/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
pub trait AsciiStr {
/// Convert to a string.
fn to_str_ascii(&self) -> ~str;
fn as_str_ascii<'a>(&'a self) -> &'a str;
/// Convert to vector representing a lower cased ascii string.
fn to_lower(&self) -> ~[Ascii];
@ -199,15 +200,14 @@ pub trait AsciiStr {
/// Convert to vector representing a upper cased ascii string.
fn to_upper(&self) -> ~[Ascii];
/// Compares two Ascii strings ignoring case
/// Compares two Ascii strings ignoring case.
fn eq_ignore_case(self, other: &[Ascii]) -> bool;
}
impl<'self> AsciiStr for &'self [Ascii] {
#[inline]
fn to_str_ascii(&self) -> ~str {
let cpy = self.to_owned();
unsafe { cast::transmute(cpy) }
fn as_str_ascii<'a>(&'a self) -> &'a str {
unsafe { cast::transmute(*self) }
}
#[inline]
@ -443,12 +443,12 @@ mod tests {
let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
let v = ~"( ;"; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#");
assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#");
assert_eq!("abCDef&?#".to_ascii().to_lower().into_str(), ~"abcdef&?#");
assert_eq!("abCDef&?#".to_ascii().to_upper().into_str(), ~"ABCDEF&?#");
assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~"");
assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca");
assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;");
assert_eq!("".to_ascii().to_lower().into_str(), ~"");
assert_eq!("YMCA".to_ascii().to_lower().into_str(), ~"ymca");
assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().into_str(), ~"ABCDEFXYZ:.;");
assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));
@ -465,7 +465,10 @@ mod tests {
}
#[test]
fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }
fn test_ascii_as_str() {
let v = v2ascii!([40, 32, 59]);
assert_eq!(v.as_str_ascii(), "( ;");
}
#[test]
fn test_ascii_into_str() {

View File

@ -72,10 +72,8 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
let (k,v) = (*kv).clone();
unsafe {
let b = str::raw::from_utf8(k);
// FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
// to_ascii_move and to_str_move to not do a unnecessary copy.
buffer.push_str(format!("{} {:0.3f}\n",
b.to_ascii().to_upper().to_str_ascii(), v));
b.into_ascii().to_upper().into_str(), v));
}
}
@ -84,9 +82,7 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
// given a map, search for the frequency of a pattern
fn find(mm: &HashMap<~[u8], uint>, key: ~str) -> uint {
// FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
// to_ascii_move and to_str_move to not do a unnecessary copy.
let key = key.to_ascii().to_lower().to_str_ascii();
let key = key.into_ascii().to_lower().into_str();
match mm.find_equiv(&key.as_bytes()) {
option::None => { return 0u; }
option::Some(&num) => { return num; }