Skip to content

Commit 09393c2

Browse files
[release/9.0] Fix IndexOf Optimization Code (#108562)
* Fix IndexOf Optimization Code * small typo * Address the feedback * Exclude hybrid globalization runs on the new added tests --------- Co-authored-by: Tarek Mahmoud Sayed <[email protected]>
1 parent 48dfbed commit 09393c2

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,14 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, Rea
130130
}
131131

132132
int startIndex, endIndex, jump;
133+
ReadOnlySpan<char> remainingSource;
133134
if (fromBeginning)
134135
{
135136
// Left to right, from zero to last possible index in the source string.
136137
// Incrementing by one after each iteration. Stop condition is last possible index plus 1.
137138
startIndex = 0;
138139
endIndex = source.Length - target.Length + 1;
140+
remainingSource = source.Slice(endIndex);
139141
jump = 1;
140142
}
141143
else
@@ -144,6 +146,7 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, Rea
144146
// Decrementing by one after each iteration. Stop condition is last possible index minus 1.
145147
startIndex = source.Length - target.Length;
146148
endIndex = -1;
149+
remainingSource = source.Slice(0, startIndex);
147150
jump = -1;
148151
}
149152

@@ -192,6 +195,12 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, Rea
192195
Next: ;
193196
}
194197

198+
// Before we return -1, check if the remaining source contains any special or non-Ascii characters.
199+
if (remainingSource.ContainsAnyExcept(s_nonSpecialAsciiChars))
200+
{
201+
goto InteropCall;
202+
}
203+
195204
return -1;
196205

197206
InteropCall:
@@ -246,12 +255,14 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<
246255
}
247256

248257
int startIndex, endIndex, jump;
258+
ReadOnlySpan<char> remainingSource;
249259
if (fromBeginning)
250260
{
251261
// Left to right, from zero to last possible index in the source string.
252262
// Incrementing by one after each iteration. Stop condition is last possible index plus 1.
253263
startIndex = 0;
254264
endIndex = source.Length - target.Length + 1;
265+
remainingSource = source.Slice(endIndex);
255266
jump = 1;
256267
}
257268
else
@@ -260,6 +271,7 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<
260271
// Decrementing by one after each iteration. Stop condition is last possible index minus 1.
261272
startIndex = source.Length - target.Length;
262273
endIndex = -1;
274+
remainingSource = source.Slice(0, startIndex);
263275
jump = -1;
264276
}
265277

@@ -297,6 +309,12 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<
297309
Next: ;
298310
}
299311

312+
// Before we return -1, check if the remaining source contains any special or non-Ascii characters.
313+
if (remainingSource.ContainsAnyExcept(s_nonSpecialAsciiChars))
314+
{
315+
goto InteropCall;
316+
}
317+
300318
return -1;
301319

302320
InteropCall:

src/libraries/System.Runtime/tests/System.Globalization.Tests/CompareInfo/CompareInfoTests.IndexOf.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ public static IEnumerable<object[]> IndexOf_TestData()
127127
yield return new object[] { s_currentCompare, "\u0130", "\u0131", 0, 1, CompareOptions.Ordinal, -1, 0 };
128128
yield return new object[] { s_currentCompare, "\u0131", "\u0130", 0, 1, CompareOptions.Ordinal, -1, 0 };
129129

130+
if (!PlatformDetection.IsHybridGlobalizationOnBrowser)
131+
{
132+
yield return new object[] { s_invariantCompare, "est", "est", 0, 2, CompareOptions.IgnoreCase, 0, 2 };
133+
yield return new object[] { s_invariantCompare, " est", "est", 0, 3, CompareOptions.IgnoreCase, 1, 2 };
134+
yield return new object[] { s_invariantCompare, " st", "st", 0, 2, CompareOptions.IgnoreCase, 1, 1 };
135+
yield return new object[] { s_invariantCompare, "est", "est", 0, 3, CompareOptions.IgnoreCase, 0, 3 };
136+
yield return new object[] { s_invariantCompare, " est", "est", 0, 4, CompareOptions.IgnoreCase, 1, 3 };
137+
yield return new object[] { s_invariantCompare, " st", "st", 0, 3, CompareOptions.IgnoreCase, 1, 2 };
138+
}
139+
130140
// Platform differences
131141
if (PlatformDetection.IsNlsGlobalization)
132142
{

0 commit comments

Comments
 (0)