diff options
Diffstat (limited to 'core/string')
-rw-r--r-- | core/string/node_path.cpp | 17 | ||||
-rw-r--r-- | core/string/optimized_translation.cpp | 6 | ||||
-rw-r--r-- | core/string/string_name.cpp | 108 | ||||
-rw-r--r-- | core/string/string_name.h | 36 | ||||
-rw-r--r-- | core/string/translation.cpp | 10 | ||||
-rw-r--r-- | core/string/translation_po.cpp | 23 | ||||
-rw-r--r-- | core/string/ustring.cpp | 7 |
7 files changed, 161 insertions, 46 deletions
diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp index d3afa7b4dd..5fae13779e 100644 --- a/core/string/node_path.cpp +++ b/core/string/node_path.cpp @@ -240,19 +240,26 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const { common_parent--; Vector<StringName> relpath; + relpath.resize(src_dirs.size() + dst_dirs.size() + 1); - for (int i = src_dirs.size() - 1; i > common_parent; i--) { - relpath.push_back(".."); + StringName *relpath_ptr = relpath.ptrw(); + + int path_size = 0; + StringName back_str(".."); + for (int i = common_parent + 1; i < src_dirs.size(); i++) { + relpath_ptr[path_size++] = back_str; } for (int i = common_parent + 1; i < dst_dirs.size(); i++) { - relpath.push_back(dst_dirs[i]); + relpath_ptr[path_size++] = dst_dirs[i]; } - if (relpath.size() == 0) { - relpath.push_back("."); + if (path_size == 0) { + relpath_ptr[path_size++] = "."; } + relpath.resize(path_size); + return NodePath(relpath, p_np.get_subnames(), false); } diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp index 268562d971..cf0b8d10db 100644 --- a/core/string/optimized_translation.cpp +++ b/core/string/optimized_translation.cpp @@ -66,9 +66,9 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { int total_compression_size = 0; int total_string_size = 0; - for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { + for (StringName &E : keys) { //hash string - CharString cs = E->get().operator String().utf8(); + CharString cs = E.operator String().utf8(); uint32_t h = hash(0, cs.get_data()); Pair<int, CharString> p; p.first = idx; @@ -76,7 +76,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) { buckets.write[h % size].push_back(p); //compress string - CharString src_s = p_from->get_message(E->get()).operator String().utf8(); + CharString src_s = p_from->get_message(E).operator String().utf8(); CompressedString ps; ps.orig_len = src_s.size(); ps.offset = total_compression_size; diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 14b87072bb..9024f60dae 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -41,13 +41,17 @@ StaticCString StaticCString::create(const char *p_ptr) { StringName::_Data *StringName::_table[STRING_TABLE_LEN]; -StringName _scs_create(const char *p_chr) { - return (p_chr[0] ? StringName(StaticCString::create(p_chr)) : StringName()); +StringName _scs_create(const char *p_chr, bool p_static) { + return (p_chr[0] ? StringName(StaticCString::create(p_chr), p_static) : StringName()); } bool StringName::configured = false; Mutex StringName::mutex; +#ifdef DEBUG_ENABLED +bool StringName::debug_stringname = false; +#endif + void StringName::setup() { ERR_FAIL_COND(configured); for (int i = 0; i < STRING_TABLE_LEN; i++) { @@ -59,12 +63,29 @@ void StringName::setup() { void StringName::cleanup() { MutexLock lock(mutex); +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + Vector<_Data *> data; + for (int i = 0; i < STRING_TABLE_LEN; i++) { + _Data *d = _table[i]; + while (d) { + data.push_back(d); + d = d->next; + } + } + print_line("\nStringName Reference Ranking:\n"); + data.sort_custom<DebugSortReferences>(); + for (int i = 0; i < MIN(100, data.size()); i++) { + print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references)); + } + } +#endif int lost_strings = 0; for (int i = 0; i < STRING_TABLE_LEN; i++) { while (_table[i]) { _Data *d = _table[i]; lost_strings++; - if (OS::get_singleton()->is_stdout_verbose()) { + if (d->static_count.get() != d->refcount.get() && OS::get_singleton()->is_stdout_verbose()) { if (d->cname) { print_line("Orphan StringName: " + String(d->cname)); } else { @@ -79,6 +100,7 @@ void StringName::cleanup() { if (lost_strings) { print_verbose("StringName: " + itos(lost_strings) + " unclaimed string names at exit."); } + configured = false; } void StringName::unref() { @@ -87,6 +109,13 @@ void StringName::unref() { if (_data && _data->refcount.unref()) { MutexLock lock(mutex); + if (_data->static_count.get() > 0) { + if (_data->cname) { + ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->cname)); + } else { + ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->name)); + } + } if (_data->prev) { _data->prev->next = _data->next; } else { @@ -153,7 +182,7 @@ StringName::StringName(const StringName &p_name) { } } -StringName::StringName(const char *p_name) { +StringName::StringName(const char *p_name, bool p_static) { _data = nullptr; ERR_FAIL_COND(!configured); @@ -181,25 +210,42 @@ StringName::StringName(const char *p_name) { if (_data) { if (_data->refcount.ref()) { // exists - return; + if (p_static) { + _data->static_count.increment(); + } +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + _data->debug_references++; + } +#endif } + + return; } _data = memnew(_Data); _data->name = p_name; _data->refcount.init(); + _data->static_count.set(p_static ? 1 : 0); _data->hash = hash; _data->idx = idx; _data->cname = nullptr; _data->next = _table[idx]; _data->prev = nullptr; +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + // Keep in memory, force static. + _data->refcount.ref(); + _data->static_count.increment(); + } +#endif if (_table[idx]) { _table[idx]->prev = _data; } _table[idx] = _data; } -StringName::StringName(const StaticCString &p_static_string) { +StringName::StringName(const StaticCString &p_static_string, bool p_static) { _data = nullptr; ERR_FAIL_COND(!configured); @@ -225,6 +271,14 @@ StringName::StringName(const StaticCString &p_static_string) { if (_data) { if (_data->refcount.ref()) { // exists + if (p_static) { + _data->static_count.increment(); + } +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + _data->debug_references++; + } +#endif return; } } @@ -232,18 +286,26 @@ StringName::StringName(const StaticCString &p_static_string) { _data = memnew(_Data); _data->refcount.init(); + _data->static_count.set(p_static ? 1 : 0); _data->hash = hash; _data->idx = idx; _data->cname = p_static_string.ptr; _data->next = _table[idx]; _data->prev = nullptr; +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + // Keep in memory, force static. + _data->refcount.ref(); + _data->static_count.increment(); + } +#endif if (_table[idx]) { _table[idx]->prev = _data; } _table[idx] = _data; } -StringName::StringName(const String &p_name) { +StringName::StringName(const String &p_name, bool p_static) { _data = nullptr; ERR_FAIL_COND(!configured); @@ -269,6 +331,14 @@ StringName::StringName(const String &p_name) { if (_data) { if (_data->refcount.ref()) { // exists + if (p_static) { + _data->static_count.increment(); + } +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + _data->debug_references++; + } +#endif return; } } @@ -276,11 +346,20 @@ StringName::StringName(const String &p_name) { _data = memnew(_Data); _data->name = p_name; _data->refcount.init(); + _data->static_count.set(p_static ? 1 : 0); _data->hash = hash; _data->idx = idx; _data->cname = nullptr; _data->next = _table[idx]; _data->prev = nullptr; +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + // Keep in memory, force static. + _data->refcount.ref(); + _data->static_count.increment(); + } +#endif + if (_table[idx]) { _table[idx]->prev = _data; } @@ -311,6 +390,12 @@ StringName StringName::search(const char *p_name) { } if (_data && _data->refcount.ref()) { +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + _data->debug_references++; + } +#endif + return StringName(_data); } @@ -368,16 +453,17 @@ StringName StringName::search(const String &p_name) { } if (_data && _data->refcount.ref()) { +#ifdef DEBUG_ENABLED + if (unlikely(debug_stringname)) { + _data->debug_references++; + } +#endif return StringName(_data); } return StringName(); //does not exist } -StringName::~StringName() { - unref(); -} - bool operator==(const String &p_name, const StringName &p_string_name) { return p_name == p_string_name.operator String(); } diff --git a/core/string/string_name.h b/core/string/string_name.h index 44d0ea14fa..ce7988744b 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -44,16 +44,19 @@ struct StaticCString { class StringName { enum { - STRING_TABLE_BITS = 12, + STRING_TABLE_BITS = 16, STRING_TABLE_LEN = 1 << STRING_TABLE_BITS, STRING_TABLE_MASK = STRING_TABLE_LEN - 1 }; struct _Data { SafeRefCount refcount; + SafeNumeric<uint32_t> static_count; const char *cname = nullptr; String name; - +#ifdef DEBUG_ENABLED + uint32_t debug_references = 0; +#endif String get_name() const { return cname ? String(cname) : name; } int idx = 0; uint32_t hash = 0; @@ -79,6 +82,15 @@ class StringName { static void setup(); static void cleanup(); static bool configured; +#ifdef DEBUG_ENABLED + struct DebugSortReferences { + bool operator()(const _Data *p_left, const _Data *p_right) const { + return p_left->debug_references > p_right->debug_references; + } + }; + + static bool debug_stringname; +#endif StringName(_Data *p_data) { _data = p_data; } @@ -146,12 +158,20 @@ public: }; void operator=(const StringName &p_name); - StringName(const char *p_name); + StringName(const char *p_name, bool p_static = false); StringName(const StringName &p_name); - StringName(const String &p_name); - StringName(const StaticCString &p_static_string); + StringName(const String &p_name, bool p_static = false); + StringName(const StaticCString &p_static_string, bool p_static = false); StringName() {} - ~StringName(); + _FORCE_INLINE_ ~StringName() { + if (likely(configured) && _data) { //only free if configured + unref(); + } + } + +#ifdef DEBUG_ENABLED + static void set_debug_stringnames(bool p_enable) { debug_stringname = p_enable; } +#endif }; bool operator==(const String &p_name, const StringName &p_string_name); @@ -159,6 +179,8 @@ bool operator!=(const String &p_name, const StringName &p_string_name); bool operator==(const char *p_name, const StringName &p_string_name); bool operator!=(const char *p_name, const StringName &p_string_name); -StringName _scs_create(const char *p_chr); +StringName _scs_create(const char *p_chr, bool p_static = false); + +#define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })() #endif // STRING_NAME_H diff --git a/core/string/translation.cpp b/core/string/translation.cpp index 153f0190fd..981954c8ae 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -84,6 +84,7 @@ static const char *locale_list[] = { "ast_ES", // Asturian (Spain) "ayc_PE", // Southern Aymara (Peru) "ay_PE", // Aymara (Peru) + "az", // Azerbaijani "az_AZ", // Azerbaijani (Azerbaijan) "be", // Belarusian "be_BY", // Belarusian (Belarus) @@ -240,6 +241,7 @@ static const char *locale_list[] = { "ka_GE", // Georgian (Georgia) "kk_KZ", // Kazakh (Kazakhstan) "kl_GL", // Kalaallisut (Greenland) + "km", // Central Khmer "km_KH", // Central Khmer (Cambodia) "kn_IN", // Kannada (India) "kok_IN", // Konkani (India) @@ -390,6 +392,7 @@ static const char *locale_list[] = { "tr_CY", // Turkish (Cyprus) "tr_TR", // Turkish (Turkey) "ts_ZA", // Tsonga (South Africa) + "tt", // Tatar "tt_RU", // Tatar (Russia) "tzm", // Central Atlas Tamazight "tzm_MA", // Central Atlas Tamazight (Marrocos) @@ -458,6 +461,7 @@ static const char *locale_names[] = { "Asturian (Spain)", "Southern Aymara (Peru)", "Aymara (Peru)", + "Azerbaijani", "Azerbaijani (Azerbaijan)", "Belarusian", "Belarusian (Belarus)", @@ -614,6 +618,7 @@ static const char *locale_names[] = { "Georgian (Georgia)", "Kazakh (Kazakhstan)", "Kalaallisut (Greenland)", + "Central Khmer", "Central Khmer (Cambodia)", "Kannada (India)", "Konkani (India)", @@ -764,6 +769,7 @@ static const char *locale_names[] = { "Turkish (Cyprus)", "Turkish (Turkey)", "Tsonga (South Africa)", + "Tatar", "Tatar (Russia)", "Central Atlas Tamazight", "Central Atlas Tamazight (Marrocos)", @@ -835,8 +841,8 @@ 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 (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - translation_map[E->get()] = p_messages[E->get()]; + for (Variant &E : keys) { + translation_map[E] = p_messages[E]; } } diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index f9b4e661e4..afd3b76588 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -47,8 +47,7 @@ void TranslationPO::print_translation_map() { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { - StringName ctx = E->get(); + for (StringName &ctx : context_l) { file->store_line(" ===== Context: " + String::utf8(String(ctx).utf8()) + " ===== "); const HashMap<StringName, Vector<StringName>> &inner_map = translation_map[ctx]; @@ -74,8 +73,7 @@ Dictionary TranslationPO::_get_messages() const { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { - StringName ctx = E->get(); + for (StringName &ctx : context_l) { const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx]; Dictionary d2; @@ -98,8 +96,7 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) { List<Variant> context_l; p_messages.get_key_list(&context_l); - for (List<Variant>::Element *E = context_l.front(); E; E = E->next()) { - StringName ctx = E->get(); + for (Variant &ctx : context_l) { const Dictionary &id_str_map = p_messages[ctx]; HashMap<StringName, Vector<StringName>> temp_map; @@ -121,8 +118,8 @@ Vector<String> TranslationPO::_get_message_list() const { get_message_list(&msgs); Vector<String> v; - for (List<StringName>::Element *E = msgs.front(); E; E = E->next()) { - v.push_back(E->get()); + for (StringName &E : msgs) { + v.push_back(E); } return v; @@ -281,13 +278,13 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { - if (String(E->get()) != "") { + for (StringName &E : context_l) { + if (String(E) != "") { continue; } List<StringName> msgid_l; - translation_map[E->get()].get_key_list(&msgid_l); + translation_map[E].get_key_list(&msgid_l); for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) { r_messages->push_back(E2->get()); @@ -300,8 +297,8 @@ int TranslationPO::get_message_count() const { translation_map.get_key_list(&context_l); int count = 0; - for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { - count += translation_map[E->get()].size(); + for (StringName &E : context_l) { + count += translation_map[E].size(); } return count; } diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 4cd2915ffa..dbb8dc8283 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3421,11 +3421,8 @@ String String::format(const Variant &values, String placeholder) const { List<Variant> keys; d.get_key_list(&keys); - for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - String key = E->get(); - String val = d[E->get()]; - - new_string = new_string.replace(placeholder.replace("_", key), val); + for (Variant &key : keys) { + new_string = new_string.replace(placeholder.replace("_", key), d[key]); } } else { ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data()); |