From 6c3b6664b55677e4d86c1728b5e483d861a6fdfe Mon Sep 17 00:00:00 2001 From: Igor Kordiukiewicz Date: Sun, 23 Jan 2022 04:37:34 +0100 Subject: [PATCH] String.Capitalize() in C# now matches the behaviour of String::capitalize() in C++ --- .../GodotSharp/Core/StringExtensions.cs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index a89dca6c347..a7ddcbb989a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -266,7 +266,7 @@ namespace Godot /// The capitalized string. public static string Capitalize(this string instance) { - string aux = instance.Replace("_", " ").ToLower(); + string aux = instance.CamelcaseToUnderscore(true).Replace("_", " ").Trim(); string cap = string.Empty; for (int i = 0; i < aux.GetSliceCount(" "); i++) @@ -284,6 +284,51 @@ namespace Godot return cap; } + private static string CamelcaseToUnderscore(this string instance, bool lowerCase) + { + string newString = string.Empty; + int startIndex = 0; + + for (int i = 1; i < instance.Length; i++) + { + bool isUpper = char.IsUpper(instance[i]); + bool isNumber = char.IsDigit(instance[i]); + + bool areNext2Lower = false; + bool isNextLower = false; + bool isNextNumber = false; + bool wasPrecedentUpper = char.IsUpper(instance[i - 1]); + bool wasPrecedentNumber = char.IsDigit(instance[i - 1]); + + if (i + 2 < instance.Length) + { + areNext2Lower = char.IsLower(instance[i + 1]) && char.IsLower(instance[i + 2]); + } + + if (i + 1 < instance.Length) + { + isNextLower = char.IsLower(instance[i + 1]); + isNextNumber = char.IsDigit(instance[i + 1]); + } + + bool condA = isUpper && !wasPrecedentUpper && !wasPrecedentNumber; + bool condB = wasPrecedentUpper && isUpper && areNext2Lower; + bool condC = isNumber && !wasPrecedentNumber; + bool canBreakNumberLetter = isNumber && !wasPrecedentNumber && isNextLower; + bool canBreakLetterNumber = !isNumber && wasPrecedentNumber && (isNextLower || isNextNumber); + + bool shouldSplit = condA || condB || condC || canBreakNumberLetter || canBreakLetterNumber; + if (shouldSplit) + { + newString += instance.Substring(startIndex, i - startIndex) + "_"; + startIndex = i; + } + } + + newString += instance.Substring(startIndex, instance.Length - startIndex); + return lowerCase ? newString.ToLower() : newString; + } + /// /// Performs a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater. ///