summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAhson Khan <ahkha@microsoft.com>2018-03-03 17:48:07 -0800
committerGitHub <noreply@github.com>2018-03-03 17:48:07 -0800
commit7ac6d5cd8db4033a4d7a4bfec34e72701b13433b (patch)
tree017e96a4244e7ff5908d93d9db18a29f36a00238 /src
parent37d1426400794bad99142d741dc38efec1175e0d (diff)
downloadcoreclr-7ac6d5cd8db4033a4d7a4bfec34e72701b13433b.tar.gz
coreclr-7ac6d5cd8db4033a4d7a4bfec34e72701b13433b.tar.bz2
coreclr-7ac6d5cd8db4033a4d7a4bfec34e72701b13433b.zip
Remove StringSpanHelpers and start using MemoryExtensions (#16718)
* Remove StringSpanHelpers and start using MemoryExtensions * Address PR feedback.
Diffstat (limited to 'src')
-rw-r--r--src/mscorlib/shared/System.Private.CoreLib.Shared.projitems1
-rw-r--r--src/mscorlib/shared/System/Boolean.cs9
-rw-r--r--src/mscorlib/shared/System/Double.cs6
-rw-r--r--src/mscorlib/shared/System/Globalization/CompareInfo.cs40
-rw-r--r--src/mscorlib/shared/System/Globalization/DateTimeParse.cs20
-rw-r--r--src/mscorlib/shared/System/Globalization/TimeSpanParse.cs76
-rw-r--r--src/mscorlib/shared/System/Guid.cs14
-rw-r--r--src/mscorlib/shared/System/IO/Path.Windows.cs8
-rw-r--r--src/mscorlib/shared/System/IO/PathHelper.Windows.cs4
-rw-r--r--src/mscorlib/shared/System/MemoryExtensions.Fast.cs72
-rw-r--r--src/mscorlib/shared/System/MemoryExtensions.cs8
-rw-r--r--src/mscorlib/shared/System/Number.Parsing.cs12
-rw-r--r--src/mscorlib/shared/System/Single.cs6
-rw-r--r--src/mscorlib/shared/System/StringSpanHelpers.cs139
-rw-r--r--src/mscorlib/shared/System/Text/StringBuilder.cs2
-rw-r--r--src/mscorlib/shared/System/Version.cs12
-rw-r--r--src/mscorlib/src/System/String.Comparison.cs34
-rw-r--r--src/mscorlib/src/System/ThrowHelper.cs4
18 files changed, 175 insertions, 292 deletions
diff --git a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
index 0b3f971b17..46a161e006 100644
--- a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
@@ -494,7 +494,6 @@
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.T.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\String.Manipulation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\String.Searching.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\StringSpanHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StackOverflowException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparison.cs" />
diff --git a/src/mscorlib/shared/System/Boolean.cs b/src/mscorlib/shared/System/Boolean.cs
index fd56082f9b..e476ef7ce6 100644
--- a/src/mscorlib/shared/System/Boolean.cs
+++ b/src/mscorlib/shared/System/Boolean.cs
@@ -12,7 +12,6 @@
**
===========================================================*/
-using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
@@ -203,14 +202,14 @@ namespace System
public static bool TryParse(ReadOnlySpan<char> value, out bool result)
{
ReadOnlySpan<char> trueSpan = TrueLiteral.AsSpan();
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (trueSpan.EqualsOrdinalIgnoreCase(value))
{
result = true;
return true;
}
ReadOnlySpan<char> falseSpan = FalseLiteral.AsSpan();
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (falseSpan.EqualsOrdinalIgnoreCase(value))
{
result = false;
return true;
@@ -219,13 +218,13 @@ namespace System
// Special case: Trim whitespace as well as null characters.
value = TrimWhiteSpaceAndNull(value);
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (trueSpan.EqualsOrdinalIgnoreCase(value))
{
result = true;
return true;
}
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (falseSpan.EqualsOrdinalIgnoreCase(value))
{
result = false;
return true;
diff --git a/src/mscorlib/shared/System/Double.cs b/src/mscorlib/shared/System/Double.cs
index 146ee46005..1351ae91d3 100644
--- a/src/mscorlib/shared/System/Double.cs
+++ b/src/mscorlib/shared/System/Double.cs
@@ -346,15 +346,15 @@ namespace System
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
diff --git a/src/mscorlib/shared/System/Globalization/CompareInfo.cs b/src/mscorlib/shared/System/Globalization/CompareInfo.cs
index c369c816b0..db0a660ddf 100644
--- a/src/mscorlib/shared/System/Globalization/CompareInfo.cs
+++ b/src/mscorlib/shared/System/Globalization/CompareInfo.cs
@@ -389,38 +389,18 @@ namespace System.Globalization
return CompareString(string1, string2, options);
}
- // TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
- internal virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
+ internal virtual int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
{
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return CompareOrdinalIgnoreCase(string1, string2);
- }
-
- // Verify the options before we do any real comparison.
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
- }
-
- return string.CompareOrdinal(string1, string2);
- }
-
- if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
-
- if (_invariantMode)
- {
- return (options & CompareOptions.IgnoreCase) != 0 ?
- CompareOrdinalIgnoreCase(string1, string2) :
- string.CompareOrdinal(string1, string2);
- }
+ return _invariantMode ?
+ string.CompareOrdinal(string1, string2) :
+ CompareString(string1, string2, CompareOptions.None);
+ }
- return CompareString(string1, string2, options);
+ internal virtual int CompareOptionIgnoreCase(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
+ {
+ return _invariantMode ?
+ CompareOrdinalIgnoreCase(string1, string2) :
+ CompareString(string1, string2, CompareOptions.IgnoreCase);
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/mscorlib/shared/System/Globalization/DateTimeParse.cs b/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
index 5b285eb5df..fd64c6d111 100644
--- a/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
+++ b/src/mscorlib/shared/System/Globalization/DateTimeParse.cs
@@ -5045,7 +5045,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5071,7 +5071,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5286,14 +5286,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- if (Char.IsWhiteSpace(Value[i - 1]))
+ if (char.IsWhiteSpace(Value[i - 1]))
{
i--;
- while (i >= 1 && Char.IsWhiteSpace(Value[i - 1]))
+ while (i >= 1 && char.IsWhiteSpace(Value[i - 1]))
{
i--;
}
- Value = Value.Remove(i, Value.Length - 1 - i);
+ Span<char> result = new char[i + 1];
+ result[i] = ch;
+ Value.Slice(0, i).CopyTo(result);
+ Value = result.AsReadOnlySpan();
}
}
}
@@ -5311,13 +5314,16 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- while ((i + 1) < Length && Char.IsWhiteSpace(Value[i + 1]))
+ while ((i + 1) < Length && char.IsWhiteSpace(Value[i + 1]))
{
i++;
}
if (i != 0)
{
- Value = Value.Remove(1, i);
+ Span<char> result = new char[Value.Length - i];
+ result[0] = ch;
+ Value.Slice(i + 1).CopyTo(result.Slice(1));
+ Value = result.AsReadOnlySpan();
}
}
}
diff --git a/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs b/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs
index ae77957cec..51fac39d0a 100644
--- a/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs
+++ b/src/mscorlib/shared/System/Globalization/TimeSpanParse.cs
@@ -274,83 +274,83 @@ namespace System.Globalization
internal bool FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals4.EqualsOrdinal(pattern.End);
internal bool PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMSF (all values matched)</summary>
internal bool FullMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == MaxLiteralTokens
&& _numCount == MaxNumericTokens
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals5, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals5.EqualsOrdinal(pattern.End);
/// <summary>D (no hours, minutes, seconds, or fractions)</summary>
internal bool FullDMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 2
&& _numCount == 1
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.End);
/// <summary>HM (no days, seconds, or fractions)</summary>
internal bool FullHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 3
&& _numCount == 2
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.End);
/// <summary>DHM (no seconds or fraction)</summary>
internal bool FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>HMS (no days or fraction)</summary>
internal bool FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMS (no fraction)</summary>
internal bool FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.End);
/// <summary>HMSF (no days)</summary>
internal bool FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals4.EqualsOrdinal(pattern.End);
internal TTT _lastSeenTTT;
internal int _tokenCount;
diff --git a/src/mscorlib/shared/System/Guid.cs b/src/mscorlib/shared/System/Guid.cs
index 423d5bc78c..1d0942f2cb 100644
--- a/src/mscorlib/shared/System/Guid.cs
+++ b/src/mscorlib/shared/System/Guid.cs
@@ -449,7 +449,7 @@ namespace System
}
// Check for braces
- bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0);
+ bool bracesExistInString = (guidString.IndexOf('{') >= 0);
if (bracesExistInString)
{
@@ -471,7 +471,7 @@ namespace System
}
// Check for parenthesis
- bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0);
+ bool parenthesisExistInString = (guidString.IndexOf('(') >= 0);
if (parenthesisExistInString)
{
@@ -548,7 +548,7 @@ namespace System
// Find the end of this hex number (since it is not fixed length)
numStart = 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -566,7 +566,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -584,7 +584,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -621,7 +621,7 @@ namespace System
// Calculate number length
if (i < 7) // first 7 cases
{
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -630,7 +630,7 @@ namespace System
}
else // last case ends with '}', not ','
{
- numLen = guidString.IndexOf('}', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf('}');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidBraceAfterLastNumber));
diff --git a/src/mscorlib/shared/System/IO/Path.Windows.cs b/src/mscorlib/shared/System/IO/Path.Windows.cs
index 0448337731..2f1a527d8b 100644
--- a/src/mscorlib/shared/System/IO/Path.Windows.cs
+++ b/src/mscorlib/shared/System/IO/Path.Windows.cs
@@ -90,7 +90,7 @@ namespace System.IO
// Drive relative paths
Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));
- if (StringSpanHelpers.Equals(GetVolumeName(path), GetVolumeName(basePath)))
+ if (GetVolumeName(path).EqualsOrdinal(GetVolumeName(basePath)))
{
// Matching root
// "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
@@ -241,11 +241,11 @@ namespace System.IO
{
bool isDevice = PathInternal.IsDevice(path);
- if (!isDevice && StringSpanHelpers.Equals(path.Slice(0, 2), @"\\") )
+ if (!isDevice && path.Slice(0, 2).EqualsOrdinal(@"\\") )
return 2;
else if (isDevice && path.Length >= 8
- && (StringSpanHelpers.Equals(path.Slice(0, 8), PathInternal.UncExtendedPathPrefix)
- || StringSpanHelpers.Equals(path.Slice(5, 4), @"UNC\")))
+ && (path.Slice(0, 8).EqualsOrdinal(PathInternal.UncExtendedPathPrefix)
+ || path.Slice(5, 4).EqualsOrdinal(@"UNC\")))
return 8;
return -1;
diff --git a/src/mscorlib/shared/System/IO/PathHelper.Windows.cs b/src/mscorlib/shared/System/IO/PathHelper.Windows.cs
index 74ceed10aa..6faebe8ffa 100644
--- a/src/mscorlib/shared/System/IO/PathHelper.Windows.cs
+++ b/src/mscorlib/shared/System/IO/PathHelper.Windows.cs
@@ -35,7 +35,7 @@ namespace System.IO
// TryExpandShortName does this input identity check.
string result = builder.AsSpan().Contains('~')
? TryExpandShortFileName(ref builder, originalPath: path)
- : builder.AsSpan().Equals(path.AsSpan()) ? path : builder.ToString();
+ : builder.AsSpan().EqualsOrdinal(path.AsSpan()) ? path : builder.ToString();
// Clear the buffer
builder.Dispose();
@@ -220,7 +220,7 @@ namespace System.IO
// Strip out any added characters at the front of the string
ReadOnlySpan<char> output = builderToUse.AsSpan().Slice(rootDifference);
- string returnValue = output.Equals(originalPath.AsSpan())
+ string returnValue = output.EqualsOrdinal(originalPath.AsSpan())
? originalPath : new string(output);
inputBuilder.Dispose();
diff --git a/src/mscorlib/shared/System/MemoryExtensions.Fast.cs b/src/mscorlib/shared/System/MemoryExtensions.Fast.cs
index 56dd203e1f..d28c3d6883 100644
--- a/src/mscorlib/shared/System/MemoryExtensions.Fast.cs
+++ b/src/mscorlib/shared/System/MemoryExtensions.Fast.cs
@@ -36,41 +36,67 @@ namespace System
/// </summary>
public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, value) == 0);
case StringComparison.CurrentCultureIgnoreCase:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, value) == 0);
case StringComparison.InvariantCulture:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.None) == 0);
+ return (CompareInfo.Invariant.CompareOptionNone(span, value) == 0);
case StringComparison.InvariantCultureIgnoreCase:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CompareInfo.Invariant.CompareOptionIgnoreCase(span, value) == 0);
case StringComparison.Ordinal:
- if (span.Length != value.Length)
- 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 EqualsOrdinal(span, value);
case StringComparison.OrdinalIgnoreCase:
- if (span.Length != value.Length)
- return false;
- if (value.Length == 0) // span.Length == value.Length == 0
- return true;
- return (CompareInfo.CompareOrdinalIgnoreCase(span, value) == 0);
+ return EqualsOrdinalIgnoreCase(span, value);
}
Debug.Fail("StringComparison outside range");
return false;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinal(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ 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
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ return false;
+ if (value.Length == 0) // span.Length == value.Length == 0
+ return true;
+ return (CompareInfo.CompareOrdinalIgnoreCase(span, value) == 0);
+ }
+
+ // TODO https://github.com/dotnet/corefx/issues/27526
+ internal static bool Contains(this ReadOnlySpan<char> source, char value)
+ {
+ for (int i = 0; i < source.Length; i++)
+ {
+ if (source[i] == value)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/// <summary>
/// Compares the specified <paramref name="span"/> and <paramref name="value"/> using the specified <paramref name="comparisonType"/>,
/// and returns an integer that indicates their relative position in the sort order.
@@ -80,21 +106,21 @@ namespace System
/// </summary>
public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, value);
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, value);
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.None);
+ return CompareInfo.Invariant.CompareOptionNone(span, value);
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.CompareOptionIgnoreCase(span, value);
case StringComparison.Ordinal:
if (span.Length == 0 || value.Length == 0)
@@ -117,7 +143,7 @@ namespace System
/// </summary>
public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
if (value.Length == 0)
{
@@ -262,7 +288,7 @@ namespace System
{
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
return true;
}
@@ -301,7 +327,7 @@ namespace System
{
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
return true;
}
diff --git a/src/mscorlib/shared/System/MemoryExtensions.cs b/src/mscorlib/shared/System/MemoryExtensions.cs
index b625ece7e3..d5a6b72eb4 100644
--- a/src/mscorlib/shared/System/MemoryExtensions.cs
+++ b/src/mscorlib/shared/System/MemoryExtensions.cs
@@ -181,7 +181,7 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -199,7 +199,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
@@ -301,7 +301,7 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -319,7 +319,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
diff --git a/src/mscorlib/shared/System/Number.Parsing.cs b/src/mscorlib/shared/System/Number.Parsing.cs
index 46951094eb..c6ae34d050 100644
--- a/src/mscorlib/shared/System/Number.Parsing.cs
+++ b/src/mscorlib/shared/System/Number.Parsing.cs
@@ -734,15 +734,15 @@ namespace System
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(numfmt.PositiveInfinitySymbol))
{
return double.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(numfmt.NegativeInfinitySymbol))
{
return double.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(numfmt.NaNSymbol))
{
return double.NaN;
}
@@ -768,15 +768,15 @@ namespace System
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(numfmt.PositiveInfinitySymbol))
{
return float.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(numfmt.NegativeInfinitySymbol))
{
return float.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(numfmt.NaNSymbol))
{
return float.NaN;
}
diff --git a/src/mscorlib/shared/System/Single.cs b/src/mscorlib/shared/System/Single.cs
index 7bffa1ac77..013dd9b40f 100644
--- a/src/mscorlib/shared/System/Single.cs
+++ b/src/mscorlib/shared/System/Single.cs
@@ -335,15 +335,15 @@ namespace System
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
diff --git a/src/mscorlib/shared/System/StringSpanHelpers.cs b/src/mscorlib/shared/System/StringSpanHelpers.cs
deleted file mode 100644
index 2d6152de56..0000000000
--- a/src/mscorlib/shared/System/StringSpanHelpers.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-
-namespace System
-{
- /// <summary>Helpers for string-like operations on spans of chars.</summary>
- internal static class StringSpanHelpers
- {
- // TODO https://github.com/dotnet/corefx/issues/21395: Provide public, efficient implementations
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right, StringComparison comparisonType) =>
- comparisonType == StringComparison.Ordinal ? Equals(left, right) :
- comparisonType == StringComparison.OrdinalIgnoreCase ? EqualsOrdinalIgnoreCase(left, right) :
- throw new ArgumentOutOfRangeException(nameof(comparisonType));
-
- public static bool Equals(this ReadOnlySpan<char> left, string right) =>
- Equals(left, right.AsSpan());
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- if (left[i] != right[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- private static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- char x = left[i], y = right[i];
- if (x != y &&
- TextInfo.ToUpperAsciiInvariant(x) != TextInfo.ToUpperAsciiInvariant(y))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value) =>
- IndexOf(source, value, 0);
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value, int startIndex)
- {
- for (int i = startIndex; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- public static bool Contains(this ReadOnlySpan<char> source, char value)
- {
- for (int i = 0; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return true;
- }
- }
-
- return false;
- }
-
- public static ReadOnlySpan<char> Remove(this ReadOnlySpan<char> source, int startIndex, int count)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
- if (count < 0)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
- if (count > source.Length - startIndex)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_IndexCount);
-
- if (count == 0)
- {
- return source;
- }
-
- int newLength = source.Length - count;
- if (newLength == 0)
- {
- return ReadOnlySpan<char>.Empty;
- }
-
- Span<char> result = new char[newLength];
- source.Slice(0, startIndex).CopyTo(result);
- source.Slice(startIndex + count).CopyTo(result.Slice(startIndex));
- return result;
- }
-
- // Returns the index of the last occurrence of a specified character in the current instance.
- public static int LastIndexOf(this ReadOnlySpan<char> source, char value)
- {
- if (source.Length == 0)
- return -1;
-
- for (int i = source.Length - 1; i >= 0; i--)
- {
- if (source[i] == value)
- return i;
- }
-
- return -1;
- }
-
- public static void CheckStringComparison(StringComparison comparisonType)
- {
- // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
- if ((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
- {
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
- }
- }
- }
-}
diff --git a/src/mscorlib/shared/System/Text/StringBuilder.cs b/src/mscorlib/shared/System/Text/StringBuilder.cs
index a7804c3991..65a4a240ef 100644
--- a/src/mscorlib/shared/System/Text/StringBuilder.cs
+++ b/src/mscorlib/shared/System/Text/StringBuilder.cs
@@ -1696,7 +1696,7 @@ namespace System.Text
ReadOnlySpan<char> chunk = new ReadOnlySpan<char>(sbChunk.m_ChunkChars, 0, chunk_length);
- if (!chunk.Equals(value.Slice(value.Length - offset, chunk_length)))
+ if (!chunk.EqualsOrdinal(value.Slice(value.Length - offset, chunk_length)))
return false;
sbChunk = sbChunk.m_ChunkPrevious;
diff --git a/src/mscorlib/shared/System/Version.cs b/src/mscorlib/shared/System/Version.cs
index 9e4cefcd6f..fe086be512 100644
--- a/src/mscorlib/shared/System/Version.cs
+++ b/src/mscorlib/shared/System/Version.cs
@@ -333,13 +333,15 @@ namespace System
// Find the ends of the optional minor and build portions.
// We musn't have any separators after build.
int buildEnd = -1;
- int minorEnd = input.IndexOf('.', majorEnd + 1);
+ int minorEnd = input.Slice(majorEnd + 1).IndexOf('.');
if (minorEnd != -1)
{
- buildEnd = input.IndexOf('.', minorEnd + 1);
+ minorEnd += (majorEnd + 1);
+ buildEnd = input.Slice(minorEnd + 1).IndexOf('.');
if (buildEnd != -1)
{
- if (input.IndexOf('.', buildEnd + 1) != -1)
+ buildEnd += (minorEnd + 1);
+ if (input.Slice(buildEnd + 1).IndexOf('.') != -1)
{
if (throwOnFailure) throw new ArgumentException(SR.Arg_VersionString, nameof(input));
return null;
@@ -347,10 +349,10 @@ namespace System
}
}
- int major, minor, build, revision;
+ int minor, build, revision;
// Parse the major version
- if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out major))
+ if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out int major))
{
return null;
}
diff --git a/src/mscorlib/src/System/String.Comparison.cs b/src/mscorlib/src/System/String.Comparison.cs
index 44b3ed94b8..23e9efe73e 100644
--- a/src/mscorlib/src/System/String.Comparison.cs
+++ b/src/mscorlib/src/System/String.Comparison.cs
@@ -387,19 +387,19 @@ namespace System
{
if (object.ReferenceEquals(strA, strB))
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return 0;
}
// They can't both be null at this point.
if (strA == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return -1;
}
if (strB == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return 1;
}
@@ -559,7 +559,7 @@ namespace System
public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
if (strA == null || strB == null)
{
@@ -652,7 +652,6 @@ namespace System
return CompareOrdinalHelper(strA, strB);
}
- // TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
internal static int CompareOrdinal(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
{
// TODO: Add a vectorized code path, similar to SequenceEqual
@@ -781,13 +780,13 @@ namespace System
if ((Object)this == (Object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
@@ -877,13 +876,13 @@ namespace System
{
if ((Object)this == (Object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if ((Object)value == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return false;
}
@@ -944,13 +943,13 @@ namespace System
{
if ((Object)a == (Object)b)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if ((Object)a == null || (Object)b == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return false;
}
@@ -1096,13 +1095,13 @@ namespace System
if ((Object)this == (Object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
@@ -1158,5 +1157,14 @@ namespace System
}
public bool StartsWith(char value) => Length != 0 && _firstChar == value;
+
+ 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))
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.NotSupported_StringComparison, ExceptionArgument.comparisonType);
+ }
+ }
}
}
diff --git a/src/mscorlib/src/System/ThrowHelper.cs b/src/mscorlib/src/System/ThrowHelper.cs
index 6b755a13fc..4eb92be31d 100644
--- a/src/mscorlib/src/System/ThrowHelper.cs
+++ b/src/mscorlib/src/System/ThrowHelper.cs
@@ -479,7 +479,8 @@ namespace System
culture,
comparable,
source,
- state
+ state,
+ comparisonType
}
//
@@ -589,6 +590,7 @@ namespace System
InvalidOperation_HandleIsNotInitialized,
AsyncMethodBuilder_InstanceNotInitialized,
ArgumentNull_SafeHandle,
+ NotSupported_StringComparison,
}
}