Skip to content

Commit 372673b

Browse files
committed
Remove char::to_lower, char::to_upper, use libc versions instead
As per Graydon's comments on #1985: remove char::to_lower and char::to_upper. The str versions of these functions now call libc::tolower and libc::toupper (using wrappers that cast between char and c_char). Not sure how much better that is, but it at least makes it clearer that these functions are Unicode-unsafe.
1 parent cab4f16 commit 372673b

File tree

3 files changed

+17
-56
lines changed

3 files changed

+17
-56
lines changed

src/libcore/char.rs

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export is_alphabetic,
3838
is_lowercase, is_uppercase,
3939
is_whitespace, is_alphanumeric,
4040
is_ascii, is_digit,
41-
to_digit, to_lower, to_upper, cmp;
41+
to_digit, cmp;
4242

4343
import is_alphabetic = unicode::derived_property::Alphabetic;
4444
import is_XID_start = unicode::derived_property::XID_Start;
@@ -122,30 +122,6 @@ pure fn to_digit(c: char, radix: uint) -> option<uint> {
122122
else { none }
123123
}
124124

125-
/*
126-
FIXME: works only on ASCII (Issue #1985)
127-
*/
128-
#[doc = "Convert a char to the corresponding lower case."]
129-
pure fn to_lower(c: char) -> char {
130-
assert is_ascii(c);
131-
alt c {
132-
'A' to 'Z' { ((c as u8) + 32u8) as char }
133-
_ { c }
134-
}
135-
}
136-
137-
/*
138-
FIXME: works only on ASCII (Issue 1985)
139-
*/
140-
#[doc = "Convert a char to the corresponding upper case."]
141-
pure fn to_upper(c: char) -> char {
142-
assert is_ascii(c);
143-
alt c {
144-
'a' to 'z' { ((c as u8) - 32u8) as char }
145-
_ { c }
146-
}
147-
}
148-
149125
#[doc = "
150126
Compare two chars
151127
@@ -206,24 +182,6 @@ fn test_to_digit() {
206182
assert to_digit('$', 36u) == none;
207183
}
208184

209-
#[test]
210-
fn test_to_lower() {
211-
assert (to_lower('H') == 'h');
212-
assert (to_lower('e') == 'e');
213-
// non-ASCII, shouldn't work (see earlier FIXME)
214-
//assert (to_lower('Ö') == 'ö');
215-
//assert (to_lower('ß') == 'ß');
216-
}
217-
218-
#[test]
219-
fn test_to_upper() {
220-
assert (to_upper('l') == 'L');
221-
assert (to_upper('Q') == 'Q');
222-
// non-ASCII, shouldn't work (see earlier FIXME)
223-
//assert (to_upper('ü') == 'Ü');
224-
//assert (to_upper('ß') == 'ß');
225-
}
226-
227185
#[test]
228186
fn test_is_ascii() unsafe {
229187
assert str::all("banana", char::is_ascii);

src/libcore/libc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,8 @@ mod funcs {
736736
fn isspace(c: c_int) -> c_int;
737737
fn isupper(c: c_int) -> c_int;
738738
fn isxdigit(c: c_int) -> c_int;
739-
fn tolower(c: c_int) -> c_int;
740-
fn toupper(c: c_int) -> c_int;
739+
fn tolower(c: c_char) -> c_char;
740+
fn toupper(c: c_char) -> c_char;
741741
}
742742

743743
#[nolink]

src/libcore/str.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ export
9595

9696
unsafe;
9797

98-
9998
#[abi = "cdecl"]
10099
native mod rustrt {
101100
fn rust_str_push(&s: str, ch: u8);
@@ -492,14 +491,14 @@ fn words(s: str) -> [str] {
492491
split_nonempty(s, {|c| char::is_whitespace(c)})
493492
}
494493

495-
#[doc = "Convert a string to lowercase"]
494+
#[doc = "Convert a string to lowercase. ASCII only"]
496495
fn to_lower(s: str) -> str {
497-
map(s, char::to_lower)
496+
map(s, {|c| (libc::tolower(c as libc::c_char)) as char})
498497
}
499498

500-
#[doc = "Convert a string to uppercase"]
499+
#[doc = "Convert a string to uppercase. ASCII only"]
501500
fn to_upper(s: str) -> str {
502-
map(s, char::to_upper)
501+
map(s, {|c| (libc::toupper(c as libc::c_char)) as char})
503502
}
504503

505504
#[doc = "
@@ -1629,6 +1628,8 @@ mod unsafe {
16291628
#[cfg(test)]
16301629
mod tests {
16311630

1631+
import libc::c_char;
1632+
16321633
#[test]
16331634
fn test_eq() {
16341635
assert (eq("", ""));
@@ -1937,9 +1938,9 @@ mod tests {
19371938

19381939
#[test]
19391940
fn test_to_upper() {
1940-
// char::to_upper, and hence str::to_upper
1941+
// libc::toupper, and hence str::to_upper
19411942
// are culturally insensitive: they only work for ASCII
1942-
// (see Issue #1985)
1943+
// (see Issue #1347)
19431944
let unicode = ""; //"\u65e5\u672c"; // uncomment once non-ASCII works
19441945
let input = "abcDEF" + unicode + "xyz:.;";
19451946
let expected = "ABCDEF" + unicode + "XYZ:.;";
@@ -1949,8 +1950,9 @@ mod tests {
19491950

19501951
#[test]
19511952
fn test_to_lower() {
1952-
assert "" == map("", char::to_lower);
1953-
assert "ymca" == map("YMCA", char::to_lower);
1953+
assert "" == map("", {|c| libc::tolower(c as c_char) as char});
1954+
assert "ymca" == map("YMCA",
1955+
{|c| libc::tolower(c as c_char) as char});
19541956
}
19551957

19561958
#[test]
@@ -2401,8 +2403,9 @@ mod tests {
24012403

24022404
#[test]
24032405
fn test_map() {
2404-
assert "" == map("", char::to_upper);
2405-
assert "YMCA" == map("ymca", char::to_upper);
2406+
assert "" == map("", {|c| libc::toupper(c as c_char) as char});
2407+
assert "YMCA" == map("ymca", {|c| libc::toupper(c as c_char)
2408+
as char});
24062409
}
24072410

24082411
#[test]

0 commit comments

Comments
 (0)