Skip to content

Commit 3cb5b8d

Browse files
author
blake2-ppc
committed
std::str: Special case char_range_at_reverse so it is faster
Implement char_range_at_reverse similarly to char_range_at, instead of re-using that method.
1 parent 4043c70 commit 3cb5b8d

File tree

1 file changed

+21
-13
lines changed

1 file changed

+21
-13
lines changed

src/libstd/str.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use iterator::{Iterator, FromIterator, Extendable};
2727
use iterator::{Filter, AdditiveIterator, Map};
2828
use iterator::{Invert, DoubleEndedIterator};
2929
use libc;
30-
use num::Zero;
30+
use num::{Saturating, Zero};
3131
use option::{None, Option, Some};
3232
use ptr;
3333
use ptr::RawPtr;
@@ -1698,21 +1698,29 @@ impl<'self> StrSlice<'self> for &'self str {
16981698
fn char_range_at_reverse(&self, start: uint) -> CharRange {
16991699
let mut prev = start;
17001700
1701-
// while there is a previous byte == 10......
1702-
while prev > 0u && self[prev - 1u] & 192u8 == TAG_CONT_U8 {
1703-
prev -= 1u;
1704-
}
1701+
prev = prev.saturating_sub(1);
1702+
if self[prev] < 128 { return CharRange{ch: self[prev] as char, next: prev} }
17051703
1706-
// now refer to the initial byte of previous char
1707-
if prev > 0u {
1708-
prev -= 1u;
1709-
} else {
1710-
prev = 0u;
1711-
}
1704+
// Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
1705+
fn multibyte_char_range_at_rev(s: &str, mut i: uint) -> CharRange {
1706+
// while there is a previous byte == 10......
1707+
while i > 0 && s[i] & 192u8 == TAG_CONT_U8 {
1708+
i -= 1u;
1709+
}
1710+
1711+
let mut val = s[i] as uint;
1712+
let w = UTF8_CHAR_WIDTH[val] as uint;
1713+
assert!((w != 0));
17121714
1715+
val = utf8_first_byte!(val, w);
1716+
val = utf8_acc_cont_byte!(val, s[i + 1]);
1717+
if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
1718+
if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
1719+
1720+
return CharRange {ch: val as char, next: i};
1721+
}
17131722
1714-
let ch = self.char_at(prev);
1715-
return CharRange {ch:ch, next:prev};
1723+
return multibyte_char_range_at_rev(*self, prev);
17161724
}
17171725
17181726
/// Plucks the character ending at the `i`th byte of a string

0 commit comments

Comments
 (0)