summaryrefslogtreecommitdiffstats
path: root/core/string
diff options
context:
space:
mode:
Diffstat (limited to 'core/string')
-rw-r--r--core/string/node_path.h2
-rw-r--r--core/string/optimized_translation.cpp (renamed from core/string/compressed_translation.cpp)31
-rw-r--r--core/string/optimized_translation.h (renamed from core/string/compressed_translation.h)14
-rw-r--r--core/string/translation.cpp4
-rw-r--r--core/string/translation_po.cpp24
-rw-r--r--core/string/ustring.cpp159
-rw-r--r--core/string/ustring.h3
7 files changed, 162 insertions, 75 deletions
diff --git a/core/string/node_path.h b/core/string/node_path.h
index 26e15636d9..a277ab26fa 100644
--- a/core/string/node_path.h
+++ b/core/string/node_path.h
@@ -66,8 +66,6 @@ public:
void prepend_period();
- NodePath get_parent() const;
-
_FORCE_INLINE_ uint32_t hash() const {
if (!data) {
return 0;
diff --git a/core/string/compressed_translation.cpp b/core/string/optimized_translation.cpp
index 15abf63f7e..268562d971 100644
--- a/core/string/compressed_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* compressed_translation.cpp */
+/* optimized_translation.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "compressed_translation.h"
+#include "optimized_translation.h"
#include "core/templates/pair.h"
@@ -36,16 +36,17 @@ extern "C" {
#include "thirdparty/misc/smaz.h"
}
-struct _PHashTranslationCmp {
+struct CompressedString {
int orig_len;
CharString compressed;
int offset;
};
-void PHashTranslation::generate(const Ref<Translation> &p_from) {
+void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
// This method compresses a Translation instance.
// Right now, it doesn't handle context or plurals, so Translation subclasses using plurals or context (i.e TranslationPO) shouldn't be compressed.
#ifdef TOOLS_ENABLED
+ ERR_FAIL_COND(p_from.is_null());
List<StringName> keys;
p_from->get_message_list(&keys);
@@ -54,7 +55,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
Vector<Vector<Pair<int, CharString>>> buckets;
Vector<Map<uint32_t, int>> table;
Vector<uint32_t> hfunc_table;
- Vector<_PHashTranslationCmp> compressed;
+ Vector<CompressedString> compressed;
table.resize(size);
hfunc_table.resize(size);
@@ -76,7 +77,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
//compress string
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
- _PHashTranslationCmp ps;
+ CompressedString ps;
ps.orig_len = src_s.size();
ps.offset = total_compression_size;
@@ -182,7 +183,7 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) {
#endif
}
-bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
+bool OptimizedTranslation::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name.operator String();
if (name == "hash_table") {
hash_table = p_value;
@@ -199,7 +200,7 @@ bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
return true;
}
-bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
+bool OptimizedTranslation::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name.operator String();
if (name == "hash_table") {
r_ret = hash_table;
@@ -214,8 +215,8 @@ bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
-StringName PHashTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const {
- // p_context passed in is ignore. The use of context is not yet supported in PHashTranslation.
+StringName OptimizedTranslation::get_message(const StringName &p_src_text, const StringName &p_context) const {
+ // p_context passed in is ignore. The use of context is not yet supported in OptimizedTranslation.
int htsize = hash_table.size();
@@ -271,18 +272,18 @@ StringName PHashTranslation::get_message(const StringName &p_src_text, const Str
}
}
-StringName PHashTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
- // The use of plurals translation is not yet supported in PHashTranslation.
+StringName OptimizedTranslation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const {
+ // The use of plurals translation is not yet supported in OptimizedTranslation.
return get_message(p_src_text, p_context);
}
-void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
+void OptimizedTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "hash_table"));
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "bucket_table"));
p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "strings"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
}
-void PHashTranslation::_bind_methods() {
- ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate);
+void OptimizedTranslation::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("generate", "from"), &OptimizedTranslation::generate);
}
diff --git a/core/string/compressed_translation.h b/core/string/optimized_translation.h
index 0abb770178..bccf932383 100644
--- a/core/string/compressed_translation.h
+++ b/core/string/optimized_translation.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* compressed_translation.h */
+/* optimized_translation.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COMPRESSED_TRANSLATION_H
-#define COMPRESSED_TRANSLATION_H
+#ifndef OPTIMIZED_TRANSLATION_H
+#define OPTIMIZED_TRANSLATION_H
#include "core/string/translation.h"
-class PHashTranslation : public Translation {
- GDCLASS(PHashTranslation, Translation);
+class OptimizedTranslation : public Translation {
+ GDCLASS(OptimizedTranslation, Translation);
//this translation uses a sort of modified perfect hash algorithm
//it requires hashing strings twice and then does a binary search,
@@ -83,7 +83,7 @@ public:
virtual StringName get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context = "") const override;
void generate(const Ref<Translation> &p_from);
- PHashTranslation() {}
+ OptimizedTranslation() {}
};
-#endif // COMPRESSED_TRANSLATION_H
+#endif // OPTIMIZED_TRANSLATION_H
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 9cee218735..153f0190fd 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -835,7 +835,7 @@ Vector<String> Translation::_get_message_list() const {
void Translation::_set_messages(const Dictionary &p_messages) {
List<Variant> keys;
p_messages.get_key_list(&keys);
- for (auto E = keys.front(); E; E = E->next()) {
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
translation_map[E->get()] = p_messages[E->get()];
}
}
@@ -853,7 +853,7 @@ void Translation::set_locale(const String &p_locale) {
locale = univ_locale;
}
- if (OS::get_singleton()->get_main_loop()) {
+ if (OS::get_singleton()->get_main_loop() && TranslationServer::get_singleton()->get_loaded_locales().has(this)) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
}
}
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 42ba30fbe5..d6b84cabc9 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -30,7 +30,7 @@
#include "translation_po.h"
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#ifdef DEBUG_TRANSLATION_PO
void TranslationPO::print_translation_map() {
@@ -47,14 +47,14 @@ void TranslationPO::print_translation_map() {
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (auto E = context_l.front(); E; E = E->next()) {
+ for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
StringName ctx = E->get();
file->store_line(" ===== Context: " + String::utf8(String(ctx).utf8()) + " ===== ");
const HashMap<StringName, Vector<StringName>> &inner_map = translation_map[ctx];
List<StringName> id_l;
inner_map.get_key_list(&id_l);
- for (auto E2 = id_l.front(); E2; E2 = E2->next()) {
+ for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
StringName id = E2->get();
file->store_line("msgid: " + String::utf8(String(id).utf8()));
for (int i = 0; i < inner_map[id].size(); i++) {
@@ -74,7 +74,7 @@ Dictionary TranslationPO::_get_messages() const {
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (auto E = context_l.front(); E; E = E->next()) {
+ for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
StringName ctx = E->get();
const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx];
@@ -82,7 +82,7 @@ Dictionary TranslationPO::_get_messages() const {
List<StringName> id_l;
id_str_map.get_key_list(&id_l);
// Save list of id and strs associated with a context in a temporary dictionary.
- for (auto E2 = id_l.front(); E2; E2 = E2->next()) {
+ for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
StringName id = E2->get();
d2[id] = id_str_map[id];
}
@@ -98,14 +98,14 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) {
List<Variant> context_l;
p_messages.get_key_list(&context_l);
- for (auto E = context_l.front(); E; E = E->next()) {
+ for (List<Variant>::Element *E = context_l.front(); E; E = E->next()) {
StringName ctx = E->get();
const Dictionary &id_str_map = p_messages[ctx];
HashMap<StringName, Vector<StringName>> temp_map;
List<Variant> id_l;
id_str_map.get_key_list(&id_l);
- for (auto E2 = id_l.front(); E2; E2 = E2->next()) {
+ for (List<Variant>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
StringName id = E2->get();
temp_map[id] = id_str_map[id];
}
@@ -121,7 +121,7 @@ Vector<String> TranslationPO::_get_message_list() const {
get_message_list(&msgs);
Vector<String> v;
- for (auto E = msgs.front(); E; E = E->next()) {
+ for (List<StringName>::Element *E = msgs.front(); E; E = E->next()) {
v.push_back(E->get());
}
@@ -275,13 +275,13 @@ void TranslationPO::erase_message(const StringName &p_src_text, const StringName
}
void TranslationPO::get_message_list(List<StringName> *r_messages) const {
- // PHashTranslation uses this function to get the list of msgid.
+ // OptimizedTranslation uses this function to get the list of msgid.
// Return all the keys of translation_map under "" context.
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (auto E = context_l.front(); E; E = E->next()) {
+ for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
if (String(E->get()) != "") {
continue;
}
@@ -289,7 +289,7 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const {
List<StringName> msgid_l;
translation_map[E->get()].get_key_list(&msgid_l);
- for (auto E2 = msgid_l.front(); E2; E2 = E2->next()) {
+ for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) {
r_messages->push_back(E2->get());
}
}
@@ -300,7 +300,7 @@ int TranslationPO::get_message_count() const {
translation_map.get_key_list(&context_l);
int count = 0;
- for (auto E = context_l.front(); E; E = E->next()) {
+ for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
count += translation_map[E->get()].size();
}
return count;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 28228e4a83..ec5ec3dd79 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -54,7 +54,7 @@
#define snprintf _snprintf_s
#endif
-#define MAX_DIGITS 6
+#define MAX_DECIMALS 32
#define UPPERCASE(m_c) (((m_c) >= 'a' && (m_c) <= 'z') ? ((m_c) - ('a' - 'A')) : (m_c))
#define LOWERCASE(m_c) (((m_c) >= 'A' && (m_c) <= 'Z') ? ((m_c) + ('a' - 'A')) : (m_c))
#define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
@@ -240,6 +240,71 @@ String String::word_wrap(int p_chars_per_line) const {
return ret;
}
+Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const {
+ // Splits the URL into scheme, host, port, path. Strip credentials when present.
+ String base = *this;
+ r_scheme = "";
+ r_host = "";
+ r_port = 0;
+ r_path = "";
+ int pos = base.find("://");
+ // Scheme
+ if (pos != -1) {
+ r_scheme = base.substr(0, pos + 3).to_lower();
+ base = base.substr(pos + 3, base.length() - pos - 3);
+ }
+ pos = base.find("/");
+ // Path
+ if (pos != -1) {
+ r_path = base.substr(pos, base.length() - pos);
+ base = base.substr(0, pos);
+ }
+ // Host
+ pos = base.find("@");
+ if (pos != -1) {
+ // Strip credentials
+ base = base.substr(pos + 1, base.length() - pos - 1);
+ }
+ if (base.begins_with("[")) {
+ // Literal IPv6
+ pos = base.rfind("]");
+ if (pos == -1) {
+ return ERR_INVALID_PARAMETER;
+ }
+ r_host = base.substr(1, pos - 1);
+ base = base.substr(pos + 1, base.length() - pos - 1);
+ } else {
+ // Anything else
+ if (base.get_slice_count(":") > 1) {
+ return ERR_INVALID_PARAMETER;
+ }
+ pos = base.rfind(":");
+ if (pos == -1) {
+ r_host = base;
+ base = "";
+ } else {
+ r_host = base.substr(0, pos);
+ base = base.substr(pos, base.length() - pos);
+ }
+ }
+ if (r_host.is_empty()) {
+ return ERR_INVALID_PARAMETER;
+ }
+ r_host = r_host.to_lower();
+ // Port
+ if (base.begins_with(":")) {
+ base = base.substr(1, base.length() - 1);
+ if (!base.is_valid_integer()) {
+ return ERR_INVALID_PARAMETER;
+ }
+ r_port = base.to_int();
+ if (r_port < 1 || r_port > 65535) {
+ return ERR_INVALID_PARAMETER;
+ }
+ }
+ return OK;
+}
+
void String::copy_from(const char *p_cstr) {
// copy Latin-1 encoded c-string directly
if (!p_cstr) {
@@ -874,7 +939,7 @@ const char32_t *String::get_data() const {
}
void String::erase(int p_pos, int p_chars) {
- *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
+ *this = left(MAX(p_pos, 0)) + substr(p_pos + p_chars, length() - ((p_pos + p_chars)));
}
String String::capitalize() const {
@@ -1138,7 +1203,7 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int
remaining_len = left_edge;
}
- ret.invert();
+ ret.reverse();
return ret;
}
@@ -1314,8 +1379,11 @@ String String::num(double p_num, int p_decimals) {
}
#ifndef NO_USE_STDLIB
- if (p_decimals > 16) {
- p_decimals = 16;
+ if (p_decimals < 0) {
+ p_decimals = 14 - (int)floor(log10(p_num));
+ }
+ if (p_decimals > MAX_DECIMALS) {
+ p_decimals = MAX_DECIMALS;
}
char fmt[7];
@@ -1326,7 +1394,6 @@ String String::num(double p_num, int p_decimals) {
fmt[1] = 'l';
fmt[2] = 'f';
fmt[3] = 0;
-
} else if (p_decimals < 10) {
fmt[2] = '0' + p_decimals;
fmt[3] = 'l';
@@ -1393,8 +1460,9 @@ String String::num(double p_num, int p_decimals) {
double dec = p_num - (double)((int)p_num);
int digit = 0;
- if (p_decimals > MAX_DIGITS)
- p_decimals = MAX_DIGITS;
+ if (p_decimals > MAX_DECIMALS) {
+ p_decimals = MAX_DECIMALS;
+ }
int dec_int = 0;
int dec_max = 0;
@@ -1406,16 +1474,18 @@ String String::num(double p_num, int p_decimals) {
digit++;
if (p_decimals == -1) {
- if (digit == MAX_DIGITS) //no point in going to infinite
+ if (digit == MAX_DECIMALS) { //no point in going to infinite
break;
+ }
if (dec - (double)((int)dec) < 1e-6) {
break;
}
}
- if (digit == p_decimals)
+ if (digit == p_decimals) {
break;
+ }
}
dec *= 10;
int last = (int)dec % 10;
@@ -1551,7 +1621,15 @@ String String::num_real(double p_num) {
double dec = p_num - (double)((int)p_num);
int digit = 0;
- int decimals = MAX_DIGITS;
+
+#if REAL_T_IS_DOUBLE
+ int decimals = 14 - (int)floor(log10(p_num));
+#else
+ int decimals = 6 - (int)floor(log10(p_num));
+#endif
+ if (decimals > MAX_DECIMALS) {
+ decimals = MAX_DECIMALS;
+ }
int dec_int = 0;
int dec_max = 0;
@@ -3317,14 +3395,14 @@ String String::format(const Variant &values, String placeholder) const {
if (value_arr.size() == 2) {
Variant v_key = value_arr[0];
String key = v_key;
- if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+ if (key.left(1) == "\"" && key.right(1) == "\"") {
key = key.substr(1, key.length() - 2);
}
Variant v_val = value_arr[1];
String val = v_val;
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3336,7 +3414,7 @@ String String::format(const Variant &values, String placeholder) const {
Variant v_val = values_arr[i];
String val = v_val;
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3356,11 +3434,11 @@ String String::format(const Variant &values, String placeholder) const {
String key = E->get();
String val = d[E->get()];
- if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") {
+ if (key.left(1) == "\"" && key.right(1) == "\"") {
key = key.substr(1, key.length() - 2);
}
- if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") {
+ if (val.left(1) == "\"" && val.right(1) == "\"") {
val = val.substr(1, val.length() - 2);
}
@@ -3464,6 +3542,10 @@ String String::repeat(int p_count) const {
}
String String::left(int p_pos) const {
+ if (p_pos < 0) {
+ p_pos = length() + p_pos;
+ }
+
if (p_pos <= 0) {
return "";
}
@@ -3476,15 +3558,19 @@ String String::left(int p_pos) const {
}
String String::right(int p_pos) const {
- if (p_pos >= length()) {
- return "";
+ if (p_pos < 0) {
+ p_pos = length() + p_pos;
}
if (p_pos <= 0) {
+ return "";
+ }
+
+ if (p_pos >= length()) {
return *this;
}
- return substr(p_pos, (length() - p_pos));
+ return substr(length() - p_pos);
}
char32_t String::unicode_at(int p_idx) const {
@@ -3713,7 +3799,7 @@ String String::humanize_size(uint64_t p_size) {
return String::num(p_size / divisor).pad_decimals(digits) + " " + prefixes[prefix_idx];
}
-bool String::is_abs_path() const {
+bool String::is_absolute_path() const {
if (length() > 1) {
return (operator[](0) == '/' || operator[](0) == '\\' || find(":/") != -1 || find(":\\") != -1);
} else if ((length()) == 1) {
@@ -3772,9 +3858,9 @@ String String::uri_encode() const {
} else {
char h_Val[3];
#if defined(__GNUC__) || defined(_MSC_VER)
- snprintf(h_Val, 3, "%hhX", ord);
+ snprintf(h_Val, 3, "%02hhX", ord);
#else
- sprintf(h_Val, "%hhX", ord);
+ sprintf(h_Val, "%02hhX", ord);
#endif
res += "%";
res += h_Val;
@@ -3784,27 +3870,28 @@ String String::uri_encode() const {
}
String String::uri_decode() const {
- String res;
- for (int i = 0; i < length(); ++i) {
- if (unicode_at(i) == '%' && i + 2 < length()) {
- char32_t ord1 = unicode_at(i + 1);
+ CharString src = utf8();
+ CharString res;
+ for (int i = 0; i < src.length(); ++i) {
+ if (src[i] == '%' && i + 2 < src.length()) {
+ char ord1 = src[i + 1];
if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) {
- char32_t ord2 = unicode_at(i + 2);
+ char ord2 = src[i + 2];
if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) {
char bytes[3] = { (char)ord1, (char)ord2, 0 };
res += (char)strtol(bytes, nullptr, 16);
i += 2;
}
} else {
- res += unicode_at(i);
+ res += src[i];
}
- } else if (unicode_at(i) == '+') {
+ } else if (src[i] == '+') {
res += ' ';
} else {
- res += unicode_at(i);
+ res += src[i];
}
}
- return String::utf8(res.ascii());
+ return String::utf8(res);
}
String String::c_unescape() const {
@@ -4322,7 +4409,7 @@ bool String::is_resource_file() const {
}
bool String::is_rel_path() const {
- return !is_abs_path();
+ return !is_absolute_path();
}
String String::get_base_dir() const {
@@ -4765,7 +4852,7 @@ Vector<uint8_t> String::to_ascii_buffer() const {
size_t len = charstr.length();
retval.resize(len);
uint8_t *w = retval.ptrw();
- copymem(w, charstr.ptr(), len);
+ memcpy(w, charstr.ptr(), len);
return retval;
}
@@ -4781,7 +4868,7 @@ Vector<uint8_t> String::to_utf8_buffer() const {
size_t len = charstr.length();
retval.resize(len);
uint8_t *w = retval.ptrw();
- copymem(w, charstr.ptr(), len);
+ memcpy(w, charstr.ptr(), len);
return retval;
}
@@ -4797,7 +4884,7 @@ Vector<uint8_t> String::to_utf16_buffer() const {
size_t len = charstr.length() * sizeof(char16_t);
retval.resize(len);
uint8_t *w = retval.ptrw();
- copymem(w, (const void *)charstr.ptr(), len);
+ memcpy(w, (const void *)charstr.ptr(), len);
return retval;
}
@@ -4812,7 +4899,7 @@ Vector<uint8_t> String::to_utf32_buffer() const {
size_t len = s->length() * sizeof(char32_t);
retval.resize(len);
uint8_t *w = retval.ptrw();
- copymem(w, (const void *)s->ptr(), len);
+ memcpy(w, (const void *)s->ptr(), len);
return retval;
}
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 1e362d7683..f05865165d 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -397,7 +397,7 @@ public:
_FORCE_INLINE_ bool is_empty() const { return length() == 0; }
// path functions
- bool is_abs_path() const;
+ bool is_absolute_path() const;
bool is_rel_path() const;
bool is_resource_file() const;
String path_to(const String &p_path) const;
@@ -416,6 +416,7 @@ public:
String c_unescape() const;
String json_escape() const;
String word_wrap(int p_chars_per_line) const;
+ Error parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path) const;
String property_name_encode() const;