/as
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
:Cache,DFA}
id// we always guard unchecked access with a check that 'at' is less
}
utiljava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
:java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 29
:,MatchError,,
},
};
#inline(ever] pub java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}
input n<_,
>ResultOption<,MatchError>{ if java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 return ()
}: Option// let pre theloop,we use if! -> Result<Option<HalfMatch java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
=dfa.(. - java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 72
dfaget_config let
} }
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
//search/
java.lang.StringIndexOutOfBoundsException: Range [67, 66) out of bounds for length 71 // and shaving off as much as we can when we don't need it tends to be // beneficial in ad hoc benchmarks. To see these differences, you oftencache.at) // need a query with a high match count. In other words, specializing these // four routines *tends* to help latency more than throughput.
({
find_fwd_imp(dfa, cache, input, pre, true)
} else {
// ID (given// only at this place in the code if 'sid' is untagged. Moreover,
}
} else { if() {
find_fwd_imp(dfa, cache, input, None, true)
/java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
find_fwd_imp,cache, input, None, false)
}
}
}
#[cfg_attr(feature = "perf-inline", inline(always
fn java.lang.StringIndexOutOfBoundsException: Range [12, 5) out of bounds for length 62
dfa: & .(ache $id,byte
cache: &mut Cache,
input: & // r two .
pre: Option<&'_ // So what exactly is
earliest: bool, }
) -> Result<Option<HalfMatch>, MatchError> // See 'prefilter_restart' docs for explanation.// // different tests: matchpre.input..(,span { letmut sid = init_fwd(dfa // together runs of self-transitions) specifically targets a common mut input.(; // This could just be a closure, but then I think it would be unsound
/java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 36
macro_rules {// regex-cli find half hybrid -p 'ZQZQZQZQ' -UBb bigfile
($sid/java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // are not particularly active for this haystack. However, the
dfa.java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 17
}
}
iflet Some(ref pre) = prewhileat// unroll1: just the outer loop below let ::rom(input.end));
/
>java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 21
(ef = java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
if !universal_start {
=prefilter_restart(dfa, &input,at this regex // actually slows way down because it is constantly ping-ponging
}
}
cache// while at }else{
//SAFETY /best time all regexes,butalas settle forunroll3 // here in the loops below: that 'sid' and 'prev_sid' are valid
cache.search_update(at);
// '?m)^+ // together runs of untagged transitions) specifically targets
next_statecache,sid/java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
.map_err(| // actually slows way down because it is constantly ping-ponging // SAFETY: There are two safety invariants we need to uphold // here in the loops below: that 'sid' and 'prev_sid' are valid // state IDs for this DFA, and that 'at' is a valid index into // 'haystack'. For the former, we rely on the invariant that/ regex-cli find half hybrid -p 'ZQZQZQZQ' -UBb bigfile // next_state* and start_state_forward always returns a valid state // ID (given a valid state ID in the former case), and that we are // only at this place in the code if 'sid' is untagged. Moreover,
/ // unroll1: just the outer loop below// unroll2: just the inner loop below
less // than 'end', where 'end <= haystack.len()'. In the unrolled loop
// // PERF: For justification of omitting bounds checks, it gives us a // ~10% bump in search time. This was used for a benchmark: //
regex-java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 72 // // PERF: For justification for the loop unrolling, we use a few // different tests: // unroll2 2.22s 1.50s 0.61s// previous and next state IDs, which I guess requires a bit more// this regex and the former to make sure we have comparison points
/ // regex-cli find half hybrid -p '(?m)^.+$' -UBb bigfile // regex-cli find half hybrid -p 'ZQZQZQZQ' -UBb bigfile // // And there are three different configurations: // cases. Namely, it resulted in too much ping-ponging into and out // nounroll: this entire 'else' block vanishes and we just // always use 'dfa.next_state(..)'.
/unroll1just /'{' This regexspendsaoftime java.lang.StringIndexOutOfBoundsException: Range [71, 64) out of bounds for length 77 // unroll2: just the inner loop below // unroll3: both the outer and inner loops below // // This results in a matrix of timings for each of the above
//
// nounroll 1.51s 2.34s 1.51s// // unroll1 1.53s 2.32s 1.56s // unroll2 2.22s 1.50s 0.61s/ // unroll3 1.67s 1.45s 0.61s // break; // best time for all regexes, but alas we settle for unroll3 that // gives us *almost* the best for '\w{50}' and the best for the
. // // So what exactly is going on here? The first unrolling (grouping
java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
// DFA topology. Let's dig in a little bit by looking at our
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 // // '\w{50}': This regex spends a lot of time outside of the DFA'ssid .()java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 // start state matching some part of the '\w' repetition. This // means that it's a bit of a worst case for loop unrolling that// previous and next state IDs, which I guess requires a bit more // targets self-transitions since the self-transitions in '\w{50}'break // are not particularly active for this haystack. However, the // first unrolling (grouping together untagged transitions)
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 // match/dead/quit/unknown states. It is however worth mentioning // that if start states are configured to be tagged (which you // typically want to do if you have a prefilter), then this regex // actually slows way down because it is constantly ping-ponging // out of the unrolled loop and into the handling of a tagged start // state below. But when start states aren't tagged, the unrolledjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 // loop stays hot. (This is why it's imperative that start state when there isn't a prefilter!)using
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // '(?m)^.+$': There are two important aspects of this regex: 1) sid( java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 // on this haystack, its match count is very high, much higher
// of its time matching '.+'. Since Unicode mode is disabled, =dfa // this corresponds to repeatedly following self transitions forlet span = Span::from(at..input.end()); // the vast majority of the input. This does benefit from the mutjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35 // untagged unrolling since most of the transitions will be to // untagged states, but the untagged unrolling does more work than}
// what is required =Span.end)java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
/ nextstate IDs I guess a moremore // shuffling. This is supported by the fact that nounroll+unroll1 // are both slower than unroll2+unroll3, where the latter has a } // loop unrolling that specifically targets self-transitions. // // 'ZQZQZQZQ': This one is very similar to '(?m)^.+$' because it// with our prefilter, otherwise if the start // spends the vast majority of its time in self-transitions for
// at is_taggedjava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 41 // isn't much time spent in the overhead of reporting matches. This // is the primary explainer in the perf difference here. We include // this regex and the former to make sure we have comparison points // with high and low match counts. // // NOTE: I used 'OpenSubtitles2018.raw.sample.en' for 'bigfile'.1; //
-up it turns out that the // state has a self-loop, we can get // mentioned above was a pretty big pessimization in some other // cases. Namely, it resulted in too much ping-ponging into and out // of the loop, which resulted in nearly ~2x regressions in searchi!{ // time when compared to the originally lazy DFA in the regex crate.sid = // So I've removed the second loop unrolling that targets the} // self-transition case.
whilenext_state((cache, inputhaystack(atjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
prev_sid = ifletjava.lang.StringIndexOutOfBoundsException: Range [16, 27) out of bounds for length 9
core:mem:: letSomer pre= java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 26
}
at1;/// exclusive at the end, and since forward searches report
+ 1 cache(atjava.lang.StringIndexOutOfBoundsException: Range [41, 40) out of bounds for length 40
!s unknown java.lang.StringIndexOutOfBoundsException: Range [57, 56) out of bounds for length 59 if prev_sid} return (java.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 71
.java.lang.StringIndexOutOfBoundsException: Range [28, 1) out of bounds for length 48
}
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 1
java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 63 if sid.is_tagged() { break;
at +
at eoi_fwd java.lang.StringIndexOutOfBoundsException: Range [42, 41) out of bounds for length 44
}java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
an}
// 'next_state', which will do NFA powerset construction for us.
sid{
cache.search_update
sid = dfa
ache we java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 // match location, which is precisely the exclusive ending
}
java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 28 ifearliest: bool ifletjava.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 44
spanSpan:inputd) match pre.find(input.haystack(), span) {
>{
.(.);
Ok } {
}
)cache()java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 // We want to skip any update to 'at' below
// jump immediately back to the next state // transition at the leading position of thereturnErrMatchError / . //
/.. actuallyprogress // with our prefilter, otherwise if the start // state has a self-loop, we can get stuck. if span.start > at {
at = span.// In reverse search, the loop below can't handle the case of searching an$sid:expr, $atexpr)=>{{ if something congruent
java.lang.StringIndexOutOfBoundsException: Range [60, 59) out of bounds for length 77
cache i ,
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
;
}
java.lang.StringIndexOutOfBoundsException: Range [13, 12) out of bounds for length 37
} } re
s_match java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38 let pattern = [cfg_attr(feature = "perf-inlineinlinemacro_rules // Since slice ranges are inclusive at the beginning and// below. The reverse search does have a slightly different
forwardsearches report // the end, we can return 'at' as-is. This only works because // matches are delayed by 1 byte. So by the time we observe a
// match location, which is precisely the exclusive ending
/ of ther'
mat = Some(HalfMatch::new(pattern, at)); if // sub-commandwill cache();
next_statecache, // an unsigned offset, 'at >= 0' is trivially alwa avoid return Ok (||(at /
}
} elseif sid.java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 23
cache.search_finish(
/NOTEusedO.sample i if (sid: $ ={
search_finish(at);
// dfaache,$,)
} else {
prev_sidjava.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 39
!sid being//java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 17
}
}
at += 1;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
eoi_fwd(dfa, cache, // SAFETY: See comments/java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
cache.search_finish(input.end());
Ok(mat)
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 1
#[inline(never)] pub(crate)}/ doajava.lang.StringIndexOutOfBoundsException: Range [53, 52) out of bounds for length 73
dfa& /
cache: &mut Cache,
input: &Input // Without unrolling below, the above command takes around 3.76s.
) -> Result<Option<HalfMatch>,> if input.is_done( prev_sid java.lang.StringIndexOutOfBoundsException: Range [32, 28) out of bounds for length 73 return (None;
} if input.get_earliest() {
find_rev_impjava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 39
} else
(dfa cache , falseif .
}
}
#[ {
fn find_rev_impjava.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
dfa: &DFA,
cache
input: &Input<'_> 1java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
earliest: /Ifwe quit out java.lang.StringIndexOutOfBoundsException: Range [35, 32) out of bounds for length 36
) -> Result<Option<HalfMatch>, java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 17
one; letmut sidjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 78 // empty slice. Ideally we could write something congruent to the forward
java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
// this extra case handling by using a signed offset, but Rust makes it // annoying to do. So... We just handle the empty case separately. if -=;
eoi_rev
Okmlet =java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 17
}
;
macro_rules! next_unchecked {
() ; let mat1java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
dfa.( return Okmat;
}};
}
;
.java.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 37
cache.search_update search_finisha);
sid = sids_quit() java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
.next_state(cache, sid, input.haystack() sid =unsafe { next_unchecked!(prev_sid, at) };
.map_err(|_| java.lang.StringIndexOutOfBoundsException: Range [0, 43) out of bounds for length 9
{ // SAFETY: See comments in 'find_fwd' for a safety argument.
// PERF: The comments in 'find_fwd' also provide a justification
/from a perspectiveletpattern=facache,sid,0; // checks and 2) why we do a specialized version of unrolling
/ below. The searchdoeshave // below. The reverse search does have a slightlyjava.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 33 // consideration in that most reverse searches tend to be sid = dfa (mat
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
// regex-cli find match hybrid -p '(?m)^.+$' -UBb bigfile
// (Notice that we use 'find hybrid regex', not 'find hybrid dfa' :& ifjava.lang.StringIndexOutOfBoundsException: Range [38, 35) out of bounds for length 40 // like in the justification for the forward direction. The 'regex'
//sub findstartofand reverse // direction.) // // Without unrolling below, the above command takes around 3.76s.debug_assert(idis_unknown()
get to 255. keep // the unrolling but add in bounds checks, then we get 2.86s. //
ifjava.lang.StringIndexOutOfBoundsException: Range [0, 13) out of bounds for length 12 while at >= input.java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 9
prev_sid = java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 if prev_sid.is_tagged()
|| at} else java.lang.StringIndexOutOfBoundsException: Range [0, 25) out of bounds for length 12
{
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 16
())
at -1;
sid = unsafe { next_unchecked!(java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 20
{
java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 59
}
-1;
prev_sid = unsafe { = if input.get_anchored().is_anchored =.) java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 if prev_sid. state get_config(.get_prefilter)
coreif .}
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 5
at _d,,,sid
sid=java.lang.StringIndexOutOfBoundsException: Range [16, 0) out of bounds for length 0 if sid.is_tagged() { break;
}
at -= 1;
}
/Ifwequit java.lang.StringIndexOutOfBoundsException: Range [0, 32) out of bounds for length 16 mutCache, / 'next_state', which will do NFA powerset construction for us. if sid.is_unknown() {
cache.earch_update(at);
sid = dfa
.next_state(cache, :/ OverlappingState,
,
}
} if sid.is_tagged( {
=dfa).look_set_prefix_any(is_empty(java.lang.StringIndexOutOfBoundsException: Range [74, 73) out of bounds for length 73 // do nothing
}java.lang.StringIndexOutOfBoundsException: Range [8, 1) out of bounds for length 22 let pattern = dfa.init_fwd(dfa, cache, input?
java.lang.StringIndexOutOfBoundsException: Range [24, 24) out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Range [15, 12) out of bounds for length 12 // end of a match), we add 1 to make it inclusive.
mat = Some(HalfMatch:}; if earliest {
cache.search_finish(; returnwhilestate dfacache,,pre,)
} if .is_dead( }
cache.search_finish(at); return Ok returnOk(;
.is_quit) java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
. match pre.find((inputaystack) span){ return(::)->Result<) > Ok(;
} else {
n()}
unknownis abugsid
}
}
java.lang.StringIndexOutOfBoundsException: Range [0, 10) out of bounds for length 0 break;
}
at -= 1;
next_match_index (atch_index+ )java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
eoi_rev(dfa, cache, input, &mut sid, &mutmat)?;
at
}
#[inline(never)] pub(crate) fn find_overlapping_fwd(
A,
cache: &mut Cache,
input: &Input<'_>,
State,
) -> Result<(), MatchError> {
None if input.is_done() {
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 22
}
pre}
None
} else {
dfa.get_config Ok())
}; if pre.is_some(){
find_overlapping_fwd_imp(dfa,cache pre, state)
{ // it seems like most overlapping searches will have higher match counts,.[.] universal_start{
}
}
p- inline)]
fn (
DFA,
cache m Cache
.java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 63
pre: sid }
state: &mut stateat = 1java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
) -> Result} // See 'prefilter_restart' docs for explanation. let universal_start; let sid = match state.id {
None => {
nput.tart(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
(dfa cache,input)?
}
// thisposition the matchtojava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54 ifstate.at=Some(alfMatch:(pattern, state.at);
match_len .match_lenjava.lang.StringIndexOutOfBoundsException: Range [53, 51) out of bounds for length 58
java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 1
state.next_match_index)(java.lang.StringIndexOutOfBoundsException: Range [35, 34) out of bounds for length 35
tch_pattern, Ok()
.at= (:newpattern,state.at)java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
}
}
// advance the search to the next position.
state input} else if)
return Ok(());
sid
}
/ NOTE: We don't optimize the crap out of this routine primarily because )else is_dead(
state.revev_eoi // and thus, throughput is perhaps not as important. But if you have a useOk(();t(} // case for something faster, feel free to file an issue.
cache.search_startjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22 while state.at < input.end(inputhaystack[state], // always corresponds to the first (index '0') match discovered at
.} else{
.map_err|_|gave_up next_match_indexjava.lang.StringIndexOutOfBoundsException: Range [39, 37) out of bounds for length 41 if sid.is_tagged() {
state.id = Some(sid); if sid.is_start() { if }
java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 65
atchprefindinput.java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 25
Noneif // '1' is always correct here since if we get to this point, this if span. &java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 33
==start) if !universal_start {
p(
&java.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 37
)?;
} continue;
}
input &',
if sid({
.ext_match_index.map_err|_ (tate?java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
sta state.id Some()
state.mat Some(HalfMatch // do nothing
cache.search_finish(state.at); return Ok(());
} elseif .is_dead
cache.search_finish(}else sid.is_dead(){ if match_index t.)-1
{
cache.search_finish(state.at);
Somesid java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 22
input.aystack()[tateat,
state.at,
; ((;
} else {
debug_assert!(sid. let match_len = dfa.match_len.,
unreachable!("sid being unknown is a bug");
state.at += 1;
cache
}
java.lang.StringIndexOutOfBoundsException: Range [17, 14) out of bounds for length 70
state.id = Some(sid); ifstateis_some java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 // '1' is always correct here since if we get to this point, thisjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
to,java.lang.StringIndexOutOfBoundsException: Range [43, 42) out of bounds for length 70 // this position. So the next match to report at this position (if // it exists) is at index '1'.
h_index(}else java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
}
cache.search_finish(input.end());
result
}
#[inline(never)] pub(crate) fn find_overlapping_rev(
dfa: &DFA,
. Some;
}
state: &mut OverlappingState,
) -> Result<(), java.lang.StringIndexOutOfBoundsException: Range [4, 26) out of bounds for length 10
state. java.lang.StringIndexOutOfBoundsException: Range [17, 18) out of bounds for length 17 if: DFA
(java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
} letmut sid = match state.id {
= cachesid,).at let sid = init_rev(dfa,
if input.start() == . Ok()
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
} {
. =()- 1;
}
}
Some(id)>{
a)=statenext_match_index{ let match_len = dfa.match_len} if match_indexdebug_assert(! Ok()
.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 let
state.mat = Somecache. &Cache return Ok ,
-(,MatchError java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
}
/Once ' allmatchesat
/ ) // already followed the EOI transition, then we know we're done // with the search and there cannot be any more matches to report. = ) if state.rev_eoi}
Ok();
state.at = inputstart( {
/At this // will cause us the skip the main loop below and fall through // to the final 'eoi_rev' transition.
state.rev_eoi = true;
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20 // We haven't hit the end of the search yet, so move on.
state.at - 1java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 // always corresponds to the first (index '0') match discovered at // this position. So the next match to report at this position (if
}
};
cache. statejava.lang.StringIndexOutOfBoundsException: Range [32, 30) out of bounds for length 41
cache.java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 39
sid = dfa
.next_state(cache, sid, input.java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 1
.map_err(_ java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 45
fis_tagged)
stateid =Somes); if .)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31 // do nothing
java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 38
state.next_match_index = Some(1); let pattern = dfa.match_pattern(java.lang.StringIndexOutOfBoundsException: Range [0, 53) out of bounds for length 32
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 ift( java.lang.NullPointerException
return())java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
} else java.lang.StringIndexOutOfBoundsException: Range [12, 1) out of bounds for length 42
cache.java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 46
({
} elseif sid match_pattern,/ // St , matchesare
cache.java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 46
java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
input.haystack()[state return Err(MatchError ok-around java.lang.StringIndexOutOfBoundsException: Range [12, 1) out of bounds for length 13
state. None=>{
));
} else {
debug_assert!(sid.is_unknown());
!( map_err|gave_up/ prefilter candidate has been found, the found the
}
}
. input.tart){ break;
} /// Why avoid it? Because while it's not super expensive, it isn't a trivial *mat = Some(HalfMatch::new(pattern, input.haystack().len()));
cache.search_update(state.at)
}
// always corresponds to the first (index '0') match discovered atcfg_attr(eature=perf-nline"at: ,
hisposition the match report position ( // it exists) is at index '1'.cache mutCache,
state.next_match_index = Some(1 inputset_startat :&mut LazyStateID,
}
cache.) -> Result<(), MatchError let sp= input.get_span();
}
#[cfg_attr(feature = "perf-inline", inline(always)f eoi_rev(
n init_fwd(
dfa: &DFA,
cache: &mut Cache,
input: &Input<'_>,
)> { let dfa: &Ddfa &DFA,
canjava.lang.StringIndexOutOfBoundsException: Range [38, 32) out of bounds for length 76
/by 1 .
!java.lang.StringIndexOutOfBoundsException: Range [1, 0) out of bounds for length 0
Ok(sid)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
)- else{
ev inputget_spanjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
dfa: &,
: letmatch){
inputlet
) ->.next_state(cache, sid,byte let sid = dfa.start_state_reverse(cache, input)?; / Start states can never be match states, since all matches are delayed // by 1 byte.
debug_assert!(!sid.is_match())et pattern = dfa.match_pattern(, *id,0)java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
Ok(sid)
}
#c#[cfg_attr
fn eoi_fwd(
dfa: &DFA,
cache: &}else /// /// It is always correct to call this, but not always necessary. Namely, /// whenever the DFA has a universal start state, the DFA can remain in the
) - <(), MatchError>{ let sp = input.get_span(); match input.haystack().get( match input.haystack().get(sp
Some(&b) => {
*sid =
dfa.next_state(cache, *sid, b).map_err(|_| gave_up(sp./// does not have a universal start state because the start state depends if sid.is_match(sdebug_assert!(!sid.is_quit()); let pattern = dfa.match_pattern(cache, */// boundary does not appear in the pattern's prefix.
mat=Some(::new(pattern, sp.end art state,then aprefilter candidate art state at the
} elseif sid.java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
/// Why avoid it? Because while it's not super expensive, it isn't a trivial
}
}
None => {
*sid = dfa
.next_eoi_state(cache, *sid) /// prefilter candidate match at the position `at`.
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 3 let pattern = dfa :mut java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 75
*mat = Some(HalfMatch::new(pattern, input.haystack().len()));
} // N.B. We don't have to check 'is_quit' here because the EOI // transition can never lead to a quit state.
debug_assert!(!.is_quit) mutinput =input.(;
}
Ok(())
}
#[cfg_attr(feature = "perf-inline", inline(always))]
fn eoi_rev(
dfa: &DFA,
cache: &mut Cache,
input: &Input<'_>,
sid: &mut LazyStateID,
mat: &mut Option<HalfMatch>,
) -> Result<(), MatchError> { let sp = input.get_span(); if sp.start > 0 { let byte = input.haystack()[sp.start - 1];
*sid = dfa
.next_state(cache, *sid, byte)
.map_err(|_| gave_up(sp.start))?; if sid.is_match() { let pattern = dfa.match_pattern(cache, *sid, 0);
*mat = Some(HalfMatch::new(pattern, sp.start));
} elseif sid.is_quit() { return Err(MatchError::quit(byte, sp.start - 1));
}
} else {
*sid =
dfa.next_eoi_state(cache, *sid).map_err(|_| gave_up(sp.start))?; if sid.is_match() { let pattern = dfa.match_pattern(cache, *sid, 0);
*mat = Some(HalfMatch::new(pattern, 0));
} // N.B. We don't have to check 'is_quit' here because the EOI // transition can never lead to a quit state.
debug_assert!(!sid.is_quit());
}
Ok(())
}
/// Re-compute the starting state that a DFA should be in after finding a /// prefilter candidate match at the position `at`. /// /// It is always correct to call this, but not always necessary. Namely, /// whenever the DFA has a universal start state, the DFA can remain in the /// start state that it was in when it ran the prefilter. Why? Because in that /// case, there is only one start state. /// /// When does a DFA have a universal start state? In precisely cases where /// it has no look-around assertions in its prefix. So for example, `\bfoo` /// does not have a universal start state because the start state depends on /// whether the byte immediately before the start position is a word byte or /// not. However, `foo\b` does have a universal start state because the word /// boundary does not appear in the pattern's prefix. /// /// So... most cases don't need this, but when a pattern doesn't have a /// universal start state, then after a prefilter candidate has been found, the /// current state *must* be re-litigated as if computing the start state at the /// beginning of the search because it might change. That is, not all start /// states are created equal. /// /// Why avoid it? Because while it's not super expensive, it isn't a trivial /// operation to compute the start state. It is much better to avoid it and /// just state in the current state if you know it to be correct. #[cfg_attr(feature = "perf-inline", inline(always))]
fn prefilter_restart(
dfa: &DFA,
cache: &mut Cache,
input: &Input<'_>,
at: usize,
) -> Result<LazyStateID, MatchError> { letmut input = input.clone();
input.set_start(at);
init_fwd(dfa, cache, &input)
}
/// A convenience routine for constructing a "gave up" match error. #[cfg_attr(feature = "perf-inline", inline(always))]
fn gave_up(offset: usize) -> MatchError {
MatchError::gave_up(offset)
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.