diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 800e2dcc2789..3c489719496d 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -419,6 +419,8 @@ struct TwoWaySearcher { memory: uint } +// This is the Two-Way search algorithm, which was introduced in the paper: +// Crochemore, M., Perrin, D., 1991, Two-way string-matching, Journal of the ACM 38(3):651-675. impl TwoWaySearcher { fn new(needle: &[u8]) -> TwoWaySearcher { let (critPos1, period1) = TwoWaySearcher::maximal_suffix(needle, false); @@ -437,7 +439,10 @@ impl TwoWaySearcher { let byteset = needle.iter() .fold(0, |a, &b| (1 << ((b & 0x3f) as uint)) | a); - if needle.slice_to(critPos) == needle.slice_from(needle.len() - critPos) { + // Check if the needle is periodic. If so, during searching when we + // find a mismatch, we must only advance the position by the length + // of the period, not the length of the entire needle + if needle.slice_to(critPos) == needle.slice(period, period + critPos) { TwoWaySearcher { critPos: critPos, period: period, diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index bac8d509b131..be2275dcd4a0 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -8,7 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn check_contains_all_substrings(s: &str) { + assert!(s.contains("")); + for i in range(0, s.len()) { + for j in range(i+1, s.len() + 1) { + assert!(s.contains(s.slice(i, j))); + } + } +} + #[test] fn strslice_issue_16589() { assert!("bananas".contains("nana")); + + // prior to the fix for #16589, x.contains("abcdabcd") returned false + // test all substrings for good measure + check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd"); +} + + +#[test] +fn test_strslice_contains() { + let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'"; + check_contains_all_substrings(x); }