mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-23 22:37:07 +00:00
feat: unlinker auto paths (#848)
* chore: extract shared search paths code from modman * feat: automatically detect search paths for game directories * chore: adjust log levels for loading and unload search paths * fix: move iwd to obj common
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#include "SharedSearchPaths.h"
|
||||
|
||||
#include "SearchPath/IWD.h"
|
||||
#include "SearchPathFilesystem.h"
|
||||
#include "Utils/Logging/Log.h"
|
||||
#include "Utils/StringUtils.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unique_ptr<ISearchPath> CreateSearchPath(const std::string& searchPathStr)
|
||||
{
|
||||
auto searchPath = std::make_unique<SearchPathFilesystem>(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<SearchPaths>(std::move(searchPaths));
|
||||
|
||||
return searchPath;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SharedSearchPathEntry::SharedSearchPathEntry(std::unique_ptr<ISearchPath> 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<SharedSearchPathEntry>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user