C#: Cleanup and sync IsValid*
StringExtensions with core
- Renamed `IsValidInteger` to `IsValidInt`. - Added `IsValidFileName`. - Added `IsValidHexNumber`. - Added support for IPv6 to `IsValidIPAddress`. - Added `ValidateNodeName`. - Updated the documentation of the `IsValid*` methods.
This commit is contained in:
parent
6178407940
commit
d9c495f322
1 changed files with 161 additions and 24 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
@ -939,19 +940,94 @@ namespace Godot
|
||||||
return instance.IsSubsequenceOf(text, caseSensitive: false);
|
return instance.IsSubsequenceOf(text, caseSensitive: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly char[] _invalidFileNameCharacters = { ':', '/', '\\', '?', '*', '"', '|', '%', '<', '>' };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the string contains a valid <see langword="float"/>.
|
/// Returns <see langword="true"/> if this string is free from characters that
|
||||||
|
/// aren't allowed in file names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">The string to check.</param>
|
/// <param name="instance">The string to check.</param>
|
||||||
|
/// <returns>If the string contains a valid file name.</returns>
|
||||||
|
public static bool IsValidFileName(this string instance)
|
||||||
|
{
|
||||||
|
var stripped = instance.Trim();
|
||||||
|
if (instance != stripped)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(stripped))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return instance.IndexOfAny(_invalidFileNameCharacters) == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns <see langword="true"/> if this string contains a valid <see langword="float"/>.
|
||||||
|
/// This is inclusive of integers, and also supports exponents.
|
||||||
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// <code>
|
||||||
|
/// GD.Print("1.7".IsValidFloat()) // Prints "True"
|
||||||
|
/// GD.Print("24".IsValidFloat()) // Prints "True"
|
||||||
|
/// GD.Print("7e3".IsValidFloat()) // Prints "True"
|
||||||
|
/// GD.Print("Hello".IsValidFloat()) // Prints "False"
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
/// <param name="instance">The string to check.</param>
|
||||||
/// <returns>If the string contains a valid floating point number.</returns>
|
/// <returns>If the string contains a valid floating point number.</returns>
|
||||||
public static bool IsValidFloat(this string instance)
|
public static bool IsValidFloat(this string instance)
|
||||||
{
|
{
|
||||||
float f;
|
return float.TryParse(instance, out _);
|
||||||
return float.TryParse(instance, out f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the string contains a valid color in HTML notation.
|
/// Returns <see langword="true"/> if this string contains a valid hexadecimal number.
|
||||||
|
/// If <paramref name="withPrefix"/> is <see langword="true"/>, then a validity of the
|
||||||
|
/// hexadecimal number is determined by <c>0x</c> prefix, for instance: <c>0xDEADC0DE</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The string to check.</param>
|
||||||
|
/// <param name="withPrefix">If the string must contain the <c>0x</c> prefix to be valid.</param>
|
||||||
|
/// <returns>If the string contains a valid hexadecimal number.</returns>
|
||||||
|
public static bool IsValidHexNumber(this string instance, bool withPrefix = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(instance))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int from = 0;
|
||||||
|
if (instance.Length != 1 && instance[0] == '+' || instance[0] == '-')
|
||||||
|
{
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withPrefix)
|
||||||
|
{
|
||||||
|
if (instance.Length < 3)
|
||||||
|
return false;
|
||||||
|
if (instance[from] != '0' || instance[from + 1] != 'x')
|
||||||
|
return false;
|
||||||
|
from += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = from; i < instance.Length; i++)
|
||||||
|
{
|
||||||
|
char c = instance[i];
|
||||||
|
if (IsHexDigit(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
static bool IsHexDigit(char c)
|
||||||
|
{
|
||||||
|
return char.IsDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns <see langword="true"/> if this string contains a valid color in hexadecimal
|
||||||
|
/// HTML notation. Other HTML notations such as named colors or <c>hsl()</c> aren't
|
||||||
|
/// considered valid by this method and will return <see langword="false"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">The string to check.</param>
|
/// <param name="instance">The string to check.</param>
|
||||||
/// <returns>If the string contains a valid HTML color.</returns>
|
/// <returns>If the string contains a valid HTML color.</returns>
|
||||||
|
@ -961,10 +1037,17 @@ namespace Godot
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the string is a valid identifier. As is common in
|
/// Returns <see langword="true"/> if this string is a valid identifier.
|
||||||
/// programming languages, a valid identifier may contain only letters,
|
/// A valid identifier may contain only letters, digits and underscores (<c>_</c>)
|
||||||
/// digits and underscores (_) and the first character may not be a digit.
|
/// and the first character may not be a digit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// <code>
|
||||||
|
/// GD.Print("good_ident_1".IsValidIdentifier()) // Prints "True"
|
||||||
|
/// GD.Print("1st_bad_ident".IsValidIdentifier()) // Prints "False"
|
||||||
|
/// GD.Print("bad_ident_#2".IsValidIdentifier()) // Prints "False"
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
/// <param name="instance">The string to check.</param>
|
/// <param name="instance">The string to check.</param>
|
||||||
/// <returns>If the string contains a valid identifier.</returns>
|
/// <returns>If the string contains a valid identifier.</returns>
|
||||||
public static bool IsValidIdentifier(this string instance)
|
public static bool IsValidIdentifier(this string instance)
|
||||||
|
@ -992,25 +1075,59 @@ namespace Godot
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the string contains a valid integer.
|
/// Returns <see langword="true"/> if this string contains a valid <see langword="int"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// <code>
|
||||||
|
/// GD.Print("7".IsValidInt()) // Prints "True"
|
||||||
|
/// GD.Print("14.6".IsValidInt()) // Prints "False"
|
||||||
|
/// GD.Print("L".IsValidInt()) // Prints "False"
|
||||||
|
/// GD.Print("+3".IsValidInt()) // Prints "True"
|
||||||
|
/// GD.Print("-12".IsValidInt()) // Prints "True"
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
/// <param name="instance">The string to check.</param>
|
/// <param name="instance">The string to check.</param>
|
||||||
/// <returns>If the string contains a valid integer.</returns>
|
/// <returns>If the string contains a valid integer.</returns>
|
||||||
public static bool IsValidInteger(this string instance)
|
public static bool IsValidInt(this string instance)
|
||||||
{
|
{
|
||||||
int f;
|
return int.TryParse(instance, out _);
|
||||||
return int.TryParse(instance, out f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the string contains a valid IP address.
|
/// Returns <see langword="true"/> if this string contains only a well-formatted
|
||||||
|
/// IPv4 or IPv6 address. This method considers reserved IP addresses such as
|
||||||
|
/// <c>0.0.0.0</c> as valid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">The string to check.</param>
|
/// <param name="instance">The string to check.</param>
|
||||||
/// <returns>If the string contains a valid IP address.</returns>
|
/// <returns>If the string contains a valid IP address.</returns>
|
||||||
public static bool IsValidIPAddress(this string instance)
|
public static bool IsValidIPAddress(this string instance)
|
||||||
{
|
{
|
||||||
// TODO: Support IPv6 addresses
|
if (instance.Contains(':'))
|
||||||
string[] ip = instance.Split(".");
|
{
|
||||||
|
string[] ip = instance.Split(':');
|
||||||
|
|
||||||
|
for (int i = 0; i < ip.Length; i++)
|
||||||
|
{
|
||||||
|
string n = ip[i];
|
||||||
|
if (n.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (n.IsValidHexNumber(withPrefix: false))
|
||||||
|
{
|
||||||
|
long nint = n.HexToInt();
|
||||||
|
if (nint < 0 || nint > 0xffff)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!n.IsValidIPAddress())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string[] ip = instance.Split('.');
|
||||||
|
|
||||||
if (ip.Length != 4)
|
if (ip.Length != 4)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1018,13 +1135,14 @@ namespace Godot
|
||||||
for (int i = 0; i < ip.Length; i++)
|
for (int i = 0; i < ip.Length; i++)
|
||||||
{
|
{
|
||||||
string n = ip[i];
|
string n = ip[i];
|
||||||
if (!n.IsValidInteger())
|
if (!n.IsValidInt())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int val = n.ToInt();
|
int val = n.ToInt();
|
||||||
if (val < 0 || val > 255)
|
if (val < 0 || val > 255)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1745,6 +1863,25 @@ namespace Godot
|
||||||
return Uri.EscapeDataString(instance);
|
return Uri.EscapeDataString(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string _uniqueNodePrefix = "%";
|
||||||
|
private static readonly string[] _invalidNodeNameCharacters = { ".", ":", "@", "/", "\"", _uniqueNodePrefix };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes any characters from the string that are prohibited in
|
||||||
|
/// <see cref="Node"/> names (<c>.</c> <c>:</c> <c>@</c> <c>/</c> <c>"</c>).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The string to sanitize.</param>
|
||||||
|
/// <returns>The string sanitized as a valid node name.</returns>
|
||||||
|
public static string ValidateNodeName(this string instance)
|
||||||
|
{
|
||||||
|
string name = instance.Replace(_invalidNodeNameCharacters[0], "");
|
||||||
|
for (int i = 1; i < _invalidNodeNameCharacters.Length; i++)
|
||||||
|
{
|
||||||
|
name = name.Replace(_invalidNodeNameCharacters[i], "");
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a copy of the string with special characters escaped using the XML standard.
|
/// Returns a copy of the string with special characters escaped using the XML standard.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue