瀏覽代碼

Rewrite of name capitalization routine 'UnderscoresToPascalOrCamelCase'

csharptest 14 年之前
父節點
當前提交
c7b23c1797
共有 1 個文件被更改,包括 47 次插入41 次删除
  1. 47 41
      src/ProtocolBuffers/NameHelpers.cs

+ 47 - 41
src/ProtocolBuffers/NameHelpers.cs

@@ -34,8 +34,10 @@
 
 #endregion
 
+using System;
 using System.Globalization;
 using System.Text;
+using System.Text.RegularExpressions;
 
 namespace Google.ProtocolBuffers
 {
@@ -64,49 +66,14 @@ namespace Google.ProtocolBuffers
         /// </summary>
         private static string UnderscoresToPascalOrCamelCase(string input, bool pascal)
         {
-            StringBuilder result = new StringBuilder();
-            bool capitaliseNext = pascal;
-            for (int i = 0; i < input.Length; i++)
+            string name = Transform(input, pascal ? UnderlineToPascal : UnderlineToCamel, x => x.Value.TrimStart('_').ToUpper());
+            if (!pascal && name.Length > 0 && Char.IsUpper(name[0]))
             {
-                char c = input[i];
-                if ('a' <= c && c <= 'z')
-                {
-                    if (capitaliseNext)
-                    {
-                        result.Append(char.ToUpper(c, CultureInfo.InvariantCulture));
-                    }
-                    else
-                    {
-                        result.Append(c);
-                    }
-                    capitaliseNext = false;
-                }
-                else if ('A' <= c && c <= 'Z')
-                {
-                    if (i == 0 && !pascal)
-                    {
-                        // Force first letter to lower-case unless explicitly told to
-                        // capitalize it.
-                        result.Append(char.ToLower(c, CultureInfo.InvariantCulture));
-                    }
-                    else
-                    {
-                        // Capital letters after the first are left as-is.
-                        result.Append(c);
-                    }
-                    capitaliseNext = false;
-                }
-                else if ('0' <= c && c <= '9')
-                {
-                    result.Append(c);
-                    capitaliseNext = true;
-                }
-                else
-                {
-                    capitaliseNext = true;
-                }
+                char[] chars = name.ToCharArray();
+                chars[0] = char.ToLower(chars[0]);
+                return new string(chars);
             }
-            return result.ToString();
+            return name;
         }
 
         internal static string StripProto(string text)
@@ -131,5 +98,44 @@ namespace Google.ProtocolBuffers
             }
             return false;
         }
+
+        /// <summary>
+        /// Similar to UnderlineToCamel, but also matches the first character if it is lower-case
+        /// </summary>
+        private static Regex UnderlineToPascal = new Regex(@"(?:^|[0-9_])[a-z]");
+
+        /// <summary>
+        /// Matches lower-case character that follow either an underscore, or a number
+        /// </summary>
+        private static Regex UnderlineToCamel = new Regex(@"[0-9_][a-z]");
+
+        /// <summary>
+        /// Used for text-template transformation where a regex match is replaced in the input string.
+        /// </summary>
+        /// <param name="input">The text to perform the replacement upon</param>
+        /// <param name="pattern">The regex used to perform the match</param>
+        /// <param name="fnReplace">A delegate that selects the appropriate replacement text</param>
+        /// <returns>The newly formed text after all replacements are made</returns>
+        /// <remarks>
+        /// Originally found at http://csharptest.net/browse/src/Library/Utils/StringUtils.cs#120
+        /// Republished here by the original author under this project's licensing.
+        /// </remarks>
+        private static string Transform(string input, Regex pattern, Converter<Match, string> fnReplace)
+        {
+            int currIx = 0;
+            StringBuilder sb = new StringBuilder();
+
+            foreach (Match match in pattern.Matches(input))
+            {
+                sb.Append(input, currIx, match.Index - currIx);
+                string replace = fnReplace(match);
+                sb.Append(replace);
+
+                currIx = match.Index + match.Length;
+            }
+
+            sb.Append(input, currIx, input.Length - currIx);
+            return sb.ToString();
+        }
     }
 }