Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String.Capitalize() in C# now matches the behaviour of String::capitalize() in C++ #57076

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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