From 0ba6924dbc8477e4ecfbb8fd7793c2788bd48cd9 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 5 May 2018 19:58:04 -0700 Subject: [PATCH] Delete unnecessary internal layer of Span globalization helpers (#17890) This change makes the code both smaller and faster. For example, the following is about 1.4x faster with this change: ``` ReadOnlySpan s1 = "Hello world"; ReadOnlySpan s2 = "world"; for (int i = 0; i < 100000000; i++) s1.EndsWith(s2, StringComparison.OrdinalIgnoreCase); ``` Also, I have ported GetCaseCompareOfComparisonCulture code size optimization from #16434 while I was on it because of it fit well with the rest of the changes. --- .../shared/System/Globalization/TextInfo.cs | 8 +- .../shared/System/MemoryExtensions.Fast.cs | 95 +++++++--------- src/mscorlib/shared/System/SpanHelpers.cs | 121 --------------------- src/mscorlib/shared/System/String.Comparison.cs | 70 ++++++------ src/mscorlib/shared/System/String.Manipulation.cs | 8 +- src/mscorlib/shared/System/String.Searching.cs | 32 ++---- 6 files changed, 88 insertions(+), 246 deletions(-) diff --git a/src/mscorlib/shared/System/Globalization/TextInfo.cs b/src/mscorlib/shared/System/Globalization/TextInfo.cs index e875e17..183f02c 100644 --- a/src/mscorlib/shared/System/Globalization/TextInfo.cs +++ b/src/mscorlib/shared/System/Globalization/TextInfo.cs @@ -419,7 +419,7 @@ namespace System.Globalization } } - private unsafe string ToLowerAsciiInvariant(string s) + private static unsafe string ToLowerAsciiInvariant(string s) { if (s.Length == 0) { @@ -465,7 +465,7 @@ namespace System.Globalization } } - internal void ToLowerAsciiInvariant(ReadOnlySpan source, Span destination) + internal static void ToLowerAsciiInvariant(ReadOnlySpan source, Span destination) { Debug.Assert(destination.Length >= source.Length); @@ -475,7 +475,7 @@ namespace System.Globalization } } - private unsafe string ToUpperAsciiInvariant(string s) + private static unsafe string ToUpperAsciiInvariant(string s) { if (s.Length == 0) { @@ -521,7 +521,7 @@ namespace System.Globalization } } - internal void ToUpperAsciiInvariant(ReadOnlySpan source, Span destination) + internal static void ToUpperAsciiInvariant(ReadOnlySpan source, Span destination) { Debug.Assert(destination.Length >= source.Length); diff --git a/src/mscorlib/shared/System/MemoryExtensions.Fast.cs b/src/mscorlib/shared/System/MemoryExtensions.Fast.cs index d256887..a9a755a 100644 --- a/src/mscorlib/shared/System/MemoryExtensions.Fast.cs +++ b/src/mscorlib/shared/System/MemoryExtensions.Fast.cs @@ -70,7 +70,7 @@ namespace System return false; if (value.Length == 0) // span.Length == value.Length == 0 return true; - return span.SequenceEqual(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487 + return span.SequenceEqual(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -155,25 +155,24 @@ namespace System return -1; } + if (GlobalizationMode.Invariant) + { + return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None); + } + switch (comparisonType) { case StringComparison.CurrentCulture: - return SpanHelpers.IndexOfCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); - case StringComparison.CurrentCultureIgnoreCase: - return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); + return CultureInfo.CurrentCulture.CompareInfo.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return SpanHelpers.IndexOfCultureHelper(span, value, CompareInfo.Invariant); - case StringComparison.InvariantCultureIgnoreCase: - return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant); + return CompareInfo.Invariant.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: - return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: false); - case StringComparison.OrdinalIgnoreCase: - return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: true); + return CompareInfo.Invariant.IndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None); } Debug.Fail("StringComparison outside range"); @@ -202,7 +201,7 @@ namespace System return -1; if (GlobalizationMode.Invariant) - culture.TextInfo.ToLowerAsciiInvariant(source, destination); + TextInfo.ToLowerAsciiInvariant(source, destination); else culture.TextInfo.ChangeCase(source, destination, toUpper: false); return source.Length; @@ -223,7 +222,7 @@ namespace System return -1; if (GlobalizationMode.Invariant) - CultureInfo.InvariantCulture.TextInfo.ToLowerAsciiInvariant(source, destination); + TextInfo.ToLowerAsciiInvariant(source, destination); else CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: false); return source.Length; @@ -251,7 +250,7 @@ namespace System return -1; if (GlobalizationMode.Invariant) - culture.TextInfo.ToUpperAsciiInvariant(source, destination); + TextInfo.ToUpperAsciiInvariant(source, destination); else culture.TextInfo.ChangeCase(source, destination, toUpper: true); return source.Length; @@ -272,7 +271,7 @@ namespace System return -1; if (GlobalizationMode.Invariant) - CultureInfo.InvariantCulture.TextInfo.ToUpperAsciiInvariant(source, destination); + TextInfo.ToUpperAsciiInvariant(source, destination); else CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: true); return source.Length; @@ -286,35 +285,29 @@ namespace System /// One of the enumeration values that determines how the and are compared. public static bool EndsWith(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { + string.CheckStringComparison(comparisonType); + if (value.Length == 0) { - string.CheckStringComparison(comparisonType); return true; } - switch (comparisonType) + if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant) { - case StringComparison.CurrentCulture: - return SpanHelpers.EndsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); + if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None) + return span.EndsWith(value); - case StringComparison.CurrentCultureIgnoreCase: - return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); - - case StringComparison.InvariantCulture: - return SpanHelpers.EndsWithCultureHelper(span, value, CompareInfo.Invariant); - - case StringComparison.InvariantCultureIgnoreCase: - return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant); - - case StringComparison.Ordinal: - return span.EndsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487 - - case StringComparison.OrdinalIgnoreCase: - return SpanHelpers.EndsWithOrdinalIgnoreCaseHelper(span, value); + return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0) : false; + } - default: - throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType)); + if (span.Length == 0) + { + return false; } + + return (comparisonType >= StringComparison.InvariantCulture) ? + CompareInfo.Invariant.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) : + CultureInfo.CurrentCulture.CompareInfo.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)); } /// @@ -325,35 +318,29 @@ namespace System /// One of the enumeration values that determines how the and are compared. public static bool StartsWith(this ReadOnlySpan span, ReadOnlySpan value, StringComparison comparisonType) { + string.CheckStringComparison(comparisonType); + if (value.Length == 0) { - string.CheckStringComparison(comparisonType); return true; } - switch (comparisonType) + if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant) { - case StringComparison.CurrentCulture: - return SpanHelpers.StartsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); - - case StringComparison.CurrentCultureIgnoreCase: - return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo); - - case StringComparison.InvariantCulture: - return SpanHelpers.StartsWithCultureHelper(span, value, CompareInfo.Invariant); + if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None) + return span.StartsWith(value); - case StringComparison.InvariantCultureIgnoreCase: - return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant); - - case StringComparison.Ordinal: - return span.StartsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487 - - case StringComparison.OrdinalIgnoreCase: - return SpanHelpers.StartsWithOrdinalIgnoreCaseHelper(span, value); + return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0) : false; + } - default: - throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType)); + if (span.Length == 0) + { + return false; } + + return (comparisonType >= StringComparison.InvariantCulture) ? + CompareInfo.Invariant.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) : + CultureInfo.CurrentCulture.CompareInfo.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)); } /// diff --git a/src/mscorlib/shared/System/SpanHelpers.cs b/src/mscorlib/shared/System/SpanHelpers.cs index c3cfe5a..83cdfce 100644 --- a/src/mscorlib/shared/System/SpanHelpers.cs +++ b/src/mscorlib/shared/System/SpanHelpers.cs @@ -19,127 +19,6 @@ namespace System { internal static partial class SpanHelpers { - public static int IndexOfCultureHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(span.Length != 0); - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return CompareInfo.InvariantIndexOf(span, value, ignoreCase: false); - } - - return compareInfo.IndexOf(span, value, CompareOptions.None); - } - - public static int IndexOfCultureIgnoreCaseHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(span.Length != 0); - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return CompareInfo.InvariantIndexOf(span, value, ignoreCase: true); - } - - return compareInfo.IndexOf(span, value, CompareOptions.IgnoreCase); - } - - public static int IndexOfOrdinalHelper(ReadOnlySpan span, ReadOnlySpan value, bool ignoreCase) - { - Debug.Assert(span.Length != 0); - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return CompareInfo.InvariantIndexOf(span, value, ignoreCase); - } - - return CompareInfo.Invariant.IndexOfOrdinal(span, value, ignoreCase); - } - - public static bool StartsWithCultureHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return span.StartsWith(value); - } - if (span.Length == 0) - { - return false; - } - return compareInfo.IsPrefix(span, value, CompareOptions.None); - } - - public static bool StartsWithCultureIgnoreCaseHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return StartsWithOrdinalIgnoreCaseHelper(span, value); - } - if (span.Length == 0) - { - return false; - } - return compareInfo.IsPrefix(span, value, CompareOptions.IgnoreCase); - } - - public static bool StartsWithOrdinalIgnoreCaseHelper(ReadOnlySpan span, ReadOnlySpan value) - { - Debug.Assert(value.Length != 0); - - if (span.Length < value.Length) - { - return false; - } - return CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0; - } - - public static bool EndsWithCultureHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return span.EndsWith(value); - } - if (span.Length == 0) - { - return false; - } - return compareInfo.IsSuffix(span, value, CompareOptions.None); - } - - public static bool EndsWithCultureIgnoreCaseHelper(ReadOnlySpan span, ReadOnlySpan value, CompareInfo compareInfo) - { - Debug.Assert(value.Length != 0); - - if (GlobalizationMode.Invariant) - { - return EndsWithOrdinalIgnoreCaseHelper(span, value); - } - if (span.Length == 0) - { - return false; - } - return compareInfo.IsSuffix(span, value, CompareOptions.IgnoreCase); - } - - public static bool EndsWithOrdinalIgnoreCaseHelper(ReadOnlySpan span, ReadOnlySpan value) - { - Debug.Assert(value.Length != 0); - - if (span.Length < value.Length) - { - return false; - } - return (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0); - } - public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) { if (byteLength == 0) diff --git a/src/mscorlib/shared/System/String.Comparison.cs b/src/mscorlib/shared/System/String.Comparison.cs index 32951b4..03c7cf6 100644 --- a/src/mscorlib/shared/System/String.Comparison.cs +++ b/src/mscorlib/shared/System/String.Comparison.cs @@ -288,16 +288,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: // Most common case: first character is different. @@ -484,16 +480,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB); @@ -645,16 +637,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0); @@ -741,16 +729,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0); - case StringComparison.CurrentCultureIgnoreCase: - return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0); + return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0); case StringComparison.InvariantCulture: - return (CompareInfo.Invariant.Compare(this, value, CompareOptions.None) == 0); - case StringComparison.InvariantCultureIgnoreCase: - return (CompareInfo.Invariant.Compare(this, value, CompareOptions.IgnoreCase) == 0); + return (CompareInfo.Invariant.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0); case StringComparison.Ordinal: if (this.Length != value.Length) @@ -808,16 +792,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0); - case StringComparison.CurrentCultureIgnoreCase: - return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0); + return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0); case StringComparison.InvariantCulture: - return (CompareInfo.Invariant.Compare(a, b, CompareOptions.None) == 0); - case StringComparison.InvariantCultureIgnoreCase: - return (CompareInfo.Invariant.Compare(a, b, CompareOptions.IgnoreCase) == 0); + return (CompareInfo.Invariant.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0); case StringComparison.Ordinal: if (a.Length != b.Length) @@ -946,16 +926,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: if (this.Length < value.Length || _firstChar != value._firstChar) @@ -1002,10 +978,30 @@ namespace System internal static void CheckStringComparison(StringComparison comparisonType) { // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase] - if ((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture)) + if ((uint)comparisonType > (uint)StringComparison.OrdinalIgnoreCase) { ThrowHelper.ThrowArgumentException(ExceptionResource.NotSupported_StringComparison, ExceptionArgument.comparisonType); } } + + internal static CompareOptions GetCaseCompareOfComparisonCulture(StringComparison comparisonType) + { + Debug.Assert((uint)comparisonType <= (uint)StringComparison.OrdinalIgnoreCase); + + // Culture enums can be & with CompareOptions.IgnoreCase 0x01 to extract if IgnoreCase or CompareOptions.None 0x00 + // + // CompareOptions.None 0x00 + // CompareOptions.IgnoreCase 0x01 + // + // StringComparison.CurrentCulture: 0x00 + // StringComparison.InvariantCulture: 0x02 + // StringComparison.Ordinal 0x04 + // + // StringComparison.CurrentCultureIgnoreCase: 0x01 + // StringComparison.InvariantCultureIgnoreCase: 0x03 + // StringComparison.OrdinalIgnoreCase 0x05 + + return (CompareOptions)((int)comparisonType & (int)CompareOptions.IgnoreCase); + } } } diff --git a/src/mscorlib/shared/System/String.Manipulation.cs b/src/mscorlib/shared/System/String.Manipulation.cs index 69609aa..5face07 100644 --- a/src/mscorlib/shared/System/String.Manipulation.cs +++ b/src/mscorlib/shared/System/String.Manipulation.cs @@ -919,16 +919,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase); + return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase); + return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: return Replace(oldValue, newValue); diff --git a/src/mscorlib/shared/System/String.Searching.cs b/src/mscorlib/shared/System/String.Searching.cs index cab9faa..3a6ffc3 100644 --- a/src/mscorlib/shared/System/String.Searching.cs +++ b/src/mscorlib/shared/System/String.Searching.cs @@ -47,16 +47,12 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.Ordinal); @@ -326,22 +322,16 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: - return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: false); - case StringComparison.OrdinalIgnoreCase: - return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: true); + return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None); default: throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType)); @@ -522,22 +512,16 @@ namespace System switch (comparisonType) { case StringComparison.CurrentCulture: - return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None); - case StringComparison.CurrentCultureIgnoreCase: - return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.InvariantCulture: - return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.None); - case StringComparison.InvariantCultureIgnoreCase: - return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType)); case StringComparison.Ordinal: - return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: false); - case StringComparison.OrdinalIgnoreCase: - return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: true); + return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None); default: throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType)); -- 2.7.4