#include "SharedSearchPaths.h" #include "SearchPath/IWD.h" #include "SearchPathFilesystem.h" #include "Utils/Logging/Log.h" #include "Utils/StringUtils.h" #include #include namespace fs = std::filesystem; namespace { std::unique_ptr CreateSearchPath(const std::string& searchPathStr) { auto searchPath = std::make_unique(searchPathStr); con::info("Loaded search path \"{}\"", searchPathStr); SearchPaths searchPaths; bool hasIwds = false; std::filesystem::directory_iterator iterator(searchPathStr); const auto end = fs::end(iterator); for (auto i = fs::begin(iterator); i != end; ++i) { if (!i->is_regular_file()) continue; auto extension = i->path().extension().string(); utils::MakeStringLowerCase(extension); if (extension == ".iwd") { std::string iwdPath = i->path().string(); auto iwd = iwd::LoadFromFile(iwdPath); if (iwd) { if (!hasIwds) { searchPaths.CommitSearchPath(std::move(searchPath)); hasIwds = true; } searchPaths.CommitSearchPath(std::move(iwd)); } } } if (hasIwds) return std::make_unique(std::move(searchPaths)); return searchPath; } } // namespace SharedSearchPathEntry::SharedSearchPathEntry(std::unique_ptr searchPath) : m_search_path(std::move(searchPath)), m_ref_count(1) { } SharedSearchPaths::SharedSearchPaths() = default; SharedSearchPaths::~SharedSearchPaths() { Clear(); } void SharedSearchPaths::Clear() { for (auto& entry : m_search_path_entries) { entry.second.reset(); con::info("Unloaded search path \"{}\"", entry.first); } m_search_path_entries.clear(); m_search_paths = SearchPaths(); } ISearchPath& SharedSearchPaths::GetSearchPath() { return m_search_paths; } void SharedSearchPaths::RefSearchPath(const std::string& searchPathStr) { const auto existingSearchPath = m_search_path_entries.find(searchPathStr); if (existingSearchPath == m_search_path_entries.end()) { auto searchPath = CreateSearchPath(searchPathStr); m_search_paths.IncludeSearchPath(searchPath.get()); m_search_path_entries.emplace(searchPathStr, std::make_unique(std::move(searchPath))); } else { existingSearchPath->second->m_ref_count++; } } void SharedSearchPaths::UnrefSearchPath(const std::string& searchPathStr) { const auto existingSearchPath = m_search_path_entries.find(searchPathStr); if (existingSearchPath != m_search_path_entries.end()) { assert(existingSearchPath->second->m_ref_count > 0); const auto newRefCount = --existingSearchPath->second->m_ref_count; if (newRefCount == 0) { m_search_paths.RemoveSearchPath(existingSearchPath->second->m_search_path.get()); m_search_path_entries.erase(existingSearchPath); con::info("Unloaded search path \"{}\"", searchPathStr); } } }