devirtualises BSAFile (#3161)

Currently, Open MW's basic file access speed is limited by a peculiar layer of virtualisation in BSAFile's interface. This PR removes such virtualisation by properly separating BSAFile from CompressedBSAFile in low level contexts.
pull/3169/head
Bo Svensson 3 years ago committed by GitHub
parent cbcdd705ee
commit 7c50f823d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -290,11 +290,6 @@ Files::IStreamPtr BSAFile::getFile(const char *file)
return Files::openConstrainedFileStream (mFilename.c_str (), fs.offset, fs.fileSize); return Files::openConstrainedFileStream (mFilename.c_str (), fs.offset, fs.fileSize);
} }
Files::IStreamPtr BSAFile::getFile(const FileStruct *file)
{
return Files::openConstrainedFileStream (mFilename.c_str (), file->offset, file->fileSize);
}
void Bsa::BSAFile::addFile(const std::string& filename, std::istream& file) void Bsa::BSAFile::addFile(const std::string& filename, std::istream& file)
{ {
if (!mIsLoaded) if (!mIsLoaded)

@ -154,7 +154,10 @@ public:
/** Open a file contained in the archive. /** Open a file contained in the archive.
* @note Thread safe. * @note Thread safe.
*/ */
virtual Files::IStreamPtr getFile(const FileStruct* file); Files::IStreamPtr getFile(const FileStruct *file)
{
return Files::openConstrainedFileStream (mFilename.c_str (), file->offset, file->fileSize);
}
virtual void addFile(const std::string& filename, std::istream& file); virtual void addFile(const std::string& filename, std::istream& file);

@ -93,7 +93,7 @@ namespace Bsa
void readHeader() override; void readHeader() override;
Files::IStreamPtr getFile(const char* filePath) override; Files::IStreamPtr getFile(const char* filePath) override;
Files::IStreamPtr getFile(const FileStruct* fileStruct) override; Files::IStreamPtr getFile(const FileStruct* fileStruct);
void addFile(const std::string& filename, std::istream& file) override; void addFile(const std::string& filename, std::istream& file) override;
}; };
} }

@ -1,5 +1,5 @@
#include "bsaarchive.hpp" #include "bsaarchive.hpp"
#include <components/bsa/compressedbsafile.hpp>
#include <memory> #include <memory>
namespace VFS namespace VFS
@ -7,15 +7,7 @@ namespace VFS
BsaArchive::BsaArchive(const std::string &filename) BsaArchive::BsaArchive(const std::string &filename)
{ {
Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(filename);
if (bsaVersion == Bsa::BSAVER_COMPRESSED) {
mFile = std::make_unique<Bsa::CompressedBSAFile>(Bsa::CompressedBSAFile());
}
else {
mFile = std::make_unique<Bsa::BSAFile>(Bsa::BSAFile()); mFile = std::make_unique<Bsa::BSAFile>(Bsa::BSAFile());
}
mFile->open(filename); mFile->open(filename);
const Bsa::BSAFile::FileList &filelist = mFile->getList(); const Bsa::BSAFile::FileList &filelist = mFile->getList();
@ -25,6 +17,10 @@ BsaArchive::BsaArchive(const std::string &filename)
} }
} }
BsaArchive::BsaArchive()
{
}
BsaArchive::~BsaArchive() { BsaArchive::~BsaArchive() {
} }
@ -56,6 +52,31 @@ std::string BsaArchive::getDescription() const
return std::string{"BSA: "} + mFile->getFilename(); return std::string{"BSA: "} + mFile->getFilename();
} }
CompressedBsaArchive::CompressedBsaArchive(const std::string &filename)
: BsaArchive()
{
mFile = std::make_unique<Bsa::BSAFile>(Bsa::CompressedBSAFile());
mFile->open(filename);
const Bsa::BSAFile::FileList &filelist = mFile->getList();
for(Bsa::BSAFile::FileList::const_iterator it = filelist.begin();it != filelist.end();++it)
{
mResources.emplace_back(&*it, mFile.get());
mCompressedResources.emplace_back(&*it, static_cast<Bsa::CompressedBSAFile*>(mFile.get()));
}
}
void CompressedBsaArchive::listResources(std::map<std::string, File *> &out, char (*normalize_function)(char))
{
for (std::vector<CompressedBsaArchiveFile>::iterator it = mCompressedResources.begin(); it != mCompressedResources.end(); ++it)
{
std::string ent = it->mInfo->name();
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
out[ent] = &*it;
}
}
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa) BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa)
@ -70,4 +91,16 @@ Files::IStreamPtr BsaArchiveFile::open()
return mFile->getFile(mInfo); return mFile->getFile(mInfo);
} }
CompressedBsaArchiveFile::CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::CompressedBSAFile* bsa)
: BsaArchiveFile(info, bsa)
, mCompressedFile(bsa)
{
}
Files::IStreamPtr CompressedBsaArchiveFile::open()
{
return mCompressedFile->getFile(mInfo);
}
} }

@ -4,6 +4,7 @@
#include "archive.hpp" #include "archive.hpp"
#include <components/bsa/bsa_file.hpp> #include <components/bsa/bsa_file.hpp>
#include <components/bsa/compressedbsafile.hpp>
namespace VFS namespace VFS
{ {
@ -18,19 +19,43 @@ namespace VFS
Bsa::BSAFile* mFile; Bsa::BSAFile* mFile;
}; };
class CompressedBsaArchiveFile : public BsaArchiveFile
{
public:
CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa);
Files::IStreamPtr open() override;
Bsa::CompressedBSAFile* mCompressedFile;
};
class BsaArchive : public Archive class BsaArchive : public Archive
{ {
public: public:
BsaArchive(const std::string& filename); BsaArchive(const std::string& filename);
BsaArchive();
virtual ~BsaArchive(); virtual ~BsaArchive();
void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override; void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override;
bool contains(const std::string& file, char (*normalize_function) (char)) const override; bool contains(const std::string& file, char (*normalize_function) (char)) const override;
std::string getDescription() const override; std::string getDescription() const override;
private: protected:
std::unique_ptr<Bsa::BSAFile> mFile; std::unique_ptr<Bsa::BSAFile> mFile;
std::vector<BsaArchiveFile> mResources; std::vector<BsaArchiveFile> mResources;
}; };
class CompressedBsaArchive : public BsaArchive
{
public:
CompressedBsaArchive(const std::string& filename);
void listResources(std::map<std::string, File*>& out, char (*normalize_function) (char)) override;
virtual ~CompressedBsaArchive() {}
private:
std::unique_ptr<Bsa::CompressedBSAFile> mCompressedFile;
std::vector<CompressedBsaArchiveFile> mCompressedResources;
};
} }
#endif #endif

@ -23,7 +23,11 @@ namespace VFS
// Last BSA has the highest priority // Last BSA has the highest priority
const std::string archivePath = collections.getPath(*archive).string(); const std::string archivePath = collections.getPath(*archive).string();
Log(Debug::Info) << "Adding BSA archive " << archivePath; Log(Debug::Info) << "Adding BSA archive " << archivePath;
Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(archivePath);
if (bsaVersion == Bsa::BSAVER_COMPRESSED)
vfs->addArchive(new CompressedBsaArchive(archivePath));
else
vfs->addArchive(new BsaArchive(archivePath)); vfs->addArchive(new BsaArchive(archivePath));
} }
else else

Loading…
Cancel
Save