mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-10 14:58:10 -05:00
refactor: rework search paths
This commit is contained in:
@ -1,363 +0,0 @@
|
||||
#include "IWD.h"
|
||||
|
||||
#include "ObjLoading.h"
|
||||
#include "Utils/FileToZlibWrapper.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unzip.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
ObjContainerRepository<IWD, ISearchPath> IWD::Repository;
|
||||
|
||||
class IWDFile final : public objbuf
|
||||
{
|
||||
public:
|
||||
class IParent
|
||||
{
|
||||
public:
|
||||
virtual ~IParent() = default;
|
||||
|
||||
virtual void OnIWDFileClose() = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
IParent* m_parent;
|
||||
bool m_open;
|
||||
int64_t m_size;
|
||||
unzFile m_container;
|
||||
bool m_peeked;
|
||||
int_type m_peek_symbol;
|
||||
|
||||
public:
|
||||
IWDFile(IParent* parent, const unzFile container, const int64_t size)
|
||||
: m_parent(parent),
|
||||
m_open(true),
|
||||
m_size(size),
|
||||
m_container(container),
|
||||
m_peeked(false),
|
||||
m_peek_symbol(0)
|
||||
{
|
||||
}
|
||||
|
||||
~IWDFile() override
|
||||
{
|
||||
if (m_open)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int_type underflow() override
|
||||
{
|
||||
if (m_peeked)
|
||||
return m_peek_symbol;
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
m_peeked = true;
|
||||
return static_cast<int_type>(m_peek_symbol);
|
||||
}
|
||||
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int_type uflow() override
|
||||
{
|
||||
if (m_peeked)
|
||||
{
|
||||
m_peeked = false;
|
||||
return m_peek_symbol;
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
return result >= 0 ? static_cast<int_type>(m_peek_symbol) : EOF;
|
||||
}
|
||||
|
||||
std::streamsize xsgetn(char* ptr, std::streamsize count) override
|
||||
{
|
||||
if (m_peeked && count >= 1)
|
||||
{
|
||||
*ptr = static_cast<char>(m_peek_symbol);
|
||||
ptr++;
|
||||
count--;
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, ptr, static_cast<unsigned>(count));
|
||||
|
||||
return result >= 0 ? static_cast<std::streamsize>(result) : 0;
|
||||
}
|
||||
|
||||
pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override
|
||||
{
|
||||
const auto currentPos = unztell64(m_container);
|
||||
|
||||
pos_type targetPos;
|
||||
if (dir == std::ios_base::beg)
|
||||
{
|
||||
targetPos = off;
|
||||
}
|
||||
else if (dir == std::ios_base::cur)
|
||||
{
|
||||
targetPos = currentPos + off;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPos = m_size - off;
|
||||
}
|
||||
|
||||
return seekpos(targetPos, mode);
|
||||
}
|
||||
|
||||
pos_type seekpos(const pos_type pos, const std::ios_base::openmode mode) override
|
||||
{
|
||||
const auto currentPos = unztell64(m_container);
|
||||
|
||||
if (static_cast<pos_type>(currentPos) < pos)
|
||||
{
|
||||
auto skipAmount = pos - static_cast<pos_type>(currentPos);
|
||||
while (skipAmount > 0)
|
||||
{
|
||||
char temp[1024];
|
||||
const auto toRead = skipAmount > sizeof(temp) ? sizeof(temp) : static_cast<size_t>(skipAmount);
|
||||
unzReadCurrentFile(m_container, temp, toRead);
|
||||
skipAmount -= toRead;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
if (currentPos == pos)
|
||||
{
|
||||
// This is fine
|
||||
return currentPos;
|
||||
}
|
||||
|
||||
return std::streampos(-1);
|
||||
}
|
||||
|
||||
public:
|
||||
_NODISCARD bool is_open() const override
|
||||
{
|
||||
return m_open;
|
||||
}
|
||||
|
||||
bool close() override
|
||||
{
|
||||
unzCloseCurrentFile(m_container);
|
||||
m_open = false;
|
||||
|
||||
m_parent->OnIWDFileClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IParent
|
||||
{
|
||||
class IWDEntry
|
||||
{
|
||||
public:
|
||||
int64_t m_size{};
|
||||
unz_file_pos m_file_pos{};
|
||||
};
|
||||
|
||||
std::string m_path;
|
||||
std::unique_ptr<std::istream> m_stream;
|
||||
unzFile m_unz_file;
|
||||
|
||||
IWDFile* m_last_file;
|
||||
|
||||
std::map<std::string, IWDEntry> m_entry_map;
|
||||
|
||||
public:
|
||||
Impl(std::string path, std::unique_ptr<std::istream> stream)
|
||||
: m_path(std::move(path)),
|
||||
m_stream(std::move(stream)),
|
||||
m_unz_file(nullptr),
|
||||
m_last_file(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~Impl() override
|
||||
{
|
||||
if (m_unz_file != nullptr)
|
||||
{
|
||||
unzClose(m_unz_file);
|
||||
m_unz_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Impl(const Impl& other) = delete;
|
||||
Impl(Impl&& other) noexcept = default;
|
||||
Impl& operator=(const Impl& other) = delete;
|
||||
Impl& operator=(Impl&& other) noexcept = default;
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_stream.get());
|
||||
m_unz_file = unzOpen2("", &ioFunctions);
|
||||
|
||||
if (m_unz_file == nullptr)
|
||||
{
|
||||
printf("Could not open IWD \"%s\"\n", m_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = unzGoToFirstFile(m_unz_file);
|
||||
while (ret == Z_OK)
|
||||
{
|
||||
unz_file_info64 info;
|
||||
char fileNameBuffer[256];
|
||||
unzGetCurrentFileInfo64(m_unz_file, &info, fileNameBuffer, sizeof(fileNameBuffer), nullptr, 0, nullptr, 0);
|
||||
|
||||
std::string fileName(fileNameBuffer);
|
||||
std::filesystem::path path(fileName);
|
||||
|
||||
if (path.has_filename())
|
||||
{
|
||||
IWDEntry entry;
|
||||
entry.m_size = info.uncompressed_size;
|
||||
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
||||
m_entry_map.emplace(std::move(fileName), entry);
|
||||
}
|
||||
|
||||
ret = unzGoToNextFile(m_unz_file);
|
||||
}
|
||||
|
||||
if (ObjLoading::Configuration.Verbose)
|
||||
{
|
||||
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entry_map.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SearchPathOpenFile Open(const std::string& fileName) override
|
||||
{
|
||||
if (m_unz_file == nullptr)
|
||||
{
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
auto iwdFilename = fileName;
|
||||
std::ranges::replace(iwdFilename, '\\', '/');
|
||||
|
||||
const auto iwdEntry = m_entry_map.find(iwdFilename);
|
||||
|
||||
if (iwdEntry != m_entry_map.end())
|
||||
{
|
||||
if (m_last_file != nullptr)
|
||||
{
|
||||
throw std::runtime_error("Trying to open new IWD file while last one was not yet closed.");
|
||||
}
|
||||
|
||||
auto pos = iwdEntry->second.m_file_pos;
|
||||
unzGoToFilePos(m_unz_file, &pos);
|
||||
|
||||
if (unzOpenCurrentFile(m_unz_file) == UNZ_OK)
|
||||
{
|
||||
auto result = std::make_unique<IWDFile>(this, m_unz_file, iwdEntry->second.m_size);
|
||||
m_last_file = result.get();
|
||||
return SearchPathOpenFile(std::make_unique<iobjstream>(std::move(result)), iwdEntry->second.m_size);
|
||||
}
|
||||
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
std::string GetPath() override
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
std::string GetName() override
|
||||
{
|
||||
return fs::path(m_path).filename().string();
|
||||
}
|
||||
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override
|
||||
{
|
||||
if (options.m_disk_files_only)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& [entryName, entry] : m_entry_map)
|
||||
{
|
||||
std::filesystem::path entryPath(entryName);
|
||||
|
||||
if (!options.m_should_include_subdirectories && entryPath.has_parent_path())
|
||||
continue;
|
||||
|
||||
if (options.m_filter_extensions && options.m_extension != entryPath.extension().string())
|
||||
continue;
|
||||
|
||||
callback(entryName);
|
||||
}
|
||||
}
|
||||
|
||||
void OnIWDFileClose() override
|
||||
{
|
||||
m_last_file = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
IWD::IWD(std::string path, std::unique_ptr<std::istream> stream)
|
||||
{
|
||||
m_impl = new Impl(std::move(path), std::move(stream));
|
||||
}
|
||||
|
||||
IWD::~IWD()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
IWD::IWD(IWD&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
IWD& IWD::operator=(IWD&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IWD::Initialize()
|
||||
{
|
||||
return m_impl->Initialize();
|
||||
}
|
||||
|
||||
SearchPathOpenFile IWD::Open(const std::string& fileName)
|
||||
{
|
||||
return m_impl->Open(fileName);
|
||||
}
|
||||
|
||||
std::string IWD::GetPath()
|
||||
{
|
||||
return m_impl->GetPath();
|
||||
}
|
||||
|
||||
std::string IWD::GetName()
|
||||
{
|
||||
return m_impl->GetName();
|
||||
}
|
||||
|
||||
void IWD::Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback)
|
||||
{
|
||||
return m_impl->Find(options, callback);
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ObjContainer/ObjContainerRepository.h"
|
||||
#include "SearchPath/ISearchPath.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Utils/ObjStream.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class IWD final : public ISearchPath, IObjContainer
|
||||
{
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
|
||||
public:
|
||||
static ObjContainerRepository<IWD, ISearchPath> Repository;
|
||||
|
||||
IWD(std::string path, std::unique_ptr<std::istream> stream);
|
||||
~IWD() override;
|
||||
|
||||
IWD(const IWD& other) = delete;
|
||||
IWD(IWD&& other) noexcept;
|
||||
IWD& operator=(const IWD& other) = delete;
|
||||
IWD& operator=(IWD&& other) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Initializes the IWD container.
|
||||
* \return \c true when initialization was successful.
|
||||
*/
|
||||
bool Initialize();
|
||||
|
||||
SearchPathOpenFile Open(const std::string& fileName) override;
|
||||
std::string GetPath() override;
|
||||
std::string GetName() override;
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||
};
|
@ -1,46 +1,3 @@
|
||||
#include "ObjLoading.h"
|
||||
|
||||
#include "IObjLoader.h"
|
||||
#include "ObjContainer/IWD/IWD.h"
|
||||
#include "SearchPath/SearchPaths.h"
|
||||
#include "Utils/ObjFileStream.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
ObjLoading::Configuration_t ObjLoading::Configuration;
|
||||
|
||||
void ObjLoading::LoadIWDsInSearchPath(ISearchPath& searchPath)
|
||||
{
|
||||
searchPath.Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
|
||||
[&searchPath](const std::string& path)
|
||||
{
|
||||
auto file = std::make_unique<std::ifstream>(path, std::fstream::in | std::fstream::binary);
|
||||
|
||||
if (file->is_open())
|
||||
{
|
||||
auto iwd = std::make_unique<IWD>(path, std::move(file));
|
||||
|
||||
if (iwd->Initialize())
|
||||
{
|
||||
IWD::Repository.AddContainer(std::move(iwd), &searchPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath& searchPath)
|
||||
{
|
||||
IWD::Repository.RemoveContainerReferences(&searchPath);
|
||||
}
|
||||
|
||||
SearchPaths ObjLoading::GetIWDSearchPaths()
|
||||
{
|
||||
SearchPaths iwdPaths;
|
||||
|
||||
for (auto* iwd : IWD::Repository)
|
||||
{
|
||||
iwdPaths.IncludeSearchPath(iwd);
|
||||
}
|
||||
|
||||
return iwdPaths;
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "SearchPath/ISearchPath.h"
|
||||
#include "SearchPath/SearchPaths.h"
|
||||
|
||||
class ObjLoading
|
||||
{
|
||||
public:
|
||||
@ -13,22 +10,4 @@ public:
|
||||
bool MenuPermissiveParsing = false;
|
||||
bool MenuNoOptimization = false;
|
||||
} Configuration;
|
||||
|
||||
/**
|
||||
* \brief Loads all IWDs that can be found in a specified search path.
|
||||
* \param searchPath The search path that contains IWDs to be loaded.
|
||||
*/
|
||||
static void LoadIWDsInSearchPath(ISearchPath& searchPath);
|
||||
|
||||
/**
|
||||
* \brief Unloads all IWDs that were loaded from the specified search path.
|
||||
* \param searchPath The search path that was used to load the IWDs to be unloaded.
|
||||
*/
|
||||
static void UnloadIWDsInSearchPath(ISearchPath& searchPath);
|
||||
|
||||
/**
|
||||
* \brief Creates a \c SearchPaths object containing all IWDs that are currently loaded.
|
||||
* \return A \c SearchPaths object containing all IWDs that are currently loaded.
|
||||
*/
|
||||
static SearchPaths GetIWDSearchPaths();
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <functional>
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class SearchPathOpenFile
|
||||
{
|
||||
@ -42,7 +43,7 @@ public:
|
||||
* \brief Returns the path to the search path.
|
||||
* \return The path to the search path.
|
||||
*/
|
||||
virtual std::string GetPath() = 0;
|
||||
virtual const std::string& GetPath() = 0;
|
||||
|
||||
/**
|
||||
* \brief Iterates through all files of the search path.
|
||||
|
337
src/ObjLoading/SearchPath/IWD.cpp
Normal file
337
src/ObjLoading/SearchPath/IWD.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
#include "IWD.h"
|
||||
|
||||
#include "ObjLoading.h"
|
||||
#include "Utils/FileToZlibWrapper.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unzip.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
class IwdFile final : public objbuf
|
||||
{
|
||||
public:
|
||||
class IParent
|
||||
{
|
||||
public:
|
||||
IParent() = default;
|
||||
virtual ~IParent() = default;
|
||||
IParent(const IParent& other) = default;
|
||||
IParent(IParent&& other) noexcept = default;
|
||||
IParent& operator=(const IParent& other) = default;
|
||||
IParent& operator=(IParent&& other) noexcept = default;
|
||||
|
||||
virtual void OnIwdFileClose() = 0;
|
||||
};
|
||||
|
||||
IwdFile(IParent* parent, const unzFile container, const int64_t size)
|
||||
: m_parent(parent),
|
||||
m_open(true),
|
||||
m_size(size),
|
||||
m_container(container),
|
||||
m_peeked(false),
|
||||
m_peek_symbol(0)
|
||||
{
|
||||
}
|
||||
|
||||
~IwdFile() override
|
||||
{
|
||||
if (m_open)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
IwdFile(const IwdFile& other) = default;
|
||||
IwdFile(IwdFile&& other) noexcept = default;
|
||||
IwdFile& operator=(const IwdFile& other) = default;
|
||||
IwdFile& operator=(IwdFile&& other) noexcept = default;
|
||||
|
||||
_NODISCARD bool is_open() const override
|
||||
{
|
||||
return m_open;
|
||||
}
|
||||
|
||||
bool close() override
|
||||
{
|
||||
unzCloseCurrentFile(m_container);
|
||||
m_open = false;
|
||||
|
||||
m_parent->OnIwdFileClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
int_type underflow() override
|
||||
{
|
||||
if (m_peeked)
|
||||
return m_peek_symbol;
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
m_peeked = true;
|
||||
return m_peek_symbol;
|
||||
}
|
||||
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int_type uflow() override
|
||||
{
|
||||
if (m_peeked)
|
||||
{
|
||||
m_peeked = false;
|
||||
return m_peek_symbol;
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
return result >= 0 ? m_peek_symbol : EOF;
|
||||
}
|
||||
|
||||
std::streamsize xsgetn(char* ptr, std::streamsize count) override
|
||||
{
|
||||
if (m_peeked && count >= 1)
|
||||
{
|
||||
*ptr = static_cast<char>(m_peek_symbol);
|
||||
ptr++;
|
||||
count--;
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, ptr, static_cast<unsigned>(count));
|
||||
|
||||
return result >= 0 ? static_cast<std::streamsize>(result) : 0;
|
||||
}
|
||||
|
||||
pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override
|
||||
{
|
||||
const auto currentPos = unztell64(m_container);
|
||||
|
||||
pos_type targetPos;
|
||||
if (dir == std::ios_base::beg)
|
||||
{
|
||||
targetPos = off;
|
||||
}
|
||||
else if (dir == std::ios_base::cur)
|
||||
{
|
||||
targetPos = static_cast<pos_type>(currentPos) + off;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPos = m_size - off;
|
||||
}
|
||||
|
||||
return seekpos(targetPos, mode);
|
||||
}
|
||||
|
||||
pos_type seekpos(const pos_type pos, const std::ios_base::openmode mode) override
|
||||
{
|
||||
const auto currentPos = unztell64(m_container);
|
||||
|
||||
if (static_cast<pos_type>(currentPos) < pos)
|
||||
{
|
||||
auto skipAmount = pos - static_cast<pos_type>(currentPos);
|
||||
while (skipAmount > 0)
|
||||
{
|
||||
char temp[1024];
|
||||
const auto toRead = skipAmount > sizeof(temp) ? sizeof(temp) : static_cast<size_t>(skipAmount);
|
||||
unzReadCurrentFile(m_container, temp, toRead);
|
||||
skipAmount -= toRead;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
if (currentPos == pos)
|
||||
return currentPos;
|
||||
|
||||
return std::streampos(-1);
|
||||
}
|
||||
|
||||
private:
|
||||
IParent* m_parent;
|
||||
bool m_open;
|
||||
int64_t m_size;
|
||||
unzFile m_container;
|
||||
bool m_peeked;
|
||||
int_type m_peek_symbol;
|
||||
};
|
||||
|
||||
struct IwdEntry
|
||||
{
|
||||
int64_t m_size;
|
||||
unz_file_pos m_file_pos;
|
||||
|
||||
explicit IwdEntry(const int64_t size)
|
||||
: m_size(size),
|
||||
m_file_pos{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Iwd final : public ISearchPath, public IwdFile::IParent
|
||||
{
|
||||
public:
|
||||
Iwd(std::string path, std::ifstream stream)
|
||||
: m_path(std::move(path)),
|
||||
m_stream(std::move(stream)),
|
||||
m_unz_file{},
|
||||
m_has_open_file(false)
|
||||
{
|
||||
}
|
||||
|
||||
~Iwd() override
|
||||
{
|
||||
if (m_unz_file != nullptr)
|
||||
{
|
||||
unzClose(m_unz_file);
|
||||
m_unz_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Iwd(const Iwd& other) = delete;
|
||||
Iwd(Iwd&& other) noexcept = delete;
|
||||
Iwd& operator=(const Iwd& other) = delete;
|
||||
Iwd& operator=(Iwd&& other) noexcept = delete;
|
||||
|
||||
/**
|
||||
* \brief Initializes the IWD container.
|
||||
* \return \c true when initialization was successful.
|
||||
*/
|
||||
bool Initialize()
|
||||
{
|
||||
auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(&m_stream);
|
||||
m_unz_file = unzOpen2("", &ioFunctions);
|
||||
|
||||
if (m_unz_file == nullptr)
|
||||
{
|
||||
std::cerr << std::format("Could not open IWD \"{}\"\n", m_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = unzGoToFirstFile(m_unz_file);
|
||||
while (ret == Z_OK)
|
||||
{
|
||||
unz_file_info64 info;
|
||||
char fileNameBuffer[256];
|
||||
unzGetCurrentFileInfo64(m_unz_file, &info, fileNameBuffer, sizeof(fileNameBuffer), nullptr, 0, nullptr, 0);
|
||||
|
||||
std::string fileName(fileNameBuffer);
|
||||
fs::path path(fileName);
|
||||
|
||||
if (path.has_filename())
|
||||
{
|
||||
IwdEntry entry(static_cast<std::int64_t>(info.uncompressed_size));
|
||||
unzGetFilePos(m_unz_file, &entry.m_file_pos);
|
||||
m_entry_map.emplace(std::move(fileName), entry);
|
||||
}
|
||||
|
||||
ret = unzGoToNextFile(m_unz_file);
|
||||
}
|
||||
|
||||
std::cout << std::format("Loaded IWD \"{}\" with {} entries\n", m_path, m_entry_map.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SearchPathOpenFile Open(const std::string& fileName) override
|
||||
{
|
||||
if (m_unz_file == nullptr)
|
||||
{
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
auto iwdFilename = fileName;
|
||||
std::ranges::replace(iwdFilename, '\\', '/');
|
||||
|
||||
const auto iwdEntry = m_entry_map.find(iwdFilename);
|
||||
|
||||
if (iwdEntry != m_entry_map.end())
|
||||
{
|
||||
assert(!m_has_open_file);
|
||||
if (m_has_open_file)
|
||||
{
|
||||
std::cerr << "Trying to open new IWD file while last one was not yet closed.\n";
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
auto pos = iwdEntry->second.m_file_pos;
|
||||
unzGoToFilePos(m_unz_file, &pos);
|
||||
|
||||
if (unzOpenCurrentFile(m_unz_file) == UNZ_OK)
|
||||
{
|
||||
auto result = std::make_unique<IwdFile>(this, m_unz_file, iwdEntry->second.m_size);
|
||||
m_has_open_file = true;
|
||||
return SearchPathOpenFile(std::make_unique<iobjstream>(std::move(result)), iwdEntry->second.m_size);
|
||||
}
|
||||
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
const std::string& GetPath() override
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void OnIwdFileClose() override
|
||||
{
|
||||
m_has_open_file = false;
|
||||
}
|
||||
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override
|
||||
{
|
||||
if (options.m_disk_files_only)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& [entryName, entry] : m_entry_map)
|
||||
{
|
||||
std::filesystem::path entryPath(entryName);
|
||||
|
||||
if (!options.m_should_include_subdirectories && entryPath.has_parent_path())
|
||||
continue;
|
||||
|
||||
if (options.m_filter_extensions && options.m_extension != entryPath.extension().string())
|
||||
continue;
|
||||
|
||||
callback(entryName);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
std::ifstream m_stream;
|
||||
unzFile m_unz_file;
|
||||
bool m_has_open_file;
|
||||
|
||||
std::map<std::string, IwdEntry> m_entry_map;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace iwd
|
||||
{
|
||||
std::unique_ptr<ISearchPath> LoadFromFile(const std::string& path)
|
||||
{
|
||||
std::ifstream inputStream(path, std::ios::in | std::ios::binary);
|
||||
if (!inputStream.is_open())
|
||||
return {};
|
||||
|
||||
auto iwd = std::make_unique<Iwd>(path, std::move(inputStream));
|
||||
if (!iwd->Initialize())
|
||||
return {};
|
||||
|
||||
return iwd;
|
||||
}
|
||||
} // namespace iwd
|
11
src/ObjLoading/SearchPath/IWD.h
Normal file
11
src/ObjLoading/SearchPath/IWD.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "SearchPath/ISearchPath.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace iwd
|
||||
{
|
||||
std::unique_ptr<ISearchPath> LoadFromFile(const std::string& path);
|
||||
}
|
@ -3,16 +3,18 @@
|
||||
#include "Utils/ObjFileStream.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
SearchPathFilesystem::SearchPathFilesystem(std::string path)
|
||||
: m_path(std::move(path))
|
||||
{
|
||||
m_path = std::move(path);
|
||||
}
|
||||
|
||||
std::string SearchPathFilesystem::GetPath()
|
||||
const std::string& SearchPathFilesystem::GetPath()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
@ -23,9 +25,7 @@ SearchPathOpenFile SearchPathFilesystem::Open(const std::string& fileName)
|
||||
std::ifstream file(filePath.string(), std::fstream::in | std::fstream::binary);
|
||||
|
||||
if (file.is_open())
|
||||
{
|
||||
return SearchPathOpenFile(std::make_unique<std::ifstream>(std::move(file)), static_cast<int64_t>(file_size(filePath)));
|
||||
}
|
||||
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
@ -59,6 +59,6 @@ void SearchPathFilesystem::Find(const SearchPathSearchOptions& options, const st
|
||||
}
|
||||
catch (std::filesystem::filesystem_error& e)
|
||||
{
|
||||
printf("Directory Iterator threw error when trying to find files: \"%s\"\n", e.what());
|
||||
std::cerr << std::format("Directory Iterator threw error when trying to find files: \"{}\"\n", e.what());
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,6 @@ public:
|
||||
explicit SearchPathFilesystem(std::string path);
|
||||
|
||||
SearchPathOpenFile Open(const std::string& fileName) override;
|
||||
std::string GetPath() override;
|
||||
const std::string& GetPath() override;
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||
};
|
||||
|
@ -18,9 +18,10 @@ SearchPathOpenFile SearchPaths::Open(const std::string& fileName)
|
||||
return SearchPathOpenFile();
|
||||
}
|
||||
|
||||
std::string SearchPaths::GetPath()
|
||||
const std::string& SearchPaths::GetPath()
|
||||
{
|
||||
return "SearchPaths: " + std::to_string(m_search_paths.size()) + " entries";
|
||||
static const std::string STATIC_NAME = "SearchPaths";
|
||||
return STATIC_NAME;
|
||||
}
|
||||
|
||||
void SearchPaths::Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ISearchPath.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class SearchPaths final : public ISearchPath
|
||||
@ -16,7 +17,7 @@ public:
|
||||
~SearchPaths() override = default;
|
||||
|
||||
SearchPathOpenFile Open(const std::string& fileName) override;
|
||||
std::string GetPath() override;
|
||||
const std::string& GetPath() override;
|
||||
void Find(const SearchPathSearchOptions& options, const std::function<void(const std::string&)>& callback) override;
|
||||
|
||||
SearchPaths(const SearchPaths& other) = delete;
|
||||
|
Reference in New Issue
Block a user