cratejava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
hybrid::{
id:L
},
util::{java.lang.StringIndexOutOfBoundsException: Range [17, 16) out of bounds for length 35 // need a query with a high match count. In other words, specializing these
! java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
,
};
#[}else { pub(crate) fn
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
&nput'>
) -> Resultcache find_fwd_imp(dfa, cinput,None,rue
find_fwd_impdfa ache , ) return Ok(None);
} let java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 12 else{
dfa.get_config().get_prefilter map_err_| gave_up(atjava.lang.StringIndexOutOfBoundsException: Range [36, 14) out of bounds for length 14
// So what we do here is specialize four different versions of 'find_fwd':
/one of combinations for 'hasprefilter'andsearliest // search'. The reason for doing this is that both of these things require
/ branches // branches and special handling andthatt is into
/and shaving off as
/hybrid: // need a query with a high match count. In other words, specializing these // four routines *tends* to help latency more than throughput.
pre.() { if input.get_earliest java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
find_fwd_impdfacache input ,truejava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
}else {
find_fwd_imp(,, /a check thatsid untagged :,OverlappingState DFA}
}
} else { if input}java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
find_fwd_imp(dfa, prefilter:Prefilter,
} else {
dfa cache ch:{,Input Span},
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
# cache:& /java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
)- Result<HalfMatch> MatchError java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
fa:DFA
cache:&mutmatch.findinput.(, span {
input: &Input< return OkNone;
e Option //
PERF unrollingusejava.lang.StringIndexOutOfBoundsException: Range [75, 76) out of bounds for length 75
>//
//Seesid = prefilter_restart, i,; let dfa) clifindhybrid p'?^.$-UBbbigfile letmut ; letmut sid = init_fwd(dfa, cache, let} // This could just be a closure, but then I think it would be unsound // because it would need to be safe to invoke. This way, the lack of safetywhile at< nput.() // search'. The reason for doing this is that both of these things require// always use 'dfa.next_state(..)'.veryhot // is clearer in the code below.
java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 61
d:xpr a:)= {java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35 let byte =*inputhaystack(.get_uncheckeda);
dfaext_state_untagged_uncheckedjava.lang.StringIndexOutOfBoundsException: Range [63, 51) out of bounds for length 64
java.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 11
java.lang.StringIndexOutOfBoundsException: Range [6, 5) out of bounds for length 5
java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 let span = // different tests: match .find.haystackjava.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 48
None= in little =.java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
Some(
at = span.start is clearer if ! macro_rules! next_unchecked ! next_unchecked {// regex-cli find half hybrid -p 'ZQZQZQZQ' -UBb bigfile
/java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
}
}
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 // unroll1: just the outer loop below ifsid.java.lang.StringIndexOutOfBoundsException: Range [29, 27) out of bounds for length 65
cache.search_update(at match
=dfa
.next_state( (ef) java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
.map_err(|// nounroll 1.51s 2.34s 1.51s// that if start states are configured to be tagged (which yousid =prefilter_restart(,cache, & // typically want to do if you have a prefilter), then
} else{
/ : / java.lang.StringIndexOutOfBoundsException: Range [24, 19) out of bounds for length 77 // 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 // loop stays hot. (This is why it's imperative that start state // 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. java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 // only at this place in the code if 'sid' is untagged. Moreover, // every call to next_state_untagged_unchecked below is guarded by // a check that sid is untagged. For the latter safety invariant,
java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78 // than 'end', where 'end <= haystack.len()'. In the unrolled loop // below, we ensure that 'at' is always in bounds. // // PERF: For justification of omitting bounds checks, it gives us a // ~10% bump in search time. This was used for a benchmark:
// regex-cli find half hybrid -p '(?m)^.+$' -UBb bigfile.next_state(cache, // match/dead/quit/unknown states. It is however worth mentioning //
java.lang.StringIndexOutOfBoundsException: Range [76, 75) out of bounds for length 75 // different tests: // // regex-cli find half hybrid -p '\w{50}' -UBb bigfile // regex-cli find half hybrid -p '(?m)^.+$' -UBb bigfile // regex-cli find half hybrid -p 'ZQZQZQZQ' -UBb bigfile // // And there are three different configurations:// on this haystack, its match count is very high, much higher// are both slower than unroll2+unroll3, where the latter has a // // nounroll: this entire 'else' block vanishes and we just
// 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// the (implicit) unanchored prefix. The main difference withjava.lang.StringIndexOutOfBoundsException: Range [78, 79) out of bounds for length 78 // regexes with each of the above unrolling configurations: // // '\w{50}' '(?m)^.+$' 'ZQZQZQZQ' // nounroll 1.51s 2.34s 1.51s/regexcli findhalf hybrid- 'm.$ UBb bigfile // unroll1 1.53s 2.32s 1.56s
// unroll3 1.67s 1.45s 0.61s // // Ideally we'd be able to find a configuration that yields the // 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 // other two regexes.
java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71 // So what exactly is going on here? The first unrolling (grouping // together runs of untagged transitions) specifically targets // our choice of representation. The second unrolling (grouping // together runs of self-transitions) specifically targets a common // the (implicit) unanchored prefix. The main difference with // regexes: // time when compared to the originally lazy DFA in the regex crate.
/w{} This regexspends lot theDFA' // start state matching some part of the '\w' repetition. This // means that it's a bit of a worst case for loop unrolling that // targets self-transitions since the self-transitions in '\w{50}' // are not particularly active for this haystack. However, the// this regex and the former to make sure we have comparison points // first unrolling (grouping together untagged transitions)// '\w{50}' '(?m)^.+$' 'ZQZQZQZQ' // does apply quite well here since very few transitions hit // 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 prev_sidjava.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57 // 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 unrolled // loop stays hot. (This is why it's imperative that start state
ther ,)} //
/ 'm^$:Therehereare / together runs of untagged transitions) specifically targets
// this haystack, its atch isveryhighi/ our choice of representation. The second unrolling (grouping // than the other two regex and 2) it spends the vast majority// together runs of self-transitions) specifically targets a common // of its time matching '.+'. Since Unicode mode is disabled, // this corresponds to repeatedly following self transitions forjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 // the vast majority of the input. This does benefit from the // untagged unrolling since most of the transitions will be to
; // what is actually required. Namely, it has to keep track of the // previous and next state IDs, which I guess requires a bit more // 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.
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // 'ZQZQZQZQ': This one is very similar to '(?m)^.+$' because it // spends the vast majority of its time in self-transitions for// If we quit out of the code above with an unknown state ID at} // the (implicit) unanchored prefix. The main difference with // '(?m)^.+$' is that it has a much lower match count. So there // 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'.} //
/NOTE a // tagging be disabled using // mentioned above was a pretty big pessimization in some other//
/if{
/of loop,which resulted in nearly ~2x regressions in search // time when compared to the originally lazy DFA in the regex crate.let// than the other two regex and 2) it spends the vast majority // So I've removed the second loop unrolling that targets the
//self-case. letmut prev_sid = sid; while at < input.end() { cache.search_finish}
prev_sid = unsafe Ok(mat; if prev_sid.is_tagged // what is actually required. Namely, it has to keep track of theactually . letspan =:from(..()java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
core::mem::swap(&mut prev_sid, &mut sid); break;
cachesearch_finish
sid return()java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43 if break;
}
at += 1;
prev_sid = unsafe { next_unchecked!(sid,
prev_sid({ if! { break;
}
at += 1java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
sid = // NOTE: In a follow, it out the " if sid.is_tagged() {
spanstart;
}
at += if {
} / If we quit out of the code above with an unknown state ID at // any point, then we need to re-compute that transition using // 'next_state', which will do NFA powerset construction for us. if sid.is_unknown() {
cache.search_update(at)}
java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 70
=
}
if sid.is_tagged() {
)java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 let span = Span::from(at match pre.findat += ;
=> the/ by1byte.Soby the time //match at has been set 1 byte HalfMatch:(pattern );
cache.search_finish(span.end} elseifsid.is_dead earliest {
Ok)java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
Some }
// at the end of this iteration and just
.; // transition at the leading position of the // candidate match.
prev_sid"id being unknownisabug")
// state has a self-loop, we can get stuck.dfa , input mut,&mutjava.lang.StringIndexOutOfBoundsException: Range [20, 1) out of bounds for length 61
span. >at{
at = java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 17
inline(never)]
prefilter_restart(
dfa, cache
)?;
} continue;
MatchError {
}
}
}
} Okmat) let pattern =dfa.atch_pattern( let pattern = dfa.match_pattern(cache
// // exclusive at the end, and since forward searches report // the end, we can return 'at' as-is. This only works because( dfa ..s_unknown)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
d1byte by time weobserve java.lang.StringIndexOutOfBoundsException: Range [77, 78) out of bounds for length 77
fnfind_rev_imp
java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 // bound of the match.
mat=(HalfMatch::s_tagged()java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
{
)-Result<HalfMatch> MatchError> { return( :rom..java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
} None= java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
} returnOk( java.lang.StringIndexOutOfBoundsException: Range [11, 10) out of bounds for length 12
cache.a)java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 return Ok(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
} // at the end of this iteration and just
ache.earch_finish(at; return Err(
{ if input() = input.ndinput:Iput<> // candidate match./candidate match.
unreachable! earliest bool / . butonly we progress
}
}
at += 1;
}
eoi_fwd(dfa, cache, input, &mut sid, &mutjava.lang.StringIndexOutOfBoundsException: Range [46, 33) out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Range [78, 37) out of bounds for length 37
Ok(mat)
}
#[(ever)] pub(crate) fn find_rev(
cache: &mut Cache,
: &Input cache.search_start(at);
) -> Resultsid = prefilter_restart(// ,' loop{ if input.is_done() {
OkNne dfa,, &nput
} if input.get_earliest() {
find_rev_imp(dfa, cache, input, true)
}
java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0
}
}
#[, inlinemacro_rules!next_unchecked{
fn find_rev_imp(
dfa:
cache: &java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
input:
earliest:bool
) -> Result<java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 14 letmut mat// match, 'at' has already been set to 1 byte past the actual.search_start; mut bound direction ' // In reverse search, the loop below can't handle the case of searching an
empty .search_updateatjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36 // search, i.e., 'while at >= start', but 'start' might be 0. Since we use
ys true. couldavoid // this extra case handling by using a signed offset, but Rust makes it returnOk .map_err_ gave_up(/
java.lang.StringIndexOutOfBoundsException: Range [8, 6) out of bounds for length 16
eoi_rev, , input } return Ok(mat /
}
macro_rules NOTE: '.'i.
($ texpr) { let bytecache.java.lang.StringIndexOutOfBoundsException: Range [38, 35) out of bounds for length 40
dfa( $,java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
}};
ifprev_sidis_tagged) loop {
sid.is_tagged( unreachable!"being ifference..Take
cache.earch_update(at);
sid = dfa
.next_state(cache, sid, input.java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 26
. }
} else { // SAFETY: See comments in 'find_fwd' for a safety argument.// // // PERF: The comments in 'find_fwd' also provide a justification // from a performance perspective as to 1) why we elide bounds
/checksand)whywe // below. The reverse search does have a slightly different:&FA/java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // consideration in that most reverse searches tend to be prev_sid unsafe { next_unchecked!(sid, at) }; // anchored and on shorter haystacks. However, this still makes a
: // // regex-cli find match hybrid -p '(?m)^.+$' -UBb bigfile // // (Notice that we use 'find hybrid regex', not 'find hybrid dfa' // like in the justification for the forward direction. The 'regex' // sub-command will find start-of-match and thus run the reverse // direction.) // // Without unrolling below, the above command takes around 3.76s. // But with the unrolling below, we get down to 2.55s. If we keepif // the unrolling but add in bounds checks, then we get 2.86s. //
is_tagged{ letmut// any point, then we need to re-compute that transition using
at=;
prev_sid = unsafe { =unsafenext_unchecked(, at cache/reverse ,java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 78
s_taggedt// search, i.e., 'while at >= start', but 'start' might be 0. Since we use
|| // an unsigned offset, 'at >= 0' is trivially always true. We could avoid
{
coreis_start() java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31 break;} else eoi_rev
at -= 1;
sid sid if sid.$sid:expr, $at:expr break break;
}
at -= 1;
prev_sid = unsafe { next_state_untagged_unchecked Ok()java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 27
:(utjava.lang.StringIndexOutOfBoundsException: Range [50, 49) out of bounds for length 61
ejava.lang.StringIndexOutOfBoundsException: Range [37, 35) out of bounds for length 40
.java.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 37
-=1;
{ java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 63 if sid.is_tagged() { break } else{
}
at -= //
} // If we quit out of the code above with an unknown state ID at/fromaperformance pattern =.atch_pattern 0 // any point, then we need to re-compute that transition using // 'next_state', which will do NFA powerset construction for us.
sidis_unknown java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 52
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 1
.map_err(|_| gave_up(at//
dfa: &DFAjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
}
java.lang.StringIndexOutOfBoundsException: Range [16, 1) out of bounds for length 40 if state: &mut OverlappingStat,
/
mat .search_finish);
pattern = .(cache java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 71 // Since reverse searches report the beginning of a match // and the beginning is inclusive (not exclusive like the // end of a match), we add 1 to make it inclusive. = if(sidbeing // But with the unrolling below, we .. we / NOTE: I used 'OpenSubtitles2018.raw.sample.en' for 'bigfile'.
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
cachesearch_finish();
returnOk
}
}elseif mat
cachejava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
} elseif breakverlapping_fwd,]
cache.search_finish(at); return Err(MatchError::quit(input.haystack()[at], at));
} else {
debug_assert!(state m OverlappingState( {
unreachable!("sid being unknown is a bug"-Result<,MatchError>java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
at-1java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
}
java.lang.StringIndexOutOfBoundsException: Range [14, 10) out of bounds for length 32 break;
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
at }i(,,java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 40
}
cache if Some(match_index)=state}
eoi_rev atrlapping( cache let match_len = dfa.match_len(cachsid;
Ok(mat) if sid = unsafe =
}
[nlinenever)java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 pub(crate ()java.lang.StringIndexOutOfBoundsException: Range [33, 22) out of bounds for length 22
dfa: &DFA,
cache: &mut Cache,
input /mutOverlappingStatejava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Range [32, 9) out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
. ifsal_start (.(; if input.is_done(if .is_done( java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
ststatet java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 37
} let pre = if//Since
None
dfa. match_len match_len(cache, sid)// it seems like most overlapping searches will have higher match counts,
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6 ifcache.java.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 44
dfa nputprestate)
} else {
java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 17
}
}
(;
fn } else if sid( {
,
cache: &mut Cache // advance the search to the next position. Somesd;
input: &Input<'_java.lang.StringIndexOutOfBoundsException: Range [12, 1) out of bounds for length 26
pre <_,
cache.earch_finish(at);match.(input.()span java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
-(,MatchError> ()java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30 // See 'prefilter_restart' docs for explanation. let universal_start = dfa.unreachable!("sid beingunknown a buga bug java.lang.StringIndexOutOfBoundsException: Range [15, 16) out of bounds for length 15 letmut sid =
None => {
state. // it seems like most overlapping searches will have higher match counts,
}
Somesid) = {
state.at <.){ let match_len =dfamatch_len(, = if match_index < match_len {
state.next_match_index =Somem +1;
tch_patternc java.lang.StringIndexOutOfBoundsException: Range [63, 62) out of bounds for length 77
state= HalfMatch: return Ok(());
}
// Once we've reported all matches at a given position, we need tojava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // advance the search to the next position.letpatternjava.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 33
state.at += 1; ifmatch prefind(nput.) ) return(); return Ok(());
java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
}
pre)java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
} { // it seems like most overlapping searches will have higher match counts,.(] !universal_start {
is not important.Butifyou use // case for something faster, feel free to file an issue.
cache.search_start(stateeature erf"inlinejava.lang.StringIndexOutOfBoundsException: Range [50, 49) out of bounds for length 52 while ,
cache:&ut Cache,
next_state(cache, sid, input.haystack()[state.at])
.map_err(|_| gave_up(state.at))?; if sid.is_tagged}
state.id } if sid.is_start() {
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 letlet match
java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 46
Some(// always corresponds to the first (index '0') match discovered at
atjava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
.mat pattern)java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68 if !universal_start {
sid = prefilter_restartifmatch_index <match_len
(return(java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
)?;
}
}
}
}
sid.is_match( {
.next_match_index Some(1java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 39 let pattern =
debug_assert.()
let sid (,cache, return Ok(());
} if sidis_dead java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
// it seems like most .ev_eoi return Ok()uendjava.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 5
} elseif state.id =(id;
.at.( {
ErrMatchError:quit(
.()[state.at],
at,
;
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
debug_asserts.)
unreachable!("sid}
}
}
state.at + result
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
let result = (crate) fn find_overlapping_rev
state.id = Some( java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 if. 've // always corresponds to the first (index '0') match discovered at // this position. So the next match to report at this position (if:mut, // it exists) is at index '1'.
state.next_match_index = state.at= input.)
}
cache.search_finish(input.end());
resultdfa, cache, &.rev_eoi=true java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
#[ >{ pub}
dfa: &DFA,
cache: &mut state.id sid);
_
state: sid=java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
) -> Resultstate.ext_match_indexjava.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 45
state.mat = None; if input.is_done() { return Ok( mat = Some state.mat = Some(HalfMatch
} letmut sid = match state.id {
None => { let statemat HalfMatch:new(,stateat 1);
state.id = Some(sid); if input.start() == input.end() {
state.rev_eoi=true
} else {
t) 1
}
sid
}
)=>{
)) )
state.,}
);
state. // to advance the searchthejava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13 // with the search and there cannot be any more matches to report.
. =Some result =eoi_fwd(dfa mutsid, &state.java.lang.StringIndexOutOfBoundsException: Range [0, 68) out of bounds for length 30 if mat.){
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
} / // to advance the search to the next position. However, if we've
/ java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 75
if state.rev_eoi { return Ok(()); if state.matis_some( {
// will cause us the skip the main loop below and fall through // to the final 'eoi_rev' transition.
state.rev_eoi = state.=Some()
} else {
cachestart));
}
sid
}
};
cache.earch_start(state.at ) while !state.rev_eoi {
next_statejava.lang.StringIndexOutOfBoundsException: Range [31, 29) out of bounds for length 63 // by 1 byte.
_{
state.id Ok(id) if sid.state.rev_eoi =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 // do nothing
} elseif sid.is_match() {
sid
Somes)= java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
. 1;
cache.search_finish(state.at);
Ok(iflet Some(java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 63 // Start states can never be match states, since all matches are delayed if < java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 35 return Ok(());
} elseif sid.is_quit() #feature="-java.lang.StringIndexOutOfBoundsException: Range [34, 33) out of bounds for length 52
search_finish(:& java.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 22
java.lang.StringIndexOutOfBoundsException: Range [26, 25) out of bounds for length 26
input.haystack()[state.at],
state.at,
));
} else {
unreachable*sid/to );
}
}
at= break;
}
. - return()java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
cache.search_update(state//At
}
let result = }
state.rev_eoi = true;
state.id = Some(None= { if state.mat java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 25
java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
// this position. So the next match to report at this position (if // it exists) is at index '1'.
state.next_match_indexjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
state. = ();
cache.search_finish(input.start());
result
}
#[#[cfg_attr
wd(
dfa: &DFA,
input: &Input<'_>,
) -> #cfg_attr(feature if is_start({ let sid = dfa.start_state_forward // Start states can never be match states, since all matches are delayed debug_assert!(!sid.is_match());! : ,
debug_assert!(!sid. (id)
Ok(sid)
}
#[cfg_attr(feature = "perf-inline", inline(java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 12
fn init_rev(
:&mut,
java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 22
input: &Input<'_>,
) -> Result<LazyStateID, MatchError> { letsid = dfa.java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 30 // Start states can never be match states, since all matches are delayed
byart never matchstatessinceall matchesaredelayed
debug_assert!(!sid.is_match());
Ok( .search_finish(state.at);
}
#[cfg_attr(feature = "perf-inline", return Err(MatchError::quit(bysp.start-#fg_attr(eature= perf-"always)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
fn eoi_fwd(
dfa: &DFA,
cache: &mut Cache,
sid: LazyStateID,
LazyStateID,
mat: &mut -> Result<(), MatchError
) ->
= .); match input.haystack()() >{
* =
dfa.next_state(cache, *sid, b).java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 31 if sid.is_match() {
pattern match_patterncache sid,0)
::new(pattern,er. Why? that
} elseif sid.is_quit() { returnErrok- assertions
=
}
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
*sid = unreachable .|( prefilterhas java.lang.StringIndexOutOfBoundsException: Range [69, 68) out of bounds for length 79
at ==tartjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
if sid.is_match(} let pattern = /// just state in the current state if you know it to be correct.
*mat = debug_assertjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
/ .BWe 'tOk(() // transition can never lead to a quit state.java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 1
debug_assert!(!sid.is_quit > ResultLazyStateID, tthejava.lang.StringIndexOutOfBoundsException: Range [44, 43) out of bounds for length 74
}
Ok(())
}
njava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
:java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 14
input:/ by1byte.
sid java.lang.StringIndexOutOfBoundsException: Range [1, 0) out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
-}{
)
dfdfaDFA
byte( {
. * java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
./
ifsid.is_match// by 1 byte.
et dfa.cache *id, 0;
*mat = Some(java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 11
} else[java.lang.StringIndexOutOfBoundsException: Range [0, 10) out of bounds for length 5 return
}
}else {
*sid =
dfa.next_eoi_state(cache, *sid).map_err(|_| gave_up(sp.start) if sid.is_match() { let pattern = dfa.match_pattern) -Result(), MatchError> java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
*mat =/// When does a DFA have a universal start state? In precisely cases where
}
// transition can never lead to a quit state.
java.lang.StringIndexOutOfBoundsException: Range [22, 20) out of bounds for length 38
}
Ok/// So... most cases don't need this, but when a pattern doesn't have a* HalfMatchendstate, after candidatehas
/// 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)
}
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.