/mcs/class/corlib/System/String.cs
C# | 3169 lines | 2543 code | 502 blank | 124 comment | 986 complexity | f1d195da3f6195b94314a15acac66761 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- //
- // System.String.cs
- //
- // Authors:
- // Patrik Torstensson
- // Jeffrey Stedfast (fejj@ximian.com)
- // Dan Lewis (dihlewis@yahoo.co.uk)
- // Sebastien Pouliot <sebastien@ximian.com>
- // Marek Safar (marek.safar@seznam.cz)
- // Andreas Nahr (Classdevelopment@A-SoftTech.com)
- //
- // (C) 2001 Ximian, Inc. http://www.ximian.com
- // Copyright (C) 2004-2005 Novell (http://www.novell.com)
- // Copyright (c) 2012 Xamarin, Inc (http://www.xamarin.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- //
- //
- // This class contains all implementation for culture-insensitive methods.
- // Culture-sensitive methods are implemented in the System.Globalization or
- // Mono.Globalization namespace.
- //
- // Ensure that argument checks on methods don't overflow
- //
- using System.Text;
- using System.Collections;
- using System.Globalization;
- using System.Runtime.CompilerServices;
- using System.Collections.Generic;
- using System.Runtime.ConstrainedExecution;
- using System.Runtime.InteropServices;
- using Mono.Globalization.Unicode;
- namespace System
- {
- [Serializable]
- [ComVisible (true)]
- [StructLayout (LayoutKind.Sequential)]
- public sealed class String : IConvertible, ICloneable, IEnumerable, IComparable, IComparable<String>, IEquatable <String>, IEnumerable<char>
- {
- [NonSerialized] private int length;
- [NonSerialized] private char start_char;
- public static readonly String Empty = "";
- internal static readonly int LOS_limit = GetLOSLimit ();
- public static unsafe bool Equals (string a, string b)
- {
- if ((a as object) == (b as object))
- return true;
- if (a == null || b == null)
- return false;
- int len = a.length;
- if (len != b.length)
- return false;
- fixed (char* s1 = &a.start_char, s2 = &b.start_char) {
- char* s1_ptr = s1;
- char* s2_ptr = s2;
- while (len >= 8) {
- if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0] ||
- ((int*)s1_ptr)[1] != ((int*)s2_ptr)[1] ||
- ((int*)s1_ptr)[2] != ((int*)s2_ptr)[2] ||
- ((int*)s1_ptr)[3] != ((int*)s2_ptr)[3])
- return false;
- s1_ptr += 8;
- s2_ptr += 8;
- len -= 8;
- }
- if (len >= 4) {
- if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0] ||
- ((int*)s1_ptr)[1] != ((int*)s2_ptr)[1])
- return false;
- s1_ptr += 4;
- s2_ptr += 4;
- len -= 4;
- }
- if (len > 1) {
- if (((int*)s1_ptr)[0] != ((int*)s2_ptr)[0])
- return false;
- s1_ptr += 2;
- s2_ptr += 2;
- len -= 2;
- }
- return len == 0 || *s1_ptr == *s2_ptr;
- }
- }
- public static bool operator == (String a, String b)
- {
- return Equals (a, b);
- }
- public static bool operator != (String a, String b)
- {
- return !Equals (a, b);
- }
- [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
- public override bool Equals (Object obj)
- {
- return Equals (this, obj as String);
- }
- [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
- public bool Equals (String value)
- {
- return Equals (this, value);
- }
- [IndexerName ("Chars")]
- public unsafe char this [int index] {
- get {
- if (index < 0 || index >= length)
- throw new IndexOutOfRangeException ();
- fixed (char* c = &start_char)
- return c[index];
- }
- }
- public Object Clone ()
- {
- return this;
- }
- public TypeCode GetTypeCode ()
- {
- return TypeCode.String;
- }
- public unsafe void CopyTo (int sourceIndex, char[] destination, int destinationIndex, int count)
- {
- if (destination == null)
- throw new ArgumentNullException ("destination");
- if (sourceIndex < 0)
- throw new ArgumentOutOfRangeException ("sourceIndex", "Cannot be negative");
- if (destinationIndex < 0)
- throw new ArgumentOutOfRangeException ("destinationIndex", "Cannot be negative.");
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count", "Cannot be negative.");
- if (sourceIndex > Length - count)
- throw new ArgumentOutOfRangeException ("sourceIndex", "sourceIndex + count > Length");
- if (destinationIndex > destination.Length - count)
- throw new ArgumentOutOfRangeException ("destinationIndex", "destinationIndex + count > destination.Length");
- fixed (char* dest = destination, src = this)
- CharCopy (dest + destinationIndex, src + sourceIndex, count);
- }
- public char[] ToCharArray ()
- {
- return ToCharArray (0, length);
- }
- public unsafe char[] ToCharArray (int startIndex, int length)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException ("startIndex", "< 0");
- if (length < 0)
- throw new ArgumentOutOfRangeException ("length", "< 0");
- if (startIndex > this.length - length)
- throw new ArgumentOutOfRangeException ("startIndex", "Must be greater than the length of the string.");
- char[] tmp = new char [length];
- fixed (char* dest = tmp, src = this)
- CharCopy (dest, src + startIndex, length);
- return tmp;
- }
- public String [] Split (params char [] separator)
- {
- return Split (separator, int.MaxValue, 0);
- }
- public String[] Split (char[] separator, int count)
- {
- return Split (separator, count, 0);
- }
- [ComVisible (false)]
- public String[] Split (char[] separator, StringSplitOptions options)
- {
- return Split (separator, Int32.MaxValue, options);
- }
- [ComVisible (false)]
- public String[] Split (char[] separator, int count, StringSplitOptions options)
- {
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count", "Count cannot be less than zero.");
- if ((options != StringSplitOptions.None) && (options != StringSplitOptions.RemoveEmptyEntries))
- throw new ArgumentException ("Illegal enum value: " + options + ".");
- if (Length == 0 && (options & StringSplitOptions.RemoveEmptyEntries) != 0)
- return EmptyArray<string>.Value;
- if (count <= 1) {
- return count == 0 ?
- EmptyArray<string>.Value :
- new String[1] { this };
- }
- return SplitByCharacters (separator, count, options != 0);
- }
- [ComVisible (false)]
- public String[] Split (string[] separator, StringSplitOptions options)
- {
- return Split (separator, Int32.MaxValue, options);
- }
- [ComVisible (false)]
- public String[] Split (string[] separator, int count, StringSplitOptions options)
- {
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count", "Count cannot be less than zero.");
- if ((options != StringSplitOptions.None) && (options != StringSplitOptions.RemoveEmptyEntries))
- throw new ArgumentException ("Illegal enum value: " + options + ".");
- if (count <= 1) {
- return count == 0 ?
- EmptyArray<string>.Value :
- new String[1] { this };
- }
- bool removeEmpty = (options & StringSplitOptions.RemoveEmptyEntries) != 0;
- if (separator == null || separator.Length == 0)
- return SplitByCharacters (null, count, removeEmpty);
- if (Length == 0 && removeEmpty)
- return EmptyArray<string>.Value;
- List<String> arr = new List<String> ();
- int pos = 0;
- int matchCount = 0;
- while (pos < this.Length) {
- int matchIndex = -1;
- int matchPos = Int32.MaxValue;
- // Find the first position where any of the separators matches
- for (int i = 0; i < separator.Length; ++i) {
- string sep = separator [i];
- if (sep == null || sep.Length == 0)
- continue;
- int match = IndexOfOrdinalUnchecked (sep, pos, length - pos);
- if (match >= 0 && match < matchPos) {
- matchIndex = i;
- matchPos = match;
- }
- }
- if (matchIndex == -1)
- break;
- if (!(matchPos == pos && removeEmpty)) {
- if (arr.Count == count - 1)
- break;
- arr.Add (this.Substring (pos, matchPos - pos));
- }
- pos = matchPos + separator [matchIndex].Length;
- matchCount ++;
- }
- if (matchCount == 0)
- return new String [] { this };
- // string contained only separators
- if (removeEmpty && matchCount != 0 && pos == this.Length && arr.Count == 0)
- return EmptyArray<string>.Value;
- if (!(removeEmpty && pos == this.Length))
- arr.Add (this.Substring (pos));
- return arr.ToArray ();
- }
- // .NET 2.0 compatibility only
- #if !NET_4_0 && !MOBILE
- static readonly char[] WhiteChars = {
- (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD,
- (char) 0x85, (char) 0x1680, (char) 0x2028, (char) 0x2029,
- (char) 0x20, (char) 0xA0, (char) 0x2000, (char) 0x2001, (char) 0x2002, (char) 0x2003, (char) 0x2004,
- (char) 0x2005, (char) 0x2006, (char) 0x2007, (char) 0x2008, (char) 0x2009, (char) 0x200A, (char) 0x200B,
- (char) 0x3000, (char) 0xFEFF
- };
- #endif
- unsafe string[] SplitByCharacters (char[] sep, int count, bool removeEmpty)
- {
- #if !NET_4_0 && !MOBILE
- if (sep == null || sep.Length == 0)
- sep = WhiteChars;
- #endif
- int[] split_points = null;
- int total_points = 0;
- --count;
- if (sep == null || sep.Length == 0) {
- fixed (char* src = this) {
- char* src_ptr = src;
- int len = Length;
- while (len > 0) {
- if (char.IsWhiteSpace (*src_ptr++)) {
- if (split_points == null) {
- split_points = new int[8];
- } else if (split_points.Length == total_points) {
- Array.Resize (ref split_points, split_points.Length * 2);
- }
- split_points[total_points++] = Length - len;
- if (total_points == count && !removeEmpty)
- break;
- }
- --len;
- }
- }
- } else {
- fixed (char* src = this) {
- fixed (char* sep_src = sep) {
- char* src_ptr = src;
- char* sep_ptr_end = sep_src + sep.Length;
- int len = Length;
- while (len > 0) {
- char* sep_ptr = sep_src;
- do {
- if (*sep_ptr++ == *src_ptr) {
- if (split_points == null) {
- split_points = new int[8];
- } else if (split_points.Length == total_points) {
- Array.Resize (ref split_points, split_points.Length * 2);
- }
- split_points[total_points++] = Length - len;
- if (total_points == count && !removeEmpty)
- len = 0;
- break;
- }
- } while (sep_ptr != sep_ptr_end);
- ++src_ptr;
- --len;
- }
- }
- }
- }
- if (total_points == 0)
- return new string[] { this };
- var res = new string[Math.Min (total_points, count) + 1];
- int prev_index = 0;
- int i = 0;
- if (!removeEmpty) {
- for (; i < total_points; ++i) {
- var start = split_points[i];
- res[i] = SubstringUnchecked (prev_index, start - prev_index);
- prev_index = start + 1;
- }
- res[i] = SubstringUnchecked (prev_index, Length - prev_index);
- } else {
- int used = 0;
- int length;
- for (; i < total_points; ++i) {
- var start = split_points[i];
- length = start - prev_index;
- if (length != 0) {
- if (used == count)
- break;
- res[used++] = SubstringUnchecked (prev_index, length);
- }
- prev_index = start + 1;
- }
- length = Length - prev_index;
- if (length != 0)
- res[used++] = SubstringUnchecked (prev_index, length);
- if (used != res.Length)
- Array.Resize (ref res, used);
- }
- return res;
- }
- public String Substring (int startIndex)
- {
- if (startIndex == 0)
- return this;
- if (startIndex < 0 || startIndex > this.length)
- throw new ArgumentOutOfRangeException ("startIndex");
- return SubstringUnchecked (startIndex, this.length - startIndex);
- }
- public String Substring (int startIndex, int length)
- {
- if (length < 0)
- throw new ArgumentOutOfRangeException ("length", "Cannot be negative.");
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException ("startIndex", "Cannot be negative.");
- if (startIndex > this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "Cannot exceed length of string.");
- if (startIndex > this.length - length)
- throw new ArgumentOutOfRangeException ("length", "startIndex + length cannot exceed length of string.");
- if (startIndex == 0 && length == this.length)
- return this;
- return SubstringUnchecked (startIndex, length);
- }
- // This method is used by StringBuilder.ToString() and is expected to
- // always create a new string object (or return String.Empty).
- internal unsafe String SubstringUnchecked (int startIndex, int length)
- {
- if (length == 0)
- return Empty;
- string tmp = InternalAllocateStr (length);
- fixed (char* dest = tmp, src = this) {
- CharCopy (dest, src + startIndex, length);
- }
- return tmp;
- }
- public String Trim ()
- {
- if (length == 0)
- return Empty;
- int start = FindNotWhiteSpace (0, length, 1);
- if (start == length)
- return Empty;
- int end = FindNotWhiteSpace (length - 1, start, -1);
- int newLength = end - start + 1;
- if (newLength == length)
- return this;
- return SubstringUnchecked (start, newLength);
- }
- public String Trim (params char[] trimChars)
- {
- if (trimChars == null || trimChars.Length == 0)
- return Trim ();
- if (length == 0)
- return Empty;
- int start = FindNotInTable (0, length, 1, trimChars);
- if (start == length)
- return Empty;
- int end = FindNotInTable (length - 1, start, -1, trimChars);
- int newLength = end - start + 1;
- if (newLength == length)
- return this;
- return SubstringUnchecked (start, newLength);
- }
- public String TrimStart (params char[] trimChars)
- {
- if (length == 0)
- return Empty;
- int start;
- if (trimChars == null || trimChars.Length == 0)
- start = FindNotWhiteSpace (0, length, 1);
- else
- start = FindNotInTable (0, length, 1, trimChars);
- if (start == 0)
- return this;
- return SubstringUnchecked (start, length - start);
- }
- public String TrimEnd (params char[] trimChars)
- {
- if (length == 0)
- return Empty;
- int end;
- if (trimChars == null || trimChars.Length == 0)
- end = FindNotWhiteSpace (length - 1, -1, -1);
- else
- end = FindNotInTable (length - 1, -1, -1, trimChars);
- end++;
- if (end == length)
- return this;
- return SubstringUnchecked (0, end);
- }
- unsafe int FindNotWhiteSpace (int pos, int target, int change)
- {
- #if NET_4_0
- fixed (char* src = this) {
- while (pos != target) {
- if (!char.IsWhiteSpace (src[pos]))
- return pos;
- pos += change;
- }
- }
- #else
- while (pos != target) {
- char c = this[pos];
- if (c < 0x85) {
- if (c != 0x20) {
- if (c < 0x9 || c > 0xD)
- return pos;
- }
- }
- else {
- if (c != 0xA0 && c != 0xFEFF && c != 0x3000) {
- if (c != 0x85 && c != 0x1680 && c != 0x2028 && c != 0x2029)
- if (c < 0x2000 || c > 0x200B)
- return pos;
- }
- }
- pos += change;
- }
- #endif
- return pos;
- }
- private unsafe int FindNotInTable (int pos, int target, int change, char[] table)
- {
- fixed (char* tablePtr = table, thisPtr = this) {
- while (pos != target) {
- char c = thisPtr[pos];
- int x = 0;
- while (x < table.Length) {
- if (c == tablePtr[x])
- break;
- x++;
- }
- if (x == table.Length)
- return pos;
- pos += change;
- }
- }
- return pos;
- }
- public static int Compare (String strA, String strB)
- {
- return CultureInfo.CurrentCulture.CompareInfo.Compare (strA, strB, CompareOptions.None);
- }
- public static int Compare (String strA, String strB, bool ignoreCase)
- {
- return CultureInfo.CurrentCulture.CompareInfo.Compare (strA, strB, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
- }
- public static int Compare (String strA, String strB, bool ignoreCase, CultureInfo culture)
- {
- if (culture == null)
- throw new ArgumentNullException ("culture");
- return culture.CompareInfo.Compare (strA, strB, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
- }
- public static int Compare (String strA, int indexA, String strB, int indexB, int length)
- {
- return Compare (strA, indexA, strB, indexB, length, false, CultureInfo.CurrentCulture);
- }
- public static int Compare (String strA, int indexA, String strB, int indexB, int length, bool ignoreCase)
- {
- return Compare (strA, indexA, strB, indexB, length, ignoreCase, CultureInfo.CurrentCulture);
- }
-
- public static int Compare (String strA, int indexA, String strB, int indexB, int length, bool ignoreCase, CultureInfo culture)
- {
- if (culture == null)
- throw new ArgumentNullException ("culture");
- if ((indexA > strA.Length) || (indexB > strB.Length) || (indexA < 0) || (indexB < 0) || (length < 0))
- throw new ArgumentOutOfRangeException ();
- if (length == 0)
- return 0;
-
- if (strA == null) {
- if (strB == null) {
- return 0;
- } else {
- return -1;
- }
- }
- else if (strB == null) {
- return 1;
- }
- CompareOptions compopts;
- if (ignoreCase)
- compopts = CompareOptions.IgnoreCase;
- else
- compopts = CompareOptions.None;
- // Need to cap the requested length to the
- // length of the string, because
- // CompareInfo.Compare will insist that length
- // <= (string.Length - offset)
- int len1 = length;
- int len2 = length;
-
- if (length > (strA.Length - indexA)) {
- len1 = strA.Length - indexA;
- }
- if (length > (strB.Length - indexB)) {
- len2 = strB.Length - indexB;
- }
- // ENHANCE: Might call internal_compare_switch directly instead of doing all checks twice
- return culture.CompareInfo.Compare (strA, indexA, len1, strB, indexB, len2, compopts);
- }
- public static int Compare (string strA, string strB, StringComparison comparisonType)
- {
- switch (comparisonType) {
- case StringComparison.CurrentCulture:
- return Compare (strA, strB, false, CultureInfo.CurrentCulture);
- case StringComparison.CurrentCultureIgnoreCase:
- return Compare (strA, strB, true, CultureInfo.CurrentCulture);
- case StringComparison.InvariantCulture:
- return Compare (strA, strB, false, CultureInfo.InvariantCulture);
- case StringComparison.InvariantCultureIgnoreCase:
- return Compare (strA, strB, true, CultureInfo.InvariantCulture);
- case StringComparison.Ordinal:
- return CompareOrdinalUnchecked (strA, 0, Int32.MaxValue, strB, 0, Int32.MaxValue);
- case StringComparison.OrdinalIgnoreCase:
- return CompareOrdinalCaseInsensitiveUnchecked (strA, 0, Int32.MaxValue, strB, 0, Int32.MaxValue);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- throw new ArgumentException (msg, "comparisonType");
- }
- }
- public static int Compare (string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType)
- {
- switch (comparisonType) {
- case StringComparison.CurrentCulture:
- return Compare (strA, indexA, strB, indexB, length, false, CultureInfo.CurrentCulture);
- case StringComparison.CurrentCultureIgnoreCase:
- return Compare (strA, indexA, strB, indexB, length, true, CultureInfo.CurrentCulture);
- case StringComparison.InvariantCulture:
- return Compare (strA, indexA, strB, indexB, length, false, CultureInfo.InvariantCulture);
- case StringComparison.InvariantCultureIgnoreCase:
- return Compare (strA, indexA, strB, indexB, length, true, CultureInfo.InvariantCulture);
- case StringComparison.Ordinal:
- return CompareOrdinal (strA, indexA, strB, indexB, length);
- case StringComparison.OrdinalIgnoreCase:
- return CompareOrdinalCaseInsensitive (strA, indexA, strB, indexB, length);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- throw new ArgumentException (msg, "comparisonType");
- }
- }
- public static bool Equals (string a, string b, StringComparison comparisonType)
- {
- return Compare (a, b, comparisonType) == 0;
- }
- public bool Equals (string value, StringComparison comparisonType)
- {
- return Compare (value, this, comparisonType) == 0;
- }
- public static int Compare (string strA, string strB, CultureInfo culture, CompareOptions options)
- {
- if (culture == null)
- throw new ArgumentNullException ("culture");
- return culture.CompareInfo.Compare (strA, strB, options);
- }
- public static int Compare (string strA, int indexA, string strB, int indexB, int length, CultureInfo culture, CompareOptions options)
- {
- if (culture == null)
- throw new ArgumentNullException ("culture");
- int len1 = length;
- int len2 = length;
-
- if (length > (strA.Length - indexA))
- len1 = strA.Length - indexA;
- if (length > (strB.Length - indexB))
- len2 = strB.Length - indexB;
- return culture.CompareInfo.Compare (strA, indexA, len1, strB, indexB, len2, options);
- }
- public int CompareTo (Object value)
- {
- if (value == null)
- return 1;
- if (!(value is String))
- throw new ArgumentException ();
- return String.Compare (this, (String) value);
- }
- public int CompareTo (String strB)
- {
- if (strB == null)
- return 1;
- return Compare (this, strB);
- }
- public static int CompareOrdinal (String strA, String strB)
- {
- return CompareOrdinalUnchecked (strA, 0, Int32.MaxValue, strB, 0, Int32.MaxValue);
- }
- public static int CompareOrdinal (String strA, int indexA, String strB, int indexB, int length)
- {
- if (strA != null && strB != null)
- {
- if (indexA > strA.Length || indexA < 0)
- throw new ArgumentOutOfRangeException ("indexA");
- if (indexB > strB.Length || indexB < 0)
- throw new ArgumentOutOfRangeException ("indexB");
- if (length < 0)
- throw new ArgumentOutOfRangeException ("length");
- }
- return CompareOrdinalUnchecked (strA, indexA, length, strB, indexB, length);
- }
- internal static int CompareOrdinalCaseInsensitive (String strA, int indexA, String strB, int indexB, int length)
- {
- if (strA != null && strB != null)
- {
- if (indexA > strA.Length || indexA < 0)
- throw new ArgumentOutOfRangeException ("indexA");
- if (indexB > strB.Length || indexB < 0)
- throw new ArgumentOutOfRangeException ("indexB");
- if (length < 0)
- throw new ArgumentOutOfRangeException ("length");
- }
- return CompareOrdinalCaseInsensitiveUnchecked (strA, indexA, length, strB, indexB, length);
- }
- internal static unsafe int CompareOrdinalUnchecked (String strA, int indexA, int lenA, String strB, int indexB, int lenB)
- {
- if (strA == null) {
- return strB == null ? 0 : -1;
- }
- if (strB == null) {
- return 1;
- }
- int lengthA = Math.Min (lenA, strA.Length - indexA);
- int lengthB = Math.Min (lenB, strB.Length - indexB);
- if (lengthA == lengthB && indexA == indexB && Object.ReferenceEquals (strA, strB))
- return 0;
- fixed (char* aptr = strA, bptr = strB) {
- char* ap = aptr + indexA;
- char* end = ap + Math.Min (lengthA, lengthB);
- char* bp = bptr + indexB;
- while (ap < end) {
- if (*ap != *bp)
- return *ap - *bp;
- ap++;
- bp++;
- }
- return lengthA - lengthB;
- }
- }
- //
- // Fastest method for internal case insensitive comparison
- //
- internal static int CompareOrdinalCaseInsensitiveUnchecked (string strA, string strB)
- {
- return CompareOrdinalCaseInsensitiveUnchecked (strA, 0, int.MaxValue, strB, 0, int.MaxValue);
- }
- internal static unsafe int CompareOrdinalCaseInsensitiveUnchecked (String strA, int indexA, int lenA, String strB, int indexB, int lenB)
- {
- // Same as above, but checks versus uppercase characters
- if (strA == null) {
- return strB == null ? 0 : -1;
- }
- if (strB == null) {
- return 1;
- }
- int lengthA = Math.Min (lenA, strA.Length - indexA);
- int lengthB = Math.Min (lenB, strB.Length - indexB);
- if (lengthA == lengthB && Object.ReferenceEquals (strA, strB))
- return 0;
- fixed (char* aptr = strA, bptr = strB) {
- char* ap = aptr + indexA;
- char* end = ap + Math.Min (lengthA, lengthB);
- char* bp = bptr + indexB;
- while (ap < end) {
- if (*ap != *bp) {
- char c1 = Char.ToUpperInvariant (*ap);
- char c2 = Char.ToUpperInvariant (*bp);
- if (c1 != c2)
- return c1 - c2;
- }
- ap++;
- bp++;
- }
- return lengthA - lengthB;
- }
- }
- public bool EndsWith (String value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- return CultureInfo.CurrentCulture.CompareInfo.IsSuffix (this, value, CompareOptions.None);
- }
- public bool EndsWith (String value, bool ignoreCase, CultureInfo culture)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (culture == null)
- culture = CultureInfo.CurrentCulture;
- return culture.CompareInfo.IsSuffix (this, value,
- ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
- }
- // Following methods are culture-insensitive
- public int IndexOfAny (char [] anyOf)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (this.length == 0)
- return -1;
- return IndexOfAnyUnchecked (anyOf, 0, this.length);
- }
- public int IndexOfAny (char [] anyOf, int startIndex)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (startIndex < 0 || startIndex > this.length)
- throw new ArgumentOutOfRangeException ();
- return IndexOfAnyUnchecked (anyOf, startIndex, this.length - startIndex);
- }
- public int IndexOfAny (char [] anyOf, int startIndex, int count)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (startIndex < 0 || startIndex > this.length)
- throw new ArgumentOutOfRangeException ();
- if (count < 0 || startIndex > this.length - count)
- throw new ArgumentOutOfRangeException ("count", "Count cannot be negative, and startIndex + count must be less than length of the string.");
- return IndexOfAnyUnchecked (anyOf, startIndex, count);
- }
- private unsafe int IndexOfAnyUnchecked (char[] anyOf, int startIndex, int count)
- {
- if (anyOf.Length == 0)
- return -1;
- if (anyOf.Length == 1)
- return IndexOfUnchecked (anyOf[0], startIndex, count);
- fixed (char* any = anyOf) {
- int highest = *any;
- int lowest = *any;
- char* end_any_ptr = any + anyOf.Length;
- char* any_ptr = any;
- while (++any_ptr != end_any_ptr) {
- if (*any_ptr > highest) {
- highest = *any_ptr;
- continue;
- }
- if (*any_ptr < lowest)
- lowest = *any_ptr;
- }
- fixed (char* start = &start_char) {
- char* ptr = start + startIndex;
- char* end_ptr = ptr + count;
- while (ptr != end_ptr) {
- if (*ptr > highest || *ptr < lowest) {
- ptr++;
- continue;
- }
- if (*ptr == *any)
- return (int)(ptr - start);
- any_ptr = any;
- while (++any_ptr != end_any_ptr) {
- if (*ptr == *any_ptr)
- return (int)(ptr - start);
- }
- ptr++;
- }
- }
- }
- return -1;
- }
- public int IndexOf (string value, StringComparison comparisonType)
- {
- return IndexOf (value, 0, this.Length, comparisonType);
- }
- public int IndexOf (string value, int startIndex, StringComparison comparisonType)
- {
- return IndexOf (value, startIndex, this.Length - startIndex, comparisonType);
- }
- public int IndexOf (string value, int startIndex, int count, StringComparison comparisonType)
- {
- 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 IndexOfOrdinal (value, startIndex, count, CompareOptions.Ordinal);
- case StringComparison.OrdinalIgnoreCase:
- return IndexOfOrdinal (value, startIndex, count, CompareOptions.OrdinalIgnoreCase);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- throw new ArgumentException (msg, "comparisonType");
- }
- }
- internal int IndexOfOrdinal (string value, int startIndex, int count, CompareOptions options)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException ("startIndex");
- if (count < 0 || (this.length - startIndex) < count)
- throw new ArgumentOutOfRangeException ("count");
- if (options == CompareOptions.Ordinal)
- return IndexOfOrdinalUnchecked (value, startIndex, count);
- return IndexOfOrdinalIgnoreCaseUnchecked (value, startIndex, count);
- }
- internal unsafe int IndexOfOrdinalUnchecked (string value)
- {
- return IndexOfOrdinalUnchecked (value, 0, length);
- }
- internal unsafe int IndexOfOrdinalUnchecked (string value, int startIndex, int count)
- {
- int valueLen = value.Length;
- if (count < valueLen)
- return -1;
- if (valueLen <= 1) {
- if (valueLen == 1)
- return IndexOfUnchecked (value[0], startIndex, count);
- return startIndex;
- }
- fixed (char* thisptr = this, valueptr = value) {
- char* ap = thisptr + startIndex;
- char* thisEnd = ap + count - valueLen + 1;
- while (ap != thisEnd) {
- if (*ap == *valueptr) {
- for (int i = 1; i < valueLen; i++) {
- if (ap[i] != valueptr[i])
- goto NextVal;
- }
- return (int)(ap - thisptr);
- }
- NextVal:
- ap++;
- }
- }
- return -1;
- }
- internal unsafe int IndexOfOrdinalIgnoreCaseUnchecked (string value, int startIndex, int count)
- {
- int valueLen = value.Length;
- if (count < valueLen)
- return -1;
- if (valueLen == 0)
- return startIndex;
- fixed (char* thisptr = this, valueptr = value) {
- char* ap = thisptr + startIndex;
- char* thisEnd = ap + count - valueLen + 1;
- while (ap != thisEnd) {
- for (int i = 0; i < valueLen; i++) {
- if (Char.ToUpperInvariant (ap[i]) != Char.ToUpperInvariant (valueptr[i]))
- goto NextVal;
- }
- return (int)(ap - thisptr);
- NextVal:
- ap++;
- }
- }
- return -1;
- }
- public int LastIndexOf (string value, StringComparison comparisonType)
- {
- if (this.Length == 0)
- return value.Length == 0 ? 0 : -1;
- else
- return LastIndexOf (value, this.Length - 1, this.Length, comparisonType);
- }
- public int LastIndexOf (string value, int startIndex, StringComparison comparisonType)
- {
- return LastIndexOf (value, startIndex, startIndex + 1, comparisonType);
- }
- public int LastIndexOf (string value, int startIndex, int count, StringComparison comparisonType)
- {
- 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 LastIndexOfOrdinal (value, startIndex, count, CompareOptions.Ordinal);
- case StringComparison.OrdinalIgnoreCase:
- return LastIndexOfOrdinal (value, startIndex, count, CompareOptions.OrdinalIgnoreCase);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- throw new ArgumentException (msg, "comparisonType");
- }
- }
- internal int LastIndexOfOrdinal (string value, int startIndex, int count, CompareOptions options)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (this.Length == 0)
- return value.Length == 0 ? 0 : -1;
- if (value.Length == 0)
- return Math.Min (this.Length - 1, startIndex);
- if (startIndex < 0 || startIndex > length)
- throw new ArgumentOutOfRangeException ("startIndex");
- if (count < 0 || (startIndex < count - 1))
- throw new ArgumentOutOfRangeException ("count");
- if (options == CompareOptions.Ordinal)
- return LastIndexOfOrdinalUnchecked (value, startIndex, count);
- return LastIndexOfOrdinalIgnoreCaseUnchecked (value, startIndex, count);
- }
- internal unsafe int LastIndexOfOrdinalUnchecked (string value, int startIndex, int count)
- {
- int valueLen = value.Length;
- if (count < valueLen)
- return -1;
- if (valueLen <= 1) {
- if (valueLen == 1)
- return LastIndexOfUnchecked (value[0], startIndex, count);
- return startIndex;
- }
- fixed (char* thisptr = this, valueptr = value) {
- char* ap = thisptr + startIndex - valueLen + 1;
- char* thisEnd = ap - count + valueLen - 1;
- while (ap != thisEnd) {
- if (*ap == *valueptr) {
- for (int i = 1; i < valueLen; i++) {
- if (ap[i] != valueptr[i])
- goto NextVal;
- }
- return (int)(ap - thisptr);
- }
- NextVal:
- ap--;
- }
- }
- return -1;
- }
- internal unsafe int LastIndexOfOrdinalIgnoreCaseUnchecked (string value, int startIndex, int count)
- {
- int valueLen = value.Length;
- if (count < valueLen)
- return -1;
- if (valueLen == 0)
- return startIndex;
- fixed (char* thisptr = this, valueptr = value) {
- char* ap = thisptr + startIndex - valueLen + 1;
- char* thisEnd = ap - count + valueLen - 1;
- while (ap != thisEnd) {
- for (int i = 0; i < valueLen; i++) {
- if (Char.ToUpperInvariant (ap[i]) != Char.ToUpperInvariant (valueptr[i]))
- goto NextVal;
- }
- return (int)(ap - thisptr);
- NextVal:
- ap--;
- }
- }
- return -1;
- }
- // Following methods are culture-insensitive
- public int IndexOf (char value)
- {
- if (this.length == 0)
- return -1;
- return IndexOfUnchecked (value, 0, this.length);
- }
- public int IndexOf (char value, int startIndex)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException ("startIndex", "< 0");
- if (startIndex > this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "startIndex > this.length");
- if ((startIndex == 0 && this.length == 0) || (startIndex == this.length))
- return -1;
- return IndexOfUnchecked (value, startIndex, this.length - startIndex);
- }
- public int IndexOf (char value, int startIndex, int count)
- {
- if (startIndex < 0 || startIndex > this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "Cannot be negative and must be< 0");
- if (count < 0)
- throw new ArgumentOutOfRangeException ("count", "< 0");
- if (startIndex > this.length - count)
- throw new ArgumentOutOfRangeException ("count", "startIndex + count > this.length");
- if ((startIndex == 0 && this.length == 0) || (startIndex == this.length) || (count == 0))
- return -1;
- return IndexOfUnchecked (value, startIndex, count);
- }
- internal unsafe int IndexOfUnchecked (char value, int startIndex, int count)
- {
- // It helps JIT compiler to optimize comparison
- int value_32 = (int)value;
- fixed (char* start = &start_char) {
- char* ptr = start + startIndex;
- char* end_ptr = ptr + (count >> 3 << 3);
- while (ptr != end_ptr) {
- if (*ptr == value_32)
- return (int)(ptr - start);
- if (ptr[1] == value_32)
- return (int)(ptr - start + 1);
- if (ptr[2] == value_32)
- return (int)(ptr - start + 2);
- if (ptr[3] == value_32)
- return (int)(ptr - start + 3);
- if (ptr[4] == value_32)
- return (int)(ptr - start + 4);
- if (ptr[5] == value_32)
- return (int)(ptr - start + 5);
- if (ptr[6] == value_32)
- return (int)(ptr - start + 6);
- if (ptr[7] == value_32)
- return (int)(ptr - start + 7);
- ptr += 8;
- }
- end_ptr += count & 0x07;
- while (ptr != end_ptr) {
- if (*ptr == value_32)
- return (int)(ptr - start);
- ptr++;
- }
- return -1;
- }
- }
- internal unsafe int IndexOfOrdinalIgnoreCase (char value, int startIndex, int count)
- {
- if (length == 0)
- return -1;
- int end = startIndex + count;
- char c = Char.ToUpperInvariant (value);
- fixed (char* s = &start_char) {
- for (int i = startIndex; i < end; i++)
- if (Char.ToUpperInvariant (s [i]) == c)
- return i;
- }
- return -1;
- }
- // Following methods are culture-sensitive
- public int IndexOf (String value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (value.length == 0)
- return 0;
- if (this.length == 0)
- return -1;
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf (this, value, 0, length, CompareOptions.Ordinal);
- }
- public int IndexOf (String value, int startIndex)
- {
- return IndexOf (value, startIndex, this.length - startIndex);
- }
- public int IndexOf (String value, int startIndex, int count)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (startIndex < 0 || startIndex > this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "Cannot be negative, and should not exceed length of string.");
- if (count < 0 || startIndex > this.length - count)
- throw new ArgumentOutOfRangeException ("count", "Cannot be negative, and should point to location in string.");
- if (value.length == 0)
- return startIndex;
- if (startIndex == 0 && this.length == 0)
- return -1;
- if (count == 0)
- return -1;
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf (this, value, startIndex, count);
- }
- // Following methods are culture-insensitive
- public int LastIndexOfAny (char [] anyOf)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (this.length == 0)
- return -1;
- return LastIndexOfAnyUnchecked (anyOf, this.length - 1, this.length);
- }
- public int LastIndexOfAny (char [] anyOf, int startIndex)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (this.length == 0)
- return -1;
- if (startIndex < 0 || startIndex >= this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "Cannot be negative, and should be less than length of string.");
- if (this.length == 0)
- return -1;
- return LastIndexOfAnyUnchecked (anyOf, startIndex, startIndex + 1);
- }
- public int LastIndexOfAny (char [] anyOf, int startIndex, int count)
- {
- if (anyOf == null)
- throw new ArgumentNullException ();
- if (this.length == 0)
- return -1;
- if ((startIndex < 0) || (startIndex >= this.Length))
- throw new ArgumentOutOfRangeException ("startIndex", "< 0 || > this.Length");
- if ((count < 0) || (count > this.Length))
- throw new ArgumentOutOfRangeException ("count", "< 0 || > this.Length");
- if (startIndex - count + 1 < 0)
- throw new ArgumentOutOfRangeException ("startIndex - count + 1 < 0");
- if (this.length == 0)
- return -1;
- return LastIndexOfAnyUnchecked (anyOf, startIndex, count);
- }
- private unsafe int LastIndexOfAnyUnchecked (char [] anyOf, int startIndex, int count)
- {
- if (anyOf.Length == 1)
- return LastIndexOfUnchecked (anyOf[0], startIndex, count);
- fixed (char* start = this, testStart = anyOf) {
- char* ptr = start + startIndex;
- char* ptrEnd = ptr - count;
- char* test;
- char* testEnd = testStart + anyOf.Length;
- while (ptr != ptrEnd) {
- test = testStart;
- while (test != testEnd) {
- if (*test == *ptr)
- return (int)(ptr - start);
- test++;
- }
- ptr--;
- }
- return -1;
- }
- }
- // Following methods are culture-insensitive
- public int LastIndexOf (char value)
- {
- if (this.length == 0)
- return -1;
-
- return LastIndexOfUnchecked (value, this.length - 1, this.length);
- }
- public int LastIndexOf (char value, int startIndex)
- {
- return LastIndexOf (value, startIndex, startIndex + 1);
- }
- public int LastIndexOf (char value, int startIndex, int count)
- {
- if (this.length == 0)
- return -1;
-
- // >= for char (> for string)
- if ((startIndex < 0) || (startIndex >= this.Length))
- throw new ArgumentOutOfRangeException ("startIndex", "< 0 || >= this.Length");
- if ((count < 0) || (count > this.Length))
- throw new ArgumentOutOfRangeException ("count", "< 0 || > this.Length");
- if (startIndex - count + 1 < 0)
- throw new ArgumentOutOfRangeException ("startIndex - count + 1 < 0");
- return LastIndexOfUnchecked (value, startIndex, count);
- }
- internal unsafe int LastIndexOfUnchecked (char value, int startIndex, int count)
- {
- // It helps JIT compiler to optimize comparison
- int value_32 = (int)value;
- fixed (char* start = &start_char) {
- char* ptr = start + startIndex;
- char* end_ptr = ptr - (count >> 3 << 3);
- while (ptr != end_ptr) {
- if (*ptr == value_32)
- return (int)(ptr - start);
- if (ptr[-1] == value_32)
- return (int)(ptr - start) - 1;
- if (ptr[-2] == value_32)
- return (int)(ptr - start) - 2;
- if (ptr[-3] == value_32)
- return (int)(ptr - start) - 3;
- if (ptr[-4] == value_32)
- return (int)(ptr - start) - 4;
- if (ptr[-5] == value_32)
- return (int)(ptr - start) - 5;
- if (ptr[-6] == value_32)
- return (int)(ptr - start) - 6;
- if (ptr[-7] == value_32)
- return (int)(ptr - start) - 7;
- ptr -= 8;
- }
- end_ptr -= count & 0x07;
- while (ptr != end_ptr) {
- if (*ptr == value_32)
- return (int)(ptr - start);
- ptr--;
- }
- return -1;
- }
- }
- internal unsafe int LastIndexOfOrdinalIgnoreCase (char value, int startIndex, int count)
- {
- if (length == 0)
- return -1;
- int end = startIndex - count;
- char c = Char.ToUpperInvariant (value);
- fixed (char* s = &start_char) {
- for (int i = startIndex; i > end; i--)
- if (Char.ToUpperInvariant (s [i]) == c)
- return i;
- }
- return -1;
- }
- // Following methods are culture-sensitive
- public int LastIndexOf (String value)
- {
- return LastIndexOf (value, this.length - 1, this.length);
- }
- public int LastIndexOf (String value, int startIndex)
- {
- int max = startIndex;
- if (max < this.Length)
- max++;
- return LastIndexOf (value, startIndex, max);
- }
- public int LastIndexOf (String value, int startIndex, int count)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (this.length == 0)
- return value.Length == 0 ? 0 : -1;
- // -1 > startIndex > for string (0 > startIndex >= for char)
- if ((startIndex < -1) || (startIndex > this.Length))
- throw new ArgumentOutOfRangeException ("startIndex", "< 0 || > this.Length");
- if ((count < 0) || (count > this.Length))
- throw new ArgumentOutOfRangeException ("count", "< 0 || > this.Length");
- if (startIndex - count + 1 < 0)
- throw new ArgumentOutOfRangeException ("startIndex - count + 1 < 0");
- if (value.Length == 0)
- return Math.Min (this.Length - 1, startIndex);
- if (startIndex == 0 && this.length == 0)
- return -1;
- // This check is needed to match undocumented MS behaviour
- if (this.length == 0 && value.length > 0)
- return -1;
- if (count == 0)
- return -1;
- if (startIndex == this.Length)
- startIndex--;
- return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf (this, value, startIndex, count);
- }
- public bool Contains (String value)
- {
- return IndexOf (value) != -1;
- }
- public static bool IsNullOrEmpty (String value)
- {
- return (value == null) || (value.Length == 0);
- }
- public string Normalize ()
- {
- return Normalization.Normalize (this, 0);
- }
- public string Normalize (NormalizationForm normalizationForm)
- {
- switch (normalizationForm) {
- default:
- return Normalization.Normalize (this, 0);
- case NormalizationForm.FormD:
- return Normalization.Normalize (this, 1);
- case NormalizationForm.FormKC:
- return Normalization.Normalize (this, 2);
- case NormalizationForm.FormKD:
- return Normalization.Normalize (this, 3);
- }
- }
- public bool IsNormalized ()
- {
- return Normalization.IsNormalized (this, 0);
- }
- public bool IsNormalized (NormalizationForm normalizationForm)
- {
- switch (normalizationForm) {
- default:
- return Normalization.IsNormalized (this, 0);
- case NormalizationForm.FormD:
- return Normalization.IsNormalized (this, 1);
- case NormalizationForm.FormKC:
- return Normalization.IsNormalized (this, 2);
- case NormalizationForm.FormKD:
- return Normalization.IsNormalized (this, 3);
- }
- }
- public string Remove (int startIndex)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException ("startIndex", "StartIndex can not be less than zero");
- if (startIndex >= this.length)
- throw new ArgumentOutOfRangeException ("startIndex", "StartIndex must be less than the length of the string");
- return Remove (startIndex, this.length - startIndex);
- }
- public String PadLeft (int totalWidth)
- {
- return PadLeft (totalWidth, ' ');
- }
- public unsafe String PadLeft (int totalWidth, char paddingChar)
- {
- //LAMESPEC: MSDN Doc says this is reversed for RtL languages, but this seems to be untrue
- if (totalWidth < 0)
- throw new ArgumentOutOfRangeException ("totalWidth", "< 0");
- if (totalWidth < this.length)
- return this;
- if (totalWidth == 0)
- return Empty;
- String tmp = InternalAllocateStr (totalWidth);
- fixed (char* dest = tmp, src = this) {
- char* padPos = dest;
- char* padTo = dest + (totalWidth - length);
- while (padPos != padTo)
- *padPos++ = paddingChar;
- CharCopy (padTo, src, length);
- }
- return tmp;
- }
- public String PadRight (int totalWidth)
- {
- return PadRight (totalWidth, ' ');
- }
- public unsafe String PadRight (int totalWidth, char paddingChar)
- {
- //LAMESPEC: MSDN Doc says this is reversed for RtL languages, but this seems to be untrue
- if (totalWidth < 0)
- throw new ArgumentOutOfRangeException ("totalWidth", "< 0");
- if (totalWidth < this.length)
- return this;
- if (totalWidth == 0)
- return Empty;
- String tmp = InternalAllocateStr (totalWidth);
- fixed (char* dest = tmp, src = this) {
- CharCopy (dest, src, length);
- char* padPos = dest + length;
- char* padTo = dest + totalWidth;
- while (padPos != padTo)
- *padPos++ = paddingChar;
- }
- return tmp;
- }
- public bool StartsWith (String value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- return CultureInfo.CurrentCulture.CompareInfo.IsPrefix (this, value, CompareOptions.None);
- }
- [ComVisible (false)]
- public bool StartsWith (string value, StringComparison comparisonType)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- 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);
- case StringComparison.InvariantCulture:
- return CultureInfo.InvariantCulture.CompareInfo.IsPrefix (this, value, CompareOptions.None);
- case StringComparison.InvariantCultureIgnoreCase:
- return CultureInfo.InvariantCulture.CompareInfo.IsPrefix (this, value, CompareOptions.IgnoreCase);
- case StringComparison.Ordinal:
- return StartsWithOrdinalUnchecked (value);
- case StringComparison.OrdinalIgnoreCase:
- return StartsWithOrdinalCaseInsensitiveUnchecked (value);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- throw new ArgumentException (msg, "comparisonType");
- }
- }
- internal bool StartsWithOrdinalUnchecked (string value)
- {
- return length >= value.length && CompareOrdinalUnchecked (this, 0, value.length, value, 0, value.length) == 0;
- }
- internal bool StartsWithOrdinalCaseInsensitiveUnchecked (string value)
- {
- return length >= value.Length && CompareOrdinalCaseInsensitiveUnchecked (this, 0, value.length, value, 0, value.length) == 0;
- }
- [ComVisible (false)]
- public bool EndsWith (string value, StringComparison comparisonType)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- 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);
- case StringComparison.InvariantCulture:
- return CultureInfo.InvariantCulture.CompareInfo.IsSuffix (this, value, CompareOptions.None);
- case StringComparison.InvariantCultureIgnoreCase:
- return CultureInfo.InvariantCulture.CompareInfo.IsSuffix (this, value, CompareOptions.IgnoreCase);
- case StringComparison.Ordinal:
- return CultureInfo.CurrentCulture.CompareInfo.IsSuffix (this, value, CompareOptions.Ordinal);
- case StringComparison.OrdinalIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IsSuffix (this, value, CompareOptions.OrdinalIgnoreCase);
- default:
- string msg = Locale.GetText ("Invalid value '{0}' for StringComparison", comparisonType);
- thr…
Large files files are truncated, but you can click here to view the full file