Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Runtime.InteropServices;
using System.Security;

using Internal.Runtime.CompilerServices;

namespace System.Globalization
{
public partial class CompareInfo
Expand Down Expand Up @@ -240,31 +242,12 @@ internal unsafe int IndexOfCore(string source, string target, int startIndex, in
Debug.Assert(!string.IsNullOrEmpty(source));
Debug.Assert(target != null);
Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);

int index;

if (target.Length == 0)
{
if (matchLengthPtr != null)
*matchLengthPtr = 0;
return startIndex;
}

if (options == CompareOptions.Ordinal)
{
index = IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
if (index != -1)
{
if (matchLengthPtr != null)
*matchLengthPtr = target.Length;
}
return index;
}
Debug.Assert((options & CompareOptions.Ordinal) == 0);

#if CORECLR
if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
{
index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
int index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
if (index != -1)
{
if (matchLengthPtr != null)
Expand All @@ -277,7 +260,7 @@ internal unsafe int IndexOfCore(string source, string target, int startIndex, in
fixed (char* pSource = source)
fixed (char* pTarget = target)
{
index = Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource + startIndex, count, options, matchLengthPtr);
int index = Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource + startIndex, count, options, matchLengthPtr);

return index != -1 ? index + startIndex : -1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

using System.Buffers;
using System.Diagnostics;
using System.Security;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Internal.Runtime.CompilerServices;

namespace System.Globalization
{
public partial class CompareInfo
Expand Down Expand Up @@ -327,37 +327,13 @@ internal unsafe int IndexOfCore(string source, string target, int startIndex, in
Debug.Assert(source != null);
Debug.Assert(target != null);
Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
Debug.Assert((options & CompareOptions.Ordinal) == 0);

if (target.Length == 0)
{
if (matchLengthPtr != null)
*matchLengthPtr = 0;
return startIndex;
}

if (source.Length == 0)
{
return -1;
}

if ((options & CompareOptions.Ordinal) != 0)
{
int retValue = FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false);
if (retValue >= 0)
{
if (matchLengthPtr != null)
*matchLengthPtr = target.Length;
}
return retValue;
}
else
int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count,
target, 0, target.Length, matchLengthPtr);
if (retValue >= 0)
{
int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count,
target, 0, target.Length, matchLengthPtr);
if (retValue >= 0)
{
return retValue + startIndex;
}
return retValue + startIndex;
}

return -1;
Expand Down Expand Up @@ -388,7 +364,7 @@ private unsafe int LastIndexOfCore(string source, string target, int startIndex,

if ((options & CompareOptions.Ordinal) != 0)
{
return FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: true);
return FastLastIndexOfString(source, target, startIndex, count, target.Length);
}
else
{
Expand Down Expand Up @@ -462,75 +438,44 @@ private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffi
private const int FIND_FROMSTART = 0x00400000;
private const int FIND_FROMEND = 0x00800000;

// TODO: Instead of this method could we just have upstack code call IndexOfOrdinal with ignoreCase = false?
private static unsafe int FastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount, bool findLastIndex)
// TODO: Instead of this method could we just have upstack code call LastIndexOfOrdinal with ignoreCase = false?
private static unsafe int FastLastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just removed the forward index, last index is still handled here. Ignoring whitespace shows removal more clearly https://github.com/dotnet/coreclr/pull/21076/files?w=1

{
int retValue = -1;

int sourceStartIndex = findLastIndex ? startIndex - sourceCount + 1 : startIndex;
int sourceStartIndex = startIndex - sourceCount + 1;

fixed (char* pSource = source, spTarget = target)
{
char* spSubSource = pSource + sourceStartIndex;

if (findLastIndex)
int endPattern = sourceCount - targetCount;
if (endPattern < 0)
return -1;

Debug.Assert(target.Length >= 1);
char patternChar0 = spTarget[0];
Comment thread
benaadams marked this conversation as resolved.
for (int ctrSrc = endPattern; ctrSrc >= 0; ctrSrc--)
{
int startPattern = (sourceCount - 1) - targetCount + 1;
if (startPattern < 0)
return -1;
if (spSubSource[ctrSrc] != patternChar0)
continue;

char patternChar0 = spTarget[0];
for (int ctrSrc = startPattern; ctrSrc >= 0; ctrSrc--)
int ctrPat;
for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
{
if (spSubSource[ctrSrc] != patternChar0)
continue;

int ctrPat;
for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
{
if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
break;
}
if (ctrPat == targetCount)
{
retValue = ctrSrc;
if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
break;
}
}

if (retValue >= 0)
if (ctrPat == targetCount)
{
retValue += startIndex - sourceCount + 1;
retValue = ctrSrc;
break;
}
}
else
{
int endPattern = (sourceCount - 1) - targetCount + 1;
if (endPattern < 0)
return -1;

char patternChar0 = spTarget[0];
for (int ctrSrc = 0; ctrSrc <= endPattern; ctrSrc++)
{
if (spSubSource[ctrSrc] != patternChar0)
continue;
int ctrPat;
for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
{
if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
break;
}
if (ctrPat == targetCount)
{
retValue = ctrSrc;
break;
}
}

if (retValue >= 0)
{
retValue += startIndex;
}
if (retValue >= 0)
{
retValue += startIndex - sourceCount + 1;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -972,20 +972,12 @@ public unsafe virtual int IndexOf(string source, char value, int startIndex, int
return -1;
}

if (options == CompareOptions.OrdinalIgnoreCase)
{
return source.IndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
}

// Validate CompareOptions
// Ordinal can't be selected with other flags
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal && options != CompareOptions.OrdinalIgnoreCase))
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));

if (GlobalizationMode.Invariant)
return IndexOfOrdinal(source, new string(value, 1), startIndex, count, ignoreCase: (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0);

return IndexOfCore(source, new string(value, 1), startIndex, count, options, null);
return IndexOf(source, new string(value, 1), startIndex, count, options, null);
}

public unsafe virtual int IndexOf(string source, string value, int startIndex, int count, CompareOptions options)
Expand Down Expand Up @@ -1020,28 +1012,21 @@ public unsafe virtual int IndexOf(string source, string value, int startIndex, i
if (count < 0 || startIndex > source.Length - count)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);

if (options == CompareOptions.OrdinalIgnoreCase)
{
return IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
}

// Validate CompareOptions
// Ordinal can't be selected with other flags
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal && options != CompareOptions.OrdinalIgnoreCase))
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));

if (GlobalizationMode.Invariant)
return IndexOfOrdinal(source, value, startIndex, count, ignoreCase: (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0);

return IndexOfCore(source, value, startIndex, count, options, null);
return IndexOf(source, value, startIndex, count, options, null);
}

internal int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
internal int IndexOfOrdinalIgnoreCase(ReadOnlySpan<char> source, ReadOnlySpan<char> value)
{
Debug.Assert(!GlobalizationMode.Invariant);
Comment thread
benaadams marked this conversation as resolved.
Debug.Assert(!source.IsEmpty);
Debug.Assert(!value.IsEmpty);
return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: true);

return IndexOfOrdinalCore(source, value, ignoreCase: true, fromBeginning: true);
}

internal int LastIndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
Expand Down Expand Up @@ -1075,16 +1060,15 @@ internal unsafe int IndexOf(string source, string value, int startIndex, int cou
Debug.Assert(source != null);
Debug.Assert(value != null);
Debug.Assert(startIndex >= 0);
Debug.Assert(matchLengthPtr != null);
*matchLengthPtr = 0;

if (source.Length == 0)
Comment thread
benaadams marked this conversation as resolved.
if (matchLengthPtr != null)
{
if (value.Length == 0)
{
return 0;
}
return -1;
*matchLengthPtr = 0;
}

if (value.Length == 0)
Comment thread
benaadams marked this conversation as resolved.
{
return startIndex;
}

if (startIndex >= source.Length)
Expand All @@ -1095,7 +1079,7 @@ internal unsafe int IndexOf(string source, string value, int startIndex, int cou
if (options == CompareOptions.OrdinalIgnoreCase)
{
int res = IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
if (res >= 0)
if (res >= 0 && matchLengthPtr != null)
{
*matchLengthPtr = value.Length;
}
Expand All @@ -1105,18 +1089,49 @@ internal unsafe int IndexOf(string source, string value, int startIndex, int cou
if (GlobalizationMode.Invariant)
{
int res = IndexOfOrdinal(source, value, startIndex, count, ignoreCase: (options & (CompareOptions.IgnoreCase | CompareOptions.OrdinalIgnoreCase)) != 0);
if (res >= 0)
if (res >= 0 && matchLengthPtr != null)
{
*matchLengthPtr = value.Length;
}
return res;
}

return IndexOfCore(source, value, startIndex, count, options, matchLengthPtr);
if (options == CompareOptions.Ordinal)
{
int retValue = SpanHelpers.IndexOf(
ref Unsafe.Add(ref source.GetRawStringData(), startIndex),
count,
ref value.GetRawStringData(),
value.Length);

if (retValue >= 0)
{
retValue += startIndex;
if (matchLengthPtr != null)
*matchLengthPtr = value.Length;
}

return retValue;
}
else
{
return IndexOfCore(source, value, startIndex, count, options, matchLengthPtr);
}
}

internal int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
{
if (!ignoreCase)
{
int result = SpanHelpers.IndexOf(
ref Unsafe.Add(ref source.GetRawStringData(), startIndex),
count,
ref value.GetRawStringData(),
value.Length);

return (result >= 0 ? startIndex : 0) + result;
}

if (GlobalizationMode.Invariant)
{
return InvariantIndexOf(source, value, startIndex, count, ignoreCase);
Expand Down
13 changes: 11 additions & 2 deletions src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value
return -1;
}

if (comparisonType == StringComparison.Ordinal)
Comment thread
benaadams marked this conversation as resolved.
{
return SpanHelpers.IndexOf(
ref MemoryMarshal.GetReference(span),
span.Length,
ref MemoryMarshal.GetReference(value),
value.Length);
}

if (GlobalizationMode.Invariant)
{
return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
Comment thread
benaadams marked this conversation as resolved.
Expand All @@ -157,8 +166,8 @@ public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value
return CompareInfo.Invariant.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));

default:
Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
return CompareInfo.Invariant.IndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase);
return CompareInfo.Invariant.IndexOfOrdinalIgnoreCase(span, value);
}
}

Expand Down
Loading