Skip to content

Commit

Permalink
Forward Span-based MemoryExtensions overloads to ReadOnlySpan overloa…
Browse files Browse the repository at this point in the history
…ds (#48669)
  • Loading branch information
stephentoub authored Feb 24, 2021
1 parent e5ae988 commit 998126c
Showing 1 changed file with 2 additions and 92 deletions.
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

0 comments on commit 998126c

Please sign in to comment.