mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-22 13:57:07 +00:00
* 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
116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
#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);
|
|
}
|
|
}
|
|
}
|