/// <summary>Try to advance to the next starting position that might be a location for a match.</summary>
/// <param name="textSpan">The text to search.</param>
/// <param name="pos">The position in <paramref name="textSpan"/>. This is updated with the found position.</param>
- /// <param name="beginning">The index in <paramref name="textSpan"/> to consider the beginning for beginning anchor purposes.</param>
/// <param name="start">The index in <paramref name="textSpan"/> to consider the start for start anchor purposes.</param>
- /// <param name="end">The index in <paramref name="textSpan"/> to consider the non-inclusive end of the string.</param>
/// <returns>true if a position to attempt a match was found; false if none was found.</returns>
- public bool TryFindNextStartingPosition(ReadOnlySpan<char> textSpan, ref int pos, int beginning, int start, int end)
+ public bool TryFindNextStartingPosition(ReadOnlySpan<char> textSpan, ref int pos, int start)
{
// Return early if we know there's not enough input left to match.
if (!_rightToLeft)
{
- if (pos > end - MinRequiredLength)
+ if (pos > textSpan.Length - MinRequiredLength)
{
- pos = end;
+ pos = textSpan.Length;
return false;
}
}
else
{
- if (pos - MinRequiredLength < beginning)
+ if (pos < MinRequiredLength)
{
- pos = beginning;
+ pos = 0;
return false;
}
}
// the beginning of the string or just after a line feed), find the next
// newline and position just after it.
Debug.Assert(!_rightToLeft);
- if (pos > beginning && textSpan[pos - 1] != '\n')
+ int posm1 = pos - 1;
+ if ((uint)posm1 < (uint)textSpan.Length && textSpan[posm1] != '\n')
{
int newline = textSpan.Slice(pos).IndexOf('\n');
- if (newline == -1 || newline + 1 + pos > end)
+ if ((uint)newline > textSpan.Length - 1 - pos)
{
- pos = end;
+ pos = textSpan.Length;
return false;
}
// For others, we can jump to the relevant location.
case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning:
- if (pos > beginning)
+ if (pos > 0)
{
- pos = end;
+ pos = textSpan.Length;
return false;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start:
if (pos > start)
{
- pos = end;
+ pos = textSpan.Length;
return false;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ:
- if (pos < end - 1)
+ if (pos < textSpan.Length - 1)
{
- pos = end - 1;
+ pos = textSpan.Length - 1;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End:
- if (pos < end)
+ if (pos < textSpan.Length)
{
- pos = end;
+ pos = textSpan.Length;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning:
- if (pos > beginning)
+ if (pos > 0)
{
- pos = beginning;
+ pos = 0;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start:
if (pos < start)
{
- pos = beginning;
+ pos = 0;
return false;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ:
- if (pos < end - 1 || (pos == end - 1 && textSpan[pos] != '\n'))
+ if (pos < textSpan.Length - 1 || ((uint)pos < (uint)textSpan.Length && textSpan[pos] != '\n'))
{
- pos = beginning;
+ pos = 0;
return false;
}
return true;
case FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End:
- if (pos < end)
+ if (pos < textSpan.Length)
{
- pos = beginning;
+ pos = 0;
return false;
}
return true;
case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ:
- if (pos < end - MinRequiredLength - 1)
+ if (pos < textSpan.Length - MinRequiredLength - 1)
{
- pos = end - MinRequiredLength - 1;
+ pos = textSpan.Length - MinRequiredLength - 1;
}
return true;
case FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End:
- if (pos < end - MinRequiredLength)
+ if (pos < textSpan.Length - MinRequiredLength)
{
- pos = end - MinRequiredLength;
+ pos = textSpan.Length - MinRequiredLength;
}
return true;
case FindNextStartingPositionMode.LeadingPrefix_LeftToRight_CaseSensitive:
{
- int i = textSpan.Slice(pos, end - pos).IndexOf(LeadingCaseSensitivePrefix.AsSpan());
+ int i = textSpan.Slice(pos).IndexOf(LeadingCaseSensitivePrefix.AsSpan());
if (i >= 0)
{
pos += i;
return true;
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
case FindNextStartingPositionMode.LeadingPrefix_RightToLeft_CaseSensitive:
{
- int i = textSpan.Slice(beginning, pos - beginning).LastIndexOf(LeadingCaseSensitivePrefix.AsSpan());
+ int i = textSpan.Slice(0, pos).LastIndexOf(LeadingCaseSensitivePrefix.AsSpan());
if (i >= 0)
{
- pos = beginning + i + LeadingCaseSensitivePrefix.Length;
+ pos = i + LeadingCaseSensitivePrefix.Length;
return true;
}
- pos = beginning;
+ pos = 0;
return false;
}
case FindNextStartingPositionMode.LeadingLiteral_RightToLeft_CaseSensitive:
{
- int i = textSpan.Slice(beginning, pos - beginning).LastIndexOf(FixedDistanceLiteral.Literal);
+ int i = textSpan.Slice(0, pos).LastIndexOf(FixedDistanceLiteral.Literal);
if (i >= 0)
{
- pos = beginning + i + 1;
+ pos = i + 1;
return true;
}
- pos = beginning;
+ pos = 0;
return false;
}
char ch = FixedDistanceLiteral.Literal;
TextInfo ti = _textInfo;
- ReadOnlySpan<char> span = textSpan.Slice(beginning, pos - beginning);
+ ReadOnlySpan<char> span = textSpan.Slice(0, pos);
for (int i = span.Length - 1; i >= 0; i--)
{
if (ti.ToLower(span[i]) == ch)
{
- pos = beginning + i + 1;
+ pos = i + 1;
return true;
}
}
- pos = beginning;
+ pos = 0;
return false;
}
{
(char[]? chars, string set, _, _) = FixedDistanceSets![0];
- ReadOnlySpan<char> span = textSpan.Slice(pos, end - pos);
+ ReadOnlySpan<char> span = textSpan.Slice(pos);
if (chars is not null)
{
int i = span.IndexOfAny(chars);
}
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
string set = FixedDistanceSets![0].Set;
TextInfo ti = _textInfo;
- ReadOnlySpan<char> span = textSpan.Slice(pos, end - pos);
+ ReadOnlySpan<char> span = textSpan.Slice(pos);
for (int i = 0; i < span.Length; i++)
{
if (RegexCharClass.CharInClass(ti.ToLower(span[i]), set, ref startingAsciiLookup))
}
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
ref uint[]? startingAsciiLookup = ref _asciiLookups![0];
string set = FixedDistanceSets![0].Set;
- ReadOnlySpan<char> span = textSpan.Slice(beginning, pos - beginning);
+ ReadOnlySpan<char> span = textSpan.Slice(0, pos);
for (int i = span.Length - 1; i >= 0; i--)
{
if (RegexCharClass.CharInClass(span[i], set, ref startingAsciiLookup))
{
- pos = beginning + i + 1;
+ pos = i + 1;
return true;
}
}
- pos = beginning;
+ pos = 0;
return false;
}
string set = FixedDistanceSets![0].Set;
TextInfo ti = _textInfo;
- ReadOnlySpan<char> span = textSpan.Slice(beginning, pos - beginning);
+ ReadOnlySpan<char> span = textSpan.Slice(0, pos);
for (int i = span.Length - 1; i >= 0; i--)
{
if (RegexCharClass.CharInClass(ti.ToLower(span[i]), set, ref startingAsciiLookup))
{
- pos = beginning + i + 1;
+ pos = i + 1;
return true;
}
}
- pos = beginning;
+ pos = 0;
return false;
}
{
Debug.Assert(FixedDistanceLiteral.Distance <= MinRequiredLength);
- int i = textSpan.Slice(pos + FixedDistanceLiteral.Distance, end - pos - FixedDistanceLiteral.Distance).IndexOf(FixedDistanceLiteral.Literal);
+ int i = textSpan.Slice(pos + FixedDistanceLiteral.Distance).IndexOf(FixedDistanceLiteral.Literal);
if (i >= 0)
{
pos += i;
return true;
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
char ch = FixedDistanceLiteral.Literal;
TextInfo ti = _textInfo;
- ReadOnlySpan<char> span = textSpan.Slice(pos + FixedDistanceLiteral.Distance, end - pos - FixedDistanceLiteral.Distance);
+ ReadOnlySpan<char> span = textSpan.Slice(pos + FixedDistanceLiteral.Distance);
for (int i = 0; i < span.Length; i++)
{
if (ti.ToLower(span[i]) == ch)
}
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
{
List<(char[]? Chars, string Set, int Distance, bool CaseInsensitive)> sets = FixedDistanceSets!;
(char[]? primaryChars, string primarySet, int primaryDistance, _) = sets[0];
- int endMinusRequiredLength = end - Math.Max(1, MinRequiredLength);
+ int endMinusRequiredLength = textSpan.Length - Math.Max(1, MinRequiredLength);
if (primaryChars is not null)
{
for (int inputPosition = pos; inputPosition <= endMinusRequiredLength; inputPosition++)
{
int offset = inputPosition + primaryDistance;
- int index = textSpan.Slice(offset, end - offset).IndexOfAny(primaryChars);
+ int index = textSpan.Slice(offset).IndexOfAny(primaryChars);
if (index < 0)
{
break;
}
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
List<(char[]? Chars, string Set, int Distance, bool CaseInsensitive)> sets = FixedDistanceSets!;
(_, string primarySet, int primaryDistance, _) = sets[0];
- int endMinusRequiredLength = end - Math.Max(1, MinRequiredLength);
+ int endMinusRequiredLength = textSpan.Length - Math.Max(1, MinRequiredLength);
TextInfo ti = _textInfo;
ref uint[]? startingAsciiLookup = ref _asciiLookups![0];
Bumpalong:;
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
int startingPos = pos;
while (true)
{
- ReadOnlySpan<char> slice = textSpan.Slice(startingPos, end - startingPos);
+ ReadOnlySpan<char> slice = textSpan.Slice(startingPos);
// Find the literal. If we can't find it, we're done searching.
int i = literal.String is not null ? slice.IndexOf(literal.String.AsSpan()) :
return true;
}
- pos = end;
+ pos = textSpan.Length;
return false;
}
private int Operand(int i) => _code.Codes[_codepos + i + 1];
- private int Leftchars() => runtextpos - runtextbeg;
-
- private int Rightchars() => runtextend - runtextpos;
-
private int Bump() => _rightToLeft ? -1 : 1;
- private int Forwardchars() => _rightToLeft ? runtextpos - runtextbeg : runtextend - runtextpos;
+ private int Forwardchars() => _rightToLeft ? runtextpos : runtextend - runtextpos;
private char Forwardcharnext(ReadOnlySpan<char> inputSpan)
{
if (!_rightToLeft)
{
- if (runtextend - runtextpos < c)
+ if (inputSpan.Length - runtextpos < c)
{
return false;
}
}
else
{
- if (runtextpos - runtextbeg < c)
+ if (runtextpos < c)
{
return false;
}
int pos;
if (!_rightToLeft)
{
- if (runtextend - runtextpos < length)
+ if (inputSpan.Length - runtextpos < length)
{
return false;
}
}
else
{
- if (runtextpos - runtextbeg < length)
+ if (runtextpos < length)
{
return false;
}
stoppos = 0;
}
- while (_code.FindOptimizations.TryFindNextStartingPosition(text, ref runtextpos, runtextbeg, runtextstart, runtextend))
+ while (_code.FindOptimizations.TryFindNextStartingPosition(text, ref runtextpos, runtextstart))
{
CheckTimeout();
break;
case RegexOpcode.Bol:
- if (Leftchars() > 0 && inputSpan[runtextpos - 1] != '\n')
{
- break;
+ int m1 = runtextpos - 1;
+ if ((uint)m1 < (uint)inputSpan.Length && inputSpan[m1] != '\n')
+ {
+ break;
+ }
+ advance = 0;
+ continue;
}
- advance = 0;
- continue;
case RegexOpcode.Eol:
- if (Rightchars() > 0 && inputSpan[runtextpos] != '\n')
{
- break;
+ int runtextpos = this.runtextpos;
+ if ((uint)runtextpos < (uint)inputSpan.Length && inputSpan[runtextpos] != '\n')
+ {
+ break;
+ }
+ advance = 0;
+ continue;
}
- advance = 0;
- continue;
case RegexOpcode.Boundary:
if (!IsBoundary(inputSpan, runtextpos))
continue;
case RegexOpcode.Beginning:
- if (Leftchars() > 0)
+ if (runtextpos > 0)
{
break;
}
continue;
case RegexOpcode.EndZ:
- if (Rightchars() > 1 || Rightchars() == 1 && inputSpan[runtextpos] != '\n')
{
- break;
+ int runtextpos = this.runtextpos;
+ if (runtextpos < inputSpan.Length - 1 || ((uint)runtextpos < (uint)inputSpan.Length && inputSpan[runtextpos] != '\n'))
+ {
+ break;
+ }
+ advance = 0;
+ continue;
}
- advance = 0;
- continue;
case RegexOpcode.End:
- if (Rightchars() > 0)
+ if (runtextpos < inputSpan.Length)
{
break;
}