Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 1e3faea

Browse files
committed
Add ReadOnlySpan string-like Equals/CompareTo/IndexOf/Contains API with globalization support (#16467)
* Add ReadOnlySpan string-like Equals/CompareTo/IndexOf/Contains API with globalization support * Address PR feedback. * Fix unix implementation Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
1 parent 59481ca commit 1e3faea

File tree

4 files changed

+203
-31
lines changed

4 files changed

+203
-31
lines changed

src/Common/src/CoreLib/Interop/Unix/System.Globalization.Native/Interop.Collation.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ internal static partial class Globalization
2222

2323
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
2424
internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
25+
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
26+
internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
2527

2628
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_LastIndexOf")]
2729
internal unsafe static extern int LastIndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
2830

2931
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOfOrdinalIgnoreCase")]
3032
internal unsafe static extern int IndexOfOrdinalIgnoreCase(string target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
33+
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOfOrdinalIgnoreCase")]
34+
internal unsafe static extern int IndexOfOrdinalIgnoreCase(char* target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
3135

3236
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_StartsWith")]
3337
[return: MarshalAs(UnmanagedType.Bool)]

src/Common/src/CoreLib/System/Globalization/CompareInfo.Invariant.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Diagnostics;
6+
using System.Runtime.InteropServices;
67

78
namespace System.Globalization
89
{
@@ -26,6 +27,18 @@ internal static unsafe int InvariantIndexOf(string source, string value, int sta
2627
}
2728
}
2829

30+
internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
31+
{
32+
Debug.Assert(source.Length != 0);
33+
Debug.Assert(value.Length != 0);
34+
35+
fixed (char* pSource = &MemoryMarshal.GetReference(source))
36+
fixed (char* pValue = &MemoryMarshal.GetReference(value))
37+
{
38+
return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, start: true);
39+
}
40+
}
41+
2942
internal static unsafe int InvariantLastIndexOf(string source, string value, int startIndex, int count, bool ignoreCase)
3043
{
3144
Debug.Assert(source != null);

src/Common/src/CoreLib/System/Globalization/CompareInfo.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ public virtual int Compare(string string1, string string2)
298298
return (Compare(string1, string2, CompareOptions.None));
299299
}
300300

301-
public unsafe virtual int Compare(string string1, string string2, CompareOptions options)
301+
public virtual int Compare(string string1, string string2, CompareOptions options)
302302
{
303303
if (options == CompareOptions.OrdinalIgnoreCase)
304304
{
@@ -350,7 +350,7 @@ public unsafe virtual int Compare(string string1, string string2, CompareOptions
350350
// TODO https://github.com/dotnet/coreclr/issues/13827:
351351
// This method shouldn't be necessary, as we should be able to just use the overload
352352
// that takes two spans. But due to this issue, that's adding significant overhead.
353-
internal unsafe int Compare(ReadOnlySpan<char> string1, string string2, CompareOptions options)
353+
internal int Compare(ReadOnlySpan<char> string1, string string2, CompareOptions options)
354354
{
355355
if (options == CompareOptions.OrdinalIgnoreCase)
356356
{
@@ -390,7 +390,7 @@ internal unsafe int Compare(ReadOnlySpan<char> string1, string string2, CompareO
390390
}
391391

392392
// TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
393-
internal unsafe virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
393+
internal virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
394394
{
395395
if (options == CompareOptions.OrdinalIgnoreCase)
396396
{
@@ -436,7 +436,7 @@ internal unsafe virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<cha
436436
////////////////////////////////////////////////////////////////////////
437437

438438

439-
public unsafe virtual int Compare(string string1, int offset1, int length1, string string2, int offset2, int length2)
439+
public virtual int Compare(string string1, int offset1, int length1, string string2, int offset2, int length2)
440440
{
441441
return Compare(string1, offset1, length1, string2, offset2, length2, 0);
442442
}
@@ -547,7 +547,7 @@ private static int CompareOrdinal(string string1, int offset1, int length1, stri
547547
// it assumes the strings are Ascii string till we hit non Ascii character in strA or strB and then we continue the comparison by
548548
// calling the OS.
549549
//
550-
internal static unsafe int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB)
550+
internal static int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB)
551551
{
552552
Debug.Assert(indexA + lengthA <= strA.Length);
553553
Debug.Assert(indexB + lengthB <= strB.Length);
@@ -910,6 +910,18 @@ public unsafe virtual int IndexOf(string source, string value, int startIndex, i
910910
return IndexOfCore(source, value, startIndex, count, options, null);
911911
}
912912

913+
internal virtual int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
914+
{
915+
Debug.Assert(!_invariantMode);
916+
return IndexOfOrdinalCore(source, value, ignoreCase);
917+
}
918+
919+
internal unsafe virtual int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
920+
{
921+
Debug.Assert(!_invariantMode);
922+
return IndexOfCore(source, value, options, null);
923+
}
924+
913925
// The following IndexOf overload is mainly used by String.Replace. This overload assumes the parameters are already validated
914926
// and the caller is passing a valid matchLengthPtr pointer.
915927
internal unsafe int IndexOf(string source, string value, int startIndex, int count, CompareOptions options, int* matchLengthPtr)

0 commit comments

Comments
 (0)