Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Memory/src/System/SpanHelpers.T.cs')
-rw-r--r--src/System.Memory/src/System/SpanHelpers.T.cs105
1 files changed, 104 insertions, 1 deletions
diff --git a/src/System.Memory/src/System/SpanHelpers.T.cs b/src/System.Memory/src/System/SpanHelpers.T.cs
index 88bb4447f8..db119a8913 100644
--- a/src/System.Memory/src/System/SpanHelpers.T.cs
+++ b/src/System.Memory/src/System/SpanHelpers.T.cs
@@ -23,7 +23,7 @@ namespace System
int valueTailLength = valueLength - 1;
int index = 0;
- for (;;)
+ for (; ; )
{
Debug.Assert(0 <= index && index <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength".
int remainingSearchSpaceLength = searchSpaceLength - index - valueTailLength;
@@ -119,6 +119,109 @@ namespace System
return (int)(byte*)(index + 7);
}
+ public static int LastIndexOf<T>(ref T searchSpace, int searchSpaceLength, ref T value, int valueLength)
+ where T : IEquatable<T>
+ {
+ Debug.Assert(searchSpaceLength >= 0);
+ Debug.Assert(valueLength >= 0);
+
+ if (valueLength == 0)
+ return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
+
+ T valueHead = value;
+ ref T valueTail = ref Unsafe.Add(ref value, 1);
+ int valueTailLength = valueLength - 1;
+
+ int index = 0;
+ for (; ; )
+ {
+ Debug.Assert(0 <= index && index <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength".
+ int remainingSearchSpaceLength = searchSpaceLength - index - valueTailLength;
+ if (remainingSearchSpaceLength <= 0)
+ break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there.
+
+ // Do a quick search for the first element of "value".
+ int relativeIndex = LastIndexOf(ref searchSpace, valueHead, remainingSearchSpaceLength);
+ if (relativeIndex == -1)
+ break;
+
+ // Found the first element of "value". See if the tail matches.
+ if (SequenceEqual(ref Unsafe.Add(ref searchSpace, relativeIndex + 1), ref valueTail, valueTailLength))
+ return relativeIndex; // The tail matched. Return a successful find.
+
+ index += remainingSearchSpaceLength - relativeIndex;
+ }
+ return -1;
+ }
+
+ public static unsafe int LastIndexOf<T>(ref T searchSpace, T value, int length)
+ where T : IEquatable<T>
+ {
+ Debug.Assert(length >= 0);
+
+ while (length >= 8)
+ {
+ length -= 8;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 7)))
+ goto Found7;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 6)))
+ goto Found6;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 5)))
+ goto Found5;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 4)))
+ goto Found4;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 3)))
+ goto Found3;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 2)))
+ goto Found2;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 1)))
+ goto Found1;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length)))
+ goto Found;
+ }
+
+ if (length >= 4)
+ {
+ length -= 4;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 3)))
+ goto Found3;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 2)))
+ goto Found2;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length + 1)))
+ goto Found1;
+ if (value.Equals(Unsafe.Add(ref searchSpace, length)))
+ goto Found;
+ }
+
+ while (length > 0)
+ {
+ length--;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, length)))
+ goto Found;
+ }
+ return -1;
+
+ Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
+ return length;
+ Found1:
+ return length + 1;
+ Found2:
+ return length + 2;
+ Found3:
+ return length + 3;
+ Found4:
+ return length + 4;
+ Found5:
+ return length + 5;
+ Found6:
+ return length + 6;
+ Found7:
+ return length + 7;
+ }
+
public static bool SequenceEqual<T>(ref T first, ref T second, int length)
where T : IEquatable<T>
{