diff options
Diffstat (limited to 'core/string')
-rw-r--r-- | core/string/optimized_translation.cpp | 15 | ||||
-rw-r--r-- | core/string/translation.cpp | 35 | ||||
-rw-r--r-- | core/string/translation.h | 5 | ||||
-rw-r--r-- | core/string/ustring.cpp | 163 | ||||
-rw-r--r-- | core/string/ustring.h | 26 |
5 files changed, 98 insertions, 146 deletions
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp index 5863bd1c46..f8be564740 100644 --- a/core/string/optimized_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -64,7 +64,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { int idx = 0; int total_compression_size = 0; - int total_string_size = 0; for (const StringName &E : keys) { //hash string @@ -102,7 +101,6 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { compressed.write[idx] = ps; total_compression_size += ps.compressed.size(); - total_string_size += src_s.size(); idx++; } @@ -147,26 +145,23 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { uint32_t *btw = (uint32_t *)&btwb[0]; int btindex = 0; - int collisions = 0; for (int i = 0; i < size; i++) { const Map<uint32_t, int> &t = table[i]; if (t.size() == 0) { htw[i] = 0xFFFFFFFF; //nothing continue; - } else if (t.size() > 1) { - collisions += t.size() - 1; } htw[i] = btindex; btw[btindex++] = t.size(); btw[btindex++] = hfunc_table[i]; - for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) { - btw[btindex++] = E->key(); - btw[btindex++] = compressed[E->get()].offset; - btw[btindex++] = compressed[E->get()].compressed.size(); - btw[btindex++] = compressed[E->get()].orig_len; + for (const KeyValue<uint32_t, int> &E : t) { + btw[btindex++] = E.key; + btw[btindex++] = compressed[E.value].offset; + btw[btindex++] = compressed[E.value].compressed.size(); + btw[btindex++] = compressed[E.value].orig_len; } } diff --git a/core/string/translation.cpp b/core/string/translation.cpp index cb7d924556..cf61467d08 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -35,7 +35,6 @@ #include "core/os/os.h" #ifdef TOOLS_ENABLED -#include "editor/editor_settings.h" #include "main/main.h" #endif @@ -810,9 +809,12 @@ static const char *locale_names[] = { // - https://msdn.microsoft.com/en-us/library/windows/desktop/ms693062(v=vs.85).aspx static const char *locale_renames[][2] = { - { "in", "id" }, // Indonesian - { "iw", "he" }, // Hebrew - { "no", "nb" }, // Norwegian Bokmål + { "in", "id" }, // Indonesian + { "iw", "he" }, // Hebrew + { "no", "nb" }, // Norwegian Bokmål + { "C", "en" }, // "C" is the simple/default/untranslated Computer locale. + // ASCII-only, English, no currency symbols. Godot treats this as "en". + // See https://unix.stackexchange.com/a/87763/164141 "The C locale is"... { nullptr, nullptr } }; @@ -820,8 +822,8 @@ static const char *locale_renames[][2] = { Dictionary Translation::_get_messages() const { Dictionary d; - for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - d[E->key()] = E->value(); + for (const KeyValue<StringName, StringName> &E : translation_map) { + d[E.key] = E.value; } return d; } @@ -830,8 +832,8 @@ Vector<String> Translation::_get_message_list() const { Vector<String> msgs; msgs.resize(translation_map.size()); int idx = 0; - for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - msgs.set(idx, E->key()); + for (const KeyValue<StringName, StringName> &E : translation_map) { + msgs.set(idx, E.key); idx += 1; } @@ -875,6 +877,11 @@ void Translation::add_plural_message(const StringName &p_src_text, const Vector< } StringName Translation::get_message(const StringName &p_src_text, const StringName &p_context) const { + StringName ret; + if (GDVIRTUAL_CALL(_get_message, p_src_text, p_context, ret)) { + return ret; + } + if (p_context != StringName()) { WARN_PRINT("Translation class doesn't handle context. Using context in get_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles context, such as TranslationPO class"); } @@ -888,6 +895,11 @@ StringName Translation::get_message(const StringName &p_src_text, const StringNa } StringName Translation::get_plural_message(const StringName &p_src_text, const StringName &p_plural_text, int p_n, const StringName &p_context) const { + StringName ret; + if (GDVIRTUAL_CALL(_get_plural_message, p_src_text, p_plural_text, p_n, p_context, ret)) { + return ret; + } + WARN_PRINT("Translation class doesn't handle plural messages. Calling get_plural_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles plurals, such as TranslationPO class"); return get_message(p_src_text); } @@ -901,8 +913,8 @@ void Translation::erase_message(const StringName &p_src_text, const StringName & } void Translation::get_message_list(List<StringName> *r_messages) const { - for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - r_messages->push_back(E->key()); + for (const KeyValue<StringName, StringName> &E : translation_map) { + r_messages->push_back(E.key); } } @@ -923,6 +935,9 @@ void Translation::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_messages"), &Translation::_set_messages); ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages); + GDVIRTUAL_BIND(_get_plural_message, "src_message", "src_plural_message", "n", "context"); + GDVIRTUAL_BIND(_get_message, "src_message", "context"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale"); } diff --git a/core/string/translation.h b/core/string/translation.h index 4f179ac0fe..6aec0bb8ea 100644 --- a/core/string/translation.h +++ b/core/string/translation.h @@ -32,6 +32,8 @@ #define TRANSLATION_H #include "core/io/resource.h" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" class Translation : public Resource { GDCLASS(Translation, Resource); @@ -48,6 +50,9 @@ class Translation : public Resource { protected: static void _bind_methods(); + GDVIRTUAL2RC(StringName, _get_message, StringName, StringName); + GDVIRTUAL4RC(StringName, _get_plural_message, StringName, StringName, int, StringName); + public: void set_locale(const String &p_locale); _FORCE_INLINE_ String get_locale() const { return locale; } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index d2d563c5dc..daeb7fbd17 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -39,12 +39,9 @@ #include "core/string/ucaps.h" #include "core/variant/variant.h" -#include <cstdint> - -#ifndef NO_USE_STDLIB #include <stdio.h> #include <stdlib.h> -#endif +#include <cstdint> #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy @@ -1393,7 +1390,6 @@ String String::num(double p_num, int p_decimals) { return "inf"; } } -#ifndef NO_USE_STDLIB if (p_decimals < 0) { p_decimals = 14; @@ -1466,87 +1462,6 @@ String String::num(double p_num, int p_decimals) { } return buf; -#else - - String s; - String sd; - /* integer part */ - - bool neg = p_num < 0; - p_num = ABS(p_num); - int intn = (int)p_num; - - /* decimal part */ - - if (p_decimals > 0 || (p_decimals == -1 && (int)p_num != p_num)) { - double dec = p_num - (double)((int)p_num); - - int digit = 0; - if (p_decimals > MAX_DECIMALS) { - p_decimals = MAX_DECIMALS; - } - - int dec_int = 0; - int dec_max = 0; - - while (true) { - dec *= 10.0; - dec_int = dec_int * 10 + (int)dec % 10; - dec_max = dec_max * 10 + 9; - digit++; - - if (p_decimals == -1) { - if (digit == MAX_DECIMALS) { //no point in going to infinite - break; - } - - if (dec - (double)((int)dec) < 1e-6) { - break; - } - } - - if (digit == p_decimals) { - break; - } - } - dec *= 10; - int last = (int)dec % 10; - - if (last > 5) { - if (dec_int == dec_max) { - dec_int = 0; - intn++; - } else { - dec_int++; - } - } - - String decimal; - for (int i = 0; i < digit; i++) { - char num[2] = { 0, 0 }; - num[0] = '0' + dec_int % 10; - decimal = num + decimal; - dec_int /= 10; - } - sd = '.' + decimal; - } - - if (intn == 0) - - s = "0"; - else { - while (intn) { - char32_t num = '0' + (intn % 10); - intn /= 10; - s = num + s; - } - } - - s = s + sd; - if (neg) - s = "-" + s; - return s; -#endif } String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { @@ -1636,19 +1551,21 @@ String String::num_real(double p_num, bool p_trailing) { bool neg = p_num < 0; p_num = ABS(p_num); - int intn = (int)p_num; + int64_t intn = (int64_t)p_num; // Decimal part. if (intn != p_num) { - double dec = p_num - (double)(intn); + double dec = p_num - (double)intn; int digit = 0; -#if REAL_T_IS_DOUBLE +#ifdef REAL_T_IS_DOUBLE int decimals = 14; + double tolerance = 1e-14; #else int decimals = 6; + double tolerance = 1e-6; #endif // We want to align the digits to the above sane default, so we only // need to subtract log10 for numbers with a positive power of ten. @@ -1660,16 +1577,21 @@ String String::num_real(double p_num, bool p_trailing) { decimals = MAX_DECIMALS; } - int dec_int = 0; - int dec_max = 0; + // In case the value ends up ending in "99999", we want to add a + // tiny bit to the value we're checking when deciding when to stop, + // so we multiply by slightly above 1 (1 + 1e-7 or 1e-15). + double check_multiplier = 1 + tolerance / 10; + + int64_t dec_int = 0; + int64_t dec_max = 0; while (true) { dec *= 10.0; - dec_int = dec_int * 10 + (int)dec % 10; + dec_int = dec_int * 10 + (int64_t)dec % 10; dec_max = dec_max * 10 + 9; digit++; - if ((dec - (double)((int)dec)) < 1e-6) { + if ((dec - (double)(int64_t)(dec * check_multiplier)) < tolerance) { break; } @@ -1679,7 +1601,7 @@ String String::num_real(double p_num, bool p_trailing) { } dec *= 10; - int last = (int)dec % 10; + int last = (int64_t)dec % 10; if (last > 5) { if (dec_int == dec_max) { @@ -1733,19 +1655,18 @@ String String::num_scientific(double p_num) { return "inf"; } } -#ifndef NO_USE_STDLIB char buf[256]; #if defined(__GNUC__) || defined(_MSC_VER) -#if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT) - // MinGW and old MSC require _set_output_format() to conform to C99 output for printf +#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT) + // MinGW requires _set_output_format() to conform to C99 output for printf unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT); #endif snprintf(buf, 256, "%lg", p_num); -#if (defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT) +#if defined(__MINGW32__) && defined(_TWO_DIGIT_EXPONENT) && !defined(_UCRT) _set_output_format(old_exponent_format); #endif @@ -1756,10 +1677,6 @@ String String::num_scientific(double p_num) { buf[255] = 0; return buf; -#else - - return String::num(p_num); -#endif } String String::md5(const uint8_t *p_md5) { @@ -3645,7 +3562,7 @@ String String::strip_edges(bool left, bool right) const { } if (right) { - for (int i = (int)(len - 1); i >= 0; i--) { + for (int i = len - 1; i >= 0; i--) { if (operator[](i) <= 32) { end--; } else { @@ -4414,28 +4331,44 @@ bool String::is_resource_file() const { return begins_with("res://") && find("::") == -1; } -bool String::is_rel_path() const { +bool String::is_relative_path() const { return !is_absolute_path(); } String String::get_base_dir() const { - int basepos = find(":/"); - if (basepos == -1) { - basepos = find(":\\"); + int end = 0; + + // url scheme style base + int basepos = find("://"); + if (basepos != -1) { + end = basepos + 3; + } + + // windows top level directory base + if (end == 0) { + basepos = find(":/"); + if (basepos == -1) { + basepos = find(":\\"); + } + if (basepos != -1) { + end = basepos + 2; + } + } + + // unix root directory base + if (end == 0) { + if (begins_with("/")) { + end = 1; + } } + String rs; String base; - if (basepos != -1) { - int end = basepos + 3; + if (end != 0) { rs = substr(end, length()); base = substr(0, end); } else { - if (begins_with("/")) { - rs = substr(1, length()); - base = "/"; - } else { - rs = *this; - } + rs = *this; } int sep = MAX(rs.rfind("/"), rs.rfind("\\")); diff --git a/core/string/ustring.h b/core/string/ustring.h index ffb354d6e1..1d80ccf58d 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -51,11 +51,15 @@ class CharProxy { CowData<T> &_cowdata; static const T _null = 0; - _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &cowdata) : + _FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) : _index(p_index), - _cowdata(cowdata) {} + _cowdata(p_cowdata) {} public: + _FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) : + _index(p_other._index), + _cowdata(p_other._cowdata) {} + _FORCE_INLINE_ operator T() const { if (unlikely(_index == _cowdata.size())) { return _null; @@ -68,12 +72,12 @@ public: return _cowdata.ptr() + _index; } - _FORCE_INLINE_ void operator=(const T &other) const { - _cowdata.set(_index, other); + _FORCE_INLINE_ void operator=(const T &p_other) const { + _cowdata.set(_index, p_other); } - _FORCE_INLINE_ void operator=(const CharProxy<T> &other) const { - _cowdata.set(_index, other.operator T()); + _FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const { + _cowdata.set(_index, p_other.operator T()); } }; @@ -398,7 +402,7 @@ public: // path functions bool is_absolute_path() const; - bool is_rel_path() const; + bool is_relative_path() const; bool is_resource_file() const; String path_to(const String &p_path) const; String path_to_file(const String &p_path) const; @@ -523,10 +527,10 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St #define TTRGET(m_value) TTR(m_value) #else -#define TTR(m_value) (String()) -#define TTRN(m_value) (String()) -#define DTR(m_value) (String()) -#define DTRN(m_value) (String()) +#define TTR(m_value) String() +#define TTRN(m_value) String() +#define DTR(m_value) String() +#define DTRN(m_value) String() #define TTRC(m_value) (m_value) #define TTRGET(m_value) (m_value) #endif |