Use map for IWD entries to speed up finding entries by name

This commit is contained in:
Jan 2020-10-17 14:59:36 +02:00
parent a1c965a4c0
commit 395c139681

View File

@ -7,6 +7,7 @@
#include <unzip.h>
#include <filesystem>
#include <cassert>
#include <map>
ObjContainerRepository<IWD, ISearchPath> IWD::Repository;
@ -125,8 +126,7 @@ class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IPar
class IWDEntry
{
public:
std::string m_name;
size_t m_size;
size_t m_size{};
unz_file_pos m_file_pos{};
};
@ -136,7 +136,7 @@ class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IPar
IWDFile* m_last_file;
std::vector<IWDEntry> m_entries;
std::map<std::string, IWDEntry> m_entry_map;
public:
Impl(std::string path, FileAPI::IFile* file)
@ -147,7 +147,7 @@ public:
m_last_file = nullptr;
}
~Impl()
~Impl() override
{
if (m_unz_file != nullptr)
{
@ -162,6 +162,11 @@ public:
}
}
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_file);
@ -186,10 +191,9 @@ public:
if (path.has_filename())
{
IWDEntry entry;
entry.m_name = std::move(fileName);
entry.m_size = info.uncompressed_size;
unzGetFilePos(m_unz_file, &entry.m_file_pos);
m_entries.push_back(entry);
m_entry_map.emplace(std::move(fileName), entry);
}
ret = unzGoToNextFile(m_unz_file);
@ -197,7 +201,7 @@ public:
if (ObjLoading::Configuration.Verbose)
{
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entries.size());
printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entry_map.size());
}
return true;
@ -213,24 +217,21 @@ public:
std::string iwdFilename = fileName;
std::replace(iwdFilename.begin(), iwdFilename.end(), '\\', '/');
const auto iwdEntry = std::find_if(m_entries.begin(), m_entries.end(), [&iwdFilename](IWDEntry& entry) -> bool
{
return entry.m_name == iwdFilename;
});
const auto iwdEntry = m_entry_map.find(iwdFilename);
if (iwdEntry != m_entries.end())
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->m_file_pos;
auto pos = iwdEntry->second.m_file_pos;
unzGoToFilePos(m_unz_file, &pos);
if (unzOpenCurrentFile(m_unz_file) == UNZ_OK)
{
m_last_file = new IWDFile(this, m_unz_file, iwdEntry->m_size);
m_last_file = new IWDFile(this, m_unz_file, iwdEntry->second.m_size);
}
return m_last_file;
@ -256,9 +257,9 @@ public:
return;
}
for(auto& entry : m_entries)
for(auto& entry : m_entry_map)
{
std::filesystem::path entryPath(entry.m_name);
std::filesystem::path entryPath(entry.first);
if(!options.m_should_include_subdirectories && entryPath.has_parent_path())
continue;
@ -266,7 +267,7 @@ public:
if(options.m_filter_extensions && options.m_extension != entryPath.extension().string())
continue;
callback(entry.m_name);
callback(entry.first);
}
}