Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forward Span-based MemoryExtensions overloads to ReadOnlySpan overloads #48669

Merged
merged 1 commit into from
Feb 24, 2021
Merged
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 @@ -619,98 +619,8 @@ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
/// <param name="span">The span to search.</param>
/// <param name="values">The set of values to search for.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T>
{
if (RuntimeHelpers.IsBitwiseEquatable<T>())
{
if (Unsafe.SizeOf<T>() == sizeof(byte))
{
ref byte valueRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values));
if (values.Length == 2)
{
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
span.Length);
}
else if (values.Length == 3)
{
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
Unsafe.Add(ref valueRef, 2),
span.Length);
}
else
{
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
span.Length,
ref valueRef,
values.Length);
}
}

if (Unsafe.SizeOf<T>() == sizeof(char))
{
ref char valueRef = ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(values));
if (values.Length == 5)
{
// Length 5 is a common length for FileSystemName expression (", <, >, *, ?) and in preference to 2 as it has an explicit overload
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
Unsafe.Add(ref valueRef, 2),
Unsafe.Add(ref valueRef, 3),
Unsafe.Add(ref valueRef, 4),
span.Length);
}
else if (values.Length == 2)
{
// Length 2 is a common length for simple wildcards (*, ?), directory separators (/, \), quotes (", '), brackets, etc
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
span.Length);
}
else if (values.Length == 4)
{
// Length 4 before 3 as 3 has an explicit overload
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
Unsafe.Add(ref valueRef, 2),
Unsafe.Add(ref valueRef, 3),
span.Length);
}
else if (values.Length == 3)
{
return SpanHelpers.IndexOfAny(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
valueRef,
Unsafe.Add(ref valueRef, 1),
Unsafe.Add(ref valueRef, 2),
span.Length);
}
else if (values.Length == 1)
{
// Length 1 last, as ctoring a ReadOnlySpan to call this overload for a single value
// is already throwing away a bunch of performance vs just calling IndexOf
return SpanHelpers.IndexOf(
ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
valueRef,
span.Length);
}
}
}

return SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
}
public static int IndexOfAny<T>(this Span<T> span, ReadOnlySpan<T> values) where T : IEquatable<T> =>
IndexOfAny((ReadOnlySpan<T>)span, values);

/// <summary>
/// Searches for the first index of any of the specified values similar to calling IndexOf several times with the logical OR operator. If not found, returns -1.
Expand Down