Skip to content

Commit 809d3d2

Browse files
authored
Expand an optimization for short values to IgnoreCase in single-value SearchValues<string> (#108368)
1 parent ef685ad commit 809d3d2

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

src/libraries/System.Private.CoreLib/src/System/SearchValues/Strings/SingleStringSearchValuesThreeChars.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ internal sealed class SingleStringSearchValuesThreeChars<TValueLength, TCaseSens
3131

3232
private static bool IgnoreCase => typeof(TCaseSensitivity) != typeof(CaseSensitive);
3333

34+
// If the value is short (!TValueLength.AtLeast4Chars => 2 or 3 characters), the anchors already represent the whole value.
35+
// With case-sensitive comparisons, we've therefore already confirmed the match.
36+
// With case-insensitive comparisons, we've applied the CaseConversionMask to the input, so while the anchors likely matched, we can't be sure.
37+
// An exception to that is if we know the value is composed of only ASCII letters, in which case masking the input can't produce false positives.
38+
private static bool CanSkipAnchorMatchVerification =>
39+
!TValueLength.AtLeast4Chars &&
40+
(typeof(TCaseSensitivity) == typeof(CaseSensitive) || typeof(TCaseSensitivity) == typeof(CaseInsensitiveAsciiLetters));
41+
3442
public SingleStringSearchValuesThreeChars(HashSet<string>? uniqueValues, string value) : base(uniqueValues)
3543
{
3644
// We could have more than one entry in 'uniqueValues' if this value is an exact prefix of all the others.
@@ -327,11 +335,7 @@ private bool TryMatch(ref char searchSpaceStart, int searchSpaceLength, ref char
327335

328336
ValidateReadPosition(ref searchSpaceStart, searchSpaceLength, ref matchRef, _value.Length);
329337

330-
// If the value is short (!TValueLength.AtLeast4Chars => 2 or 3 characters), the anchors already represent the whole value.
331-
// With case-sensitive comparisons, we've therefore already confirmed the match, so we can skip doing so here.
332-
// With case-insensitive comparisons, we applied a mask to the input, so while the anchors likely matched, we can't be sure.
333-
if ((typeof(TCaseSensitivity) == typeof(CaseSensitive) && !TValueLength.AtLeast4Chars) ||
334-
TCaseSensitivity.Equals<TValueLength>(ref matchRef, _value))
338+
if (CanSkipAnchorMatchVerification || TCaseSensitivity.Equals<TValueLength>(ref matchRef, _value))
335339
{
336340
offsetFromStart = (int)((nuint)Unsafe.ByteOffset(ref searchSpaceStart, ref matchRef) / 2);
337341
return true;
@@ -359,11 +363,7 @@ private bool TryMatch(ref char searchSpaceStart, int searchSpaceLength, ref char
359363

360364
ValidateReadPosition(ref searchSpaceStart, searchSpaceLength, ref matchRef, _value.Length);
361365

362-
// If the value is short (!TValueLength.AtLeast4Chars => 2 or 3 characters), the anchors already represent the whole value.
363-
// With case-sensitive comparisons, we've therefore already confirmed the match, so we can skip doing so here.
364-
// With case-insensitive comparisons, we applied a mask to the input, so while the anchors likely matched, we can't be sure.
365-
if ((typeof(TCaseSensitivity) == typeof(CaseSensitive) && !TValueLength.AtLeast4Chars) ||
366-
TCaseSensitivity.Equals<TValueLength>(ref matchRef, _value))
366+
if (CanSkipAnchorMatchVerification || TCaseSensitivity.Equals<TValueLength>(ref matchRef, _value))
367367
{
368368
offsetFromStart = (int)((nuint)Unsafe.ByteOffset(ref searchSpaceStart, ref matchRef) / 2);
369369
return true;

0 commit comments

Comments
 (0)