summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/String.Comparison.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/String.Comparison.cs')
-rw-r--r--src/mscorlib/src/System/String.Comparison.cs383
1 files changed, 223 insertions, 160 deletions
diff --git a/src/mscorlib/src/System/String.Comparison.cs b/src/mscorlib/src/System/String.Comparison.cs
index 2ac1d78997..c2c3a8709a 100644
--- a/src/mscorlib/src/System/String.Comparison.cs
+++ b/src/mscorlib/src/System/String.Comparison.cs
@@ -24,16 +24,17 @@ namespace System
Contract.Requires(strB != null);
Contract.EndContractBlock();
int length = Math.Min(strA.Length, strB.Length);
-
+
fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
{
char* a = ap;
char* b = bp;
+ int charA = 0, charB = 0;
- while (length != 0)
+ while (length != 0)
{
- int charA = *a;
- int charB = *b;
+ charA = *a;
+ charB = *b;
Debug.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");
@@ -43,7 +44,7 @@ namespace System
//Return the (case-insensitive) difference between them.
if (charA != charB)
- return charA - charB;
+ goto ReturnCharAMinusCharB; // TODO: Workaround for https://github.com/dotnet/coreclr/issues/9692
// Next char
a++; b++;
@@ -51,6 +52,9 @@ namespace System
}
return strA.Length - strB.Length;
+
+ ReturnCharAMinusCharB:
+ return charA - charB;
}
}
@@ -61,14 +65,14 @@ namespace System
//This will not work in case-insensitive mode for any character greater than 0x80.
//We'll throw an ArgumentException.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- unsafe internal static extern int nativeCompareOrdinalIgnoreCaseWC(String strA, sbyte *strBBytes);
+ unsafe internal static extern int nativeCompareOrdinalIgnoreCaseWC(String strA, sbyte* strBBytes);
//
//
// NATIVE INSTANCE METHODS
//
//
-
+
//
// Search/Query methods
//
@@ -120,7 +124,7 @@ namespace System
// always zero terminated and that the terminating zero is not included
// in the length. For odd string sizes, the last compare will include
// the zero terminator.
- while (length > 0)
+ while (length > 0)
{
if (*(int*)a != *(int*)b) goto ReturnFalse;
length -= 2; a += 2; b += 2;
@@ -128,7 +132,49 @@ namespace System
return true;
- ReturnFalse:
+ ReturnFalse:
+ return false;
+ }
+ }
+
+ private unsafe static bool EqualsIgnoreCaseAsciiHelper(String strA, String strB)
+ {
+ Contract.Requires(strA != null);
+ Contract.Requires(strB != null);
+ Contract.Requires(strA.Length == strB.Length);
+ Contract.EndContractBlock();
+ int length = strA.Length;
+
+ fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+ while (length != 0)
+ {
+ int charA = *a;
+ int charB = *b;
+
+ Debug.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");
+
+ // Ordinal equals or lowercase equals if the result ends up in the a-z range
+ if (charA == charB ||
+ ((charA | 0x20) == (charB | 0x20) &&
+ (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
+ {
+ a++;
+ b++;
+ length--;
+ }
+ else
+ {
+ goto ReturnFalse;
+ }
+ }
+
+ return true;
+
+ ReturnFalse:
return false;
}
}
@@ -183,7 +229,7 @@ namespace System
// this compare can include the zero terminator. Bitwise OR avoids a branch.
return length == 0 | *a == *b;
- ReturnFalse:
+ ReturnFalse:
return false;
}
}
@@ -214,7 +260,7 @@ namespace System
// if the first two chars the same we can increment by 4 bytes,
// leaving us word-aligned on both 32-bit (12 bytes into the string)
// and 64-bit (16 bytes) platforms.
-
+
// For empty strings, the second char will be null due to padding.
// The start of the string (not including sync block pointer)
// is the method table pointer + string length, which takes up
@@ -222,7 +268,7 @@ namespace System
// terminator immediately follows, leaving us with an object
// 10/14 bytes in size. Since everything needs to be a multiple
// of 4/8, this will get padded and zeroed out.
-
+
// For one-char strings the second char will be the null terminator.
// NOTE: If in the future there is a way to read the second char
@@ -231,7 +277,7 @@ namespace System
// then do that and short-circuit before the fixed.
if (*(a + 1) != *(b + 1)) goto DiffOffset1;
-
+
// Since we know that the first two chars are the same,
// we can increment by 2 here and skip 4 bytes.
// This leaves us 8-byte aligned, which results
@@ -269,17 +315,17 @@ namespace System
{
if (*(int*)a != *(int*)b) goto DiffNextInt;
length -= 2;
- a += 2;
- b += 2;
+ a += 2;
+ b += 2;
}
// At this point, we have compared all the characters in at least one string.
// The longer string will be larger.
return strA.Length - strB.Length;
-
+
#if BIT64
- DiffOffset8: a += 4; b += 4;
- DiffOffset4: a += 4; b += 4;
+ DiffOffset8: a += 4; b += 4;
+ DiffOffset4: a += 4; b += 4;
#else // BIT64
// Use jumps instead of falling through, since
// otherwise going to DiffOffset8 will involve
@@ -289,8 +335,8 @@ namespace System
DiffOffset4: a += 2; b += 2;
DiffOffset2: a += 2; b += 2;
#endif // BIT64
-
- DiffOffset0:
+
+ DiffOffset0:
// If we reached here, we already see a difference in the unrolled loop above
#if BIT64
if (*(int*)a == *(int*)b)
@@ -299,7 +345,7 @@ namespace System
}
#endif // BIT64
- DiffNextInt:
+ DiffNextInt:
if (*a != *b) return *a - *b;
DiffOffset1:
@@ -307,7 +353,7 @@ namespace System
return *(a + 1) - *(b + 1);
}
}
-
+
// Provides a culture-correct string comparison. StrA is compared to StrB
// to determine whether it is lexicographically less, equal, or greater, and then returns
// either a negative integer, 0, or a positive integer; respectively.
@@ -317,7 +363,7 @@ namespace System
{
return Compare(strA, strB, StringComparison.CurrentCulture);
}
-
+
// Provides a culture-correct string comparison. strA is compared to strB
// to determine whether it is lexicographically less, equal, or greater, and then a
@@ -331,16 +377,16 @@ namespace System
return Compare(strA, strB, comparisonType);
}
-
+
// Provides a more flexible function for string comparision. See StringComparison
// for meaning of different comparisonType.
[Pure]
- public static int Compare(String strA, String strB, StringComparison comparisonType)
+ public static int Compare(String strA, String strB, StringComparison comparisonType)
{
// Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
if ((uint)(comparisonType - StringComparison.CurrentCulture) > (uint)(StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
{
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
Contract.EndContractBlock();
@@ -359,7 +405,8 @@ namespace System
return 1;
}
- switch (comparisonType) {
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
@@ -384,19 +431,15 @@ namespace System
case StringComparison.OrdinalIgnoreCase:
// If both strings are ASCII strings, we can take the fast path.
- if (strA.IsAscii() && strB.IsAscii()) {
+ if (strA.IsAscii() && strB.IsAscii())
+ {
return (CompareOrdinalIgnoreCaseHelper(strA, strB));
}
-#if FEATURE_COREFX_GLOBALIZATION
return CompareInfo.CompareOrdinalIgnoreCase(strA, 0, strA.Length, strB, 0, strB.Length);
-#else
- // Take the slow path.
- return TextInfo.CompareOrdinalIgnoreCase(strA, strB);
-#endif
default:
- throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
+ throw new NotSupportedException(SR.NotSupported_StringComparison);
}
}
@@ -406,7 +449,8 @@ namespace System
// negative integer, 0, or a positive integer is returned; respectively.
//
[Pure]
- public static int Compare(String strA, String strB, CultureInfo culture, CompareOptions options) {
+ public static int Compare(String strA, String strB, CultureInfo culture, CompareOptions options)
+ {
if (culture == null)
{
throw new ArgumentNullException(nameof(culture));
@@ -466,7 +510,7 @@ namespace System
int lengthA = length;
int lengthB = length;
-
+
if (strA != null)
{
lengthA = Math.Min(lengthA, strA.Length - indexA);
@@ -519,17 +563,19 @@ namespace System
{
lengthB = Math.Min(lengthB, strB.Length - indexB);
}
-
+
return culture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
}
[Pure]
- public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType) {
- if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType)
+ {
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
+ {
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
Contract.EndContractBlock();
-
+
if (strA == null || strB == null)
{
if (object.ReferenceEquals(strA, strB))
@@ -543,19 +589,19 @@ namespace System
if (length < 0)
{
- throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
}
if (indexA < 0 || indexB < 0)
{
string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB);
- throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
}
if (strA.Length - indexA < 0 || strB.Length - indexB < 0)
{
string paramName = strA.Length - indexA < 0 ? nameof(indexA) : nameof(indexB);
- throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
}
if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
@@ -566,7 +612,8 @@ namespace System
int lengthA = Math.Min(length, strA.Length - indexA);
int lengthB = Math.Min(length, strB.Length - indexB);
- switch (comparisonType) {
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
@@ -583,16 +630,11 @@ namespace System
return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
case StringComparison.OrdinalIgnoreCase:
-#if FEATURE_COREFX_GLOBALIZATION
return (CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB));
-#else
- return (TextInfo.CompareOrdinalIgnoreCaseEx(strA, indexA, strB, indexB, lengthA, lengthB));
-#endif
default:
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"));
+ throw new ArgumentException(SR.NotSupported_StringComparison);
}
-
}
// Compares strA and strB using an ordinal (code-point) comparison.
@@ -624,7 +666,7 @@ namespace System
return CompareOrdinalHelper(strA, strB);
}
-
+
// Compares strA and strB using an ordinal (code-point) comparison.
//
@@ -647,22 +689,22 @@ namespace System
if (length < 0)
{
- throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeCount);
}
if (indexA < 0 || indexB < 0)
{
string paramName = indexA < 0 ? nameof(indexA) : nameof(indexB);
- throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
}
-
+
int lengthA = Math.Min(length, strA.Length - indexA);
int lengthB = Math.Min(length, strB.Length - indexB);
if (lengthA < 0 || lengthB < 0)
{
string paramName = lengthA < 0 ? nameof(indexA) : nameof(indexB);
- throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_Index);
}
if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
@@ -689,12 +731,12 @@ namespace System
if (other == null)
{
- throw new ArgumentException(Environment.GetResourceString("Arg_MustBeString"));
+ throw new ArgumentException(SR.Arg_MustBeString);
}
return CompareTo(other); // will call the string-based overload
}
-
+
// Determines the sorting relation of StrB to the current instance.
//
[Pure]
@@ -709,30 +751,37 @@ namespace System
// and the default culture is used.
//
[Pure]
- public Boolean EndsWith(String value) {
+ public Boolean EndsWith(String value)
+ {
return EndsWith(value, StringComparison.CurrentCulture);
}
[Pure]
- public Boolean EndsWith(String value, StringComparison comparisonType) {
- if( (Object)value == null) {
- throw new ArgumentNullException(nameof(value));
+ public Boolean EndsWith(String value, StringComparison comparisonType)
+ {
+ if ((Object)value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
}
- if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
+ {
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
Contract.EndContractBlock();
- if( (Object)this == (Object)value) {
+ if ((Object)this == (Object)value)
+ {
return true;
}
- if( value.Length == 0) {
+ if (value.Length == 0)
+ {
return true;
}
-
- switch (comparisonType) {
+
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
@@ -743,30 +792,29 @@ namespace System
return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
case StringComparison.InvariantCultureIgnoreCase:
- return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
case StringComparison.Ordinal:
return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
case StringComparison.OrdinalIgnoreCase:
-#if FEATURE_COREFX_GLOBALIZATION
return this.Length < value.Length ? false : (CompareInfo.CompareOrdinalIgnoreCase(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
-#else
- return this.Length < value.Length ? false : (TextInfo.CompareOrdinalIgnoreCaseEx(this, this.Length - value.Length, value, 0, value.Length, value.Length) == 0);
-#endif
default:
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
- }
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
}
[Pure]
- public Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture) {
- if (null==value) {
+ public Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture)
+ {
+ if (null == value)
+ {
throw new ArgumentNullException(nameof(value));
}
Contract.EndContractBlock();
-
- if((object)this == (object)value) {
+
+ if ((object)this == (object)value)
+ {
return true;
}
@@ -780,21 +828,15 @@ namespace System
}
[Pure]
- internal bool EndsWith(char value) {
- int thisLen = this.Length;
- if (thisLen != 0) {
- if (this[thisLen - 1] == value)
- return true;
- }
- return false;
+ public bool EndsWith(char value)
+ {
+ int thisLen = Length;
+ return thisLen != 0 && this[thisLen - 1] == value;
}
// Determines whether two strings match.
public override bool Equals(Object obj)
{
- if (this == null) // this is necessary to guard against reverse-pinvokes and
- throw new NullReferenceException(); // other callers who do not use the callvirt instruction
-
if (object.ReferenceEquals(this, obj))
return true;
@@ -812,9 +854,6 @@ namespace System
[Pure]
public bool Equals(String value)
{
- if (this == null) // this is necessary to guard against reverse-pinvokes and
- throw new NullReferenceException(); // other callers who do not use the callvirt instruction
-
if (object.ReferenceEquals(this, value))
return true;
@@ -824,7 +863,7 @@ namespace System
// instead of calling string.op_Equality.
if (value == null)
return false;
-
+
if (this.Length != value.Length)
return false;
@@ -832,20 +871,24 @@ namespace System
}
[Pure]
- public bool Equals(String value, StringComparison comparisonType) {
+ public bool Equals(String value, StringComparison comparisonType)
+ {
if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
Contract.EndContractBlock();
- if ((Object)this == (Object)value) {
+ if ((Object)this == (Object)value)
+ {
return true;
}
- if ((Object)value == null) {
+ if ((Object)value == null)
+ {
return false;
}
- switch (comparisonType) {
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);
@@ -868,31 +911,30 @@ namespace System
return false;
// If both strings are ASCII strings, we can take the fast path.
- if (this.IsAscii() && value.IsAscii()) {
- return (CompareOrdinalIgnoreCaseHelper(this, value) == 0);
+ if (this.IsAscii() && value.IsAscii())
+ {
+ return EqualsIgnoreCaseAsciiHelper(this, value);
}
-#if FEATURE_COREFX_GLOBALIZATION
return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, this.Length, value, 0, value.Length) == 0);
-#else
- // Take the slow path.
- return (TextInfo.CompareOrdinalIgnoreCase(this, value) == 0);
-#endif
default:
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
// Determines whether two Strings match.
[Pure]
- public static bool Equals(String a, String b) {
- if ((Object)a==(Object)b) {
+ public static bool Equals(String a, String b)
+ {
+ if ((Object)a == (Object)b)
+ {
return true;
}
- if ((Object)a == null || (Object)b == null || a.Length != b.Length) {
+ if ((Object)a == null || (Object)b == null || a.Length != b.Length)
+ {
return false;
}
@@ -900,20 +942,24 @@ namespace System
}
[Pure]
- public static bool Equals(String a, String b, StringComparison comparisonType) {
+ public static bool Equals(String a, String b, StringComparison comparisonType)
+ {
if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
Contract.EndContractBlock();
- if ((Object)a==(Object)b) {
+ if ((Object)a == (Object)b)
+ {
return true;
}
-
- if ((Object)a==null || (Object)b==null) {
+
+ if ((Object)a == null || (Object)b == null)
+ {
return false;
}
- switch (comparisonType) {
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);
@@ -935,31 +981,31 @@ namespace System
case StringComparison.OrdinalIgnoreCase:
if (a.Length != b.Length)
return false;
- else {
+ else
+ {
// If both strings are ASCII strings, we can take the fast path.
- if (a.IsAscii() && b.IsAscii()) {
- return (CompareOrdinalIgnoreCaseHelper(a, b) == 0);
+ if (a.IsAscii() && b.IsAscii())
+ {
+ return EqualsIgnoreCaseAsciiHelper(a, b);
}
// Take the slow path.
-#if FEATURE_COREFX_GLOBALIZATION
return (CompareInfo.CompareOrdinalIgnoreCase(a, 0, a.Length, b, 0, b.Length) == 0);
-#else
- return (TextInfo.CompareOrdinalIgnoreCase(a, b) == 0);
-#endif
}
default:
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
- public static bool operator == (String a, String b) {
- return String.Equals(a, b);
+ public static bool operator ==(String a, String b)
+ {
+ return String.Equals(a, b);
}
- public static bool operator != (String a, String b) {
- return !String.Equals(a, b);
+ public static bool operator !=(String a, String b)
+ {
+ return !String.Equals(a, b);
}
#if FEATURE_RANDOMIZED_STRING_HASHING
@@ -968,7 +1014,8 @@ namespace System
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int InternalMarvin32HashString(string s, int strLen, long additionalEntropy);
- internal static bool UseRandomizedHashing() {
+ internal static bool UseRandomizedHashing()
+ {
return InternalUseRandomizedHashing();
}
@@ -997,11 +1044,14 @@ namespace System
// Use this if and only if you need the hashcode to not change across app domains (e.g. you have an app domain agile
// hash table).
- internal int GetLegacyNonRandomizedHashCode() {
- unsafe {
- fixed (char* src = &m_firstChar) {
+ internal int GetLegacyNonRandomizedHashCode()
+ {
+ unsafe
+ {
+ fixed (char* src = &m_firstChar)
+ {
Debug.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'");
- Debug.Assert( ((int)src)%4 == 0, "Managed string should start at 4 bytes boundary");
+ Debug.Assert(((int)src) % 4 == 0, "Managed string should start at 4 bytes boundary");
#if BIT64
int hash1 = 5381;
#else // !BIT64 (32)
@@ -1010,9 +1060,10 @@ namespace System
int hash2 = hash1;
#if BIT64
- int c;
- char *s = src;
- while ((c = s[0]) != 0) {
+ int c;
+ char* s = src;
+ while ((c = s[0]) != 0)
+ {
hash1 = ((hash1 << 5) + hash1) ^ c;
c = s[1];
if (c == 0)
@@ -1048,12 +1099,14 @@ namespace System
}
}
}
-
+
// Determines whether a specified string is a prefix of the current instance
//
[Pure]
- public Boolean StartsWith(String value) {
- if ((Object)value == null) {
+ public Boolean StartsWith(String value)
+ {
+ if ((Object)value == null)
+ {
throw new ArgumentNullException(nameof(value));
}
Contract.EndContractBlock();
@@ -1061,25 +1114,31 @@ namespace System
}
[Pure]
- public Boolean StartsWith(String value, StringComparison comparisonType) {
- if( (Object)value == null) {
- throw new ArgumentNullException(nameof(value));
+ public Boolean StartsWith(String value, StringComparison comparisonType)
+ {
+ if ((Object)value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
}
- if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
+ {
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
Contract.EndContractBlock();
- if( (Object)this == (Object)value) {
+ if ((Object)this == (Object)value)
+ {
return true;
}
- if( value.Length == 0) {
+ if (value.Length == 0)
+ {
return true;
}
- switch (comparisonType) {
+ switch (comparisonType)
+ {
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
@@ -1090,10 +1149,11 @@ namespace System
return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
case StringComparison.InvariantCultureIgnoreCase:
- return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
case StringComparison.Ordinal:
- if( this.Length < value.Length || m_firstChar != value.m_firstChar) {
+ if (this.Length < value.Length || m_firstChar != value.m_firstChar)
+ {
return false;
}
return (value.Length == 1) ?
@@ -1101,29 +1161,29 @@ namespace System
StartsWithOrdinalHelper(this, value);
case StringComparison.OrdinalIgnoreCase:
- if( this.Length < value.Length) {
+ if (this.Length < value.Length)
+ {
return false;
}
-
-#if FEATURE_COREFX_GLOBALIZATION
+
return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, value.Length, value, 0, value.Length) == 0);
-#else
- return (TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0);
-#endif
default:
- throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
- }
+ throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ }
}
[Pure]
- public Boolean StartsWith(String value, Boolean ignoreCase, CultureInfo culture) {
- if (null==value) {
+ public Boolean StartsWith(String value, Boolean ignoreCase, CultureInfo culture)
+ {
+ if (null == value)
+ {
throw new ArgumentNullException(nameof(value));
}
Contract.EndContractBlock();
- if((object)this == (object)value) {
+ if ((object)this == (object)value)
+ {
return true;
}
@@ -1135,5 +1195,8 @@ namespace System
return referenceCulture.CompareInfo.IsPrefix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
+
+ [Pure]
+ public bool StartsWith(char value) => Length != 0 && m_firstChar == value;
}
-} \ No newline at end of file
+}