using System.Collections.Generic; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System; public static class MemoryExtensions { internal static readonly IntPtr StringAdjustment = MeasureStringAdjustment(); public static ReadOnlySpan Trim(this ReadOnlySpan span) { return span.TrimStart().TrimEnd(); } public static ReadOnlySpan TrimStart(this ReadOnlySpan span) { int i; for (i = 0; i < span.Length && char.IsWhiteSpace(span[i]); i++) { } return span.Slice(i); } public static ReadOnlySpan TrimEnd(this ReadOnlySpan span) { int num = span.Length - 1; while (num >= 0 && char.IsWhiteSpace(span[num])) { num--; } return span.Slice(0, num + 1); } public static ReadOnlySpan Trim(this ReadOnlySpan span, char trimChar) { return span.TrimStart(trimChar).TrimEnd(trimChar); } public static ReadOnlySpan TrimStart(this ReadOnlySpan span, char trimChar) { int i; for (i = 0; i < span.Length && span[i] == trimChar; i++) { } return span.Slice(i); } public static ReadOnlySpan TrimEnd(this ReadOnlySpan span, char trimChar) { int num = span.Length - 1; while (num >= 0 && span[num] == trimChar) { num--; } return span.Slice(0, num + 1); } public static ReadOnlySpan Trim(this ReadOnlySpan span, ReadOnlySpan trimChars) { return span.TrimStart(trimChars).TrimEnd(trimChars); } public static ReadOnlySpan TrimStart(this ReadOnlySpan span, ReadOnlySpan trimChars) { if (trimChars.IsEmpty) { return span.TrimStart(); } int i; for (i = 0; i < span.Length; i++) { int num = 0; while (num < trimChars.Length) { if (span[i] != trimChars[num]) { num++; continue; } goto IL_003c; } break; IL_003c:; } return span.Slice(i); } public static ReadOnlySpan TrimEnd(this ReadOnlySpan span, ReadOnlySpan trimChars) { if (trimChars.IsEmpty) { return span.TrimEnd(); } int num; for (num = span.Length - 1; num >= 0; num--) { int num2 = 0; while (num2 < trimChars.Length) { if (span[num] != trimChars[num2]) { num2++; continue; } goto IL_0044; } break; IL_0044:; } return span.Slice(0, num + 1); } public static bool IsWhiteSpace(this ReadOnlySpan span) { for (int i = 0; i < span.Length; i++) { if (!char.IsWhiteSpace(span[i])) { return false; } } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this Span span, T value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this Span span, ReadOnlySpan value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this Span span, T value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this Span span, ReadOnlySpan value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool SequenceEqual(this Span span, ReadOnlySpan other) where T : IEquatable { int length = span.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), (NUInt)length * size); } return false; } if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } return false; } public static int SequenceCompareTo(this Span span, ReadOnlySpan other) where T : IComparable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(other)), other.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(other)), other.Length); } return System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this ReadOnlySpan span, T value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this ReadOnlySpan span, T value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value), span.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOf(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOf(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(value)), value.Length); } return System.SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this Span span, T value0, T value1) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this Span span, T value0, T value1, T value2) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this Span span, ReadOnlySpan values) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this ReadOnlySpan span, T value0, T value1) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfAny(this ReadOnlySpan span, ReadOnlySpan values) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.IndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, T value0, T value1) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, T value0, T value1, T value2) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this Span span, ReadOnlySpan values) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this ReadOnlySpan span, T value0, T value1) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), Unsafe.As(ref value0), Unsafe.As(ref value1), Unsafe.As(ref value2), span.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LastIndexOfAny(this ReadOnlySpan span, ReadOnlySpan values) where T : IEquatable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.LastIndexOfAny(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length); } return System.SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool SequenceEqual(this ReadOnlySpan span, ReadOnlySpan other) where T : IEquatable { int length = span.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), (NUInt)length * size); } return false; } if (length == other.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SequenceCompareTo(this ReadOnlySpan span, ReadOnlySpan other) where T : IComparable { if (typeof(T) == typeof(byte)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(other)), other.Length); } if (typeof(T) == typeof(char)) { return System.SpanHelpers.SequenceCompareTo(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length, ref Unsafe.As(ref MemoryMarshal.GetReference(other)), other.Length); } return System.SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool StartsWith(this Span span, ReadOnlySpan value) where T : IEquatable { int length = value.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(value)), (NUInt)length * size); } return false; } if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool StartsWith(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { int length = value.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(value)), (NUInt)length * size); } return false; } if (length <= span.Length) { return System.SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), length); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EndsWith(this Span span, ReadOnlySpan value) where T : IEquatable { int length = span.Length; int length2 = value.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As(ref MemoryMarshal.GetReference(value)), (NUInt)length2 * size); } return false; } if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2); } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool EndsWith(this ReadOnlySpan span, ReadOnlySpan value) where T : IEquatable { int length = span.Length; int length2 = value.Length; if (default(T) != null && IsTypeComparableAsBytes(out var size)) { if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2)), ref Unsafe.As(ref MemoryMarshal.GetReference(value)), (NUInt)length2 * size); } return false; } if (length2 <= length) { return System.SpanHelpers.SequenceEqual(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), length - length2), ref MemoryMarshal.GetReference(value), length2); } return false; } public static void Reverse(this Span span) { ref T reference = ref MemoryMarshal.GetReference(span); int num = 0; int num2 = span.Length - 1; while (num < num2) { T val = Unsafe.Add(ref reference, num); Unsafe.Add(ref reference, num) = Unsafe.Add(ref reference, num2); Unsafe.Add(ref reference, num2) = val; num++; num2--; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this T[] array) { return new Span(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this T[] array, int start, int length) { return new Span(array, start, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this ArraySegment segment) { return new Span(segment.Array, segment.Offset, segment.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this ArraySegment segment, int start) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new Span(segment.Array, segment.Offset + start, segment.Count - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this ArraySegment segment, int start, int length) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } if ((uint)length > segment.Count - start) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); } return new Span(segment.Array, segment.Offset + start, length); } public static Memory AsMemory(this T[] array) { return new Memory(array); } public static Memory AsMemory(this T[] array, int start) { return new Memory(array, start); } public static Memory AsMemory(this T[] array, int start, int length) { return new Memory(array, start, length); } public static Memory AsMemory(this ArraySegment segment) { return new Memory(segment.Array, segment.Offset, segment.Count); } public static Memory AsMemory(this ArraySegment segment, int start) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new Memory(segment.Array, segment.Offset + start, segment.Count - start); } public static Memory AsMemory(this ArraySegment segment, int start, int length) { if ((uint)start > segment.Count) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } if ((uint)length > segment.Count - start) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); } return new Memory(segment.Array, segment.Offset + start, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this T[] source, Span destination) { new ReadOnlySpan(source).CopyTo(destination); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this T[] source, Memory destination) { source.CopyTo(destination.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Overlaps(this Span span, ReadOnlySpan other) { return ((ReadOnlySpan)span).Overlaps(other); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool Overlaps(this Span span, ReadOnlySpan other, out int elementOffset) { return ((ReadOnlySpan)span).Overlaps(other, out elementOffset); } public static bool Overlaps(this ReadOnlySpan span, ReadOnlySpan other) { if (span.IsEmpty || other.IsEmpty) { return false; } IntPtr intPtr = Unsafe.ByteOffset(in MemoryMarshal.GetReference(span), in MemoryMarshal.GetReference(other)); if (Unsafe.SizeOf() == 4) { if ((uint)(int)intPtr >= (uint)(span.Length * Unsafe.SizeOf())) { return (uint)(int)intPtr > (uint)(-(other.Length * Unsafe.SizeOf())); } return true; } if ((ulong)(long)intPtr >= (ulong)((long)span.Length * (long)Unsafe.SizeOf())) { return (ulong)(long)intPtr > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf())); } return true; } public static bool Overlaps(this ReadOnlySpan span, ReadOnlySpan other, out int elementOffset) { if (span.IsEmpty || other.IsEmpty) { elementOffset = 0; return false; } IntPtr intPtr = Unsafe.ByteOffset(in MemoryMarshal.GetReference(span), in MemoryMarshal.GetReference(other)); if (Unsafe.SizeOf() == 4) { if ((uint)(int)intPtr < (uint)(span.Length * Unsafe.SizeOf()) || (uint)(int)intPtr > (uint)(-(other.Length * Unsafe.SizeOf()))) { if ((int)intPtr % Unsafe.SizeOf() != 0) { System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch(); } elementOffset = (int)intPtr / Unsafe.SizeOf(); return true; } elementOffset = 0; return false; } if ((ulong)(long)intPtr < (ulong)((long)span.Length * (long)Unsafe.SizeOf()) || (ulong)(long)intPtr > (ulong)(-((long)other.Length * (long)Unsafe.SizeOf()))) { if ((long)intPtr % Unsafe.SizeOf() != 0L) { System.ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch(); } elementOffset = (int)((long)intPtr / Unsafe.SizeOf()); return true; } elementOffset = 0; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this Span span, IComparable comparable) { return span.BinarySearch>(comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this Span span, TComparable comparable) where TComparable : IComparable { return BinarySearch((ReadOnlySpan)span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this Span span, T value, TComparer comparer) where TComparer : IComparer { return ((ReadOnlySpan)span).BinarySearch(value, comparer); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this ReadOnlySpan span, IComparable comparable) { return MemoryExtensions.BinarySearch>(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this ReadOnlySpan span, TComparable comparable) where TComparable : IComparable { return System.SpanHelpers.BinarySearch(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BinarySearch(this ReadOnlySpan span, T value, TComparer comparer) where TComparer : IComparer { if (comparer == null) { System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.comparer); } System.SpanHelpers.ComparerComparable comparable = new System.SpanHelpers.ComparerComparable(value, comparer); return BinarySearch(span, comparable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsTypeComparableAsBytes(out NUInt size) { if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)) { size = (NUInt)1; return true; } if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort)) { size = (NUInt)2; return true; } if (typeof(T) == typeof(int) || typeof(T) == typeof(uint)) { size = (NUInt)4; return true; } if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong)) { size = (NUInt)8; return true; } size = default(NUInt); return false; } public static Span AsSpan(this T[] array, int start) { return Span.Create(array, start); } public static bool Contains(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { return span.IndexOf(value, comparisonType) >= 0; } public static bool Equals(this ReadOnlySpan span, ReadOnlySpan other, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.SequenceEqual(other); case StringComparison.OrdinalIgnoreCase: if (span.Length != other.Length) { return false; } return EqualsOrdinalIgnoreCase(span, other); default: return span.ToString().Equals(other.ToString(), comparisonType); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool EqualsOrdinalIgnoreCase(ReadOnlySpan span, ReadOnlySpan other) { if (other.Length == 0) { return true; } return CompareToOrdinalIgnoreCase(span, other) == 0; } public static int CompareTo(this ReadOnlySpan span, ReadOnlySpan other, StringComparison comparisonType) { return comparisonType switch { StringComparison.Ordinal => span.SequenceCompareTo(other), StringComparison.OrdinalIgnoreCase => CompareToOrdinalIgnoreCase(span, other), _ => string.Compare(span.ToString(), other.ToString(), comparisonType), }; } private unsafe static int CompareToOrdinalIgnoreCase(ReadOnlySpan strA, ReadOnlySpan strB) { int num = Math.Min(strA.Length, strB.Length); int num2 = num; fixed (char* reference = &MemoryMarshal.GetReference(strA)) { fixed (char* reference2 = &MemoryMarshal.GetReference(strB)) { char* ptr = reference; char* ptr2 = reference2; while (num != 0 && *ptr <= '\u007f' && *ptr2 <= '\u007f') { int num3 = *ptr; int num4 = *ptr2; if (num3 == num4) { ptr++; ptr2++; num--; continue; } if ((uint)(num3 - 97) <= 25u) { num3 -= 32; } if ((uint)(num4 - 97) <= 25u) { num4 -= 32; } if (num3 != num4) { return num3 - num4; } ptr++; ptr2++; num--; } if (num == 0) { return strA.Length - strB.Length; } num2 -= num; return string.Compare(strA.Slice(num2).ToString(), strB.Slice(num2).ToString(), StringComparison.OrdinalIgnoreCase); } } } public static int IndexOf(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { if (comparisonType == StringComparison.Ordinal) { return span.IndexOf(value); } return span.ToString().IndexOf(value.ToString(), comparisonType); } public static int ToLower(this ReadOnlySpan source, Span destination, CultureInfo culture) { if (culture == null) { System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.culture); } if (destination.Length < source.Length) { return -1; } string text = source.ToString(); string text2 = text.ToLower(culture); AsSpan(text2).CopyTo(destination); return source.Length; } public static int ToLowerInvariant(this ReadOnlySpan source, Span destination) { return source.ToLower(destination, CultureInfo.InvariantCulture); } public static int ToUpper(this ReadOnlySpan source, Span destination, CultureInfo culture) { if (culture == null) { System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.culture); } if (destination.Length < source.Length) { return -1; } string text = source.ToString(); string text2 = text.ToUpper(culture); AsSpan(text2).CopyTo(destination); return source.Length; } public static int ToUpperInvariant(this ReadOnlySpan source, Span destination) { return source.ToUpper(destination, CultureInfo.InvariantCulture); } public static bool EndsWith(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.EndsWith(value); case StringComparison.OrdinalIgnoreCase: if (value.Length <= span.Length) { return EqualsOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value); } return false; default: { string text = span.ToString(); string value2 = value.ToString(); return text.EndsWith(value2, comparisonType); } } } public static bool StartsWith(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { switch (comparisonType) { case StringComparison.Ordinal: return span.StartsWith(value); case StringComparison.OrdinalIgnoreCase: if (value.Length <= span.Length) { return EqualsOrdinalIgnoreCase(span.Slice(0, value.Length), value); } return false; default: { string text = span.ToString(); string value2 = value.ToString(); return text.StartsWith(value2, comparisonType); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan AsSpan(this string text) { if (text == null) { return default(ReadOnlySpan); } return new ReadOnlySpan(Unsafe.As>(text), StringAdjustment, text.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan AsSpan(this string text, int start) { if (text == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlySpan); } if ((uint)start > (uint)text.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlySpan(Unsafe.As>(text), StringAdjustment + start * 2, text.Length - start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan AsSpan(this string text, int start, int length) { if (text == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlySpan); } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlySpan(Unsafe.As>(text), StringAdjustment + start * 2, length); } public static ReadOnlyMemory AsMemory(this string text) { if (text == null) { return default(ReadOnlyMemory); } return new ReadOnlyMemory(text, 0, text.Length); } public static ReadOnlyMemory AsMemory(this string text, int start) { if (text == null) { if (start != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlyMemory); } if ((uint)start > (uint)text.Length) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory(text, start, text.Length - start); } public static ReadOnlyMemory AsMemory(this string text, int start, int length) { if (text == null) { if (start != 0 || length != 0) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return default(ReadOnlyMemory); } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) { System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.start); } return new ReadOnlyMemory(text, start, length); } private unsafe static IntPtr MeasureStringAdjustment() { string text = "a"; fixed (char* source = text) { return Unsafe.ByteOffset(in Unsafe.As>(text).Data, in Unsafe.AsRef(source)); } } }