From bfc720152a389c8110c814f600125ccf480075ac Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 21 Feb 2026 18:38:32 +0100 Subject: [vfs] remove usage of 'dynamic_cast', use ankerl::map for files (#3594) Do I need to writeout everything wrong with `dynamic_cast`? Also the usual std::map -> `ankerl::unordered_dense::map` conversion, seems to work just fine - but of course test that updates/DLCs/mods/cheats/etc are still being applied :) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3594 Reviewed-by: DraVee Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/core/file_sys/registered_cache.cpp | 219 +++++++++++---------------------- 1 file changed, 71 insertions(+), 148 deletions(-) (limited to 'src/core/file_sys/registered_cache.cpp') diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 42ec878436..1b2c45176b 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -353,8 +353,7 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const { return file; } -static std::optional CheckMapForContentRecord(const std::map& map, u64 title_id, - ContentRecordType type) { +static std::optional CheckMapForContentRecord(const ankerl::unordered_dense::map& map, u64 title_id, ContentRecordType type) { const auto cmnt_iter = map.find(title_id); if (cmnt_iter == map.cend()) { return std::nullopt; @@ -829,133 +828,96 @@ bool RegisteredCache::RawInstallYuzuMeta(const CNMT& cnmt) { } } Refresh(); - return std::find_if(yuzu_meta.begin(), yuzu_meta.end(), - [&cnmt](const std::pair& kv) { - return kv.second.GetType() == cnmt.GetType() && - kv.second.GetTitleID() == cnmt.GetTitleID(); - }) != yuzu_meta.end(); + return std::find_if(yuzu_meta.begin(), yuzu_meta.end(), [&cnmt](const std::pair& kv) { + return kv.second.GetType() == cnmt.GetType() && kv.second.GetTitleID() == cnmt.GetTitleID(); + }) != yuzu_meta.end(); } ContentProviderUnion::~ContentProviderUnion() = default; void ContentProviderUnion::SetSlot(ContentProviderUnionSlot slot, ContentProvider* provider) { - providers[slot] = provider; -} - -void ContentProviderUnion::ClearSlot(ContentProviderUnionSlot slot) { - providers[slot] = nullptr; + providers[size_t(slot)] = provider; } void ContentProviderUnion::Refresh() { - for (auto& provider : providers) { - if (provider.second == nullptr) - continue; - - provider.second->Refresh(); - } + for (auto e : providers) + if (e != nullptr) + e->Refresh(); } bool ContentProviderUnion::HasEntry(u64 title_id, ContentRecordType type) const { - for (const auto& provider : providers) { - if (provider.second == nullptr) - continue; - - if (provider.second->HasEntry(title_id, type)) + for (auto const e : providers) + if (e && e->HasEntry(title_id, type)) return true; - } - return false; } std::optional ContentProviderUnion::GetEntryVersion(u64 title_id) const { - for (const auto& provider : providers) { - if (provider.second == nullptr) + for (auto const e : providers) { + if (e == nullptr) continue; - - const auto res = provider.second->GetEntryVersion(title_id); - if (res != std::nullopt) + if (auto const res = e->GetEntryVersion(title_id); res != std::nullopt) return res; } - return std::nullopt; } VirtualFile ContentProviderUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const { - for (const auto& provider : providers) { - if (provider.second == nullptr) + for (auto const e : providers) { + if (e == nullptr) continue; - - const auto res = provider.second->GetEntryUnparsed(title_id, type); - if (res != nullptr) + if (auto const res = e->GetEntryUnparsed(title_id, type); res != nullptr) return res; } - return nullptr; } VirtualFile ContentProviderUnion::GetEntryRaw(u64 title_id, ContentRecordType type) const { - for (const auto& provider : providers) { - if (provider.second == nullptr) + for (auto const e : providers) { + if (e == nullptr) continue; - - const auto res = provider.second->GetEntryRaw(title_id, type); - if (res != nullptr) + if (auto const res = e->GetEntryRaw(title_id, type); res != nullptr) return res; } - return nullptr; } std::unique_ptr ContentProviderUnion::GetEntry(u64 title_id, ContentRecordType type) const { - for (const auto& provider : providers) { - if (provider.second == nullptr) + for (auto const e : providers) { + if (e == nullptr) continue; - - auto res = provider.second->GetEntry(title_id, type); - if (res != nullptr) + if (auto res = e->GetEntry(title_id, type); res != nullptr) return res; } - return nullptr; } -std::vector ContentProviderUnion::ListEntriesFilter( - std::optional title_type, std::optional record_type, - std::optional title_id) const { +std::vector ContentProviderUnion::ListEntriesFilter(std::optional title_type, std::optional record_type, std::optional title_id) const { std::vector out; - - for (const auto& provider : providers) { - if (provider.second == nullptr) - continue; - - const auto vec = provider.second->ListEntriesFilter(title_type, record_type, title_id); - std::copy(vec.begin(), vec.end(), std::back_inserter(out)); + for (auto const& e : providers) { + if (e != nullptr) { + auto const vec = e->ListEntriesFilter(title_type, record_type, title_id); + std::copy(vec.begin(), vec.end(), std::back_inserter(out)); + } } - std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); return out; } -std::vector> -ContentProviderUnion::ListEntriesFilterOrigin(std::optional origin, - std::optional title_type, - std::optional record_type, - std::optional title_id) const { +std::vector> ContentProviderUnion::ListEntriesFilterOrigin(std::optional origin, std::optional title_type, std::optional record_type, std::optional title_id) const { std::vector> out; - for (const auto& provider : providers) { - if (provider.second == nullptr) + for (size_t i = 0; i < providers.size(); ++i) { + auto const& e = providers[i]; + if (e == nullptr) continue; - - if (origin.has_value() && *origin != provider.first) + if (origin.has_value() && *origin != ContentProviderUnionSlot(i)) continue; - - const auto vec = provider.second->ListEntriesFilter(title_type, record_type, title_id); - std::transform(vec.begin(), vec.end(), std::back_inserter(out), - [&provider](const ContentProviderEntry& entry) { - return std::make_pair(provider.first, entry); - }); + auto const vec = e->ListEntriesFilter(title_type, record_type, title_id); + std::transform(vec.begin(), vec.end(), std::back_inserter(out), [i](const ContentProviderEntry& entry) { + return std::make_pair(ContentProviderUnionSlot(i), entry); + }); } std::sort(out.begin(), out.end()); @@ -963,40 +925,22 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional ContentProviderUnion::GetSlotForEntry( - u64 title_id, ContentRecordType type) const { - const auto iter = - std::find_if(providers.begin(), providers.end(), [title_id, type](const auto& provider) { - return provider.second != nullptr && provider.second->HasEntry(title_id, type); - }); - - if (iter == providers.end()) { - return std::nullopt; +std::optional ContentProviderUnion::GetSlotForEntry(u64 title_id, ContentRecordType type) const { + for (size_t i = 0; i < providers.size(); ++i) { + auto const& e = providers[i]; + if (e != nullptr && e->HasEntry(title_id, type)) + return {ContentProviderUnionSlot(i)}; } - - return iter->first; + return std::nullopt; } const ExternalContentProvider* ContentProviderUnion::GetExternalProvider() const { - auto it = providers.find(ContentProviderUnionSlot::External); - if (it != providers.end() && it->second != nullptr) { - return dynamic_cast(it->second); - } - return nullptr; -} - -const ContentProvider* ContentProviderUnion::GetSlotProvider(ContentProviderUnionSlot slot) const { - auto it = providers.find(slot); - if (it != providers.end()) { - return it->second; - } - return nullptr; + return static_cast(providers[size_t(ContentProviderUnionSlot::External)]); } ManualContentProvider::~ManualContentProvider() = default; -void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type, - u64 title_id, VirtualFile file) { +void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type, u64 title_id, VirtualFile file) { entries.insert_or_assign({title_type, content_type, title_id}, file); } @@ -1004,14 +948,13 @@ void ManualContentProvider::AddEntryWithVersion(TitleType title_type, ContentRec u64 title_id, u32 version, const std::string& version_string, VirtualFile file) { if (title_type == TitleType::Update) { - auto it = std::find_if(multi_version_entries.begin(), multi_version_entries.end(), - [title_id, version](const ExternalUpdateEntry& entry) { - return entry.title_id == title_id && entry.version == version; - }); + auto it = std::find_if(multi_version_entries.begin(), multi_version_entries.end(), [title_id, version](const ExternalUpdateEntry& entry) { + return entry.title_id == title_id && entry.version == version; + }); if (it != multi_version_entries.end()) { // Update existing entry - it->files[content_type] = file; + it->files[size_t(content_type)] = file; if (!version_string.empty()) { it->version_string = version_string; } @@ -1021,7 +964,7 @@ void ManualContentProvider::AddEntryWithVersion(TitleType title_type, ContentRec new_entry.title_id = title_id; new_entry.version = version; new_entry.version_string = version_string; - new_entry.files[content_type] = file; + new_entry.files[size_t(content_type)] = file; multi_version_entries.push_back(new_entry); } @@ -1118,26 +1061,19 @@ std::vector ManualContentProvider::ListUpdateVersions(u64 t VirtualFile ManualContentProvider::GetEntryForVersion(u64 title_id, ContentRecordType type, u32 version) const { for (const auto& entry : multi_version_entries) { if (entry.title_id == title_id && entry.version == version) { - auto it = entry.files.find(type); - if (it != entry.files.end()) { - return it->second; - } + if (auto const p = entry.files[size_t(type)]) + return p; } } return nullptr; } bool ManualContentProvider::HasMultipleVersions(u64 title_id, ContentRecordType type) const { - int count = 0; - for (const auto& entry : multi_version_entries) { - if (entry.title_id == title_id && entry.files.count(type) > 0) { - count++; - if (count > 1) { - return true; - } - } - } - return false; + size_t count = 0; + for (const auto& entry : multi_version_entries) + if (entry.title_id == title_id && entry.files[size_t(type)]) + ++count; + return count > 0; } ExternalContentProvider::ExternalContentProvider(std::vector load_directories) @@ -1256,7 +1192,7 @@ void ExternalContentProvider::ProcessNSP(const VirtualFile& file) { } } - std::map, std::map> version_files; + std::map, std::array> version_files; for (const auto& [title_id, nca_map] : ncas) { for (const auto& [type_pair, nca] : nca_map) { @@ -1277,7 +1213,7 @@ void ExternalContentProvider::ProcessNSP(const VirtualFile& file) { version = ver_it->second; } - version_files[{title_id, version}][content_type] = nca_file; + version_files[{title_id, version}][size_t(content_type)] = nca_file; } LOG_DEBUG(Service_FS, "Added entry - Title ID: {:016X}, Type: {}, Content: {}", @@ -1298,9 +1234,7 @@ void ExternalContentProvider::ProcessNSP(const VirtualFile& file) { bool version_exists = false; for (auto& existing : multi_version_entries) { if (existing.title_id == title_id && existing.version == version) { - for (const auto& [content_type, _file] : files_map) { - existing.files[content_type] = _file; - } + existing.files = files_map; if (existing.version_string.empty() && !ver_str.empty()) { existing.version_string = ver_str; } @@ -1383,7 +1317,7 @@ void ExternalContentProvider::ProcessXCI(const VirtualFile& file) { } } - std::map, std::map> version_files; + std::map, std::array> version_files; for (const auto& [title_id, nca_map] : ncas) { for (const auto& [type_pair, nca] : nca_map) { @@ -1404,7 +1338,7 @@ void ExternalContentProvider::ProcessXCI(const VirtualFile& file) { version = ver_it->second; } - version_files[{title_id, version}][content_type] = nca_file; + version_files[{title_id, version}][size_t(content_type)] = nca_file; } } } @@ -1422,9 +1356,7 @@ void ExternalContentProvider::ProcessXCI(const VirtualFile& file) { bool version_exists = false; for (auto& existing : multi_version_entries) { if (existing.title_id == title_id && existing.version == version) { - for (const auto& [content_type, _file] : files_map) { - existing.files[content_type] = _file; - } + existing.files = files_map; if (existing.version_string.empty() && !ver_str.empty()) { existing.version_string = ver_str; } @@ -1529,28 +1461,19 @@ std::vector ExternalContentProvider::ListUpdateVersions(u64 } VirtualFile ExternalContentProvider::GetEntryForVersion(u64 title_id, ContentRecordType type, u32 version) const { - for (const auto& entry : multi_version_entries) { - if (entry.title_id == title_id && entry.version == version) { - auto it = entry.files.find(type); - if (it != entry.files.end()) { - return it->second; - } - } - } + for (const auto& entry : multi_version_entries) + if (entry.title_id == title_id && entry.version == version) + if (auto const p = entry.files[size_t(type)]) + return p; return nullptr; } bool ExternalContentProvider::HasMultipleVersions(u64 title_id, ContentRecordType type) const { size_t count = 0; - for (const auto& entry : multi_version_entries) { - if (entry.title_id == title_id && entry.files.count(type) > 0) { - count++; - if (count > 1) { - return true; - } - } - } - return false; + for (const auto& entry : multi_version_entries) + if (entry.title_id == title_id && entry.files[size_t(type)]) + ++count; + return count > 1; } } // namespace FileSys -- cgit v1.2.3