Skip to content

Commit c2d1026

Browse files
committed
Use find_byte (memchr) in substring search
1 parent 7948224 commit c2d1026

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

Diff for: src/libcore/str/pattern.rs

+84
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use prelude::v1::*;
2121

2222
use cmp;
23+
use slice;
2324
use usize;
2425

2526
// Pattern
@@ -545,6 +546,7 @@ pub struct StrSearcher<'a, 'b> {
545546
#[derive(Clone, Debug)]
546547
enum StrSearcherImpl {
547548
Empty(EmptyNeedle),
549+
Single(SingleByte),
548550
TwoWay(TwoWaySearcher),
549551
}
550552

@@ -556,6 +558,15 @@ struct EmptyNeedle {
556558
is_match_bw: bool,
557559
}
558560

561+
#[derive(Clone, Debug)]
562+
struct SingleByte {
563+
byte: u8,
564+
position: usize,
565+
end: usize,
566+
is_match_fw: bool,
567+
is_match_bw: bool,
568+
}
569+
559570
impl<'a, 'b> StrSearcher<'a, 'b> {
560571
fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> {
561572
if needle.is_empty() {
@@ -569,6 +580,19 @@ impl<'a, 'b> StrSearcher<'a, 'b> {
569580
is_match_bw: true,
570581
}),
571582
}
583+
} else if needle.len() == 1 {
584+
// Note: A single byte needle must have a single ASCII byte.
585+
StrSearcher {
586+
haystack: haystack,
587+
needle: needle,
588+
searcher: StrSearcherImpl::Single(SingleByte {
589+
byte: needle.as_bytes()[0],
590+
position: 0,
591+
end: haystack.len(),
592+
is_match_fw: false,
593+
is_match_bw: false,
594+
}),
595+
}
572596
} else {
573597
StrSearcher {
574598
haystack: haystack,
@@ -601,6 +625,24 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
601625
}
602626
}
603627
}
628+
StrSearcherImpl::Single(ref mut searcher) => {
629+
let pos = searcher.position;
630+
if searcher.is_match_fw {
631+
searcher.is_match_fw = false;
632+
searcher.position += 1;
633+
SearchStep::Match(pos, pos + 1)
634+
} else {
635+
match slice::bytes::find_byte(searcher.byte,
636+
&self.haystack.as_bytes()[pos..]) {
637+
None => SearchStep::Done,
638+
Some(index) => {
639+
searcher.position += index;
640+
searcher.is_match_fw = true;
641+
SearchStep::Reject(pos, searcher.position)
642+
}
643+
}
644+
}
645+
}
604646
StrSearcherImpl::TwoWay(ref mut searcher) => {
605647
// TwoWaySearcher produces valid *Match* indices that split at char boundaries
606648
// as long as it does correct matching and that haystack and needle are
@@ -641,6 +683,18 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
641683
}
642684
}
643685
}
686+
StrSearcherImpl::Single(ref mut searcher) => {
687+
let pos = searcher.position;
688+
searcher.is_match_fw = false;
689+
match slice::bytes::find_byte(searcher.byte,
690+
&self.haystack.as_bytes()[pos..]) {
691+
None => None,
692+
Some(index) => {
693+
searcher.position += index;
694+
Some((index, index + 1))
695+
}
696+
}
697+
}
644698
StrSearcherImpl::TwoWay(ref mut searcher) => {
645699
let is_long = searcher.memory == usize::MAX;
646700
// write out `true` and `false` cases to encourage the compiler
@@ -676,6 +730,24 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
676730
}
677731
}
678732
}
733+
StrSearcherImpl::Single(ref mut searcher) => {
734+
let end = searcher.position;
735+
if searcher.is_match_bw {
736+
searcher.is_match_bw = false;
737+
searcher.end -= 1;
738+
SearchStep::Match(end - 1, end)
739+
} else {
740+
match slice::bytes::rfind_byte(searcher.byte,
741+
&self.haystack.as_bytes()[..end]) {
742+
None => SearchStep::Done,
743+
Some(index) => {
744+
searcher.end = index + 1;
745+
searcher.is_match_bw = true;
746+
SearchStep::Reject(index, end)
747+
}
748+
}
749+
}
750+
}
679751
StrSearcherImpl::TwoWay(ref mut searcher) => {
680752
if searcher.end == 0 {
681753
return SearchStep::Done;
@@ -711,6 +783,18 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
711783
}
712784
}
713785
}
786+
StrSearcherImpl::Single(ref mut searcher) => {
787+
let end = searcher.position;
788+
searcher.is_match_bw = false;
789+
match slice::bytes::rfind_byte(searcher.byte,
790+
&self.haystack.as_bytes()[..end]) {
791+
None => None,
792+
Some(index) => {
793+
searcher.end = index;
794+
Some((index, index + 1))
795+
}
796+
}
797+
}
714798
StrSearcherImpl::TwoWay(ref mut searcher) => {
715799
let is_long = searcher.memory == usize::MAX;
716800
// write out `true` and `false`, like `next_match`

0 commit comments

Comments
 (0)