From 7b56e30a574d644fa7fc8721fb2d4c3590fea644 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Wed, 14 Jun 2023 15:39:55 +0200 Subject: [PATCH 1/8] Add ContainsAny{Except} --- .../System.Memory/ref/System.Memory.cs | 22 ++ .../src/System/MemoryExtensions.cs | 195 +++++++++++++++++- 2 files changed, 210 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index e36ecb74617760..eef0f940d10823 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -234,6 +234,28 @@ public static partial class MemoryExtensions public static bool Contains(this System.ReadOnlySpan span, System.ReadOnlySpan value, System.StringComparison comparisonType) { throw null; } public static bool Contains(this System.ReadOnlySpan span, T value) where T : System.IEquatable? { throw null; } public static bool Contains(this System.Span span, T value) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.ReadOnlySpan span, System.Buffers.SearchValues values) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.ReadOnlySpan span, System.ReadOnlySpan values) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.ReadOnlySpan span, T value0, T value1) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.ReadOnlySpan span, T value0, T value1, T value2) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.Span span, System.Buffers.SearchValues values) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.Span span, T value0, T value1) where T : System.IEquatable? { throw null; } + public static bool ContainsAny(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.ReadOnlySpan span, System.Buffers.SearchValues values) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.ReadOnlySpan span, System.ReadOnlySpan values) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.ReadOnlySpan span, T value) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.ReadOnlySpan span, T value0, T value1) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.ReadOnlySpan span, T value0, T value1, T value2) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.Span span, System.Buffers.SearchValues values) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.Span span, T value) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.Span span, T value0, T value1) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExcept(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable? { throw null; } + public static bool ContainsAnyExceptInRange(this System.ReadOnlySpan span, T lowInclusive, T highInclusive) where T : System.IComparable { throw null; } + public static bool ContainsAnyExceptInRange(this System.Span span, T lowInclusive, T highInclusive) where T : System.IComparable { throw null; } + public static bool ContainsAnyInRange(this System.ReadOnlySpan span, T lowInclusive, T highInclusive) where T : System.IComparable { throw null; } + public static bool ContainsAnyInRange(this System.Span span, T lowInclusive, T highInclusive) where T : System.IComparable { throw null; } public static void CopyTo(this T[]? source, System.Memory destination) { } public static void CopyTo(this T[]? source, System.Span destination) { } public static int Count(this System.Span span, T value) where T : System.IEquatable? { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 681f0dc52e775c..d3dd82fd939d80 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -313,12 +313,7 @@ public static ReadOnlyMemory AsMemory(this string? text, Range range) return new ReadOnlyMemory(text, start, length); } - /// - /// Searches for the specified value and returns true if found. If not found, returns false. Values are compared using IEquatable{T}.Equals(T). - /// - /// - /// The span to search. - /// The value to search for. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool Contains(this Span span, T value) where T : IEquatable? { @@ -401,6 +396,192 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this Span span, T value0, T value1) where T : IEquatable? => + ContainsAny((ReadOnlySpan)span, value0, value1); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this Span span, T value0, T value1, T value2) where T : IEquatable? => + ContainsAny((ReadOnlySpan)span, value0, value1, value2); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this Span span, ReadOnlySpan values) where T : IEquatable? => + ContainsAny((ReadOnlySpan)span, values); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this Span span, SearchValues values) where T : IEquatable? => + ContainsAny((ReadOnlySpan)span, values); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this Span span, T value) where T : IEquatable? => + ContainsAnyExcept((ReadOnlySpan)span, value); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this Span span, T value0, T value1) where T : IEquatable? => + ContainsAnyExcept((ReadOnlySpan)span, value0, value1); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this Span span, T value0, T value1, T value2) where T : IEquatable? => + ContainsAnyExcept((ReadOnlySpan)span, value0, value1, value2); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this Span span, ReadOnlySpan values) where T : IEquatable? => + ContainsAnyExcept((ReadOnlySpan)span, values); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this Span span, SearchValues values) where T : IEquatable? => + ContainsAnyExcept((ReadOnlySpan)span, values); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyInRange(this Span span, T lowInclusive, T highInclusive) where T : IComparable => + ContainsAnyInRange((ReadOnlySpan)span, lowInclusive, highInclusive); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExceptInRange(this Span span, T lowInclusive, T highInclusive) where T : IComparable => + ContainsAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive); + + /// + /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// + /// The span to search. + /// One of the values to search for. + /// One of the values to search for. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this ReadOnlySpan span, T value0, T value1) where T : IEquatable? => + IndexOfAny(span, value0, value1) >= 0; + + /// + /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// + /// The span to search. + /// One of the values to search for. + /// One of the values to search for. + /// One of the values to search for. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable? => + IndexOfAny(span, value0, value1, value2) >= 0; + + /// + /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// + /// The span to search. + /// The set of values to search for. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this ReadOnlySpan span, ReadOnlySpan values) where T : IEquatable? => + IndexOfAny(span, values) >= 0; + + /// + /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// + /// The span to search. + /// The set of values to search for. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAny(this ReadOnlySpan span, SearchValues values) where T : IEquatable? => + IndexOfAny(span, values) >= 0; + + /// + /// Searches for any value other than the specified . + /// + /// The span to search. + /// A value to avoid. + /// + /// True if any value other than is present in the span. + /// If all of the values are , returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this ReadOnlySpan span, T value) where T : IEquatable? => + IndexOfAnyExcept(span, value) >= 0; + + /// + /// Searches for any value other than the specified or . + /// + /// The span to search. + /// A value to avoid. + /// A value to avoid. + /// + /// True if any value other than and is present in the span. + /// If all of the values are or , returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this ReadOnlySpan span, T value0, T value1) where T : IEquatable? => + IndexOfAnyExcept(span, value0, value1) >= 0; + + /// + /// Searches for any value other than the specified , , or . + /// + /// The span to search. + /// A value to avoid. + /// A value to avoid. + /// A value to avoid. + /// + /// True if any value other than , , and is present in the span. + /// If all of the values are , , or , returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this ReadOnlySpan span, T value0, T value1, T value2) where T : IEquatable? => + IndexOfAnyExcept(span, value0, value1, value2) >= 0; + + /// + /// Searches for any value other than the specified . + /// + /// The span to search. + /// The values to avoid. + /// + /// True if any value other than those in is present in the span. + /// If all of the values are in , returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this ReadOnlySpan span, ReadOnlySpan values) where T : IEquatable? => + IndexOfAnyExcept(span, values) >= 0; + + /// + /// Searches for any value other than the specified . + /// + /// The span to search. + /// The values to avoid. + /// + /// True if any value other than those in is present in the span. + /// If all of the values are in , returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExcept(this ReadOnlySpan span, SearchValues values) where T : IEquatable? => + IndexOfAnyExcept(span, values) >= 0; + + /// + /// Searches for any value in the range between and , inclusive, and returns true if found. If not found, returns false. + /// + /// The span to search. + /// A lower bound, inclusive, of the range for which to search. + /// A upper bound, inclusive, of the range for which to search. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyInRange(this ReadOnlySpan span, T lowInclusive, T highInclusive) where T : IComparable => + IndexOfAnyInRange(span, lowInclusive, highInclusive) >= 0; + + /// + /// Searches for any value outside of the range between and , inclusive. + /// + /// The span to search. + /// A lower bound, inclusive, of the excluded range. + /// A upper bound, inclusive, of the excluded range. + /// + /// True if any value other than those in the specified range is present in the span. + /// If all of the values are inside of the specified range, returns false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsAnyExceptInRange(this ReadOnlySpan span, T lowInclusive, T highInclusive) where T : IComparable => + IndexOfAnyExceptInRange(span, lowInclusive, highInclusive) >= 0; + /// /// Searches for the specified value and returns the index of its first occurrence. If not found, returns -1. Values are compared using IEquatable{T}.Equals(T). /// @@ -572,7 +753,7 @@ public static int IndexOfAnyExcept(this Span span, T value0, T value1) whe /// A value to avoid /// /// The index in the span of the first occurrence of any value other than , , and . - /// If all of the values are , , and , returns -1. + /// If all of the values are , , or , returns -1. /// public static int IndexOfAnyExcept(this Span span, T value0, T value1, T value2) where T : IEquatable? => IndexOfAnyExcept((ReadOnlySpan)span, value0, value1, value2); From 86ff910c1a0e81c92c21081186db853f6b46c338 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Wed, 14 Jun 2023 22:22:25 +0200 Subject: [PATCH 2/8] Use it everywhere --- .../System/Globalization/FormatProvider.Number.cs | 2 +- .../Common/src/System/Net/HttpValidationHelpers.cs | 2 +- .../src/System/Net/Security/TargetHostNameHelper.cs | 2 +- .../src/System/Security/Cryptography/RSAAndroid.cs | 2 +- .../src/Internal/PathUtils.cs | 4 ++-- .../Collections/Concurrent/ConcurrentDictionary.cs | 2 +- .../System/Collections/Frozen/String/KeyAnalyzer.cs | 2 +- .../src/System/Collections/BitArray.cs | 4 ++-- .../src/System/Formats/Tar/TarHelpers.cs | 2 +- .../src/System/IO/Compression/ZipHelper.cs | 2 +- .../src/System/IO/Pipes/PipeStream.Unix.cs | 4 ++-- .../src/System/Net/Http/Headers/UriHeaderParser.cs | 2 +- .../src/System/Net/Http/HttpRuleParser.cs | 6 +++--- .../src/System/Net/Http/MultipartContent.cs | 2 +- .../Net/Managed/HttpListenerRequest.Managed.cs | 2 +- .../src/System/Net/Mail/Attachment.cs | 2 +- .../src/System/Net/Mail/MailBnfHelper.cs | 4 ++-- .../src/System/Net/Mime/MimeBasePart.cs | 2 +- .../System.Net.Primitives/src/System/Net/Cookie.cs | 12 ++++++------ .../System.Private.CoreLib/src/System/Byte.cs | 4 ++-- .../System.Private.CoreLib/src/System/Char.cs | 4 ++-- .../src/System/Globalization/CompareInfo.Icu.cs | 8 ++++---- .../src/System/Globalization/CultureData.cs | 2 +- .../src/System/Globalization/DateTimeParse.cs | 2 +- .../System.Private.CoreLib/src/System/Guid.cs | 2 +- .../src/System/IO/Directory.cs | 2 +- .../IO/Enumeration/FileSystemEnumerableFactory.cs | 2 +- .../src/System/IO/Enumeration/FileSystemName.cs | 6 +++--- .../System.Private.CoreLib/src/System/Int128.cs | 4 ++-- .../System.Private.CoreLib/src/System/Int16.cs | 4 ++-- .../System.Private.CoreLib/src/System/Int32.cs | 4 ++-- .../System.Private.CoreLib/src/System/Int64.cs | 4 ++-- .../System.Private.CoreLib/src/System/IntPtr.cs | 4 ++-- .../src/System/Number.Parsing.cs | 2 +- .../src/System/Reflection/AssemblyNameParser.cs | 2 +- .../System.Private.CoreLib/src/System/SByte.cs | 4 ++-- .../src/System/Security/SecurityElement.cs | 6 +++--- .../src/System/TimeZoneInfo.FullGlobalizationData.cs | 4 ++-- .../System.Private.CoreLib/src/System/UInt128.cs | 4 ++-- .../System.Private.CoreLib/src/System/UInt16.cs | 4 ++-- .../System.Private.CoreLib/src/System/UInt32.cs | 4 ++-- .../System.Private.CoreLib/src/System/UInt64.cs | 4 ++-- .../System.Private.CoreLib/src/System/UIntPtr.cs | 4 ++-- .../Serialization/Json/JsonObjectDataContract.cs | 2 +- .../src/System/Xml/XmlBaseWriter.cs | 2 +- .../src/System/Xml/XmlConverter.cs | 4 ++-- .../src/System/DomainNameHelper.cs | 4 ++-- src/libraries/System.Private.Uri/src/System/Uri.cs | 4 ++-- .../System.Private.Uri/src/System/UriBuilder.cs | 2 +- .../src/System/Xml/Linq/XDocument.cs | 2 +- .../Xml/Serialization/XmlSerializationWriter.cs | 2 +- .../System.Private.Xml/src/System/Xml/XmlCharType.cs | 2 +- .../System.Private.Xml/src/System/Xml/XmlConvert.cs | 8 ++++---- .../src/System/Xml/Xsl/Xslt/QilGenerator.cs | 4 ++-- .../System/Security/Cryptography/Base64Transforms.cs | 2 +- .../System/Security/Cryptography/SymmetricPadding.cs | 2 +- .../Cryptography/X509Certificates/X500NameEncoder.cs | 2 +- .../src/System/ServiceProcess/ServiceBase.cs | 2 +- .../src/System/Text/Json/Reader/JsonReaderHelper.cs | 8 +++++--- src/tests/Common/XUnitWrapperLibrary/TestFilter.cs | 2 +- 60 files changed, 103 insertions(+), 101 deletions(-) diff --git a/src/libraries/Common/src/System/Globalization/FormatProvider.Number.cs b/src/libraries/Common/src/System/Globalization/FormatProvider.Number.cs index 0a7a7a4a89536c..4c7bc5bbce2aa9 100644 --- a/src/libraries/Common/src/System/Globalization/FormatProvider.Number.cs +++ b/src/libraries/Common/src/System/Globalization/FormatProvider.Number.cs @@ -596,7 +596,7 @@ private static unsafe bool ParseNumber(ref char* str, char* strEnd, NumberStyles [MethodImpl(MethodImplOptions.NoInlining)] // rare slow path that shouldn't impact perf of the main use case private static bool TrailingZeros(ReadOnlySpan s, int index) => // For compatibility, we need to allow trailing zeros at the end of a number string - s.Slice(index).IndexOfAnyExcept('\0') < 0; + !s.Slice(index).ContainsAnyExcept('\0'); internal static unsafe bool TryStringToNumber(ReadOnlySpan str, NumberStyles options, scoped ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, bool parseDecimal) { diff --git a/src/libraries/Common/src/System/Net/HttpValidationHelpers.cs b/src/libraries/Common/src/System/Net/HttpValidationHelpers.cs index 8ab68a43f0bd4d..0dd393025595c7 100644 --- a/src/libraries/Common/src/System/Net/HttpValidationHelpers.cs +++ b/src/libraries/Common/src/System/Net/HttpValidationHelpers.cs @@ -22,7 +22,7 @@ internal static string CheckBadHeaderNameChars(string name) } internal static bool ContainsNonAsciiChars(string token) => - token.AsSpan().IndexOfAnyExceptInRange((char)0x20, (char)0x7e) >= 0; + token.AsSpan().ContainsAnyExceptInRange((char)0x20, (char)0x7e); internal static bool IsValidToken(string token) { diff --git a/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs b/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs index f4dbaeee55b783..7202cebe142bab 100644 --- a/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs +++ b/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs @@ -14,7 +14,7 @@ internal static class TargetHostNameHelper SearchValues.Create("-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"); private static bool IsSafeDnsString(ReadOnlySpan name) => - name.IndexOfAnyExcept(s_safeDnsChars) < 0; + !name.ContainsAnyExcept(s_safeDnsChars); internal static string NormalizeHostName(string? targetHost) { diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs index 2fbad637e81b37..10a3585483ed37 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs @@ -306,7 +306,7 @@ public override void ImportParameters(RSAParameters parameters) ValidateParameters(ref parameters); ThrowIfDisposed(); - if (parameters.Exponent == null || parameters.Modulus.AsSpan().IndexOfAnyExcept((byte)0) < 0) + if (parameters.Exponent == null || !parameters.Modulus.AsSpan().ContainsAnyExcept((byte)0)) { throw new CryptographicException(SR.Cryptography_InvalidRsaParameters); } diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs index 6321adbfc72f16..5ecd13583c1349 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs @@ -30,12 +30,12 @@ private static char[] GetInvalidFilterChars() => GetInvalidFileNameChars() internal static bool HasInvalidPathChars(string path) { - return path.AsSpan().IndexOfAny(_invalidFileNameChars) >= 0; + return path.AsSpan().ContainsAny(_invalidFileNameChars); } internal static bool HasInvalidFilterChars(string path) { - return path.AsSpan().IndexOfAny(_invalidFilterChars) >= 0; + return path.AsSpan().ContainsAny(_invalidFilterChars); } internal static string EnsureTrailingSlash(string path) diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs index 9ffe1ec88db679..4371968af780a3 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -1923,7 +1923,7 @@ void ICollection.CopyTo(Array array, int index) #endregion private bool AreAllBucketsEmpty() => - _tables._countPerLock.AsSpan().IndexOfAnyExcept(0) < 0; + !_tables._countPerLock.AsSpan().ContainsAnyExcept(0); /// /// Replaces the bucket table with a larger one. To prevent multiple threads from resizing the diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs index 9da8b3c61e5739..4cdf5ba7a58b23 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs @@ -207,7 +207,7 @@ private static bool ContainsAnyLetters(ReadOnlySpan s) Debug.Assert(IsAllAscii(s)); #if NET8_0_OR_GREATER - return s.IndexOfAny(s_asciiLetters) >= 0; + return s.ContainsAny(s_asciiLetters); #else foreach (char c in s) { diff --git a/src/libraries/System.Collections/src/System/Collections/BitArray.cs b/src/libraries/System.Collections/src/System/Collections/BitArray.cs index c514f9c7d2f064..db0f59e8ac7af2 100644 --- a/src/libraries/System.Collections/src/System/Collections/BitArray.cs +++ b/src/libraries/System.Collections/src/System/Collections/BitArray.cs @@ -924,7 +924,7 @@ public bool HasAllSet() } const int AllSetBits = -1; // 0xFF_FF_FF_FF - if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(AllSetBits) >= 0) + if (m_array.AsSpan(0, intCount).ContainsAnyExcept(AllSetBits)) { return false; } @@ -954,7 +954,7 @@ public bool HasAnySet() intCount--; } - if (m_array.AsSpan(0, intCount).IndexOfAnyExcept(0) >= 0) + if (m_array.AsSpan(0, intCount).ContainsAnyExcept(0)) { return true; } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs index 028ed59ea9e1fc..8c9737b1ec2939 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs @@ -132,7 +132,7 @@ internal static int CalculatePadding(long size) // Returns true if all the bytes in the specified array are nulls, false otherwise. internal static bool IsAllNullBytes(Span buffer) => - buffer.IndexOfAnyExcept((byte)0) < 0; + !buffer.ContainsAnyExcept((byte)0); // Converts the specified number of seconds that have passed since the Unix Epoch to a DateTimeOffset. internal static DateTimeOffset GetDateTimeOffsetFromSecondsSinceEpoch(long secondsSinceUnixEpoch) => diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipHelper.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipHelper.cs index 22d784eb495bb3..4feb3299bc3053 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipHelper.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipHelper.cs @@ -22,7 +22,7 @@ internal static class ZipHelper internal static Encoding GetEncoding(string text) { - if (text.AsSpan().IndexOfAnyExceptInRange((char)32, (char)126) >= 0) + if (text.AsSpan().ContainsAnyExceptInRange((char)32, (char)126)) { // The Zip Format uses code page 437 when the Unicode bit is not set. This format // is the same as ASCII for characters 32-126 but differs otherwise. If we can fit diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs index bba294894df431..8cb46d143ea103 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs @@ -202,14 +202,14 @@ internal static string GetPipePath(string serverName, string pipeName) // cross-platform with Windows (which has only '\' as an invalid char). if (Path.IsPathRooted(pipeName)) { - if (pipeName.IndexOfAny(s_invalidPathNameChars) >= 0 || pipeName.EndsWith(Path.DirectorySeparatorChar)) + if (pipeName.ContainsAny(s_invalidPathNameChars) || pipeName.EndsWith(Path.DirectorySeparatorChar)) throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars); // Caller is in full control of file location. return pipeName; } - if (pipeName.IndexOfAny(s_invalidFileNameChars) >= 0) + if (pipeName.ContainsAny(s_invalidFileNameChars)) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/UriHeaderParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/UriHeaderParser.cs index 7a29df14946913..f96477a5cde139 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/UriHeaderParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/UriHeaderParser.cs @@ -64,7 +64,7 @@ internal static string DecodeUtf8FromString(string input) { int possibleUtf8Pos = input.AsSpan().IndexOfAnyExceptInRange((char)0, (char)127); if (possibleUtf8Pos >= 0 && - input.AsSpan(possibleUtf8Pos).IndexOfAnyExceptInRange((char)0, (char)255) < 0) + !input.AsSpan(possibleUtf8Pos).ContainsAnyExceptInRange((char)0, (char)255)) { Span rawBytes = input.Length <= 256 ? stackalloc byte[input.Length] : new byte[input.Length]; for (int i = 0; i < input.Length; i++) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs index 83fd0b2dc0e872..cad5eda382ca00 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpRuleParser.cs @@ -41,10 +41,10 @@ internal static int GetTokenLength(string input, int startIndex) } internal static bool IsToken(ReadOnlySpan input) => - input.IndexOfAnyExcept(s_tokenChars) < 0; + !input.ContainsAnyExcept(s_tokenChars); internal static bool IsToken(ReadOnlySpan input) => - input.IndexOfAnyExcept(s_tokenBytes) < 0; + !input.ContainsAnyExcept(s_tokenBytes); internal static string GetTokenString(ReadOnlySpan input) { @@ -83,7 +83,7 @@ internal static int GetWhitespaceLength(string input, int startIndex) } internal static bool ContainsNewLine(string value, int startIndex = 0) => - value.AsSpan(startIndex).IndexOfAny('\r', '\n') >= 0; + value.AsSpan(startIndex).ContainsAny('\r', '\n'); internal static int GetNumberLength(string input, int startIndex, bool allowDecimal) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs index 961de333e1d6fa..2d3d8598b55cf0 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs @@ -82,7 +82,7 @@ private static void ValidateBoundary(string boundary) throw new ArgumentException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_headers_invalid_value, boundary), nameof(boundary)); } - if (boundary.AsSpan().IndexOfAnyExcept(s_allowedBoundaryChars) >= 0) + if (boundary.AsSpan().ContainsAnyExcept(s_allowedBoundaryChars)) { throw new ArgumentException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_headers_invalid_value, boundary), nameof(boundary)); } diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs index 651a5f39ad39df..213567d483ca88 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpListenerRequest.Managed.cs @@ -84,7 +84,7 @@ internal void SetRequestLine(string req) } _method = req[parts[0]]; - if (_method.AsSpan().IndexOfAnyExcept(s_validMethodChars) >= 0) + if (_method.AsSpan().ContainsAnyExcept(s_validMethodChars)) { _context.ErrorMessage = "(Invalid verb)"; return; diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index 93e472fc9b4260..2dbb15891d013e 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -219,7 +219,7 @@ public string ContentId } else { - if (value.AsSpan().IndexOfAny('<', '>') >= 0) // invalid chars + if (value.AsSpan().ContainsAny('<', '>')) // invalid chars { throw new ArgumentException(SR.MailHeaderInvalidCID, nameof(value)); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs index 0df8b537c63942..658ef63a54173d 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs @@ -146,7 +146,7 @@ internal static bool SkipCFWS(string data, ref int offset) internal static void ValidateHeaderName(string data) { - if (data.Length == 0 || data.AsSpan().IndexOfAnyExcept(s_charactersAllowedInHeaderNames) >= 0) + if (data.Length == 0 || data.AsSpan().ContainsAnyExcept(s_charactersAllowedInHeaderNames)) { throw new FormatException(SR.InvalidHeaderName); } @@ -354,7 +354,7 @@ internal static bool IsAllowedWhiteSpace(char c) => c == Tab || c == Space || c == CR || c == LF; internal static bool HasCROrLF(string data) => - data.AsSpan().IndexOfAny(CR, LF) >= 0; + data.AsSpan().ContainsAny(CR, LF); // Is there a FWS ("\r\n " or "\r\n\t") starting at the given index? internal static bool IsFWSAt(string data, int index) diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/MimeBasePart.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/MimeBasePart.cs index 35a642ee56667e..305dacb05a0661 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/MimeBasePart.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/MimeBasePart.cs @@ -111,7 +111,7 @@ internal static bool IsAscii(string value, bool permitCROrLF) { ArgumentNullException.ThrowIfNull(value); - return Ascii.IsValid(value) && (permitCROrLF || value.AsSpan().IndexOfAny('\r', '\n') < 0); + return Ascii.IsValid(value) && (permitCROrLF || !value.AsSpan().ContainsAny('\r', '\n')); } internal string? ContentID diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 1908de07c31b30..8e21138d1b58f5 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -242,7 +242,7 @@ internal bool InternalSetName(string? value) || value.StartsWith('$') || value.StartsWith(' ') || value.EndsWith(' ') - || value.AsSpan().IndexOfAny(s_reservedToNameChars) >= 0) + || value.AsSpan().ContainsAny(s_reservedToNameChars)) { m_name = string.Empty; return false; @@ -350,7 +350,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma m_name.StartsWith('$') || m_name.StartsWith(' ') || m_name.EndsWith(' ') || - m_name.AsSpan().IndexOfAny(s_reservedToNameChars) >= 0) + m_name.AsSpan().ContainsAny(s_reservedToNameChars)) { if (shouldThrow) { @@ -361,7 +361,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check the value if (m_value == null || - (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.AsSpan().IndexOfAny(';', ',') >= 0)) + (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.AsSpan().ContainsAny(';', ','))) { if (shouldThrow) { @@ -372,7 +372,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check Comment syntax if (Comment != null && !(Comment.Length > 2 && Comment.StartsWith('\"') && Comment.EndsWith('\"')) - && (Comment.AsSpan().IndexOfAny(';', ',') >= 0)) + && (Comment.AsSpan().ContainsAny(';', ','))) { if (shouldThrow) { @@ -383,7 +383,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check Path syntax if (Path != null && !(Path.Length > 2 && Path.StartsWith('\"') && Path.EndsWith('\"')) - && (Path.AsSpan().IndexOfAny(';', ',') != -1)) + && (Path.AsSpan().ContainsAny(';', ','))) { if (shouldThrow) { @@ -565,7 +565,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // as per RFC 952 (relaxed on first char could be a digit and string can have '_'). private static bool DomainCharsTest(string name) => !string.IsNullOrEmpty(name) && - name.AsSpan().IndexOfAnyExcept(s_domainChars) < 0; + !name.AsSpan().ContainsAnyExcept(s_domainChars); [AllowNull] public string Port diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index 6716614028f666..e778864eedb92f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -303,7 +303,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, boo return false; } - if ((source.Length > sizeof(byte)) && (source[..^sizeof(byte)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(byte)) && (source[..^sizeof(byte)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -336,7 +336,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if ((source.Length > sizeof(byte)) && (source[sizeof(byte)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(byte)) && (source[sizeof(byte)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index 31998153de572d..159f74f2e37755 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1197,7 +1197,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, boo return false; } - if ((source.Length > sizeof(char)) && (source[..^sizeof(char)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(char)) && (source[..^sizeof(char)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -1247,7 +1247,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if ((source.Length > sizeof(char)) && (source[sizeof(char)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(char)) && (source[sizeof(char)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs index 0d15aa194f9e05..f29904d65e9f64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.Icu.cs @@ -104,14 +104,14 @@ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan source, Rea char* a = ap; char* b = bp; - if (target.IndexOfAnyExcept(s_nonSpecialAsciiChars) >= 0) + if (target.ContainsAnyExcept(s_nonSpecialAsciiChars)) { goto InteropCall; } if (target.Length > source.Length) { - if (source.IndexOfAnyExcept(s_nonSpecialAsciiChars) >= 0) + if (source.ContainsAnyExcept(s_nonSpecialAsciiChars)) { goto InteropCall; } @@ -214,14 +214,14 @@ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan source, ReadOnlySpan< char* a = ap; char* b = bp; - if (target.IndexOfAnyExcept(s_nonSpecialAsciiChars) >= 0) + if (target.ContainsAnyExcept(s_nonSpecialAsciiChars)) { goto InteropCall; } if (target.Length > source.Length) { - if (source.IndexOfAnyExcept(s_nonSpecialAsciiChars) >= 0) + if (source.ContainsAnyExcept(s_nonSpecialAsciiChars)) { goto InteropCall; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index 69c8ec34aa7156..0aa517ef6990f7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -2112,7 +2112,7 @@ private static string GetSeparator(string format, string timeParts) private static int IndexOfTimePart(string format, int startIndex, string timeParts) { Debug.Assert(startIndex >= 0, "startIndex cannot be negative"); - Debug.Assert(timeParts.AsSpan().IndexOfAny('\'', '\\') < 0, "timeParts cannot include quote characters"); + Debug.Assert(!timeParts.AsSpan().ContainsAny('\'', '\\'), "timeParts cannot include quote characters"); bool inQuote = false; for (int i = startIndex; i < format.Length; ++i) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs index 270b580e4178bf..9fe6ff109653c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs @@ -1225,7 +1225,7 @@ private static bool VerifyValidPunctuation(ref __DTString str) else if (ch == '\0') { // Nulls are only valid if they are the only trailing character - if (str.Value.Slice(str.Index + 1).IndexOfAnyExcept('\0') >= 0) + if (str.Value.Slice(str.Index + 1).ContainsAnyExcept('\0')) { return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 16be7a891741b3..6c31cf523c5032 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -466,7 +466,7 @@ private static bool TryParseExactD(ReadOnlySpan guidString, ref GuidResult // We continue to support these but expect them to be incredibly rare. As such, we // optimize for correctly formed strings where all the digits are valid hex, and only // fall back to supporting these other forms if parsing fails. - if (guidString.IndexOfAny('X', 'x', '+') >= 0 && TryCompatParsing(guidString, ref result)) + if (guidString.ContainsAny('X', 'x', '+') && TryCompatParsing(guidString, ref result)) { return true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs index 672c515595e72e..dc8f28f66fa43e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs @@ -70,7 +70,7 @@ public static unsafe DirectoryInfo CreateTempSubdirectory(string? prefix = null) private static void EnsureNoDirectorySeparators(string? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) { - if (value is not null && value.AsSpan().IndexOfAny(PathInternal.DirectorySeparators) >= 0) + if (value is not null && value.AsSpan().ContainsAny(PathInternal.DirectorySeparators)) { throw new ArgumentException(SR.Argument_DirectorySeparatorInvalid, paramName); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs index dbe0a624ed82b0..cd2f9fb2f35387 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs @@ -74,7 +74,7 @@ internal static bool NormalizeInputs(ref string directory, ref string expression // is the directory separator and cannot be part of any path segment in Windows). The other three are the // special case wildcards that we'll convert some * and ? into. They're also valid as filenames on Unix, // which is not true in Windows and as such we'll escape any that occur on the input string. - if (Path.DirectorySeparatorChar != '\\' && expression.AsSpan().IndexOfAny(@"\""<>") >= 0) + if (Path.DirectorySeparatorChar != '\\' && expression.AsSpan().ContainsAny(@"\""<>")) { // Backslash isn't the default separator, need to escape (e.g. Unix) expression = expression.Replace("\\", "\\\\"); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs index 1ecb3b0373578a..fa95554cbc49c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs @@ -152,9 +152,9 @@ private static bool MatchPattern(ReadOnlySpan expression, ReadOnlySpan*?") : - expressionEnd.IndexOfAny('*', '?')) >= 0; + bool hasWildcards = useExtendedWildcards ? + expressionEnd.ContainsAny("\"<>*?") : + expressionEnd.ContainsAny('*', '?'); if (!hasWildcards) { // Handle the special case of a single starting *, which essentially means "ends with" diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs index c6b98d28526c9a..33746544708655 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs @@ -792,7 +792,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, b if (source.Length > Size) { - if (source[..^Size].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^Size].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -874,7 +874,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source if (source.Length > Size) { - if (source[Size..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[Size..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index 02d896f981fb3a..7b4261e77882a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -316,7 +316,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo if (source.Length > sizeof(short)) { - if (source[..^sizeof(short)].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^sizeof(short)].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -391,7 +391,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, if (source.Length > sizeof(short)) { - if (source[sizeof(short)..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[sizeof(short)..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index a0c055cd21a34b..7660fbaaae8b3c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -330,7 +330,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bool if (source.Length > sizeof(int)) { - if (source[..^sizeof(int)].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^sizeof(int)].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -412,7 +412,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, b if (source.Length > sizeof(int)) { - if (source[sizeof(int)..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[sizeof(int)..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index 7f4ace2b1c7252..cf8bf7850790f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -327,7 +327,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, boo if (source.Length > sizeof(long)) { - if (source[..^sizeof(long)].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^sizeof(long)].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -409,7 +409,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, if (source.Length > sizeof(long)) { - if (source[sizeof(long)..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[sizeof(long)..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index 0457b6917bba95..3c6434b0d2ce97 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -334,7 +334,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, boo if (source.Length > sizeof(nint_t)) { - if (source[..^sizeof(nint_t)].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^sizeof(nint_t)].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -416,7 +416,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, if (source.Length > sizeof(nint_t)) { - if (source[sizeof(nint_t)..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[sizeof(nint_t)..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs index 5756b5d93b0b0e..ff94db3bcf9c80 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs @@ -1219,7 +1219,7 @@ internal static unsafe bool TryStringToNumber(ReadOnlySpan value, NumberSt [MethodImpl(MethodImplOptions.NoInlining)] // rare slow path that shouldn't impact perf of the main use case private static bool TrailingZeros(ReadOnlySpan value, int index) => // For compatibility, we need to allow trailing zeros at the end of a number string - value.Slice(index).IndexOfAnyExcept('\0') < 0; + !value.Slice(index).ContainsAnyExcept('\0'); private static bool IsSpaceReplacingChar(char c) => c == '\u00a0' || c == '\u202f'; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs index f7e5e95f634c36..2b8a93ff4f2686 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs @@ -90,7 +90,7 @@ private AssemblyNameParts Parse() if (token != Token.String) ThrowInvalidAssemblyName(); - if (string.IsNullOrEmpty(name) || name.AsSpan().IndexOfAny('/', '\\', ':') != -1) + if (string.IsNullOrEmpty(name) || name.AsSpan().ContainsAny('/', '\\', ':')) ThrowInvalidAssemblyName(); Version? version = null; diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index 3b6441b1eb16bd..496eefa87b10cd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -319,7 +319,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo if (source.Length > sizeof(sbyte)) { - if (source[..^sizeof(sbyte)].IndexOfAnyExcept((byte)sign) >= 0) + if (source[..^sizeof(sbyte)].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range @@ -372,7 +372,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, if (source.Length > sizeof(sbyte)) { - if (source[sizeof(sbyte)..].IndexOfAnyExcept((byte)sign) >= 0) + if (source[sizeof(sbyte)..].ContainsAnyExcept((byte)sign)) { // When we are unsigned and have any non-zero leading data or signed with any non-set leading // data, we are a large positive/negative, respectively, and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index fc993e7058e883..f4e9d47be5f146 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -289,16 +289,16 @@ public SecurityElement Copy() } public static bool IsValidTag([NotNullWhen(true)] string? tag) => - tag != null && tag.AsSpan().IndexOfAny(' ', '<', '>') < 0; + tag != null && !tag.AsSpan().ContainsAny(' ', '<', '>'); public static bool IsValidText([NotNullWhen(true)] string? text) => - text != null && text.AsSpan().IndexOfAny('<', '>') < 0; + text != null && !text.AsSpan().ContainsAny('<', '>'); public static bool IsValidAttributeName([NotNullWhen(true)] string? name) => IsValidTag(name); public static bool IsValidAttributeValue([NotNullWhen(true)] string? value) => - value != null && value.AsSpan().IndexOfAny('<', '>', '\"') < 0; + value != null && !value.AsSpan().ContainsAny('<', '>', '\"'); private static string GetEscapeSequence(char c) { diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs index e0643c21be2837..17b677ca37a9ae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.cs @@ -12,7 +12,7 @@ private static unsafe bool TryConvertIanaIdToWindowsId(string ianaId, bool alloc if (GlobalizationMode.Invariant || GlobalizationMode.UseNls || ianaId is null || - ianaId.AsSpan().IndexOfAny('\\', '\n', '\r') >= 0) // ICU uses these characters as a separator + ianaId.AsSpan().ContainsAny('\\', '\n', '\r')) // ICU uses these characters as a separator { windowsId = null; return false; @@ -46,7 +46,7 @@ private static unsafe bool TryConvertWindowsIdToIanaId(string windowsId, string? return true; } - if (windowsId.AsSpan().IndexOfAny('\\', '\n', '\r') >= 0) // ICU uses these characters as a separator + if (windowsId.AsSpan().ContainsAny('\\', '\n', '\r')) // ICU uses these characters as a separator { ianaId = null; return false; diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs index 85ff1a912a4c48..00e61cd6383026 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs @@ -842,7 +842,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, return false; } - if ((source.Length > Size) && (source[..^Size].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > Size) && (source[..^Size].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -899,7 +899,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan sourc return false; } - if ((source.Length > Size) && (source[Size..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > Size) && (source[Size..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index 54f87f1264cea1..3d86e2fe8640f5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -300,7 +300,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, b return false; } - if ((source.Length > sizeof(ushort)) && (source[..^sizeof(ushort)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(ushort)) && (source[..^sizeof(ushort)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -350,7 +350,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source return false; } - if ((source.Length > sizeof(ushort)) && (source[sizeof(ushort)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(ushort)) && (source[sizeof(ushort)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index dcec51866930df..6f2209d5f347a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -315,7 +315,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, boo return false; } - if ((source.Length > sizeof(uint)) && (source[..^sizeof(uint)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(uint)) && (source[..^sizeof(uint)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -372,7 +372,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if ((source.Length > sizeof(uint)) && (source[sizeof(uint)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(uint)) && (source[sizeof(uint)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index c9b2e057480d71..bb09e77c185faa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -314,7 +314,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo return false; } - if ((source.Length > sizeof(ulong)) && (source[..^sizeof(ulong)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(ulong)) && (source[..^sizeof(ulong)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -371,7 +371,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if ((source.Length > sizeof(ulong)) && (source[sizeof(ulong)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(ulong)) && (source[sizeof(ulong)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index 6c2d77d29779a0..79566c793c0f80 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -320,7 +320,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo return false; } - if ((source.Length > sizeof(nuint_t)) && (source[..^sizeof(nuint_t)].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(nuint_t)) && (source[..^sizeof(nuint_t)].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range @@ -377,7 +377,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if ((source.Length > sizeof(nuint_t)) && (source[sizeof(nuint_t)..].IndexOfAnyExcept((byte)0x00) >= 0)) + if ((source.Length > sizeof(nuint_t)) && (source[sizeof(nuint_t)..].ContainsAnyExcept((byte)0x00))) { // When we have any non-zero leading data, we are a large positive and therefore // definitely out of range diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs index bd0fa0e2762f90..e8b2db0bfbce6c 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs @@ -70,7 +70,7 @@ internal static object ParseJsonNumber(string value, out TypeCode objectTypeCode throw new XmlException(SR.Format(SR.XmlInvalidConversion, value, Globals.TypeOfInt)); } - if (value.AsSpan().IndexOfAny('.', 'e', 'E') < 0) + if (!value.AsSpan().ContainsAny('.', 'e', 'E')) { int intValue; if (int.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out intValue)) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs index ff1572fcd7c601..b964dd7bec9dbf 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs @@ -962,7 +962,7 @@ public override void WriteWhitespace(string? whitespace) ArgumentNullException.ThrowIfNull(whitespace); - if (whitespace.AsSpan().IndexOfAnyExcept(" \t\r\n") >= 0) + if (whitespace.AsSpan().ContainsAnyExcept(" \t\r\n")) { throw new ArgumentException(SR.XmlOnlyWhitespace, nameof(whitespace)); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs index 55b9a1e8f24721..6f57e42585cd23 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlConverter.cs @@ -1085,10 +1085,10 @@ public static int ToChars(DateTime value, byte[] chars, int offset) } public static bool IsWhitespace(ReadOnlySpan chars) => - chars.IndexOfAnyExcept(s_whitespaceChars) < 0; + !chars.ContainsAnyExcept(s_whitespaceChars); public static bool IsWhitespace(ReadOnlySpan bytes) => - bytes.IndexOfAnyExcept(s_whitespaceBytes) < 0; + !bytes.ContainsAnyExcept(s_whitespaceBytes); public static bool IsWhitespace(char ch) => ch is <= ' ' and (' ' or '\t' or '\r' or '\n'); diff --git a/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs b/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs index 79fc70291d9f25..7bbce795d009ed 100644 --- a/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs +++ b/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs @@ -150,7 +150,7 @@ public static bool IsValid(ReadOnlySpan hostname, bool iri, bool notImplic { // s_iriInvalidAsciiChars confirmed everything in [0, 7F] range. // Chars in [80, 9F] range are also invalid, check for them now. - if (hostname.IndexOfAnyInRange('\u0080', '\u009F') >= 0) + if (hostname.ContainsAnyInRange('\u0080', '\u009F')) { return false; } @@ -206,7 +206,7 @@ public static string IdnEquivalent(string hostname) try { string asciiForm = s_idnMapping.GetAscii(bidiStrippedHost); - if (asciiForm.AsSpan().IndexOfAny(s_unsafeForNormalizedHostChars) >= 0) + if (asciiForm.AsSpan().ContainsAny(s_unsafeForNormalizedHostChars)) { throw new UriFormatException(SR.net_uri_BadUnicodeHostForIdn); } diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index b848cad5e8552a..df8060e1943798 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -1472,7 +1472,7 @@ public static bool IsHexEncoding(string pattern, int index) public static bool CheckSchemeName([NotNullWhen(true)] string? schemeName) => !string.IsNullOrEmpty(schemeName) && char.IsAsciiLetter(schemeName[0]) && - schemeName.AsSpan().IndexOfAnyExcept(s_schemeChars) < 0; + !schemeName.AsSpan().ContainsAnyExcept(s_schemeChars); // // IsHexDigit @@ -3972,7 +3972,7 @@ private unsafe int CheckAuthorityHelper(char* pString, int idx, int length, flags |= Flags.DnsHostType; // Canonical DNS hostnames don't contain uppercase letters - if (new ReadOnlySpan(pString + start, domainNameLength).IndexOfAnyInRange('A', 'Z') < 0) + if (!new ReadOnlySpan(pString + start, domainNameLength).ContainsAnyInRange('A', 'Z')) { flags |= Flags.CanonicalDnsHost; } diff --git a/src/libraries/System.Private.Uri/src/System/UriBuilder.cs b/src/libraries/System.Private.Uri/src/System/UriBuilder.cs index 8ebf02784e4422..e890e9aa45e998 100644 --- a/src/libraries/System.Private.Uri/src/System/UriBuilder.cs +++ b/src/libraries/System.Private.Uri/src/System/UriBuilder.cs @@ -262,7 +262,7 @@ public Uri Uri private static string EncodeUserInfo(string input) { - if (input.AsSpan().IndexOfAny(s_userInfoReservedChars) < 0) + if (!input.AsSpan().ContainsAny(s_userInfoReservedChars)) { return input; } diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs index 5e1ab4f439f1bb..47ab2e742a6b7c 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XDocument.cs @@ -936,7 +936,7 @@ private void ValidateDocument(XNode? previous, XmlNodeType allowBefore, XmlNodeT internal override void ValidateString(string s) { - if (s.AsSpan().IndexOfAnyExcept(" \t\r\n") >= 0) + if (s.AsSpan().ContainsAnyExcept(" \t\r\n")) { throw new ArgumentException(SR.Argument_AddNonWhitespace); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs index 596af9c47037d9..10ad5f886a476f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs @@ -411,7 +411,7 @@ protected void WriteTypedPrimitive(string? name, string? ns, object o, bool xsiT #if DEBUG const string escapeChars = "<>\"'&"; ReadOnlySpan span = _primitivesBuffer; - Debug.Assert(span.Slice(0, charsWritten).IndexOfAny(escapeChars) == -1, "Primitive value contains illegal xml char."); + Debug.Assert(!span.Slice(0, charsWritten).ContainsAny(escapeChars), "Primitive value contains illegal xml char."); #endif //all the primitive types except string and XmlQualifiedName writes to the buffer _w.WriteRaw(_primitivesBuffer, 0, charsWritten); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlCharType.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlCharType.cs index 3039572cc9e64d..9af1fe2a4f9aba 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlCharType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlCharType.cs @@ -169,7 +169,7 @@ internal static bool IsOnlyDigits(string str, int startPos, int len) Debug.Assert(startPos <= str.Length); Debug.Assert(startPos + len <= str.Length); - return str.AsSpan(startPos, len).IndexOfAnyExceptInRange('0', '9') < 0; + return !str.AsSpan(startPos, len).ContainsAnyExceptInRange('0', '9'); } internal static int IsPublicId(string str) => diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs index 931ac4de8459dc..9c2bf0f2b8c388 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs @@ -33,7 +33,7 @@ public enum XmlDateTimeSerializationMode /// public partial class XmlConvert { - internal static char[] crt = new char[] { '\n', '\r', '\t' }; + private const string Crt = "\t\n\r"; /// /// @@ -408,7 +408,7 @@ internal static string VerifyNCName(string name, ExceptionType exceptionType) if (token.StartsWith(' ') || token.EndsWith(' ') || - token.IndexOfAny(crt) >= 0 || + token.AsSpan().ContainsAny(Crt) || token.Contains(" ")) { throw new XmlException(SR.Sch_NotTokenString, token); @@ -425,7 +425,7 @@ internal static string VerifyNCName(string name, ExceptionType exceptionType) if (token.StartsWith(' ') || token.EndsWith(' ') || - token.IndexOfAny(crt) >= 0 || + token.AsSpan().ContainsAny(Crt) || token.Contains(" ")) { return new XmlException(SR.Sch_NotTokenString, token); @@ -480,7 +480,7 @@ internal static string VerifyNMTOKEN(string name, ExceptionType exceptionType) internal static Exception? TryVerifyNormalizedString(string str) { - if (str.IndexOfAny(crt) != -1) + if (str.AsSpan().ContainsAny(Crt)) { return new XmlSchemaException(SR.Sch_NotNormalizedString, str); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs index cf6898aeed4aed..dab9de57043218 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs @@ -1061,7 +1061,7 @@ private QilNode CompileAvt(string source) { return null; } - if (avt.AsSpan().IndexOfAny('{', '}') < 0) + if (!avt.AsSpan().ContainsAny('{', '}')) { return _f.String(avt); } @@ -1071,7 +1071,7 @@ private QilNode CompileAvt(string source) private QilNode CompileTextAvt(string avt) { Debug.Assert(avt != null); - if (avt.AsSpan().IndexOfAny('{', '}') < 0) + if (!avt.AsSpan().ContainsAny('{', '}')) { return _f.TextCtor(_f.String(avt)); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Base64Transforms.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Base64Transforms.cs index 275a708b38fb62..65c197182626fd 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Base64Transforms.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Base64Transforms.cs @@ -240,7 +240,7 @@ private Span AppendInputBuffers(ReadOnlySpan inputBuffer, Span if (_whitespaces == FromBase64TransformMode.DoNotIgnoreWhiteSpaces) { - if (inputBuffer.IndexOfAny(s_whiteSpace) >= 0) + if (inputBuffer.ContainsAny(s_whiteSpace)) { ThrowHelper.ThrowBase64FormatException(); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs index c293c12374ff26..a0ff45433cef02 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs @@ -164,7 +164,7 @@ public static int GetPaddingLength(ReadOnlySpan block, PaddingMode padding } // Verify that all the padding bytes are 0s - if (block.Slice(block.Length - padBytes, padBytes - 1).IndexOfAnyExcept((byte)0) >= 0) + if (block.Slice(block.Length - padBytes, padBytes - 1).ContainsAnyExcept((byte)0)) { throw new CryptographicException(SR.Cryptography_InvalidPadding); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs index 200c1c95ca176b..d2509eca3c3da1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X500NameEncoder.cs @@ -125,7 +125,7 @@ private static bool NeedsQuoting(ReadOnlySpan rdnValue) => rdnValue.IsEmpty || IsQuotableWhitespace(rdnValue[0]) || IsQuotableWhitespace(rdnValue[^1]) || - rdnValue.IndexOfAny(s_needsQuotingChars) >= 0; + rdnValue.ContainsAny(s_needsQuotingChars); private static bool IsQuotableWhitespace(char c) { diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs index c745593bc25d65..78d1ed94ab942f 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs @@ -291,7 +291,7 @@ public string ServiceName internal static bool ValidServiceName(string serviceName) => !string.IsNullOrEmpty(serviceName) && serviceName.Length <= ServiceBase.MaxNameLength && // not too long - serviceName.AsSpan().IndexOfAny('\\', '/') < 0; // no slashes or backslash allowed + !serviceName.AsSpan().ContainsAny('\\', '/'); // no slashes or backslash allowed /// /// Disposes of the resources (other than memory ) used by diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs index 2459acf7681f66..9db9e80c771d76 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs @@ -14,11 +14,13 @@ internal static partial class JsonReaderHelper private const string SpecialCharacters = ". '/\"[]()\t\n\r\f\b\\\u0085\u2028\u2029"; #if NET8_0_OR_GREATER private static readonly SearchValues s_specialCharacters = SearchValues.Create(SpecialCharacters); + + public static bool ContainsSpecialCharacters(this ReadOnlySpan text) => + text.ContainsAny(s_specialCharacters); #else - private static ReadOnlySpan s_specialCharacters => SpecialCharacters.AsSpan(); + public static bool ContainsSpecialCharacters(this ReadOnlySpan text) => + text.IndexOfAny(SpecialCharacters.AsSpan()) >= 0; #endif - public static bool ContainsSpecialCharacters(this ReadOnlySpan text) - => text.IndexOfAny(s_specialCharacters) >= 0; public static (int, int) CountNewLines(ReadOnlySpan data) { diff --git a/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs b/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs index 837bc5462e2e2a..1682321a728146 100644 --- a/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs +++ b/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs @@ -157,7 +157,7 @@ public TestFilter(string[] filterArgs, HashSet? testExclusionList) if (filterString is not null) { - if (filterString.IndexOfAny(new[] { '!', '(', ')', '~', '=' }) != -1) + if (filterString.ContainsAny("!()~=")) { throw new ArgumentException("Complex test filter expressions are not supported today. The only filters supported today are the simple form supported in 'dotnet test --filter' (substrings of the test's fully qualified name). If further filtering options are desired, file an issue on dotnet/runtime for support.", nameof(filterArgs)); } From 51b47b5233b13effd7212f8282c31da6c28b56b3 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Wed, 14 Jun 2023 22:22:29 +0200 Subject: [PATCH 3/8] Test coverage --- .../System.Memory/tests/Span/IndexOfAny.T.cs | 194 ++++++++++++------ .../tests/Span/IndexOfAny.byte.cs | 45 +--- .../tests/Span/IndexOfAny.char.cs | 29 --- .../tests/Span/IndexOfAnyExcept.T.cs | 77 +++++-- .../tests/Span/IndexOfAnyInRange.cs | 8 + .../System.Memory/tests/Span/SearchValues.cs | 57 +++-- 6 files changed, 246 insertions(+), 164 deletions(-) diff --git a/src/libraries/System.Memory/tests/Span/IndexOfAny.T.cs b/src/libraries/System.Memory/tests/Span/IndexOfAny.T.cs index d6b525741806e4..fbc1b6dd60cab9 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfAny.T.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfAny.T.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Xunit; namespace System.SpanTests @@ -11,7 +14,7 @@ public static partial class SpanTests public static void ZeroLengthIndexOfAny_TwoInteger() { var sp = new Span(Array.Empty()); - int idx = sp.IndexOfAny(0, 0); + int idx = IndexOfAny(sp, 0, 0); Assert.Equal(-1, idx); } @@ -32,7 +35,7 @@ public static void DefaultFilledIndexOfAny_TwoInteger() int index = rnd.Next(0, 2) == 0 ? 0 : 1; int target0 = targets[index]; int target1 = targets[(index + 1) % 2]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(0, idx); } } @@ -56,7 +59,7 @@ public static void TestMatchIndexOfAny_TwoInteger() { int target0 = a[targetIndex]; int target1 = 0; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex, idx); } @@ -65,7 +68,7 @@ public static void TestMatchIndexOfAny_TwoInteger() int index = rnd.Next(0, 2) == 0 ? 0 : 1; int target0 = a[targetIndex + index]; int target1 = a[targetIndex + (index + 1) % 2]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex, idx); } @@ -73,7 +76,7 @@ public static void TestMatchIndexOfAny_TwoInteger() { int target0 = 0; int target1 = a[targetIndex]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex, idx); } } @@ -90,7 +93,7 @@ public static void TestNoMatchIndexOfAny_TwoInteger() int target1 = rnd.Next(1, 256); var span = new Span(a); - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(-1, idx); } } @@ -112,7 +115,7 @@ public static void TestMultipleMatchIndexOfAny_TwoInteger() a[length - 3] = 200; var span = new Span(a); - int idx = span.IndexOfAny(200, 200); + int idx = IndexOfAny(span, 200, 200); Assert.Equal(length - 3, idx); } } @@ -126,7 +129,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoInteger() a[0] = 99; a[length + 1] = 98; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny(99, 98); + int index = IndexOfAny(span, 99, 98); Assert.Equal(-1, index); } @@ -136,7 +139,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoInteger() a[0] = 99; a[length + 1] = 99; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny(99, 99); + int index = IndexOfAny(span, 99, 99); Assert.Equal(-1, index); } } @@ -145,7 +148,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoInteger() public static void ZeroLengthIndexOfAny_ThreeInteger() { var sp = new Span(Array.Empty()); - int idx = sp.IndexOfAny(0, 0, 0); + int idx = IndexOfAny(sp, 0, 0, 0); Assert.Equal(-1, idx); } @@ -167,7 +170,7 @@ public static void DefaultFilledIndexOfAny_ThreeInteger() int target0 = targets[index]; int target1 = targets[(index + 1) % 2]; int target2 = targets[(index + 1) % 3]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(0, idx); } } @@ -192,7 +195,7 @@ public static void TestMatchIndexOfAny_ThreeInteger() int target0 = a[targetIndex]; int target1 = 0; int target2 = 0; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } @@ -202,7 +205,7 @@ public static void TestMatchIndexOfAny_ThreeInteger() int target0 = a[targetIndex + index]; int target1 = a[targetIndex + (index + 1) % 2]; int target2 = a[targetIndex + (index + 1) % 3]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } @@ -211,7 +214,7 @@ public static void TestMatchIndexOfAny_ThreeInteger() int target0 = 0; int target1 = 0; int target2 = a[targetIndex]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } } @@ -229,7 +232,7 @@ public static void TestNoMatchIndexOfAny_ThreeInteger() int target2 = rnd.Next(1, 256); var span = new Span(a); - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(-1, idx); } } @@ -252,7 +255,7 @@ public static void TestMultipleMatchIndexOfAny_ThreeInteger() a[length - 4] = 200; var span = new Span(a); - int idx = span.IndexOfAny(200, 200, 200); + int idx = IndexOfAny(span, 200, 200, 200); Assert.Equal(length - 4, idx); } } @@ -266,7 +269,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ThreeInteger() a[0] = 99; a[length + 1] = 98; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny(99, 98, 99); + int index = IndexOfAny(span, 99, 98, 99); Assert.Equal(-1, index); } @@ -276,7 +279,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ThreeInteger() a[0] = 99; a[length + 1] = 99; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny(99, 99, 99); + int index = IndexOfAny(span, 99, 99, 99); Assert.Equal(-1, index); } } @@ -286,11 +289,11 @@ public static void ZeroLengthIndexOfAny_ManyInteger() { var sp = new Span(Array.Empty()); var values = new ReadOnlySpan(new int[] { 0, 0, 0, 0 }); - int idx = sp.IndexOfAny(values); + int idx = IndexOfAny(sp, values); Assert.Equal(-1, idx); values = new ReadOnlySpan(new int[] { }); - idx = sp.IndexOfAny(values); + idx = IndexOfAny(sp, values); Assert.Equal(-1, idx); } @@ -306,7 +309,7 @@ public static void DefaultFilledIndexOfAny_ManyInteger() for (int i = 0; i < length; i++) { - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(0, idx); } } @@ -329,7 +332,7 @@ public static void TestMatchIndexOfAny_ManyInteger() for (int targetIndex = 0; targetIndex < length; targetIndex++) { var values = new ReadOnlySpan(new int[] { a[targetIndex], 0, 0, 0 }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } @@ -343,14 +346,14 @@ public static void TestMatchIndexOfAny_ManyInteger() a[targetIndex + (index + 1) % 3], a[targetIndex + (index + 1) % 4] }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } for (int targetIndex = 0; targetIndex < length; targetIndex++) { var values = new ReadOnlySpan(new int[] { 0, 0, 0, a[targetIndex] }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } } @@ -385,7 +388,7 @@ public static void TestMatchValuesLargerIndexOfAny_ManyInteger() } var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(expectedIndex, idx); } } @@ -405,7 +408,7 @@ public static void TestNoMatchIndexOfAny_ManyInteger() var span = new Span(a); var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(-1, idx); } } @@ -425,7 +428,7 @@ public static void TestNoMatchValuesLargerIndexOfAny_ManyInteger() var span = new Span(a); var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(-1, idx); } } @@ -450,7 +453,7 @@ public static void TestMultipleMatchIndexOfAny_ManyInteger() var span = new Span(a); var values = new ReadOnlySpan(new int[] { 200, 200, 200, 200, 200, 200, 200, 200, 200 }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(length - 5, idx); } } @@ -465,7 +468,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyInteger() a[length + 1] = 98; var span = new Span(a, 1, length - 1); var values = new Span(new int[] { 99, 98, 99, 98, 99, 98 }); - int index = span.IndexOfAny(values); + int index = IndexOfAny(span, values); Assert.Equal(-1, index); } @@ -476,7 +479,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyInteger() a[length + 1] = 99; var span = new Span(a, 1, length - 1); var values = new ReadOnlySpan(new int[] { 99, 99, 99, 99, 99, 99 }); - int index = span.IndexOfAny(values); + int index = IndexOfAny(span, values); Assert.Equal(-1, index); } } @@ -485,7 +488,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyInteger() public static void ZeroLengthIndexOfAny_TwoString() { var sp = new Span(Array.Empty()); - int idx = sp.IndexOfAny("0", "0"); + int idx = IndexOfAny(sp, "0", "0"); Assert.Equal(-1, idx); } @@ -508,7 +511,7 @@ public static void DefaultFilledIndexOfAny_TwoString() int index = rnd.Next(0, 2) == 0 ? 0 : 1; string target0 = targets[index]; string target1 = targets[(index + 1) % 2]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(0, idx); } } @@ -532,7 +535,7 @@ public static void TestMatchIndexOfAny_TwoString() { string target0 = a[targetIndex]; string target1 = "0"; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex, idx); } @@ -541,7 +544,7 @@ public static void TestMatchIndexOfAny_TwoString() int index = rnd.Next(0, 2) == 0 ? 0 : 1; string target0 = a[targetIndex + index]; string target1 = a[targetIndex + (index + 1) % 2]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex, idx); } @@ -549,7 +552,7 @@ public static void TestMatchIndexOfAny_TwoString() { string target0 = "0"; string target1 = a[targetIndex + 1]; - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(targetIndex + 1, idx); } } @@ -566,7 +569,7 @@ public static void TestNoMatchIndexOfAny_TwoString() string target1 = rnd.Next(1, 256).ToString(); var span = new Span(a); - int idx = span.IndexOfAny(target0, target1); + int idx = IndexOfAny(span, target0, target1); Assert.Equal(-1, idx); } } @@ -588,7 +591,7 @@ public static void TestMultipleMatchIndexOfAny_TwoString() a[length - 3] = "200"; var span = new Span(a); - int idx = span.IndexOfAny("200", "200"); + int idx = IndexOfAny(span, "200", "200"); Assert.Equal(length - 3, idx); } } @@ -602,7 +605,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoString() a[0] = "99"; a[length + 1] = "98"; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny("99", "98"); + int index = IndexOfAny(span, "99", "98"); Assert.Equal(-1, index); } @@ -612,7 +615,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoString() a[0] = "99"; a[length + 1] = "99"; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny("99", "99"); + int index = IndexOfAny(span, "99", "99"); Assert.Equal(-1, index); } } @@ -621,7 +624,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_TwoString() public static void ZeroLengthIndexOf_ThreeString() { var sp = new Span(Array.Empty()); - int idx = sp.IndexOfAny("0", "0", "0"); + int idx = IndexOfAny(sp, "0", "0", "0"); Assert.Equal(-1, idx); } @@ -645,7 +648,7 @@ public static void DefaultFilledIndexOfAny_ThreeString() string target0 = targets[index]; string target1 = targets[(index + 1) % 2]; string target2 = targets[(index + 1) % 3]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(0, idx); } } @@ -670,7 +673,7 @@ public static void TestMatchIndexOfAny_ThreeString() string target0 = a[targetIndex]; string target1 = "0"; string target2 = "0"; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } @@ -680,7 +683,7 @@ public static void TestMatchIndexOfAny_ThreeString() string target0 = a[targetIndex + index]; string target1 = a[targetIndex + (index + 1) % 2]; string target2 = a[targetIndex + (index + 1) % 3]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } @@ -689,7 +692,7 @@ public static void TestMatchIndexOfAny_ThreeString() string target0 = "0"; string target1 = "0"; string target2 = a[targetIndex]; - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(targetIndex, idx); } } @@ -707,7 +710,7 @@ public static void TestNoMatchIndexOfAny_ThreeString() string target2 = rnd.Next(1, 256).ToString(); var span = new Span(a); - int idx = span.IndexOfAny(target0, target1, target2); + int idx = IndexOfAny(span, target0, target1, target2); Assert.Equal(-1, idx); } } @@ -730,7 +733,7 @@ public static void TestMultipleMatchIndexOfAny_ThreeString() a[length - 4] = "200"; var span = new Span(a); - int idx = span.IndexOfAny("200", "200", "200"); + int idx = IndexOfAny(span, "200", "200", "200"); Assert.Equal(length - 4, idx); } } @@ -744,7 +747,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ThreeString() a[0] = "99"; a[length + 1] = "98"; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny("99", "98", "99"); + int index = IndexOfAny(span, "99", "98", "99"); Assert.Equal(-1, index); } @@ -754,7 +757,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ThreeString() a[0] = "99"; a[length + 1] = "99"; var span = new Span(a, 1, length - 1); - int index = span.IndexOfAny("99", "99", "99"); + int index = IndexOfAny(span, "99", "99", "99"); Assert.Equal(-1, index); } } @@ -764,11 +767,11 @@ public static void ZeroLengthIndexOfAny_ManyString() { var sp = new Span(Array.Empty()); var values = new ReadOnlySpan(new string[] { "0", "0", "0", "0" }); - int idx = sp.IndexOfAny(values); + int idx = IndexOfAny(sp, values); Assert.Equal(-1, idx); values = new ReadOnlySpan(new string[] { }); - idx = sp.IndexOfAny(values); + idx = IndexOfAny(sp, values); Assert.Equal(-1, idx); } @@ -786,7 +789,7 @@ public static void DefaultFilledIndexOfAny_ManyString() for (int i = 0; i < length; i++) { - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(0, idx); } } @@ -809,7 +812,7 @@ public static void TestMatchIndexOfAny_ManyString() for (int targetIndex = 0; targetIndex < length; targetIndex++) { var values = new ReadOnlySpan(new string[] { a[targetIndex], "0", "0", "0" }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } @@ -823,14 +826,14 @@ public static void TestMatchIndexOfAny_ManyString() a[targetIndex + (index + 1) % 3], a[targetIndex + (index + 1) % 4] }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } for (int targetIndex = 0; targetIndex < length; targetIndex++) { var values = new ReadOnlySpan(new string[] { "0", "0", "0", a[targetIndex] }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(targetIndex, idx); } } @@ -867,7 +870,7 @@ public static void TestMatchValuesLargerIndexOfAny_ManyString() } var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(expectedIndex, idx); } } @@ -887,7 +890,7 @@ public static void TestNoMatchIndexOfAny_ManyString() var span = new Span(a); var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(-1, idx); } } @@ -907,7 +910,7 @@ public static void TestNoMatchValuesLargerIndexOfAny_ManyString() var span = new Span(a); var values = new ReadOnlySpan(targets); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(-1, idx); } } @@ -932,7 +935,7 @@ public static void TestMultipleMatchIndexOfAny_ManyString() var span = new Span(a); var values = new ReadOnlySpan(new string[] { "200", "200", "200", "200", "200", "200", "200", "200", "200" }); - int idx = span.IndexOfAny(values); + int idx = IndexOfAny(span, values); Assert.Equal(length - 5, idx); } } @@ -947,7 +950,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyString() a[length + 1] = "98"; var span = new Span(a, 1, length - 1); var values = new ReadOnlySpan(new string[] { "99", "98", "99", "98", "99", "98" }); - int index = span.IndexOfAny(values); + int index = IndexOfAny(span, values); Assert.Equal(-1, index); } @@ -958,7 +961,7 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyString() a[length + 1] = "99"; var span = new Span(a, 1, length - 1); var values = new ReadOnlySpan(new string[] { "99", "99", "99", "99", "99", "99" }); - int index = span.IndexOfAny(values); + int index = IndexOfAny(span, values); Assert.Equal(-1, index); } } @@ -968,21 +971,84 @@ public static void MakeSureNoChecksGoOutOfRangeIndexOfAny_ManyString() public static void IndexOfAnyNullSequence_String(string[] spanInput, string[] searchInput, int expected) { Span theStrings = spanInput; - Assert.Equal(expected, theStrings.IndexOfAny(searchInput)); - Assert.Equal(expected, theStrings.IndexOfAny((ReadOnlySpan)searchInput)); + Assert.Equal(expected, IndexOfAny(theStrings, searchInput)); if (searchInput != null) { if (searchInput.Length >= 3) { - Assert.Equal(expected, theStrings.IndexOfAny(searchInput[0], searchInput[1], searchInput[2])); + Assert.Equal(expected, IndexOfAny(theStrings, searchInput[0], searchInput[1], searchInput[2])); } if (searchInput.Length >= 2) { - Assert.Equal(expected, theStrings.IndexOfAny(searchInput[0], searchInput[1])); + Assert.Equal(expected, IndexOfAny(theStrings, searchInput[0], searchInput[1])); } } } + + private static int IndexOf(Span span, T value) where T : IEquatable? + { + int index = span.IndexOf(value); + Assert.Equal(index, ((ReadOnlySpan)span).IndexOf(value)); + + Assert.Equal(index >= 0, span.Contains(value)); + Assert.Equal(index >= 0, ((ReadOnlySpan)span).Contains(value)); + + AssertSearchValues(span, new ReadOnlySpan(value), index); + return index; + } + + private static int IndexOfAny(Span span, T value0, T value1) where T : IEquatable? + { + int index = span.IndexOfAny(value0, value1); + Assert.Equal(index, ((ReadOnlySpan)span).IndexOfAny(value0, value1)); + + Assert.Equal(index >= 0, span.ContainsAny(value0, value1)); + Assert.Equal(index >= 0, ((ReadOnlySpan)span).ContainsAny(value0, value1)); + + AssertSearchValues(span, new[] { value0, value1 }, index); + return index; + } + + private static int IndexOfAny(Span span, T value0, T value1, T value2) where T : IEquatable? + { + int index = span.IndexOfAny(value0, value1, value2); + Assert.Equal(index, ((ReadOnlySpan)span).IndexOfAny(value0, value1, value2)); + + Assert.Equal(index >= 0, span.ContainsAny(value0, value1, value2)); + Assert.Equal(index >= 0, ((ReadOnlySpan)span).ContainsAny(value0, value1, value2)); + + AssertSearchValues(span, new[] { value0, value1, value2 }, index); + return index; + } + + private static int IndexOfAny(Span span, ReadOnlySpan values) where T : IEquatable? + { + int index = span.IndexOfAny(values); + Assert.Equal(index, ((ReadOnlySpan)span).IndexOfAny(values)); + + Assert.Equal(index >= 0, span.ContainsAny(values)); + Assert.Equal(index >= 0, ((ReadOnlySpan)span).ContainsAny(values)); + + AssertSearchValues(span, values, index); + return index; + } + + private static void AssertSearchValues(Span span, ReadOnlySpan values, int expectedIndex) where T : IEquatable? + { + if (typeof(T) == typeof(byte) || typeof(T) == typeof(char)) + { + SearchValues searchValuesInstance = (SearchValues)(object)(typeof(T) == typeof(byte) + ? SearchValues.Create(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length)) + : SearchValues.Create(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length))); + + Assert.Equal(expectedIndex, span.IndexOfAny(searchValuesInstance)); + Assert.Equal(expectedIndex, ((ReadOnlySpan)span).IndexOfAny(searchValuesInstance)); + + Assert.Equal(expectedIndex >= 0, span.ContainsAny(searchValuesInstance)); + Assert.Equal(expectedIndex >= 0, ((ReadOnlySpan)span).ContainsAny(searchValuesInstance)); + } + } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfAny.byte.cs b/src/libraries/System.Memory/tests/Span/IndexOfAny.byte.cs index 40f2de438d88c1..b2e66cf27c8a6a 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfAny.byte.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfAny.byte.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; using System.Text; using Xunit; @@ -60,7 +59,7 @@ public static void ZeroLengthIndexOfTwo_Byte() { Span span = new Span(Array.Empty()); - Assert.Equal(-1, IndexOfAny(span, 0, 0)); + Assert.Equal(-1, IndexOfAny(span, 0, 0)); Assert.Equal(-1, IndexOfAny(span, new byte[2])); } @@ -163,7 +162,7 @@ public static void TestMultipleMatchTwo_Byte() Span span = new Span(a); - Assert.Equal(length - 3, IndexOfAny(span, 200, 200)); + Assert.Equal(length - 3, IndexOfAny(span, 200, 200)); Assert.Equal(length - 3, IndexOfAny(span, new byte[] { 200, 200 })); } } @@ -178,7 +177,7 @@ public static void MakeSureNoChecksGoOutOfRangeTwo_Byte() a[length + 1] = 98; Span span = new Span(a, 1, length - 1); - Assert.Equal(-1, IndexOfAny(span, 99, 98)); + Assert.Equal(-1, IndexOfAny(span, 99, 98)); Assert.Equal(-1, IndexOfAny(span, new byte[] { 99, 98 })); } @@ -189,7 +188,7 @@ public static void MakeSureNoChecksGoOutOfRangeTwo_Byte() a[length + 1] = 99; Span span = new Span(a, 1, length - 1); - Assert.Equal(-1, IndexOfAny(span, 99, 99)); + Assert.Equal(-1, IndexOfAny(span, 99, 99)); Assert.Equal(-1, IndexOfAny(span, new byte[] { 99, 99 })); } } @@ -199,7 +198,7 @@ public static void ZeroLengthIndexOfThree_Byte() { Span span = new Span(Array.Empty()); - Assert.Equal(-1, IndexOfAny(span, 0, 0, 0)); + Assert.Equal(-1, IndexOfAny(span, 0, 0, 0)); Assert.Equal(-1, IndexOfAny(span, new byte[3])); } @@ -308,7 +307,7 @@ public static void TestMultipleMatchThree_Byte() Span span = new Span(a); - Assert.Equal(length - 4, IndexOfAny(span, 200, 200, 200)); + Assert.Equal(length - 4, IndexOfAny(span, 200, 200, 200)); Assert.Equal(length - 4, IndexOfAny(span, new byte[] { 200, 200, 200 })); } } @@ -323,7 +322,7 @@ public static void MakeSureNoChecksGoOutOfRangeThree_Byte() a[length + 1] = 98; Span span = new Span(a, 1, length - 1); - Assert.Equal(-1, IndexOfAny(span, 99, 98, 99)); + Assert.Equal(-1, IndexOfAny(span, 99, 98, 99)); Assert.Equal(-1, IndexOfAny(span, new byte[] { 99, 98, 99 })); } @@ -334,7 +333,7 @@ public static void MakeSureNoChecksGoOutOfRangeThree_Byte() a[length + 1] = 99; Span span = new Span(a, 1, length - 1); - Assert.Equal(-1, IndexOfAny(span, 99, 99, 99)); + Assert.Equal(-1, IndexOfAny(span, 99, 99, 99)); Assert.Equal(-1, IndexOfAny(span, new byte[] { 99, 99, 99 })); } } @@ -529,33 +528,5 @@ public static void MakeSureNoChecksGoOutOfRangeMany_Byte() Assert.Equal(-1, index); } } - - private static int IndexOf(Span span, byte value) - { - int index = span.IndexOf(value); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc byte[] { value }))); - return index; - } - - private static int IndexOfAny(Span span, byte value0, byte value1) - { - int index = span.IndexOfAny(value0, value1); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc byte[] { value0, value1 }))); - return index; - } - - private static int IndexOfAny(Span span, byte value0, byte value1, byte value2) - { - int index = span.IndexOfAny(value0, value1, value2); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc byte[] { value0, value1, value2 }))); - return index; - } - - private static int IndexOfAny(Span span, ReadOnlySpan values) - { - int index = span.IndexOfAny(values); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(values))); - return index; - } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfAny.char.cs b/src/libraries/System.Memory/tests/Span/IndexOfAny.char.cs index bf51860f51bf18..409ca0ef00889b 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfAny.char.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfAny.char.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; using System.Linq; using System.Numerics; using Xunit; @@ -772,33 +771,5 @@ public static void MakeSureNoChecksGoOutOfRangeMany_Char() Assert.Equal(-1, index); } } - - private static int IndexOf(Span span, char value) - { - int index = span.IndexOf(value); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc char[] { value }))); - return index; - } - - private static int IndexOfAny(Span span, char value0, char value1) - { - int index = span.IndexOfAny(value0, value1); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc char[] { value0, value1 }))); - return index; - } - - private static int IndexOfAny(Span span, char value0, char value1, char value2) - { - int index = span.IndexOfAny(value0, value1, value2); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(stackalloc char[] { value0, value1, value2 }))); - return index; - } - - private static int IndexOfAny(Span span, ReadOnlySpan values) - { - int index = span.IndexOfAny(values); - Assert.Equal(index, span.IndexOfAny(SearchValues.Create(values))); - return index; - } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfAnyExcept.T.cs b/src/libraries/System.Memory/tests/Span/IndexOfAnyExcept.T.cs index 69ef7ec1334ea3..d773e8f3a508c5 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfAnyExcept.T.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfAnyExcept.T.cs @@ -183,8 +183,11 @@ private static int IndexOfAnyExcept(Span span, T value) Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, value)); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((Span)span, new[] { value })); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, new[] { value })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value })); + AssertSearchValues(span, new[] { value }, result, last: false); return result; } private static int IndexOfAnyExcept(Span span, T value0, T value1) @@ -193,8 +196,11 @@ private static int IndexOfAnyExcept(Span span, T value0, T value1) Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, value0, value1)); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((Span)span, new[] { value0, value1 })); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, new[] { value0, value1 })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1 })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1 })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value0, value1)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value0, value1)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value0, value1 })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value0, value1 })); + AssertSearchValues(span, new[] { value0, value1 }, result, last: false); return result; } private static int IndexOfAnyExcept(Span span, T value0, T value1, T value2) @@ -203,16 +209,20 @@ private static int IndexOfAnyExcept(Span span, T value0, T value1, T value2) Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, value0, value1, value2)); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((Span)span, new[] { value0, value1, value2 })); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, new[] { value0, value1, value2 })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1, value2 })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1, value2 })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value0, value1, value2)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value0, value1, value2)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value0, value1, value2 })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value0, value1, value2 })); + AssertSearchValues(span, new[] { value0, value1, value2 }, result, last: false); return result; } private static int IndexOfAnyExcept(Span span, params T[] values) { int result = MemoryExtensions.IndexOfAnyExcept(span, values); Assert.Equal(result, MemoryExtensions.IndexOfAnyExcept((ReadOnlySpan)span, values)); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(values)))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).IndexOfAnyExcept(SearchValues.Create(Cast(values)))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, values)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, values)); + AssertSearchValues(span, values, result, last: false); return result; } private static int LastIndexOfAnyExcept(Span span, T value) @@ -221,8 +231,11 @@ private static int LastIndexOfAnyExcept(Span span, T value) Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, value)); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((Span)span, new[] { value })); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, new[] { value })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value })); + AssertSearchValues(span, new[] { value }, result, last: true); return result; } private static int LastIndexOfAnyExcept(Span span, T value0, T value1) @@ -231,8 +244,11 @@ private static int LastIndexOfAnyExcept(Span span, T value0, T value1) Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, value0, value1)); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((Span)span, new[] { value0, value1 })); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, new[] { value0, value1 })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1 })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1 })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value0, value1)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value0, value1)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value0, value1 })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value0, value1 })); + AssertSearchValues(span, new[] { value0, value1 }, result, last: true); return result; } private static int LastIndexOfAnyExcept(Span span, T value0, T value1, T value2) @@ -241,20 +257,45 @@ private static int LastIndexOfAnyExcept(Span span, T value0, T value1, T valu Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, value0, value1, value2)); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((Span)span, new[] { value0, value1, value2 })); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, new[] { value0, value1, value2 })); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1, value2 })))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(new T[] { value0, value1, value2 })))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, value0, value1, value2)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, value0, value1, value2)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, new[] { value0, value1, value2 })); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, new[] { value0, value1, value2 })); + AssertSearchValues(span, new[] { value0, value1, value2 }, result, last: true); return result; } private static int LastIndexOfAnyExcept(Span span, params T[] values) { int result = MemoryExtensions.LastIndexOfAnyExcept(span, values); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExcept((ReadOnlySpan)span, values)); - if (typeof(T) == typeof(byte)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(values)))); - if (typeof(T) == typeof(char)) Assert.Equal(result, Cast(span).LastIndexOfAnyExcept(SearchValues.Create(Cast(values)))); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept(span, values)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExcept((ReadOnlySpan)span, values)); + AssertSearchValues(span, values, result, last: true); return result; } - private static ReadOnlySpan Cast(ReadOnlySpan span) => - MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref MemoryMarshal.GetReference(span)), span.Length); + private static void AssertSearchValues(Span span, ReadOnlySpan values, int expectedIndex, bool last) + { + if (typeof(T) == typeof(byte) || typeof(T) == typeof(char)) + { + SearchValues searchValuesInstance = (SearchValues)(object)(typeof(T) == typeof(byte) + ? SearchValues.Create(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length)) + : SearchValues.Create(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref MemoryMarshal.GetReference(values)), values.Length))); + + if (last) + { + Assert.Equal(expectedIndex, span.LastIndexOfAnyExcept(searchValuesInstance)); + Assert.Equal(expectedIndex, ((ReadOnlySpan)span).LastIndexOfAnyExcept(searchValuesInstance)); + } + else + { + Assert.Equal(expectedIndex, span.IndexOfAnyExcept(searchValuesInstance)); + Assert.Equal(expectedIndex, ((ReadOnlySpan)span).IndexOfAnyExcept(searchValuesInstance)); + } + + Assert.Equal(expectedIndex >= 0, span.ContainsAnyExcept(searchValuesInstance)); + Assert.Equal(expectedIndex >= 0, ((ReadOnlySpan)span).ContainsAnyExcept(searchValuesInstance)); + } + } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfAnyInRange.cs b/src/libraries/System.Memory/tests/Span/IndexOfAnyInRange.cs index 1814e10949c2e0..c761759eef4013 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfAnyInRange.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfAnyInRange.cs @@ -175,6 +175,8 @@ protected static int IndexOfAnyInRange(Span span, T lowInclusive, T highInclu { int result = MemoryExtensions.IndexOfAnyInRange(span, lowInclusive, highInclusive); Assert.Equal(result, MemoryExtensions.IndexOfAnyInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyInRange(span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); return result; } @@ -182,6 +184,8 @@ protected static int LastIndexOfAnyInRange(Span span, T lowInclusive, T highI { int result = MemoryExtensions.LastIndexOfAnyInRange(span, lowInclusive, highInclusive); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyInRange(span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); return result; } @@ -189,6 +193,8 @@ protected static int IndexOfAnyExceptInRange(Span span, T lowInclusive, T hig { int result = MemoryExtensions.IndexOfAnyExceptInRange(span, lowInclusive, highInclusive); Assert.Equal(result, MemoryExtensions.IndexOfAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExceptInRange(span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); return result; } @@ -196,6 +202,8 @@ protected static int LastIndexOfAnyExceptInRange(Span span, T lowInclusive, T { int result = MemoryExtensions.LastIndexOfAnyExceptInRange(span, lowInclusive, highInclusive); Assert.Equal(result, MemoryExtensions.LastIndexOfAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExceptInRange(span, lowInclusive, highInclusive)); + Assert.Equal(result >= 0, MemoryExtensions.ContainsAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive)); return result; } } diff --git a/src/libraries/System.Memory/tests/Span/SearchValues.cs b/src/libraries/System.Memory/tests/Span/SearchValues.cs index b6ab088f23c215..211e03593852db 100644 --- a/src/libraries/System.Memory/tests/Span/SearchValues.cs +++ b/src/libraries/System.Memory/tests/Span/SearchValues.cs @@ -215,7 +215,8 @@ public static void TestIndexOfAny_RandomInputs_Byte() SearchValuesTestHelper.TestRandomInputs( expected: IndexOfAnyReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.IndexOfAny(values), - searchValues: (searchSpace, values) => searchSpace.IndexOfAny(values)); + searchValues: (searchSpace, values) => searchSpace.IndexOfAny(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAny(values)); static int IndexOfAnyReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -238,7 +239,8 @@ public static void TestIndexOfAny_RandomInputs_Char() SearchValuesTestHelper.TestRandomInputs( expected: IndexOfAnyReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.IndexOfAny(values), - searchValues: (searchSpace, values) => searchSpace.IndexOfAny(values)); + searchValues: (searchSpace, values) => searchSpace.IndexOfAny(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAny(values)); static int IndexOfAnyReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -261,7 +263,8 @@ public static void TestLastIndexOfAny_RandomInputs_Byte() SearchValuesTestHelper.TestRandomInputs( expected: LastIndexOfAnyReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.LastIndexOfAny(values), - searchValues: (searchSpace, values) => searchSpace.LastIndexOfAny(values)); + searchValues: (searchSpace, values) => searchSpace.LastIndexOfAny(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAny(values)); static int LastIndexOfAnyReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -284,7 +287,8 @@ public static void TestLastIndexOfAny_RandomInputs_Char() SearchValuesTestHelper.TestRandomInputs( expected: LastIndexOfAnyReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.LastIndexOfAny(values), - searchValues: (searchSpace, values) => searchSpace.LastIndexOfAny(values)); + searchValues: (searchSpace, values) => searchSpace.LastIndexOfAny(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAny(values)); static int LastIndexOfAnyReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -307,7 +311,8 @@ public static void TestIndexOfAnyExcept_RandomInputs_Byte() SearchValuesTestHelper.TestRandomInputs( expected: IndexOfAnyExceptReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values), - searchValues: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values)); + searchValues: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAnyExcept(values)); static int IndexOfAnyExceptReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -330,7 +335,8 @@ public static void TestIndexOfAnyExcept_RandomInputs_Char() SearchValuesTestHelper.TestRandomInputs( expected: IndexOfAnyExceptReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values), - searchValues: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values)); + searchValues: (searchSpace, values) => searchSpace.IndexOfAnyExcept(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAnyExcept(values)); static int IndexOfAnyExceptReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -353,7 +359,8 @@ public static void TestLastIndexOfAnyExcept_RandomInputs_Byte() SearchValuesTestHelper.TestRandomInputs( expected: LastIndexOfAnyExceptReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values), - searchValues: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values)); + searchValues: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAnyExcept(values)); static int LastIndexOfAnyExceptReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -376,7 +383,8 @@ public static void TestLastIndexOfAnyExcept_RandomInputs_Char() SearchValuesTestHelper.TestRandomInputs( expected: LastIndexOfAnyExceptReferenceImpl, indexOfAny: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values), - searchValues: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values)); + searchValues: (searchSpace, values) => searchSpace.LastIndexOfAnyExcept(values), + searchValuesContains: (searchSpace, values) => searchSpace.ContainsAnyExcept(values)); static int LastIndexOfAnyExceptReferenceImpl(ReadOnlySpan searchSpace, ReadOnlySpan values) { @@ -433,36 +441,47 @@ static SearchValuesTestHelper() public delegate int SearchValuesSearchDelegate(ReadOnlySpan searchSpace, SearchValues values) where T : IEquatable?; - public static void TestRandomInputs(IndexOfAnySearchDelegate expected, IndexOfAnySearchDelegate indexOfAny, SearchValuesSearchDelegate searchValues) + public delegate bool SearchValuesContainsDelegate(ReadOnlySpan searchSpace, SearchValues values) where T : IEquatable?; + + public static void TestRandomInputs( + IndexOfAnySearchDelegate expected, + IndexOfAnySearchDelegate indexOfAny, + SearchValuesSearchDelegate searchValues, + SearchValuesContainsDelegate searchValuesContains) { var rng = new Random(42); for (int iterations = 0; iterations < 1_000_000; iterations++) { // There are more interesting corner cases with ASCII needles, test those more. - Test(rng, s_randomBytes, s_randomAsciiBytes, expected, indexOfAny, searchValues); + Test(rng, s_randomBytes, s_randomAsciiBytes, expected, indexOfAny, searchValues, searchValuesContains); - Test(rng, s_randomBytes, s_randomBytes, expected, indexOfAny, searchValues); + Test(rng, s_randomBytes, s_randomBytes, expected, indexOfAny, searchValues, searchValuesContains); } } - public static void TestRandomInputs(IndexOfAnySearchDelegate expected, IndexOfAnySearchDelegate indexOfAny, SearchValuesSearchDelegate searchValues) + public static void TestRandomInputs( + IndexOfAnySearchDelegate expected, + IndexOfAnySearchDelegate indexOfAny, + SearchValuesSearchDelegate searchValues, + SearchValuesContainsDelegate searchValuesContains) { var rng = new Random(42); for (int iterations = 0; iterations < 1_000_000; iterations++) { // There are more interesting corner cases with ASCII needles, test those more. - Test(rng, s_randomChars, s_randomAsciiChars, expected, indexOfAny, searchValues); + Test(rng, s_randomChars, s_randomAsciiChars, expected, indexOfAny, searchValues, searchValuesContains); - Test(rng, s_randomChars, s_randomLatin1Chars, expected, indexOfAny, searchValues); + Test(rng, s_randomChars, s_randomLatin1Chars, expected, indexOfAny, searchValues, searchValuesContains); - Test(rng, s_randomChars, s_randomChars, expected, indexOfAny, searchValues); + Test(rng, s_randomChars, s_randomChars, expected, indexOfAny, searchValues, searchValuesContains); } } private static void Test(Random rng, ReadOnlySpan haystackRandom, ReadOnlySpan needleRandom, - IndexOfAnySearchDelegate expected, IndexOfAnySearchDelegate indexOfAny, SearchValuesSearchDelegate searchValues) + IndexOfAnySearchDelegate expected, IndexOfAnySearchDelegate indexOfAny, + SearchValuesSearchDelegate searchValues, SearchValuesContainsDelegate searchValuesContains) where T : struct, INumber, IMinMaxValue { ReadOnlySpan haystack = GetRandomSlice(rng, haystackRandom, MaxHaystackLength); @@ -475,6 +494,7 @@ private static void Test(Random rng, ReadOnlySpan haystackRandom, ReadOnly int expectedIndex = expected(haystack, needle); int indexOfAnyIndex = indexOfAny(haystack, needle); int searchValuesIndex = searchValues(haystack, searchValuesInstance); + bool searchValuesContainsResult = searchValuesContains(haystack, searchValuesInstance); if (expectedIndex != indexOfAnyIndex) { @@ -485,6 +505,11 @@ private static void Test(Random rng, ReadOnlySpan haystackRandom, ReadOnly { AssertionFailed(haystack, needle, expectedIndex, searchValuesIndex, nameof(searchValues)); } + + if ((expectedIndex >= 0) != searchValuesContainsResult) + { + AssertionFailed(haystack, needle, expectedIndex, searchValuesContainsResult ? 0 : -1, nameof(searchValuesContainsResult)); + } } private static ReadOnlySpan GetRandomSlice(Random rng, ReadOnlySpan span, int maxLength) From 1db908e0a39c239184df5e7601e460f7c548b83f Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Thu, 15 Jun 2023 18:07:44 +0200 Subject: [PATCH 4/8] Fix ContainsAny on a string --- .../System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs index 8cb46d143ea103..8b13fb83bb9198 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs @@ -202,14 +202,14 @@ internal static string GetPipePath(string serverName, string pipeName) // cross-platform with Windows (which has only '\' as an invalid char). if (Path.IsPathRooted(pipeName)) { - if (pipeName.ContainsAny(s_invalidPathNameChars) || pipeName.EndsWith(Path.DirectorySeparatorChar)) + if (pipeName.AsSpan().ContainsAny(s_invalidPathNameChars) || pipeName.EndsWith(Path.DirectorySeparatorChar)) throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars); // Caller is in full control of file location. return pipeName; } - if (pipeName.ContainsAny(s_invalidFileNameChars)) + if (pipeName.AsSpan().ContainsAny(s_invalidFileNameChars)) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars); } From 10094819cf85f7346a6d2dd82c5a91e7331f7dbb Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Thu, 15 Jun 2023 18:46:40 +0200 Subject: [PATCH 5/8] Reword summaries on ContainsAny --- .../System.Private.CoreLib/src/System/MemoryExtensions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index d3dd82fd939d80..9153dc2d9e2fdf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -452,7 +452,7 @@ public static bool ContainsAnyExceptInRange(this Span span, T lowInclusive ContainsAnyExceptInRange((ReadOnlySpan)span, lowInclusive, highInclusive); /// - /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// Searches for any occurance of the specified or , and returns true if found. If not found, returns false. /// /// The span to search. /// One of the values to search for. @@ -462,7 +462,7 @@ public static bool ContainsAny(this ReadOnlySpan span, T value0, T value1) IndexOfAny(span, value0, value1) >= 0; /// - /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// Searches for any occurance of the specified , , or , and returns true if found. If not found, returns false. /// /// The span to search. /// One of the values to search for. @@ -473,7 +473,7 @@ public static bool ContainsAny(this ReadOnlySpan span, T value0, T value1, IndexOfAny(span, value0, value1, value2) >= 0; /// - /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// Searches for any occurance of any of the specified and returns true if found. If not found, returns false. /// /// The span to search. /// The set of values to search for. @@ -482,7 +482,7 @@ public static bool ContainsAny(this ReadOnlySpan span, ReadOnlySpan val IndexOfAny(span, values) >= 0; /// - /// Searches for any of the specified values and returns true if found. If not found, returns false. + /// Searches for any occurance of any of the specified and returns true if found. If not found, returns false. /// /// The span to search. /// The set of values to search for. From 4e5da319e16b1164c65ce8e6446f47ce25740ec5 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Thu, 15 Jun 2023 19:10:35 +0200 Subject: [PATCH 6/8] Appease older TFMs --- .../src/Internal/PathUtils.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs index 5ecd13583c1349..02bc4d5f6acf41 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/Internal/PathUtils.cs @@ -20,24 +20,26 @@ private static char[] GetInvalidFilterChars() => GetInvalidFileNameChars() #if NET8_0_OR_GREATER private static readonly SearchValues _invalidFileNameChars = SearchValues.Create(GetInvalidFileNameChars()); private static readonly SearchValues _invalidFilterChars = SearchValues.Create(GetInvalidFilterChars()); + + internal static bool HasInvalidPathChars(string path) => + path.AsSpan().ContainsAny(_invalidFileNameChars); + + internal static bool HasInvalidFilterChars(string path) => + path.AsSpan().ContainsAny(_invalidFilterChars); #else private static readonly char[] _invalidFileNameChars = GetInvalidFileNameChars(); private static readonly char[] _invalidFilterChars = GetInvalidFilterChars(); + + internal static bool HasInvalidPathChars(string path) => + path.IndexOfAny(_invalidFileNameChars) >= 0; + + internal static bool HasInvalidFilterChars(string path) => + path.IndexOfAny(_invalidFilterChars) >= 0; #endif private static readonly char[] _pathSeparators = new[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}; - internal static bool HasInvalidPathChars(string path) - { - return path.AsSpan().ContainsAny(_invalidFileNameChars); - } - - internal static bool HasInvalidFilterChars(string path) - { - return path.AsSpan().ContainsAny(_invalidFilterChars); - } - internal static string EnsureTrailingSlash(string path) { if (!string.IsNullOrEmpty(path) && From 909a331721e968c8297bc4a9d0be767f9082602f Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Thu, 15 Jun 2023 19:40:42 +0200 Subject: [PATCH 7/8] Revert TestFilter.cs changes --- src/tests/Common/XUnitWrapperLibrary/TestFilter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs b/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs index 1682321a728146..837bc5462e2e2a 100644 --- a/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs +++ b/src/tests/Common/XUnitWrapperLibrary/TestFilter.cs @@ -157,7 +157,7 @@ public TestFilter(string[] filterArgs, HashSet? testExclusionList) if (filterString is not null) { - if (filterString.ContainsAny("!()~=")) + if (filterString.IndexOfAny(new[] { '!', '(', ')', '~', '=' }) != -1) { throw new ArgumentException("Complex test filter expressions are not supported today. The only filters supported today are the simple form supported in 'dotnet test --filter' (substrings of the test's fully qualified name). If further filtering options are desired, file an issue on dotnet/runtime for support.", nameof(filterArgs)); } From e7651e83fa2298961d3eeeff6919332957fcfd4a Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Thu, 15 Jun 2023 20:31:57 +0200 Subject: [PATCH 8/8] Appease older TFMs part 2 --- .../src/System/ServiceProcess/ServiceBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs index 78d1ed94ab942f..c745593bc25d65 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System/ServiceProcess/ServiceBase.cs @@ -291,7 +291,7 @@ public string ServiceName internal static bool ValidServiceName(string serviceName) => !string.IsNullOrEmpty(serviceName) && serviceName.Length <= ServiceBase.MaxNameLength && // not too long - !serviceName.AsSpan().ContainsAny('\\', '/'); // no slashes or backslash allowed + serviceName.AsSpan().IndexOfAny('\\', '/') < 0; // no slashes or backslash allowed /// /// Disposes of the resources (other than memory ) used by