diff options
Diffstat (limited to 'src/mscorlib/src/System/String.Searching.cs')
-rw-r--r-- | src/mscorlib/src/System/String.Searching.cs | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/String.Searching.cs b/src/mscorlib/src/System/String.Searching.cs new file mode 100644 index 0000000000..b972529694 --- /dev/null +++ b/src/mscorlib/src/System/String.Searching.cs @@ -0,0 +1,358 @@ +// 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.Diagnostics.Contracts; +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace System +{ + public partial class String + { + [Pure] + public bool Contains( string value ) { + return ( IndexOf(value, StringComparison.Ordinal) >=0 ); + } + + // Returns the index of the first occurrence of a specified character in the current instance. + // The search starts at startIndex and runs thorough the next count characters. + // + [Pure] + public int IndexOf(char value) { + return IndexOf(value, 0, this.Length); + } + + [Pure] + public int IndexOf(char value, int startIndex) { + return IndexOf(value, startIndex, this.Length - startIndex); + } + + [Pure] + [System.Security.SecuritySafeCritical] // auto-generated + public unsafe int IndexOf(char value, int startIndex, int count) { + if (startIndex < 0 || startIndex > Length) + throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + + if (count < 0 || count > Length - startIndex) + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + + fixed (char* pChars = &m_firstChar) + { + char* pCh = pChars + startIndex; + + while (count >= 4) + { + if (*pCh == value) goto ReturnIndex; + if (*(pCh + 1) == value) goto ReturnIndex1; + if (*(pCh + 2) == value) goto ReturnIndex2; + if (*(pCh + 3) == value) goto ReturnIndex3; + + count -= 4; + pCh += 4; + } + + while (count > 0) + { + if (*pCh == value) + goto ReturnIndex; + + count--; + pCh++; + } + + return -1; + + ReturnIndex3: pCh++; + ReturnIndex2: pCh++; + ReturnIndex1: pCh++; + ReturnIndex: + return (int)(pCh - pChars); + } + } + + // Returns the index of the first occurrence of any specified character in the current instance. + // The search starts at startIndex and runs to startIndex + count -1. + // + [Pure] + public int IndexOfAny(char [] anyOf) { + return IndexOfAny(anyOf,0, this.Length); + } + + [Pure] + public int IndexOfAny(char [] anyOf, int startIndex) { + return IndexOfAny(anyOf, startIndex, this.Length - startIndex); + } + + [Pure] + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern int IndexOfAny(char [] anyOf, int startIndex, int count); + + + // Determines the position within this string of the first occurrence of the specified + // string, according to the specified search criteria. The search begins at + // the first character of this string, it is case-sensitive and the current culture + // comparison is used. + // + [Pure] + public int IndexOf(String value) { + return IndexOf(value, StringComparison.CurrentCulture); + } + + // Determines the position within this string of the first occurrence of the specified + // string, according to the specified search criteria. The search begins at + // startIndex, it is case-sensitive and the current culture comparison is used. + // + [Pure] + public int IndexOf(String value, int startIndex) { + return IndexOf(value, startIndex, StringComparison.CurrentCulture); + } + + // Determines the position within this string of the first occurrence of the specified + // string, according to the specified search criteria. The search begins at + // startIndex, ends at endIndex and the current culture comparison is used. + // + [Pure] + public int IndexOf(String value, int startIndex, int count) { + if (startIndex < 0 || startIndex > this.Length) { + throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + } + + if (count < 0 || count > this.Length - startIndex) { + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + } + Contract.EndContractBlock(); + + return IndexOf(value, startIndex, count, StringComparison.CurrentCulture); + } + + [Pure] + public int IndexOf(String value, StringComparison comparisonType) { + return IndexOf(value, 0, this.Length, comparisonType); + } + + [Pure] + public int IndexOf(String value, int startIndex, StringComparison comparisonType) { + return IndexOf(value, startIndex, this.Length - startIndex, comparisonType); + } + + [Pure] + [System.Security.SecuritySafeCritical] + public int IndexOf(String value, int startIndex, int count, StringComparison comparisonType) { + // Validate inputs + if (value == null) + throw new ArgumentNullException("value"); + + if (startIndex < 0 || startIndex > this.Length) + throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + + if (count < 0 || startIndex > this.Length - count) + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + Contract.EndContractBlock(); + + 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); + + case StringComparison.InvariantCulture: + return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); + + case StringComparison.InvariantCultureIgnoreCase: + return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + + case StringComparison.Ordinal: + return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal); + + case StringComparison.OrdinalIgnoreCase: + if (value.IsAscii() && this.IsAscii()) + return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + else + return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); + + default: + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + } + } + + // Returns the index of the last occurrence of a specified character in the current instance. + // The search starts at startIndex and runs backwards to startIndex - count + 1. + // The character at position startIndex is included in the search. startIndex is the larger + // index within the string. + // + [Pure] + public int LastIndexOf(char value) { + return LastIndexOf(value, this.Length-1, this.Length); + } + + [Pure] + public int LastIndexOf(char value, int startIndex){ + return LastIndexOf(value,startIndex,startIndex + 1); + } + + [Pure] + [System.Security.SecuritySafeCritical] // auto-generated + public unsafe int LastIndexOf(char value, int startIndex, int count) { + if (Length == 0) + return -1; + + if (startIndex < 0 || startIndex >= Length) + throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + + if (count < 0 || count - 1 > startIndex) + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + + fixed (char* pChars = &m_firstChar) + { + char* pCh = pChars + startIndex; + + //We search [startIndex..EndIndex] + while (count >= 4) + { + if (*pCh == value) goto ReturnIndex; + if (*(pCh - 1) == value) goto ReturnIndex1; + if (*(pCh - 2) == value) goto ReturnIndex2; + if (*(pCh - 3) == value) goto ReturnIndex3; + + count -= 4; + pCh -= 4; + } + + while (count > 0) + { + if (*pCh == value) + goto ReturnIndex; + + count--; + pCh--; + } + + return -1; + + ReturnIndex3: pCh--; + ReturnIndex2: pCh--; + ReturnIndex1: pCh--; + ReturnIndex: + return (int)(pCh - pChars); + } + } + + // Returns the index of the last occurrence of any specified character in the current instance. + // The search starts at startIndex and runs backwards to startIndex - count + 1. + // The character at position startIndex is included in the search. startIndex is the larger + // index within the string. + // + + //ForceInline ... Jit can't recognize String.get_Length to determine that this is "fluff" + [Pure] + public int LastIndexOfAny(char [] anyOf) { + return LastIndexOfAny(anyOf,this.Length-1,this.Length); + } + + [Pure] + public int LastIndexOfAny(char [] anyOf, int startIndex) { + return LastIndexOfAny(anyOf,startIndex,startIndex + 1); + } + + [Pure] + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public extern int LastIndexOfAny(char [] anyOf, int startIndex, int count); + + + // Returns the index of the last occurrence of any character in value in the current instance. + // The search starts at startIndex and runs backwards to startIndex - count + 1. + // The character at position startIndex is included in the search. startIndex is the larger + // index within the string. + // + [Pure] + public int LastIndexOf(String value) { + return LastIndexOf(value, this.Length-1,this.Length, StringComparison.CurrentCulture); + } + + [Pure] + public int LastIndexOf(String value, int startIndex) { + return LastIndexOf(value, startIndex, startIndex + 1, StringComparison.CurrentCulture); + } + + [Pure] + public int LastIndexOf(String value, int startIndex, int count) { + if (count<0) { + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + } + Contract.EndContractBlock(); + + return LastIndexOf(value, startIndex, count, StringComparison.CurrentCulture); + } + + [Pure] + public int LastIndexOf(String value, StringComparison comparisonType) { + return LastIndexOf(value, this.Length-1, this.Length, comparisonType); + } + + [Pure] + public int LastIndexOf(String value, int startIndex, StringComparison comparisonType) { + return LastIndexOf(value, startIndex, startIndex + 1, comparisonType); + } + + [Pure] + [System.Security.SecuritySafeCritical] + public int LastIndexOf(String value, int startIndex, int count, StringComparison comparisonType) { + if (value == null) + throw new ArgumentNullException("value"); + Contract.EndContractBlock(); + + // Special case for 0 length input strings + if (this.Length == 0 && (startIndex == -1 || startIndex == 0)) + return (value.Length == 0) ? 0 : -1; + + // Now after handling empty strings, make sure we're not out of range + if (startIndex < 0 || startIndex > this.Length) + throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); + + // Make sure that we allow startIndex == this.Length + if (startIndex == this.Length) + { + startIndex--; + if (count > 0) + count--; + + // If we are looking for nothing, just return 0 + if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0) + return startIndex; + } + + // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. + if (count < 0 || startIndex - count + 1 < 0) + throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); + + + 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); + + case StringComparison.InvariantCulture: + return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None); + + case StringComparison.InvariantCultureIgnoreCase: + return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + case StringComparison.Ordinal: + return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.Ordinal); + + case StringComparison.OrdinalIgnoreCase: + if (value.IsAscii() && this.IsAscii()) + return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); + else + return TextInfo.LastIndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); + default: + throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); + } + } + } +} |