diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index cf08072b6..5f069e744 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3381,6 +3381,39 @@ CharString String::utf8() const { return utf8s; } +int String::utf8_length() const { + int l = length(); + if (!l) { + return 0; + } + + const CharType *d = &operator[](0); + int fl = 0; + for (int i = 0; i < l; i++) { + uint32_t c = d[i]; + if (c <= 0x7f) { // 7 bits. + fl += 1; + } else if (c <= 0x7ff) { // 11 bits + fl += 2; + } else if (c <= 0xffff) { // 16 bits + fl += 3; + } else if (c <= 0x001fffff) { // 21 bits + fl += 4; + } else if (c <= 0x03ffffff) { // 26 bits + fl += 5; + print_unicode_error(vformat("Invalid unicode codepoint (%x)", c)); + } else if (c <= 0x7fffffff) { // 31 bits + fl += 6; + print_unicode_error(vformat("Invalid unicode codepoint (%x)", c)); + } else { + fl += 1; + print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as UTF-8", c), true); + } + } + + return fl; +} + String String::utf16(const char16_t *p_utf16, int p_len) { String ret; ret.parse_utf16(p_utf16, p_len); @@ -3554,6 +3587,32 @@ Char16String String::utf16() const { return utf16s; } +int String::utf16_length() const { + int l = length(); + if (!l) { + return 0; + } + + const CharType *d = &operator[](0); + int fl = 0; + for (int i = 0; i < l; i++) { + uint32_t c = d[i]; + if (c <= 0xffff) { // 16 bits. + fl += 1; + if ((c & 0xfffff800) == 0xd800) { + print_unicode_error(vformat("Unpaired surrogate (%x)", c)); + } + } else if (c <= 0x10ffff) { // 32 bits. + fl += 2; + } else { + print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as UTF-16", c), true); + fl += 1; + } + } + + return fl; +} + uint32_t String::hash(const char *p_cstr) { uint32_t hashv = 5381; uint32_t c; diff --git a/core/string/ustring.h b/core/string/ustring.h index fa312b62d..375fd26e6 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -436,10 +436,12 @@ public: CharString utf8() const; Error parse_utf8(const char *p_utf8, int p_len = -1, bool p_skip_cr = false); //return true on error static String utf8(const char *p_utf8, int p_len = -1); + int utf8_length() const; Char16String utf16() const; Error parse_utf16(const char16_t *p_utf16, int p_len = -1); static String utf16(const char16_t *p_utf16, int p_len = -1); + int utf16_length() const; static uint32_t hash(const char *p_cstr); /* hash the string */ static uint32_t hash(const char *p_cstr, int p_len); /* hash the string */ diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 80ab2d935..d680f0b19 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -30,14 +30,14 @@ #include "variant.h" -#include "core/math/color_names.inc" #include "core/core_string_names.h" #include "core/crypto/crypto_core.h" #include "core/io/compression.h" +#include "core/math/color_names.inc" #include "core/object/object.h" #include "core/object/object_rc.h" -#include "core/os/os.h" #include "core/object/script_language.h" +#include "core/os/os.h" typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args); typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); @@ -377,6 +377,8 @@ struct _VariantCall { VCALL_LOCALMEM1R(String, unicode_at); VCALL_LOCALMEM1R(String, ord_at); VCALL_LOCALMEM2(String, erase); + VCALL_LOCALMEM0R(String, utf8_length); + VCALL_LOCALMEM0R(String, utf16_length); VCALL_LOCALMEM0R(String, hash); VCALL_LOCALMEM0R(String, md5_text); VCALL_LOCALMEM0R(String, sha1_text); @@ -1650,7 +1652,7 @@ struct _VariantCall { VCALL_PTR1(Projection, adjust_perspective_znear); VCALL_PTR1R(Projection, perspective_znear_adjusted); static void _call_Projection_get_projection_plane(Variant &r_ret, Variant &p_self, const Variant **p_args) { - r_ret = reinterpret_cast(p_self._data._ptr)->get_projection_plane((Projection::Planes)(p_args[0]->operator int())); + r_ret = reinterpret_cast(p_self._data._ptr)->get_projection_plane((Projection::Planes)(p_args[0]->operator int())); } VCALL_PTR0R(Projection, flipped_y); VCALL_PTR1R(Projection, jitter_offseted); @@ -2553,6 +2555,9 @@ void register_variant_methods() { ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray()); + ADDFUNC0R(STRING, INT, String, utf8_length, varray()); + ADDFUNC0R(STRING, INT, String, utf16_length, varray()); + ADDFUNC0R(STRING, INT, String, hash, varray()); ADDFUNC0R(STRING, STRING, String, md5_text, varray()); ADDFUNC0R(STRING, STRING, String, sha1_text, varray());