Skip to content

Commit

Permalink
Merge pull request #57076 from IgorKordiukiewicz/fix-mono-string-capi…
Browse files Browse the repository at this point in the history
…talize

String.Capitalize() in C# now matches the behaviour of String::capitalize() in C++
  • Loading branch information
neikeq authored Feb 8, 2022
2 parents 76ce5c1 + 6c3b666 commit f05f2dd
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public static string CUnescape(this string instance)
/// <returns>The capitalized string.</returns>
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++)
Expand All @@ -284,6 +284,51 @@ public static string Capitalize(this string instance)
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;
}

/// <summary>
/// Performs a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
/// </summary>
Expand Down

0 comments on commit f05f2dd

Please sign in to comment.