Ver Fonte

Merge pull request #43978 from aaronfranke/cs-string

Unify URI encoding/decoding, handle spaces-are-pluses, and handle hex/bin prefix automatically
Rémi Verschelde há 4 anos atrás
pai
commit
e50422d01c

+ 3 - 3
core/io/http_client.cpp

@@ -736,14 +736,14 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
 	String query = "";
 	Array keys = p_dict.keys();
 	for (int i = 0; i < keys.size(); ++i) {
-		String encoded_key = String(keys[i]).http_escape();
+		String encoded_key = String(keys[i]).uri_encode();
 		Variant value = p_dict[keys[i]];
 		switch (value.get_type()) {
 			case Variant::ARRAY: {
 				// Repeat the key with every values
 				Array values = value;
 				for (int j = 0; j < values.size(); ++j) {
-					query += "&" + encoded_key + "=" + String(values[j]).http_escape();
+					query += "&" + encoded_key + "=" + String(values[j]).uri_encode();
 				}
 				break;
 			}
@@ -754,7 +754,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
 			}
 			default: {
 				// Add the key-value pair
-				query += "&" + encoded_key + "=" + String(value).http_escape();
+				query += "&" + encoded_key + "=" + String(value).uri_encode();
 			}
 		}
 	}

+ 13 - 72
core/string/ustring.cpp

@@ -2097,8 +2097,9 @@ String::String(const StrRange &p_range) {
 	copy_from(p_range.c_str, p_range.len);
 }
 
-int64_t String::hex_to_int(bool p_with_prefix) const {
-	if (p_with_prefix && length() < 3) {
+int64_t String::hex_to_int() const {
+	int len = length();
+	if (len == 0) {
 		return 0;
 	}
 
@@ -2110,10 +2111,7 @@ int64_t String::hex_to_int(bool p_with_prefix) const {
 		s++;
 	}
 
-	if (p_with_prefix) {
-		if (s[0] != '0' || s[1] != 'x') {
-			return 0;
-		}
+	if (len > 2 && s[0] == '0' && s[1] == 'x') {
 		s += 2;
 	}
 
@@ -2140,8 +2138,9 @@ int64_t String::hex_to_int(bool p_with_prefix) const {
 	return hex * sign;
 }
 
-int64_t String::bin_to_int(bool p_with_prefix) const {
-	if (p_with_prefix && length() < 3) {
+int64_t String::bin_to_int() const {
+	int len = length();
+	if (len == 0) {
 		return 0;
 	}
 
@@ -2153,10 +2152,7 @@ int64_t String::bin_to_int(bool p_with_prefix) const {
 		s++;
 	}
 
-	if (p_with_prefix) {
-		if (s[0] != '0' || s[1] != 'b') {
-			return 0;
-		}
+	if (len > 2 && s[0] == '0' && s[1] == 'b') {
 		s += 2;
 	}
 
@@ -3756,7 +3752,7 @@ bool String::is_valid_string() const {
 	return valid;
 }
 
-String String::http_escape() const {
+String String::uri_encode() const {
 	const CharString temp = utf8();
 	String res;
 	for (int i = 0; i < temp.length(); ++i) {
@@ -3780,7 +3776,7 @@ String String::http_escape() const {
 	return res;
 }
 
-String String::http_unescape() const {
+String String::uri_decode() const {
 	String res;
 	for (int i = 0; i < length(); ++i) {
 		if (unicode_at(i) == '%' && i + 2 < length()) {
@@ -3795,6 +3791,8 @@ String String::http_unescape() const {
 			} else {
 				res += unicode_at(i);
 			}
+		} else if (unicode_at(i) == '+') {
+			res += ' ';
 		} else {
 			res += unicode_at(i);
 		}
@@ -4251,7 +4249,7 @@ bool String::is_valid_ip_address() const {
 				continue;
 			}
 			if (n.is_valid_hex_number(false)) {
-				int64_t nint = n.hex_to_int(false);
+				int64_t nint = n.hex_to_int();
 				if (nint < 0 || nint > 0xffff) {
 					return false;
 				}
@@ -4346,63 +4344,6 @@ String String::plus_file(const String &p_file) const {
 	return *this + "/" + p_file;
 }
 
-String String::percent_encode() const {
-	CharString cs = utf8();
-	String encoded;
-	for (int i = 0; i < cs.length(); i++) {
-		uint8_t c = cs[i];
-		if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '.') {
-			char p[2] = { (char)c, 0 };
-			encoded += p;
-		} else {
-			char p[4] = { '%', 0, 0, 0 };
-			static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
-			p[1] = hex[c >> 4];
-			p[2] = hex[c & 0xF];
-			encoded += p;
-		}
-	}
-
-	return encoded;
-}
-
-String String::percent_decode() const {
-	CharString pe;
-
-	CharString cs = utf8();
-	for (int i = 0; i < cs.length(); i++) {
-		uint8_t c = cs[i];
-		if (c == '%' && i < length() - 2) {
-			uint8_t a = LOWERCASE(cs[i + 1]);
-			uint8_t b = LOWERCASE(cs[i + 2]);
-
-			if (a >= '0' && a <= '9') {
-				c = (a - '0') << 4;
-			} else if (a >= 'a' && a <= 'f') {
-				c = (a - 'a' + 10) << 4;
-			} else {
-				continue;
-			}
-
-			uint8_t d = 0;
-
-			if (b >= '0' && b <= '9') {
-				d = (b - '0');
-			} else if (b >= 'a' && b <= 'f') {
-				d = (b - 'a' + 10);
-			} else {
-				continue;
-			}
-			c += d;
-			i += 2;
-		}
-		pe += c;
-	}
-
-	return String::utf8(pe.ptr());
-}
-
 String String::property_name_encode() const {
 	// Escape and quote strings with extended ASCII or further Unicode characters
 	// as well as '"', '=' or ' ' (32)

+ 4 - 7
core/string/ustring.h

@@ -318,8 +318,8 @@ public:
 	bool is_numeric() const;
 
 	double to_float() const;
-	int64_t hex_to_int(bool p_with_prefix = true) const;
-	int64_t bin_to_int(bool p_with_prefix = true) const;
+	int64_t hex_to_int() const;
+	int64_t bin_to_int() const;
 	int64_t to_int() const;
 
 	static int64_t to_int(const char *p_str, int p_len = -1);
@@ -409,17 +409,14 @@ public:
 
 	String xml_escape(bool p_escape_quotes = false) const;
 	String xml_unescape() const;
-	String http_escape() const;
-	String http_unescape() const;
+	String uri_encode() const;
+	String uri_decode() const;
 	String c_escape() const;
 	String c_escape_multiline() const;
 	String c_unescape() const;
 	String json_escape() const;
 	String word_wrap(int p_chars_per_line) const;
 
-	String percent_encode() const;
-	String percent_decode() const;
-
 	String property_name_encode() const;
 
 	bool is_valid_identifier() const;

+ 4 - 6
core/variant/variant_call.cpp

@@ -950,13 +950,11 @@ static void _register_variant_builtin_methods() {
 	bind_method(String, get_file, sarray(), varray());
 	bind_method(String, xml_escape, sarray("escape_quotes"), varray(false));
 	bind_method(String, xml_unescape, sarray(), varray());
-	bind_method(String, http_escape, sarray(), varray());
-	bind_method(String, http_unescape, sarray(), varray());
+	bind_method(String, uri_encode, sarray(), varray());
+	bind_method(String, uri_decode, sarray(), varray());
 	bind_method(String, c_escape, sarray(), varray());
 	bind_method(String, c_unescape, sarray(), varray());
 	bind_method(String, json_escape, sarray(), varray());
-	bind_method(String, percent_encode, sarray(), varray());
-	bind_method(String, percent_decode, sarray(), varray());
 
 	bind_method(String, is_valid_identifier, sarray(), varray());
 	bind_method(String, is_valid_integer, sarray(), varray());
@@ -968,8 +966,8 @@ static void _register_variant_builtin_methods() {
 
 	bind_method(String, to_int, sarray(), varray());
 	bind_method(String, to_float, sarray(), varray());
-	bind_method(String, hex_to_int, sarray("with_prefix"), varray(true));
-	bind_method(String, bin_to_int, sarray("with_prefix"), varray(true));
+	bind_method(String, hex_to_int, sarray(), varray());
+	bind_method(String, bin_to_int, sarray(), varray());
 
 	bind_method(String, lpad, sarray("min_length", "character"), varray(" "));
 	bind_method(String, rpad, sarray("min_length", "character"), varray(" "));

+ 1 - 1
doc/classes/HTTPClient.xml

@@ -175,7 +175,7 @@
 				var result = new HTTPClient().Request(HTTPClient.Method.Post, "index.php", headers, queryString);
 				[/csharp]
 				[/codeblocks]
-				[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
+				[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.uri_encode] for an example.
 			</description>
 		</method>
 		<method name="request_raw">

+ 1 - 1
doc/classes/HTTPRequest.xml

@@ -203,7 +203,7 @@
 			<description>
 				Creates request on the underlying [HTTPClient]. If there is no configuration errors, it tries to connect using [method HTTPClient.connect_to_host] and passes parameters onto [method HTTPClient.request].
 				Returns [constant OK] if request is successfully created. (Does not imply that the server has responded), [constant ERR_UNCONFIGURED] if not in the tree, [constant ERR_BUSY] if still processing previous request, [constant ERR_INVALID_PARAMETER] if given string is not a valid URL format, or [constant ERR_CANT_CONNECT] if not using thread and the [HTTPClient] cannot connect to host.
-				[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
+				[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.uri_encode] for an example.
 			</description>
 		</method>
 		<method name="request_raw">

+ 52 - 43
doc/classes/String.xml

@@ -63,9 +63,18 @@
 		<method name="bin_to_int">
 			<return type="int">
 			</return>
-			<argument index="0" name="with_prefix" type="bool" default="true">
-			</argument>
 			<description>
+				Converts a string containing a binary number into an integer. Binary strings can either be prefixed with [code]0b[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+				[codeblocks]
+				[gdscript]
+				print("0x101".bin_to_int()) # Prints "5".
+				print("101".bin_to_int()) # Prints "5".
+				[/gdscript]
+				[csharp]
+				GD.Print("0x101".BinToInt()); // Prints "5".
+				GD.Print("101".BinToInt()); // Prints "5".
+				[/csharp]
+				[/codeblocks]
 			</description>
 		</method>
 		<method name="c_escape">
@@ -221,34 +230,18 @@
 		<method name="hex_to_int">
 			<return type="int">
 			</return>
-			<argument index="0" name="with_prefix" type="bool" default="true">
-			</argument>
 			<description>
-				Converts a string containing a hexadecimal number into a decimal integer. If [code]with_prefix[/code] is [code]true[/code], the hexadecimal string should start with the [code]0x[/code] prefix, otherwise [code]0[/code] is returned.
-				[codeblock]
-				print("0xff".hex_to_int()) # Print "255"
-				print("ab".hex_to_int(false)) # Print "171"
-				[/codeblock]
-			</description>
-		</method>
-		<method name="http_escape">
-			<return type="String">
-			</return>
-			<description>
-				Escapes (encodes) a string to URL friendly format. Also referred to as 'URL encode'.
-				[codeblock]
-				print("https://example.org/?escaped=" + "Godot Engine:'docs'".http_escape())
-				[/codeblock]
-			</description>
-		</method>
-		<method name="http_unescape">
-			<return type="String">
-			</return>
-			<description>
-				Unescapes (decodes) a string in URL encoded format. Also referred to as 'URL decode'.
-				[codeblock]
-				print("https://example.org/?escaped=" + "Godot%20Engine%3A%27docs%27".http_unescape())
-				[/codeblock]
+				Converts a string containing a hexadecimal number into an integer. Hexadecimal strings can either be prefixed with [code]0x[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+				[codeblocks]
+				[gdscript]
+				print("0xff".hex_to_int()) # Prints "255".
+				print("ab".hex_to_int()) # Prints "171".
+				[/gdscript]
+				[csharp]
+				GD.Print("0xff".HexToInt()); // Prints "255".
+				GD.Print("ab".HexToInt()); // Prints "171".
+				[/csharp]
+				[/codeblocks]
 			</description>
 		</method>
 		<method name="insert">
@@ -565,20 +558,6 @@
 				Formats a number to have an exact number of [code]digits[/code] before the decimal point.
 			</description>
 		</method>
-		<method name="percent_decode">
-			<return type="String">
-			</return>
-			<description>
-				Decode a percent-encoded string. See [method percent_encode].
-			</description>
-		</method>
-		<method name="percent_encode">
-			<return type="String">
-			</return>
-			<description>
-				Percent-encodes a string. Encodes parameters in a URL when sending a HTTP GET request (and bodies of form-urlencoded POST requests).
-			</description>
-		</method>
 		<method name="plus_file">
 			<return type="String">
 			</return>
@@ -878,6 +857,36 @@
 				Returns the character code at position [code]at[/code].
 			</description>
 		</method>
+		<method name="uri_decode">
+			<return type="String">
+			</return>
+			<description>
+				Decodes a string in URL encoded format. This is meant to decode parameters in a URL when receiving an HTTP request.
+				[codeblocks]
+				[gdscript]
+				print("https://example.org/?escaped=" + "Godot%20Engine%3A%27docs%27".uri_decode())
+				[/gdscript]
+				[csharp]
+				GD.Print("https://example.org/?escaped=" + "Godot%20Engine%3a%27Docs%27".URIDecode());
+				[/csharp]
+				[/codeblocks]
+			</description>
+		</method>
+		<method name="uri_encode">
+			<return type="String">
+			</return>
+			<description>
+				Encodes a string to URL friendly format. This is meant to encode parameters in a URL when sending an HTTP request.
+				[codeblocks]
+				[gdscript]
+				print("https://example.org/?escaped=" + "Godot Engine:'docs'".uri_encode())
+				[/gdscript]
+				[csharp]
+				GD.Print("https://example.org/?escaped=" + "Godot Engine:'docs'".URIEncode());
+				[/csharp]
+				[/codeblocks]
+			</description>
+		</method>
 		<method name="xml_escape">
 			<return type="String">
 			</return>

+ 1 - 1
drivers/unix/dir_access_unix.cpp

@@ -232,7 +232,7 @@ static void _get_drives(List<String> *list) {
 				// Parse only file:// links
 				if (strncmp(string, "file://", 7) == 0) {
 					// Strip any unwanted edges on the strings and push_back if it's not a duplicate
-					String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode();
+					String fpath = String(string + 7).strip_edges().split_spaces()[0].uri_decode();
 					if (!list->find(fpath)) {
 						list->push_back(fpath);
 					}

+ 2 - 2
editor/import/collada.cpp

@@ -289,7 +289,7 @@ void Collada::_parse_image(XMLParser &parser) {
 		String path = parser.get_attribute_value("source").strip_edges();
 		if (path.find("://") == -1 && path.is_rel_path()) {
 			// path is relative to file being loaded, so convert to a resource path
-			image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.percent_decode()));
+			image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.uri_decode()));
 		}
 	} else {
 		while (parser.read() == OK) {
@@ -298,7 +298,7 @@ void Collada::_parse_image(XMLParser &parser) {
 
 				if (name == "init_from") {
 					parser.read();
-					String path = parser.get_node_data().strip_edges().percent_decode();
+					String path = parser.get_node_data().strip_edges().uri_decode();
 
 					if (path.find("://") == -1 && path.is_rel_path()) {
 						// path is relative to file being loaded, so convert to a resource path

+ 1 - 1
editor/plugins/asset_library_editor_plugin.cpp

@@ -900,7 +900,7 @@ void EditorAssetLibrary::_search(int p_page) {
 	}
 
 	if (filter->get_text() != String()) {
-		args += "&filter=" + filter->get_text().http_escape();
+		args += "&filter=" + filter->get_text().uri_encode();
 	}
 
 	if (p_page > 0) {

+ 1 - 1
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -350,7 +350,7 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) {
 String GDScriptWorkspace::get_file_path(const String &p_uri) const {
 	String path = p_uri;
 	path = path.replace(root_uri + "/", "res://");
-	path = path.http_unescape();
+	path = path.uri_decode();
 	return path;
 }
 

+ 75 - 23
modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs

@@ -97,6 +97,36 @@ namespace Godot
             return b;
         }
 
+        /// <summary>
+        /// Converts a string containing a binary number into an integer.
+        /// Binary strings can either be prefixed with `0b` or not,
+        /// and they can also start with a `-` before the optional prefix.
+        /// </summary>
+        /// <param name="instance">The string to convert.</param>
+        /// <returns>The converted string.</returns>
+        public static int BinToInt(this string instance)
+        {
+            if (instance.Length == 0)
+            {
+                return 0;
+            }
+
+            int sign = 1;
+
+            if (instance[0] == '-')
+            {
+                sign = -1;
+                instance = instance.Substring(1);
+            }
+
+            if (instance.StartsWith("0b"))
+            {
+                instance = instance.Substring(2);
+            }
+
+            return sign * Convert.ToInt32(instance, 2);;
+        }
+
         // <summary>
         // Return the amount of substrings in string.
         // </summary>
@@ -449,7 +479,7 @@ namespace Godot
         /// <summary>
         /// Returns a hexadecimal representation of this byte as a string.
         /// </summary>
-        /// <param name="bytes">The byte to encode.</param>
+        /// <param name="b">The byte to encode.</param>
         /// <returns>The hexadecimal representation of this byte.</returns>
         internal static string HexEncode(this byte b)
         {
@@ -493,11 +523,20 @@ namespace Godot
             return ret;
         }
 
-        // <summary>
-        // Convert a string containing an hexadecimal number into an int.
-        // </summary>
+        /// <summary>
+        /// Converts a string containing a hexadecimal number into an integer.
+        /// Hexadecimal strings can either be prefixed with `0x` or not,
+        /// and they can also start with a `-` before the optional prefix.
+        /// </summary>
+        /// <param name="instance">The string to convert.</param>
+        /// <returns>The converted string.</returns>
         public static int HexToInt(this string instance)
         {
+            if (instance.Length == 0)
+            {
+                return 0;
+            }
+
             int sign = 1;
 
             if (instance[0] == '-')
@@ -506,10 +545,12 @@ namespace Godot
                 instance = instance.Substring(1);
             }
 
-            if (!instance.StartsWith("0x"))
-                return 0;
+            if (instance.StartsWith("0x"))
+            {
+                instance = instance.Substring(2);
+            }
 
-            return sign * int.Parse(instance.Substring(2), NumberStyles.HexNumber);
+            return sign * int.Parse(instance, NumberStyles.HexNumber);
         }
 
         // <summary>
@@ -891,22 +932,6 @@ namespace Godot
             return s;
         }
 
-        // <summary>
-        // Decode a percent-encoded string. See [method percent_encode].
-        // </summary>
-        public static string PercentDecode(this string instance)
-        {
-            return Uri.UnescapeDataString(instance);
-        }
-
-        // <summary>
-        // Percent-encode a string. This is meant to encode parameters in a URL when sending a HTTP GET request and bodies of form-urlencoded POST request.
-        // </summary>
-        public static string PercentEncode(this string instance)
-        {
-            return Uri.EscapeDataString(instance);
-        }
-
         // <summary>
         // If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
         // </summary>
@@ -1169,6 +1194,33 @@ namespace Godot
             return Encoding.UTF8.GetBytes(instance);
         }
 
+        /// <summary>
+        /// Decodes a string in URL encoded format. This is meant to
+        /// decode parameters in a URL when receiving an HTTP request.
+        /// This mostly wraps around `System.Uri.UnescapeDataString()`,
+        /// but also handles `+`.
+        /// See <see cref="URIEncode"/> for encoding.
+        /// </summary>
+        /// <param name="instance">The string to decode.</param>
+        /// <returns>The unescaped string.</returns>
+        public static string URIDecode(this string instance)
+        {
+            return Uri.UnescapeDataString(instance.Replace("+", "%20"));
+        }
+
+        /// <summary>
+        /// Encodes a string to URL friendly format. This is meant to
+        /// encode parameters in a URL when sending an HTTP request.
+        /// This wraps around `System.Uri.EscapeDataString()`.
+        /// See <see cref="URIDecode"/> for decoding.
+        /// </summary>
+        /// <param name="instance">The string to encode.</param>
+        /// <returns>The escaped string.</returns>
+        public static string URIEncode(this string instance)
+        {
+            return Uri.EscapeDataString(instance);
+        }
+
         // <summary>
         // Return a copy of the string with special characters escaped using the XML standard.
         // </summary>

+ 1 - 1
platform/linuxbsd/display_server_x11.cpp

@@ -3360,7 +3360,7 @@ void DisplayServerX11::process_events() {
 
 					Vector<String> files = String((char *)p.data).split("\n", false);
 					for (int i = 0; i < files.size(); i++) {
-						files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges();
+						files.write[i] = files[i].replace("file://", "").uri_decode().strip_edges();
 					}
 
 					if (!windows[window_id].drop_files_callback.is_null()) {

+ 1 - 1
platform/linuxbsd/os_linuxbsd.cpp

@@ -410,7 +410,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
 	OS::Time time = OS::get_singleton()->get_time(false);
 	String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, date.month, date.day, time.hour, time.min);
 	timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
-	String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
+	String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
 	{
 		Error err;
 		FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);

+ 1 - 1
servers/rendering/shader_language.cpp

@@ -643,7 +643,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
 					}
 
 					if (hexa_found) {
-						tk.constant = (double)str.hex_to_int(true);
+						tk.constant = (double)str.hex_to_int();
 					} else {
 						tk.constant = str.to_float();
 					}

+ 4 - 15
tests/test_string.h

@@ -370,12 +370,9 @@ TEST_CASE("[String] String to integer") {
 TEST_CASE("[String] Hex to integer") {
 	static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" };
 	static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD };
-	static const bool wo_prefix[4] = { false, true, true, true };
-	static const bool w_prefix[4] = { true, false, true, false };
 
 	for (int i = 0; i < 4; i++) {
-		CHECK((String(nums[i]).hex_to_int(true) == num[i]) == w_prefix[i]);
-		CHECK((String(nums[i]).hex_to_int(false) == num[i]) == wo_prefix[i]);
+		CHECK(String(nums[i]).hex_to_int() == num[i]);
 	}
 }
 
@@ -1155,20 +1152,12 @@ TEST_CASE("[String] hash") {
 	CHECK(a.hash64() != c.hash64());
 }
 
-TEST_CASE("[String] http_escape/unescape") {
+TEST_CASE("[String] uri_encode/unescape") {
 	String s = "Godot Engine:'docs'";
 	String t = "Godot%20Engine%3A%27docs%27";
 
-	CHECK(s.http_escape() == t);
-	CHECK(t.http_unescape() == s);
-}
-
-TEST_CASE("[String] percent_encode/decode") { // Note: is it redundant? Seems to be same as http_escape/unescape but in lower case.
-	String s = "Godot Engine:'docs'";
-	String t = "Godot%20Engine%3a%27docs%27";
-
-	CHECK(s.percent_encode() == t);
-	CHECK(t.percent_decode() == s);
+	CHECK(s.uri_encode() == t);
+	CHECK(t.uri_decode() == s);
 }
 
 TEST_CASE("[String] xml_escape/unescape") {