Add String.Trim overloads that take a single char (dotnet/coreclr#9009)
authorJustin Van Patten <jvp@justinvp.com>
Mon, 23 Jan 2017 18:29:52 +0000 (13:29 -0500)
committerJan Kotas <jkotas@microsoft.com>
Mon, 23 Jan 2017 18:29:52 +0000 (10:29 -0800)
* Add String.Trim overloads that take a single char
* Cleanup uses of string.Trim/TrimEnd

Commit migrated from https://github.com/dotnet/coreclr/commit/fc2448ffa0492774e6ca41ad5ef7b2c085231c87

src/coreclr/src/mscorlib/model.xml
src/coreclr/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs
src/coreclr/src/mscorlib/src/System/Reflection/MethodBase.cs
src/coreclr/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs
src/coreclr/src/mscorlib/src/System/String.Manipulation.cs

index a1673c3..09a9ba8 100644 (file)
       <Member Name="ToUpper(System.Globalization.CultureInfo)" />
       <Member Name="ToUpperInvariant" />
       <Member Name="Trim" />
+      <Member Name="Trim(System.Char)" />
       <Member Name="Trim(System.Char[])" />
+      <Member Name="TrimEnd(System.Char)" />
       <Member Name="TrimEnd(System.Char[])" />
       <Member Name="TrimEnd" />
+      <Member Name="TrimStart(System.Char)" />
       <Member Name="TrimStart(System.Char[])" />
       <Member Name="TrimStart" />
       <Member MemberType="Property" Name="Chars(System.Int32)" />
index 14cdeb6..ecbc6db 100644 (file)
@@ -2455,7 +2455,7 @@ namespace System.Globalization {
                             case DateTimeFormatInfoScanner.IgnorableSymbolChar:
                                 String symbol = dateWords[i].Substring(1);
                                 InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
-                                if (this.DateSeparator.Trim(null).Equals(symbol))
+                                if (this.DateSeparator.Trim().Equals(symbol))
                                 {
                                     // The date separator is the same as the ingorable symbol.
                                     useDateSepAsIgnorableSymbol = true;
@@ -2802,7 +2802,7 @@ namespace System.Globalization {
             // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
             // DateTime.Parse().
             if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) {
-                str = str.Trim(null);   // Trim white space characters.
+                str = str.Trim();   // Trim white space characters.
                 // Could have space for separators
                 if (str.Length == 0)
                     return;
index 644a1ac..8c77411 100644 (file)
@@ -269,7 +269,7 @@ namespace System.Reflection
                 // Why don't we just use "&"?
                 if (t.IsByRef && !serialization)
                 {
-                    sbParamList.Append(typeName.TrimEnd(new char[] { '&' }));
+                    sbParamList.Append(typeName.TrimEnd('&'));
                     sbParamList.Append(" ByRef");
                 }
                 else
index 8d1d351..cc7a15a 100644 (file)
@@ -35,7 +35,6 @@ namespace System.Security.Util {
         protected bool m_throwOnRelative;
 
         private const char Separator = ';';
-        protected static readonly char[] m_trimChars = { ' ' };
 #if !PLATFORM_UNIX
         protected static readonly char m_directorySeparator = '\\';
         protected static readonly char m_alternateDirectorySeparator = '/';
@@ -101,7 +100,7 @@ namespace System.Security.Util {
 
         private static String StaticProcessSingleString( String str )
         {
-            return str.Trim( m_trimChars );
+            return str.Trim(' ');
         }
 
         protected virtual String ProcessWholeString( String str )
index 51007ba..7b51abf 100644 (file)
@@ -14,10 +14,6 @@ namespace System
 {
     public partial class String
     {
-        private const int TrimHead = 0;
-        private const int TrimTail = 1;
-        private const int TrimBoth = 2;
-
         unsafe private static void FillStringChecked(String dest, int destPos, String src)
         {
             Contract.Requires(dest != null);
@@ -1536,123 +1532,177 @@ namespace System
             Contract.EndContractBlock();
             return this.ToUpper(CultureInfo.InvariantCulture);
         }
-    
-        // Removes a set of characters from the end of this string.
+
+        // Trims the whitespace from both ends of the string.  Whitespace is defined by
+        // Char.IsWhiteSpace.
+        //
         [Pure]
-        public String Trim(params char[] trimChars) {
-            if (null==trimChars || trimChars.Length == 0) {
-                return TrimHelper(TrimBoth);
-            }
-            return TrimHelper(trimChars,TrimBoth);
+        public string Trim()
+        {
+            Contract.Ensures(Contract.Result<string>() != null);
+            Contract.EndContractBlock();
+
+            return TrimWhiteSpaceHelper(TrimType.Both);
         }
-    
-        // Removes a set of characters from the beginning of this string.
-        public String TrimStart(params char[] trimChars) {
-            if (null==trimChars || trimChars.Length == 0) {
-                return TrimHelper(TrimHead);
+
+        // Removes a set of characters from the beginning and end of this string.
+        public unsafe string Trim(char trimChar) => TrimHelper(&trimChar, 1, TrimType.Both);
+
+        // Removes a set of characters from the beginning and end of this string.
+        [Pure]
+        public unsafe string Trim(params char[] trimChars)
+        {
+            if (trimChars == null || trimChars.Length == 0)
+            {
+                return TrimWhiteSpaceHelper(TrimType.Both);
+            }
+            fixed (char* pTrimChars = trimChars)
+            {
+                return TrimHelper(pTrimChars, trimChars.Length, TrimType.Both);
             }
-            return TrimHelper(trimChars,TrimHead);
         }
 
         // Removes a set of characters from the beginning of this string.
-        public String TrimStart() => TrimHelper(TrimHead);
-        
+        public string TrimStart() => TrimWhiteSpaceHelper(TrimType.Head);
 
-        // Removes a set of characters from the end of this string.
-        public String TrimEnd(params char[] trimChars) {
-            if (null==trimChars || trimChars.Length == 0) {
-                return TrimHelper(TrimTail);
+        // Removes a set of characters from the beginning of this string.
+        public unsafe string TrimStart(char trimChar) => TrimHelper(&trimChar, 1, TrimType.Head);
+
+        // Removes a set of characters from the beginning of this string.
+        public unsafe string TrimStart(params char[] trimChars)
+        {
+            if (trimChars == null || trimChars.Length == 0)
+            {
+                return TrimWhiteSpaceHelper(TrimType.Head);
+            }
+            fixed (char* pTrimChars = trimChars)
+            {
+                return TrimHelper(pTrimChars, trimChars.Length, TrimType.Head);
             }
-            return TrimHelper(trimChars,TrimTail);
         }
-        
+
         // Removes a set of characters from the end of this string.
-        public String TrimEnd()=> TrimHelper(TrimTail);
-        
+        public string TrimEnd() => TrimWhiteSpaceHelper(TrimType.Tail);
 
-        // Trims the whitespace from both ends of the string.  Whitespace is defined by
-        // Char.IsWhiteSpace.
-        //
-        [Pure]
-        public String Trim() {
-            Contract.Ensures(Contract.Result<String>() != null);
-            Contract.EndContractBlock();
+        // Removes a set of characters from the end of this string.
+        public unsafe string TrimEnd(char trimChar) => TrimHelper(&trimChar, 1, TrimType.Tail);
 
-            return TrimHelper(TrimBoth);        
+        // Removes a set of characters from the end of this string.
+        public unsafe string TrimEnd(params char[] trimChars)
+        {
+            if (trimChars == null || trimChars.Length == 0)
+            {
+                return TrimWhiteSpaceHelper(TrimType.Tail);
+            }
+            fixed (char* pTrimChars = trimChars)
+            {
+                return TrimHelper(pTrimChars, trimChars.Length, TrimType.Tail);
+            }
         }
 
-       
-        private String TrimHelper(int trimType) {
-            //end will point to the first non-trimmed character on the right
-            //start will point to the first non-trimmed character on the Left
-            int end = this.Length-1;
-            int start=0;
-
-            //Trim specified characters.
-            if (trimType !=TrimTail)  {
-                for (start=0; start < this.Length; start++) {
-                    if (!Char.IsWhiteSpace(this[start])) break;
+        private string TrimWhiteSpaceHelper(TrimType trimType)
+        {
+            // end will point to the first non-trimmed character on the right.
+            // start will point to the first non-trimmed character on the left.
+            int end = Length - 1;
+            int start = 0;
+
+            // Trim specified characters.
+            if (trimType != TrimType.Tail)
+            {
+                for (start = 0; start < Length; start++)
+                {
+                    if (!char.IsWhiteSpace(this[start]))
+                    {
+                        break;
+                    }
                 }
             }
-            
-            if (trimType !=TrimHead) {
-                for (end= Length -1; end >= start;  end--) {
-                    if (!Char.IsWhiteSpace(this[end])) break;
+
+            if (trimType != TrimType.Head)
+            {
+                for (end = Length - 1; end >= start; end--)
+                {
+                    if (!char.IsWhiteSpace(this[end]))
+                    {
+                        break;
+                    }
                 }
             }
 
             return CreateTrimmedString(start, end);
         }
-    
-    
-        private String TrimHelper(char[] trimChars, int trimType) {
-            //end will point to the first non-trimmed character on the right
-            //start will point to the first non-trimmed character on the Left
-            int end = this.Length-1;
-            int start=0;
-
-            //Trim specified characters.
-            if (trimType !=TrimTail)  {
-                for (start=0; start < this.Length; start++) {
+
+        private unsafe string TrimHelper(char* trimChars, int trimCharsLength, TrimType trimType)
+        {
+            Debug.Assert(trimChars != null);
+            Debug.Assert(trimCharsLength > 0);
+
+            // end will point to the first non-trimmed character on the right.
+            // start will point to the first non-trimmed character on the left.
+            int end = Length - 1;
+            int start = 0;
+
+            // Trim specified characters.
+            if (trimType != TrimType.Tail)
+            {
+                for (start = 0; start < Length; start++)
+                {
                     int i = 0;
                     char ch = this[start];
-                    for( i = 0; i < trimChars.Length; i++) {
-                        if( trimChars[i] == ch) break;
+                    for (i = 0; i < trimCharsLength; i++)
+                    {
+                        if (trimChars[i] == ch)
+                        {
+                            break;
+                        }
                     }
-                    if( i == trimChars.Length) { // the character is not white space
-                        break;  
+                    if (i == trimCharsLength)
+                    {
+                        // The character is not in trimChars, so stop trimming.
+                        break;
                     }
                 }
             }
-            
-            if (trimType !=TrimHead) {
-                for (end= Length -1; end >= start;  end--) {
-                    int i = 0;    
-                    char ch = this[end];                    
-                    for(i = 0; i < trimChars.Length; i++) {
-                        if( trimChars[i] == ch) break;
+
+            if (trimType != TrimType.Head)
+            {
+                for (end = Length - 1; end >= start; end--)
+                {
+                    int i = 0;
+                    char ch = this[end];
+                    for (i = 0; i < trimCharsLength; i++)
+                    {
+                        if (trimChars[i] == ch)
+                        {
+                            break;
+                        }
+                    }
+                    if (i == trimCharsLength)
+                    {
+                        // The character is not in trimChars, so stop trimming.
+                        break;
                     }
-                    if( i == trimChars.Length) { // the character is not white space
-                        break;  
-                    }                    
                 }
             }
 
             return CreateTrimmedString(start, end);
         }
 
+        private string CreateTrimmedString(int start, int end)
+        {
+            int len = end - start + 1;
+            return
+                len == Length ? this :
+                len == 0 ? string.Empty :
+                InternalSubString(start, len);
+        }
 
-        private String CreateTrimmedString(int start, int end) {
-            int len = end -start + 1;
-            if (len == this.Length) {
-                // Don't allocate a new string as the trimmed string has not changed.
-                return this;
-            }
-
-            if( len == 0) {
-                return String.Empty;
-            }
-            return InternalSubString(start, len);
+        private enum TrimType
+        {
+            Head = 0,
+            Tail = 1,
+            Both = 2
         }
     }
 }