Skip to content

Commit 5036087

Browse files
committed
(core::str) added rindex and rewrote pop_char with char_range_at_reverse
1 parent 27161f4 commit 5036087

File tree

1 file changed

+91
-13
lines changed

1 file changed

+91
-13
lines changed

src/libcore/str.rs

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export
7171

7272
// Searching
7373
index,
74-
//rindex,
74+
rindex,
7575
index_byte,
7676
rindex_byte,
7777
find,
@@ -255,15 +255,12 @@ Function: pop_char
255255
Remove the final character from a string and return it.
256256
257257
Failure:
258-
259258
If the string does not contain any characters.
260259
*/
261260
fn pop_char(&s: str) -> char unsafe {
262261
let end = byte_len(s);
263-
while end > 0u && s[end - 1u] & 192u8 == tag_cont_u8 { end -= 1u; }
264-
assert (end > 0u);
265-
let ch = char_at(s, end - 1u);
266-
s = unsafe::slice_bytes(s, 0u, end - 1u);
262+
let {ch:ch, prev:end} = char_range_at_reverse(s, end);
263+
s = unsafe::slice_bytes(s, 0u, end);
267264
ret ch;
268265
}
269266

@@ -894,6 +891,28 @@ fn index(ss: str, cc: char) -> option<uint> {
894891
ret option::none;
895892
}
896893

894+
// Function: rindex
895+
//
896+
// Returns the index of the first matching char
897+
// (as option some/none)
898+
fn rindex(ss: str, cc: char) -> option<uint> {
899+
let bii = byte_len(ss);
900+
let cii = char_len(ss);
901+
while bii > 0u {
902+
let {ch, prev} = char_range_at_reverse(ss, bii);
903+
cii -= 1u;
904+
bii = prev;
905+
906+
// found here?
907+
if ch == cc {
908+
ret option::some(cii);
909+
}
910+
}
911+
912+
// wasn't found
913+
ret option::none;
914+
}
915+
897916
/*
898917
Function: index
899918
@@ -1259,6 +1278,25 @@ Pluck a character out of a string
12591278
*/
12601279
fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }
12611280

1281+
// Function: char_range_at_reverse
1282+
//
1283+
// Given a byte position and a str, return the previous char and its position
1284+
// This function can be used to iterate over a unicode string in reverse.
1285+
fn char_range_at_reverse(ss: str, start: uint) -> {ch: char, prev: uint} {
1286+
let prev = start;
1287+
1288+
// while there is a previous byte == 10......
1289+
while prev > 0u && ss[prev - 1u] & 192u8 == tag_cont_u8 {
1290+
prev -= 1u;
1291+
}
1292+
1293+
// now refer to the initial byte of previous char
1294+
prev -= 1u;
1295+
1296+
let ch = char_at(ss, prev);
1297+
ret {ch:ch, prev:prev};
1298+
}
1299+
12621300
/*
12631301
Function: substr_all
12641302
@@ -1468,18 +1506,58 @@ mod tests {
14681506
}
14691507

14701508
#[test]
1471-
fn test_index_and_rindex() {
1472-
assert (index_byte("hello", 'e' as u8) == 1);
1473-
assert (index_byte("hello", 'o' as u8) == 4);
1474-
assert (index_byte("hello", 'z' as u8) == -1);
1475-
assert (index("hello", 'e') == option::some(1u));
1476-
assert (index("hello", 'o') == option::some(4u));
1477-
assert (index("hello", 'z') == option::none);
1509+
fn test_index() {
1510+
assert ( index("hello", 'h') == option::some(0u));
1511+
assert ( index("hello", 'e') == option::some(1u));
1512+
assert ( index("hello", 'o') == option::some(4u));
1513+
assert ( index("hello", 'z') == option::none);
1514+
}
1515+
1516+
#[test]
1517+
fn test_rindex() {
1518+
assert (rindex("hello", 'l') == option::some(3u));
1519+
assert (rindex("hello", 'o') == option::some(4u));
1520+
assert (rindex("hello", 'h') == option::some(0u));
1521+
assert (rindex("hello", 'z') == option::none);
1522+
}
1523+
1524+
#[test]
1525+
fn test_index_byte() {
1526+
assert ( index_byte("hello", 'e' as u8) == 1);
1527+
assert ( index_byte("hello", 'o' as u8) == 4);
1528+
assert ( index_byte("hello", 'z' as u8) == -1);
1529+
}
1530+
1531+
#[test]
1532+
fn test_rindex_byte() {
14781533
assert (rindex_byte("hello", 'l' as u8) == 3);
14791534
assert (rindex_byte("hello", 'h' as u8) == 0);
14801535
assert (rindex_byte("hello", 'z' as u8) == -1);
14811536
}
14821537

1538+
#[test]
1539+
fn test_pop_char() {
1540+
let data = "ประเทศไทย中华";
1541+
let cc = pop_char(data);
1542+
assert "ประเทศไทย中" == data;
1543+
assert '华' == cc;
1544+
}
1545+
1546+
#[test]
1547+
fn test_pop_char_2() {
1548+
let data2 = "华";
1549+
let cc2 = pop_char(data2);
1550+
assert "" == data2;
1551+
assert '华' == cc2;
1552+
}
1553+
1554+
#[test]
1555+
#[should_fail]
1556+
fn test_pop_char_fail() {
1557+
let data = "";
1558+
let _cc3 = pop_char(data);
1559+
}
1560+
14831561
#[test]
14841562
fn test_split_byte() {
14851563
fn t(s: str, c: char, u: [str]) {

0 commit comments

Comments
 (0)