Skip to content

Commit 7e2827b

Browse files
committed
auto merge of #9059 : Kimundi/rust/master, r=huonw
- Marked a unsafe helper function as unsafe, added a second helper function - Added moving implementations
2 parents fd49f6d + 3a39342 commit 7e2827b

File tree

1 file changed

+77
-20
lines changed

1 file changed

+77
-20
lines changed

src/libstd/str/ascii.rs

+77-20
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ use str::StrSlice;
1616
use str::OwnedStr;
1717
use container::Container;
1818
use cast;
19-
use ptr;
2019
use iter::Iterator;
21-
use vec::{CopyableVector, ImmutableVector};
20+
use vec::{CopyableVector, ImmutableVector, MutableVector};
2221
use to_bytes::IterBytes;
2322
use option::{Some, None};
2423

@@ -61,7 +60,7 @@ impl Ascii {
6160
impl ToStr for Ascii {
6261
#[inline]
6362
fn to_str(&self) -> ~str {
64-
// self.chr is allways a valid utf8 byte, no need for the check
63+
// self.chr is always a valid utf8 byte, no need for the check
6564
unsafe { str::raw::from_byte(self.chr) }
6665
}
6766
}
@@ -253,16 +252,29 @@ impl ToBytesConsume for ~[Ascii] {
253252
}
254253
}
255254

256-
/// Extension methods for ASCII-subset only operations on strings
257-
pub trait StrAsciiExt {
255+
/// Extension methods for ASCII-subset only operations on owned strings
256+
pub trait OwnedStrAsciiExt {
258257
/// Convert the string to ASCII upper case:
259258
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
260259
/// but non-ASCII letters are unchanged.
261-
fn to_ascii_upper(&self) -> ~str;
260+
fn into_ascii_upper(self) -> ~str;
262261

263262
/// Convert the string to ASCII lower case:
264263
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
265264
/// but non-ASCII letters are unchanged.
265+
fn into_ascii_lower(self) -> ~str;
266+
}
267+
268+
/// Extension methods for ASCII-subset only operations on string slices
269+
pub trait StrAsciiExt {
270+
/// Makes a copy of the string in ASCII upper case:
271+
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
272+
/// but non-ASCII letters are unchanged.
273+
fn to_ascii_upper(&self) -> ~str;
274+
275+
/// Makes a copy of the string in ASCII lower case:
276+
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
277+
/// but non-ASCII letters are unchanged.
266278
fn to_ascii_lower(&self) -> ~str;
267279

268280
/// Check that two strings are an ASCII case-insensitive match.
@@ -274,12 +286,12 @@ pub trait StrAsciiExt {
274286
impl<'self> StrAsciiExt for &'self str {
275287
#[inline]
276288
fn to_ascii_upper(&self) -> ~str {
277-
map_bytes(*self, ASCII_UPPER_MAP)
289+
unsafe { str_copy_map_bytes(*self, ASCII_UPPER_MAP) }
278290
}
279291

280292
#[inline]
281293
fn to_ascii_lower(&self) -> ~str {
282-
map_bytes(*self, ASCII_LOWER_MAP)
294+
unsafe { str_copy_map_bytes(*self, ASCII_LOWER_MAP) }
283295
}
284296

285297
#[inline]
@@ -289,20 +301,34 @@ impl<'self> StrAsciiExt for &'self str {
289301
}
290302
}
291303

304+
impl OwnedStrAsciiExt for ~str {
305+
#[inline]
306+
fn into_ascii_upper(self) -> ~str {
307+
unsafe { str_map_bytes(self, ASCII_UPPER_MAP) }
308+
}
309+
310+
#[inline]
311+
fn into_ascii_lower(self) -> ~str {
312+
unsafe { str_map_bytes(self, ASCII_LOWER_MAP) }
313+
}
314+
}
315+
292316
#[inline]
293-
fn map_bytes(string: &str, map: &'static [u8]) -> ~str {
294-
let len = string.len();
295-
let mut result = str::with_capacity(len);
296-
unsafe {
297-
do result.as_mut_buf |mut buf, _| {
298-
for c in string.as_bytes().iter() {
299-
*buf = map[*c];
300-
buf = ptr::mut_offset(buf, 1)
301-
}
302-
}
303-
str::raw::set_len(&mut result, len);
317+
unsafe fn str_map_bytes(string: ~str, map: &'static [u8]) -> ~str {
318+
let mut bytes = string.into_bytes();
319+
320+
for b in bytes.mut_iter() {
321+
*b = map[*b];
304322
}
305-
result
323+
324+
str::raw::from_utf8_owned(bytes)
325+
}
326+
327+
#[inline]
328+
unsafe fn str_copy_map_bytes(string: &str, map: &'static [u8]) -> ~str {
329+
let bytes = string.byte_iter().map(|b| map[b]).to_owned_vec();
330+
331+
str::raw::from_utf8_owned(bytes)
306332
}
307333

308334
static ASCII_LOWER_MAP: &'static [u8] = &[
@@ -494,6 +520,37 @@ mod tests {
494520
}
495521
}
496522
523+
#[test]
524+
fn test_into_ascii_upper() {
525+
assert_eq!((~"url()URL()uRl()ürl").into_ascii_upper(), ~"URL()URL()URL()üRL");
526+
assert_eq!((~"hıKß").into_ascii_upper(), ~"HıKß");
527+
528+
let mut i = 0;
529+
while i <= 500 {
530+
let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
531+
else { i };
532+
assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_upper(),
533+
from_char(from_u32(upper).unwrap()))
534+
i += 1;
535+
}
536+
}
537+
538+
#[test]
539+
fn test_into_ascii_lower() {
540+
assert_eq!((~"url()URL()uRl()Ürl").into_ascii_lower(), ~"url()url()url()Ürl");
541+
// Dotted capital I, Kelvin sign, Sharp S.
542+
assert_eq!((~"HİKß").into_ascii_lower(), ~"hİKß");
543+
544+
let mut i = 0;
545+
while i <= 500 {
546+
let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
547+
else { i };
548+
assert_eq!(from_char(from_u32(i).unwrap()).into_ascii_lower(),
549+
from_char(from_u32(lower).unwrap()))
550+
i += 1;
551+
}
552+
}
553+
497554
#[test]
498555
fn test_eq_ignore_ascii_case() {
499556
assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));

0 commit comments

Comments
 (0)