C#: Cleanup and sync StringExtensions with core

- Moved `GetBaseName` to keep methods alphabetically sorted.
- Removed `Length`, users should just use the Length property.
- Removed `Insert`, string already has a method with the same signature that takes precedence.
- Removed `Erase`.
- Removed `ToLower` and `ToUpper`, string already has methods with the same signature that take precedence.
- Removed `FindLast` in favor of `RFind`.
- Replaced `RFind` and `RFindN` implemenation with a ca ll to `string.LastIndexOf` to avoid marshaling.
- Added `LPad` and `RPad`.
- Added `StripEscapes`.
- Replaced `LStrip` and `RStrip` implementation with a call to `string.TrimStart` and `string.TrimEnd`.
- Added `TrimPrefix` and `TrimSuffix`.
- Renamed `OrdAt` to `UnicodeAt`.
- Added `CountN` and move the `caseSensitive` parameter of `Count` to the end.
- Added `Indent` and `Dedent`.
This commit is contained in:
Raul Santos 2022-10-05 18:15:39 +02:00
parent a9fbf3718d
commit 6178407940
No known key found for this signature in database
GPG key ID: B532473AE3A803E4
3 changed files with 278 additions and 212 deletions

View file

@ -414,21 +414,6 @@ namespace Godot.NativeInterop
// StringExtensions // StringExtensions
public static partial void godotsharp_string_md5_buffer(in godot_string p_self,
out godot_packed_byte_array r_md5_buffer);
public static partial void godotsharp_string_md5_text(in godot_string p_self, out godot_string r_md5_text);
public static partial int godotsharp_string_rfind(in godot_string p_self, in godot_string p_what, int p_from);
public static partial int godotsharp_string_rfindn(in godot_string p_self, in godot_string p_what, int p_from);
public static partial void godotsharp_string_sha256_buffer(in godot_string p_self,
out godot_packed_byte_array r_sha256_buffer);
public static partial void godotsharp_string_sha256_text(in godot_string p_self,
out godot_string r_sha256_text);
public static partial void godotsharp_string_simplify_path(in godot_string p_self, public static partial void godotsharp_string_simplify_path(in godot_string p_self,
out godot_string r_simplified_path); out godot_string r_simplified_path);

View file

@ -66,24 +66,6 @@ namespace Godot
return string.Empty; return string.Empty;
} }
/// <summary>
/// If the string is a path to a file, return the path to the file without the extension.
/// </summary>
/// <seealso cref="GetExtension(string)"/>
/// <seealso cref="GetBaseDir(string)"/>
/// <seealso cref="GetFile(string)"/>
/// <param name="instance">The path to a file.</param>
/// <returns>The path to the file without the extension.</returns>
public static string GetBaseName(this string instance)
{
int index = instance.LastIndexOf('.');
if (index > 0)
return instance.Substring(0, index);
return instance;
}
/// <summary> /// <summary>
/// Returns <see langword="true"/> if the strings begins /// Returns <see langword="true"/> if the strings begins
/// with the given string <paramref name="text"/>. /// with the given string <paramref name="text"/>.
@ -144,15 +126,15 @@ namespace Godot
} }
/// <summary> /// <summary>
/// Returns the amount of substrings <paramref name="what"/> in the string. /// Returns the number of occurrences of substring <paramref name="what"/> in the string.
/// </summary> /// </summary>
/// <param name="instance">The string where the substring will be searched.</param> /// <param name="instance">The string where the substring will be searched.</param>
/// <param name="what">The substring that will be counted.</param> /// <param name="what">The substring that will be counted.</param>
/// <param name="caseSensitive">If the search is case sensitive.</param>
/// <param name="from">Index to start searching from.</param> /// <param name="from">Index to start searching from.</param>
/// <param name="to">Index to stop searching at.</param> /// <param name="to">Index to stop searching at.</param>
/// <returns>Amount of substrings in the string.</returns> /// <param name="caseSensitive">If the search is case sensitive.</param>
public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0) /// <returns>Number of occurrences of the substring in the string.</returns>
public static int Count(this string instance, string what, int from = 0, int to = 0, bool caseSensitive = true)
{ {
if (what.Length == 0) if (what.Length == 0)
{ {
@ -210,6 +192,82 @@ namespace Godot
return c; return c;
} }
/// <summary>
/// Returns the number of occurrences of substring <paramref name="what"/> (ignoring case)
/// between <paramref name="from"/> and <paramref name="to"/> positions. If <paramref name="from"/>
/// and <paramref name="to"/> equals 0 the whole string will be used. If only <paramref name="to"/>
/// equals 0 the remained substring will be used.
/// </summary>
/// <param name="instance">The string where the substring will be searched.</param>
/// <param name="what">The substring that will be counted.</param>
/// <param name="from">Index to start searching from.</param>
/// <param name="to">Index to stop searching at.</param>
/// <returns>Number of occurrences of the substring in the string.</returns>
public static int CountN(this string instance, string what, int from = 0, int to = 0)
{
return instance.Count(what, from, to, caseSensitive: false);
}
/// <summary>
/// Returns a copy of the string with indentation (leading tabs and spaces) removed.
/// See also <see cref="Indent"/> to add indentation.
/// </summary>
/// <param name="instance">The string to remove the indentation from.</param>
/// <returns>The string with the indentation removed.</returns>
public static string Dedent(this string instance)
{
var sb = new StringBuilder();
string indent = "";
bool hasIndent = false;
bool hasText = false;
int lineStart = 0;
int indentStop = -1;
for (int i = 0; i < instance.Length; i++)
{
char c = instance[i];
if (c == '\n')
{
if (hasText)
{
sb.Append(instance.Substring(indentStop, i - indentStop));
}
sb.Append('\n');
hasText = false;
lineStart = i + 1;
indentStop = -1;
}
else if (!hasText)
{
if (c > 32)
{
hasText = true;
if (!hasIndent)
{
hasIndent = true;
indent = instance.Substring(lineStart, i - lineStart);
indentStop = i;
}
}
if (hasIndent && indentStop < 0)
{
int j = i - lineStart;
if (j >= indent.Length || c != indent[j])
{
indentStop = i;
}
}
}
}
if (hasText)
{
sb.Append(instance.Substring(indentStop, instance.Length - indentStop));
}
return sb.ToString();
}
/// <summary> /// <summary>
/// Returns a copy of the string with special characters escaped using the C language standard. /// Returns a copy of the string with special characters escaped using the C language standard.
/// </summary> /// </summary>
@ -454,17 +512,6 @@ namespace Godot
return instance.EndsWith(text); return instance.EndsWith(text);
} }
/// <summary>
/// Erase <paramref name="chars"/> characters from the string starting from <paramref name="pos"/>.
/// </summary>
/// <param name="instance">The string to modify.</param>
/// <param name="pos">Starting position from which to erase.</param>
/// <param name="chars">Amount of characters to erase.</param>
public static void Erase(this StringBuilder instance, int pos, int chars)
{
instance.Remove(pos, chars);
}
/// <summary> /// <summary>
/// Returns the extension without the leading period character (<c>.</c>) /// Returns the extension without the leading period character (<c>.</c>)
/// if the string is a valid file name or path. If the string does not contain /// if the string is a valid file name or path. If the string does not contain
@ -489,7 +536,7 @@ namespace Godot
/// <returns>The extension of the file or an empty string.</returns> /// <returns>The extension of the file or an empty string.</returns>
public static string GetExtension(this string instance) public static string GetExtension(this string instance)
{ {
int pos = instance.FindLast("."); int pos = instance.RFind(".");
if (pos < 0) if (pos < 0)
return instance; return instance;
@ -498,12 +545,16 @@ namespace Godot
} }
/// <summary> /// <summary>
/// Find the first occurrence of a substring. Optionally, the search starting position can be passed. /// Returns the index of the first occurrence of the specified string in this instance,
/// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
/// to the end of the string.
/// Note: If you just want to know whether a string contains a substring, use the
/// <see cref="string.Contains(string)"/> method.
/// </summary> /// </summary>
/// <seealso cref="Find(string, char, int, bool)"/> /// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindLast(string, string, bool)"/>
/// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/> /// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFind(string, string, int, bool)"/>
/// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param> /// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param> /// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param> /// <param name="from">The search starting position.</param>
@ -519,9 +570,9 @@ namespace Godot
/// Find the first occurrence of a char. Optionally, the search starting position can be passed. /// Find the first occurrence of a char. Optionally, the search starting position can be passed.
/// </summary> /// </summary>
/// <seealso cref="Find(string, string, int, bool)"/> /// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="FindLast(string, string, bool)"/>
/// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/> /// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFind(string, string, int, bool)"/>
/// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param> /// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param> /// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param> /// <param name="from">The search starting position.</param>
@ -529,50 +580,21 @@ namespace Godot
/// <returns>The first instance of the char, or -1 if not found.</returns> /// <returns>The first instance of the char, or -1 if not found.</returns>
public static int Find(this string instance, char what, int from = 0, bool caseSensitive = true) public static int Find(this string instance, char what, int from = 0, bool caseSensitive = true)
{ {
// TODO: Could be more efficient if we get a char version of `IndexOf`. if (caseSensitive)
// See https://github.com/dotnet/runtime/issues/44116 return instance.IndexOf(what, from);
return instance.IndexOf(what.ToString(), from,
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
/// <summary>Find the last occurrence of a substring.</summary> return CultureInfo.InvariantCulture.CompareInfo.IndexOf(instance, what, from, CompareOptions.OrdinalIgnoreCase);
/// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindLast(string, string, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
/// <returns>The starting position of the substring, or -1 if not found.</returns>
public static int FindLast(this string instance, string what, bool caseSensitive = true)
{
return instance.FindLast(what, instance.Length - 1, caseSensitive);
}
/// <summary>Find the last occurrence of a substring specifying the search starting position.</summary>
/// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindLast(string, string, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param>
/// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
/// <returns>The starting position of the substring, or -1 if not found.</returns>
public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
{
return instance.LastIndexOf(what, from,
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
} }
/// <summary> /// <summary>
/// Find the first occurrence of a substring but search as case-insensitive. /// Returns the index of the first case-insensitive occurrence of the specified string in this instance,
/// Optionally, the search starting position can be passed. /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing
/// to the end of the string.
/// </summary> /// </summary>
/// <seealso cref="Find(string, string, int, bool)"/> /// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/> /// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindLast(string, string, bool)"/> /// <seealso cref="RFind(string, string, int, bool)"/>
/// <seealso cref="FindLast(string, string, int, bool)"/> /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param> /// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to find.</param> /// <param name="what">The substring to find.</param>
/// <param name="from">The search starting position.</param> /// <param name="from">The search starting position.</param>
@ -616,7 +638,7 @@ namespace Godot
} }
} }
int sep = Mathf.Max(rs.FindLast("/"), rs.FindLast("\\")); int sep = Mathf.Max(rs.RFind("/"), rs.RFind("\\"));
if (sep == -1) if (sep == -1)
return directory; return directory;
@ -624,6 +646,24 @@ namespace Godot
return directory + rs.Substr(0, sep); return directory + rs.Substr(0, sep);
} }
/// <summary>
/// If the string is a path to a file, return the path to the file without the extension.
/// </summary>
/// <seealso cref="GetExtension(string)"/>
/// <seealso cref="GetBaseDir(string)"/>
/// <seealso cref="GetFile(string)"/>
/// <param name="instance">The path to a file.</param>
/// <returns>The path to the file without the extension.</returns>
public static string GetBaseName(this string instance)
{
int index = instance.RFind(".");
if (index > 0)
return instance.Substring(0, index);
return instance;
}
/// <summary> /// <summary>
/// If the string is a path to a file, return the file and ignore the base directory. /// If the string is a path to a file, return the file and ignore the base directory.
/// </summary> /// </summary>
@ -634,7 +674,7 @@ namespace Godot
/// <returns>The file name.</returns> /// <returns>The file name.</returns>
public static string GetFile(this string instance) public static string GetFile(this string instance)
{ {
int sep = Mathf.Max(instance.FindLast("/"), instance.FindLast("\\")); int sep = Mathf.Max(instance.RFind("/"), instance.RFind("\\"));
if (sep == -1) if (sep == -1)
return instance; return instance;
@ -766,18 +806,44 @@ namespace Godot
} }
/// <summary> /// <summary>
/// Inserts a substring at a given position. /// Returns a copy of the string with lines indented with <paramref name="prefix"/>.
/// For example, the string can be indented with two tabs using <c>"\t\t"</c>,
/// or four spaces using <c>" "</c>. The prefix can be any string so it can
/// also be used to comment out strings with e.g. <c>"// </c>.
/// See also <see cref="Dedent"/> to remove indentation.
/// Note: Empty lines are kept empty.
/// </summary> /// </summary>
/// <param name="instance">The string to modify.</param> /// <param name="instance">The string to add indentation to.</param>
/// <param name="pos">Position at which to insert the substring.</param> /// <param name="prefix">The string to use as indentation.</param>
/// <param name="what">Substring to insert.</param> /// <returns>The string with indentation added.</returns>
/// <returns> public static string Indent(this string instance, string prefix)
/// The string with <paramref name="what"/> inserted at the given
/// position <paramref name="pos"/>.
/// </returns>
public static string Insert(this string instance, int pos, string what)
{ {
return instance.Insert(pos, what); var sb = new StringBuilder();
int lineStart = 0;
for (int i = 0; i < instance.Length; i++)
{
char c = instance[i];
if (c == '\n')
{
if (i == lineStart)
{
sb.Append(c); // Leave empty lines empty.
}
else
{
sb.Append(prefix);
sb.Append(instance.Substring(lineStart, i - lineStart + 1));
}
lineStart = i + 1;
}
}
if (lineStart != instance.Length)
{
sb.Append(prefix);
sb.Append(instance.Substring(lineStart));
}
return sb.ToString();
} }
/// <summary> /// <summary>
@ -1003,17 +1069,24 @@ namespace Godot
} }
/// <summary> /// <summary>
/// Returns the length of the string in characters. /// Formats a string to be at least <paramref name="minLength"/> long by
/// adding <paramref name="character"/>s to the left of the string.
/// </summary> /// </summary>
/// <param name="instance">The string to check.</param> /// <param name="instance">String that will be padded.</param>
/// <returns>The length of the string.</returns> /// <param name="minLength">Minimum length that the resulting string must have.</param>
public static int Length(this string instance) /// <param name="character">Character to add to the left of the string.</param>
/// <returns>String padded with the specified character.</returns>
public static string LPad(this string instance, int minLength, char character = ' ')
{ {
return instance.Length; return instance.PadLeft(minLength, character);
} }
/// <summary> /// <summary>
/// Returns a copy of the string with characters removed from the left. /// Returns a copy of the string with characters removed from the left.
/// The <paramref name="chars"/> argument is a string specifying the set of characters
/// to be removed.
/// Note: The <paramref name="chars"/> is not a prefix. See <see cref="TrimPrefix"/>
/// method that will remove a single prefix string rather than a set of characters.
/// </summary> /// </summary>
/// <seealso cref="RStrip(string, string)"/> /// <seealso cref="RStrip(string, string)"/>
/// <param name="instance">The string to remove characters from.</param> /// <param name="instance">The string to remove characters from.</param>
@ -1021,23 +1094,7 @@ namespace Godot
/// <returns>A copy of the string with characters removed from the left.</returns> /// <returns>A copy of the string with characters removed from the left.</returns>
public static string LStrip(this string instance, string chars) public static string LStrip(this string instance, string chars)
{ {
int len = instance.Length; return instance.TrimStart(chars.ToCharArray());
int beg;
for (beg = 0; beg < len; beg++)
{
if (chars.Find(instance[beg]) == -1)
{
break;
}
}
if (beg == 0)
{
return instance;
}
return instance.Substr(beg, len - beg);
} }
/// <summary> /// <summary>
@ -1150,17 +1207,6 @@ namespace Godot
return instance.CompareTo(to, caseSensitive: false); return instance.CompareTo(to, caseSensitive: false);
} }
/// <summary>
/// Returns the character code at position <paramref name="at"/>.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <param name="at">The position int the string for the character to check.</param>
/// <returns>The character code.</returns>
public static int OrdAt(this string instance, int at)
{
return instance[at];
}
/// <summary> /// <summary>
/// Format a number to have an exact number of <paramref name="digits"/> /// Format a number to have an exact number of <paramref name="digits"/>
/// after the decimal point. /// after the decimal point.
@ -1282,34 +1328,47 @@ namespace Godot
} }
/// <summary> /// <summary>
/// Perform a search for a substring, but start from the end of the string instead of the beginning. /// Returns the index of the last occurrence of the specified string in this instance,
/// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
/// the beginning of the string.
/// </summary> /// </summary>
/// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFindN(string, string, int)"/> /// <seealso cref="RFindN(string, string, int)"/>
/// <param name="instance">The string that will be searched.</param> /// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param> /// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param> /// <param name="from">The position at which to start searching.</param>
/// <param name="caseSensitive">If <see langword="true"/>, the search is case sensitive.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns> /// <returns>The position at which the substring was found, or -1 if not found.</returns>
public static int RFind(this string instance, string what, int from = -1) public static int RFind(this string instance, string what, int from = -1, bool caseSensitive = true)
{ {
using godot_string instanceStr = Marshaling.ConvertStringToNative(instance); if (from == -1)
using godot_string whatStr = Marshaling.ConvertStringToNative(instance); from = instance.Length - 1;
return NativeFuncs.godotsharp_string_rfind(instanceStr, whatStr, from);
return instance.LastIndexOf(what, from,
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
} }
/// <summary> /// <summary>
/// Perform a search for a substring, but start from the end of the string instead of the beginning. /// Returns the index of the last case-insensitive occurrence of the specified string in this instance,
/// Also search case-insensitive. /// or <c>-1</c>. Optionally, the starting search index can be specified, continuing to
/// the beginning of the string.
/// </summary> /// </summary>
/// <seealso cref="RFind(string, string, int)"/> /// <seealso cref="Find(string, string, int, bool)"/>
/// <seealso cref="Find(string, char, int, bool)"/>
/// <seealso cref="FindN(string, string, int)"/>
/// <seealso cref="RFind(string, string, int, bool)"/>
/// <param name="instance">The string that will be searched.</param> /// <param name="instance">The string that will be searched.</param>
/// <param name="what">The substring to search in the string.</param> /// <param name="what">The substring to search in the string.</param>
/// <param name="from">The position at which to start searching.</param> /// <param name="from">The position at which to start searching.</param>
/// <returns>The position at which the substring was found, or -1 if not found.</returns> /// <returns>The position at which the substring was found, or -1 if not found.</returns>
public static int RFindN(this string instance, string what, int from = -1) public static int RFindN(this string instance, string what, int from = -1)
{ {
using godot_string instanceStr = Marshaling.ConvertStringToNative(instance); if (from == -1)
using godot_string whatStr = Marshaling.ConvertStringToNative(instance); from = instance.Length - 1;
return NativeFuncs.godotsharp_string_rfindn(instanceStr, whatStr, from);
return instance.LastIndexOf(what, from, StringComparison.OrdinalIgnoreCase);
} }
/// <summary> /// <summary>
@ -1330,8 +1389,25 @@ namespace Godot
return instance.Substring(pos, instance.Length - pos); return instance.Substring(pos, instance.Length - pos);
} }
/// <summary>
/// Formats a string to be at least <paramref name="minLength"/> long by
/// adding <paramref name="character"/>s to the right of the string.
/// </summary>
/// <param name="instance">String that will be padded.</param>
/// <param name="minLength">Minimum length that the resulting string must have.</param>
/// <param name="character">Character to add to the right of the string.</param>
/// <returns>String padded with the specified character.</returns>
public static string RPad(this string instance, int minLength, char character = ' ')
{
return instance.PadRight(minLength, character);
}
/// <summary> /// <summary>
/// Returns a copy of the string with characters removed from the right. /// Returns a copy of the string with characters removed from the right.
/// The <paramref name="chars"/> argument is a string specifying the set of characters
/// to be removed.
/// Note: The <paramref name="chars"/> is not a suffix. See <see cref="TrimSuffix"/>
/// method that will remove a single suffix string rather than a set of characters.
/// </summary> /// </summary>
/// <seealso cref="LStrip(string, string)"/> /// <seealso cref="LStrip(string, string)"/>
/// <param name="instance">The string to remove characters from.</param> /// <param name="instance">The string to remove characters from.</param>
@ -1339,15 +1415,7 @@ namespace Godot
/// <returns>A copy of the string with characters removed from the right.</returns> /// <returns>A copy of the string with characters removed from the right.</returns>
public static string RStrip(this string instance, string chars) public static string RStrip(this string instance, string chars)
{ {
int len = instance.Length; return instance.TrimEnd(chars.ToCharArray());
int end;
for (end = len - 1; end >= 0; end--)
{
if (chars.Find(instance[end]) == -1)
{
break;
}
} }
if (end == len - 1) if (end == len - 1)
@ -1455,7 +1523,7 @@ namespace Godot
/// <returns>The array of strings split from the string.</returns> /// <returns>The array of strings split from the string.</returns>
public static string[] Split(this string instance, string divisor, bool allowEmpty = true) public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
{ {
return instance.Split(new[] { divisor }, return instance.Split(divisor,
allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries); allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
} }
@ -1503,8 +1571,10 @@ namespace Godot
}; };
/// <summary> /// <summary>
/// Returns a copy of the string stripped of any non-printable character at the beginning and the end. /// Returns a copy of the string stripped of any non-printable character
/// The optional arguments are used to toggle stripping on the left and right edges respectively. /// (including tabulations, spaces and line breaks) at the beginning and the end.
/// The optional arguments are used to toggle stripping on the left and right
/// edges respectively.
/// </summary> /// </summary>
/// <param name="instance">The string to strip.</param> /// <param name="instance">The string to strip.</param>
/// <param name="left">If the left side should be stripped.</param> /// <param name="left">If the left side should be stripped.</param>
@ -1522,6 +1592,30 @@ namespace Godot
return instance.TrimEnd(_nonPrintable); return instance.TrimEnd(_nonPrintable);
} }
/// <summary>
/// Returns a copy of the string stripped of any escape character.
/// These include all non-printable control characters of the first page
/// of the ASCII table (&lt; 32), such as tabulation (<c>\t</c>) and
/// newline (<c>\n</c> and <c>\r</c>) characters, but not spaces.
/// </summary>
/// <param name="instance">The string to strip.</param>
/// <returns>The string stripped of any escape characters.</returns>
public static string StripEscapes(this string instance)
{
var sb = new StringBuilder();
for (int i = 0; i < instance.Length; i++)
{
// Escape characters on first page of the ASCII table, before 32 (Space).
if (instance[i] < 32)
continue;
sb.Append(instance[i]);
}
return sb.ToString();
}
/// <summary> /// <summary>
/// Returns part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>. /// Returns part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
/// </summary> /// </summary>
@ -1572,28 +1666,6 @@ namespace Godot
return int.Parse(instance); return int.Parse(instance);
} }
/// <summary>
/// Returns the string converted to lowercase.
/// </summary>
/// <seealso cref="ToUpper(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string converted to lowercase.</returns>
public static string ToLower(this string instance)
{
return instance.ToLower();
}
/// <summary>
/// Returns the string converted to uppercase.
/// </summary>
/// <seealso cref="ToLower(string)"/>
/// <param name="instance">The string to convert.</param>
/// <returns>The string converted to uppercase.</returns>
public static string ToUpper(this string instance)
{
return instance.ToUpper();
}
/// <summary> /// <summary>
/// Converts the String (which is an array of characters) to PackedByteArray (which is an array of bytes). /// Converts the String (which is an array of characters) to PackedByteArray (which is an array of bytes).
/// The conversion is a bit slower than <see cref="ToAscii(string)"/>, but supports all UTF-8 characters. /// The conversion is a bit slower than <see cref="ToAscii(string)"/>, but supports all UTF-8 characters.
@ -1607,6 +1679,45 @@ namespace Godot
return Encoding.UTF8.GetBytes(instance); return Encoding.UTF8.GetBytes(instance);
} }
/// <summary>
/// Removes a given string from the start if it starts with it or leaves the string unchanged.
/// </summary>
/// <param name="instance">The string to remove the prefix from.</param>
/// <param name="prefix">The string to remove from the start.</param>
/// <returns>A copy of the string with the prefix string removed from the start.</returns>
public static string TrimPrefix(this string instance, string prefix)
{
if (instance.StartsWith(prefix))
return instance.Substring(prefix.Length);
return instance;
}
/// <summary>
/// Removes a given string from the end if it ends with it or leaves the string unchanged.
/// </summary>
/// <param name="instance">The string to remove the suffix from.</param>
/// <param name="suffix">The string to remove from the end.</param>
/// <returns>A copy of the string with the suffix string removed from the end.</returns>
public static string TrimSuffix(this string instance, string suffix)
{
if (instance.EndsWith(suffix))
return instance.Substring(0, instance.Length - suffix.Length);
return instance;
}
/// <summary>
/// Returns the character code at position <paramref name="at"/>.
/// </summary>
/// <param name="instance">The string to check.</param>
/// <param name="at">The position int the string for the character to check.</param>
/// <returns>The character code.</returns>
public static int UnicodeAt(this string instance, int at)
{
return instance[at];
}
/// <summary> /// <summary>
/// Decodes a string in URL encoded format. This is meant to /// Decodes a string in URL encoded format. This is meant to
/// decode parameters in a URL when receiving an HTTP request. /// decode parameters in a URL when receiving an HTTP request.

View file

@ -1067,30 +1067,6 @@ void godotsharp_dictionary_to_string(const Dictionary *p_self, String *r_str) {
*r_str = Variant(*p_self).operator String(); *r_str = Variant(*p_self).operator String();
} }
void godotsharp_string_md5_buffer(const String *p_self, PackedByteArray *r_md5_buffer) {
memnew_placement(r_md5_buffer, PackedByteArray(p_self->md5_buffer()));
}
void godotsharp_string_md5_text(const String *p_self, String *r_md5_text) {
memnew_placement(r_md5_text, String(p_self->md5_text()));
}
int32_t godotsharp_string_rfind(const String *p_self, const String *p_what, int32_t p_from) {
return p_self->rfind(*p_what, p_from);
}
int32_t godotsharp_string_rfindn(const String *p_self, const String *p_what, int32_t p_from) {
return p_self->rfindn(*p_what, p_from);
}
void godotsharp_string_sha256_buffer(const String *p_self, PackedByteArray *r_sha256_buffer) {
memnew_placement(r_sha256_buffer, PackedByteArray(p_self->sha256_buffer()));
}
void godotsharp_string_sha256_text(const String *p_self, String *r_sha256_text) {
memnew_placement(r_sha256_text, String(p_self->sha256_text()));
}
void godotsharp_string_simplify_path(const String *p_self, String *r_simplified_path) { void godotsharp_string_simplify_path(const String *p_self, String *r_simplified_path) {
memnew_placement(r_simplified_path, String(p_self->simplify_path())); memnew_placement(r_simplified_path, String(p_self->simplify_path()));
} }
@ -1473,12 +1449,6 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_dictionary_duplicate, (void *)godotsharp_dictionary_duplicate,
(void *)godotsharp_dictionary_remove_key, (void *)godotsharp_dictionary_remove_key,
(void *)godotsharp_dictionary_to_string, (void *)godotsharp_dictionary_to_string,
(void *)godotsharp_string_md5_buffer,
(void *)godotsharp_string_md5_text,
(void *)godotsharp_string_rfind,
(void *)godotsharp_string_rfindn,
(void *)godotsharp_string_sha256_buffer,
(void *)godotsharp_string_sha256_text,
(void *)godotsharp_string_simplify_path, (void *)godotsharp_string_simplify_path,
(void *)godotsharp_string_to_camel_case, (void *)godotsharp_string_to_camel_case,
(void *)godotsharp_string_to_pascal_case, (void *)godotsharp_string_to_pascal_case,