From 5f19a1f3c12e5b85a7119a7f880003ef6f1def72 Mon Sep 17 00:00:00 2001 From: Rob Hague Date: Wed, 14 Sep 2022 23:34:56 +0200 Subject: [PATCH 1/3] Add missing char specialisation to LastIndexOf(Span, ROS) This method is updated to match LastIndexOf(ROS, ROS) --- .../src/System/MemoryExtensions.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index fd6229f70c1b0..83826a8ac5e0c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -461,12 +461,25 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this Span span, ReadOnlySpan value) where T : IEquatable? { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOf( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(value)), - value.Length); + if (RuntimeHelpers.IsBitwiseEquatable()) + { + if (Unsafe.SizeOf() == sizeof(byte)) + { + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + } + else if (Unsafe.SizeOf() == sizeof(char)) + { + return SpanHelpers.LastIndexOf( + ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + span.Length, + ref Unsafe.As(ref MemoryMarshal.GetReference(value)), + value.Length); + } + } return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } From 3ce1ea20da7bc07627b552f2f0fb7fb62677f406 Mon Sep 17 00:00:00 2001 From: Rob Hague Date: Thu, 15 Sep 2022 22:09:09 +0200 Subject: [PATCH 2/3] Forward LastIndexOfAny(Span, ROS) to (ROS, ROS) version This is consistent with IndexOfAny(Span, ROS) --- .../src/System/MemoryExtensions.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 83826a8ac5e0c..5b2c23743dece 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -1491,18 +1491,8 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), /// /// The span to search. /// The set of values to search for. - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, ReadOnlySpan values) where T : IEquatable? - { - if (Unsafe.SizeOf() == sizeof(byte) && RuntimeHelpers.IsBitwiseEquatable()) - return SpanHelpers.LastIndexOfAny( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - span.Length, - ref Unsafe.As(ref MemoryMarshal.GetReference(values)), - values.Length); - - return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); - } + => LastIndexOfAny((ReadOnlySpan)span, values); /// /// Searches for the last index of any of the specified values similar to calling LastIndexOf several times with the logical OR operator. If not found, returns -1. From cc8bd944acab42eefb4b9438a4d40370919f42af Mon Sep 17 00:00:00 2001 From: Rob Hague Date: Thu, 22 Sep 2022 20:57:02 +0200 Subject: [PATCH 3/3] Add missing special cases for {Last}IndexOfAny(ROS, ROS) --- .../src/System/MemoryExtensions.cs | 105 +++++++++++++----- 1 file changed, 75 insertions(+), 30 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 5b2c23743dece..25a7e17a6dc07 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -1314,23 +1314,50 @@ public static int IndexOfAny(this ReadOnlySpan span, ReadOnlySpan value { if (Unsafe.SizeOf() == sizeof(byte)) { + ref byte spanRef = ref Unsafe.As(ref MemoryMarshal.GetReference(span)); ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) - { - return SpanHelpers.IndexOfAnyValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 3) + switch (values.Length) { - return SpanHelpers.IndexOfAnyValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); + case 0: + return -1; + + case 1: + return SpanHelpers.IndexOfValueType(ref spanRef, valueRef, span.Length); + + case 2: + return SpanHelpers.IndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + + case 3: + return SpanHelpers.IndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + +#if !MONO // We don't have a mono overload for 4 values + case 4: + return SpanHelpers.IndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + span.Length); +#endif + case 5: + return SpanHelpers.IndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + Unsafe.Add(ref valueRef, 4), + span.Length); } } @@ -1573,23 +1600,41 @@ public static int LastIndexOfAny(this ReadOnlySpan span, ReadOnlySpan v { if (Unsafe.SizeOf() == sizeof(byte)) { + ref byte spanRef = ref Unsafe.As(ref MemoryMarshal.GetReference(span)); ref byte valueRef = ref Unsafe.As(ref MemoryMarshal.GetReference(values)); - if (values.Length == 2) - { - return SpanHelpers.LastIndexOfAnyValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - span.Length); - } - else if (values.Length == 3) + switch (values.Length) { - return SpanHelpers.LastIndexOfAnyValueType( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), - valueRef, - Unsafe.Add(ref valueRef, 1), - Unsafe.Add(ref valueRef, 2), - span.Length); + case 0: + return -1; + + case 1: + return SpanHelpers.LastIndexOfValueType(ref spanRef, valueRef, span.Length); + + case 2: + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + span.Length); + + case 3: + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + span.Length); + +#if !MONO // We don't have a mono overload for 4 values + case 4: + return SpanHelpers.LastIndexOfAnyValueType( + ref spanRef, + valueRef, + Unsafe.Add(ref valueRef, 1), + Unsafe.Add(ref valueRef, 2), + Unsafe.Add(ref valueRef, 3), + span.Length); +#endif } }