diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index 4057d627c4..24c98fd139 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -151,62 +151,11 @@ bool parseOptions (int argc, char** argv, Arguments &info) return true; } -int list(std::unique_ptr& bsa, Arguments& info); -int extract(std::unique_ptr& bsa, Arguments& info); -int extractAll(std::unique_ptr& bsa, Arguments& info); -int add(std::unique_ptr& bsa, Arguments& info); - -int main(int argc, char** argv) -{ - try - { - Arguments info; - if(!parseOptions (argc, argv, info)) - return 1; - - // Open file - std::unique_ptr bsa; - - Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(info.filename); - - if (bsaVersion == Bsa::BSAVER_COMPRESSED) - bsa = std::make_unique(Bsa::CompressedBSAFile()); - else - bsa = std::make_unique(Bsa::BSAFile()); - - if (info.mode == "create") - { - bsa->open(info.filename); - return 0; - } - - bsa->open(info.filename); - - if (info.mode == "list") - return list(bsa, info); - else if (info.mode == "extract") - return extract(bsa, info); - else if (info.mode == "extractall") - return extractAll(bsa, info); - else if (info.mode == "add") - return add(bsa, info); - else - { - std::cout << "Unsupported mode. That is not supposed to happen." << std::endl; - return 1; - } - } - catch (std::exception& e) - { - std::cerr << "ERROR reading BSA archive\nDetails:\n" << e.what() << std::endl; - return 2; - } -} - -int list(std::unique_ptr& bsa, Arguments& info) +template +int list(std::unique_ptr& bsa, Arguments& info) { // List all files - const Bsa::BSAFile::FileList &files = bsa->getList(); + const auto &files = bsa->getList(); for (const auto& file : files) { if(info.longformat) @@ -225,7 +174,8 @@ int list(std::unique_ptr& bsa, Arguments& info) return 0; } -int extract(std::unique_ptr& bsa, Arguments& info) +template +int extract(std::unique_ptr& bsa, Arguments& info) { std::string archivePath = info.extractfile; Misc::StringUtils::replaceAll(archivePath, "/", "\\"); @@ -281,7 +231,8 @@ int extract(std::unique_ptr& bsa, Arguments& info) return 0; } -int extractAll(std::unique_ptr& bsa, Arguments& info) +template +int extractAll(std::unique_ptr& bsa, Arguments& info) { for (const auto &file : bsa->getList()) { @@ -315,10 +266,62 @@ int extractAll(std::unique_ptr& bsa, Arguments& info) return 0; } -int add(std::unique_ptr& bsa, Arguments& info) +template +int add(std::unique_ptr& bsa, Arguments& info) { boost::filesystem::fstream stream(info.addfile, std::ios_base::binary | std::ios_base::out | std::ios_base::in); bsa->addFile(info.addfile, stream); return 0; } + +template +int call(Arguments& info) +{ + std::unique_ptr bsa = std::make_unique(); + if (info.mode == "create") + { + bsa->open(info.filename); + return 0; + } + + bsa->open(info.filename); + + if (info.mode == "list") + return list(bsa, info); + else if (info.mode == "extract") + return extract(bsa, info); + else if (info.mode == "extractall") + return extractAll(bsa, info); + else if (info.mode == "add") + return add(bsa, info); + else + { + std::cout << "Unsupported mode. That is not supposed to happen." << std::endl; + return 1; + } +} + +int main(int argc, char** argv) +{ + try + { + Arguments info; + if (!parseOptions(argc, argv, info)) + return 1; + + // Open file + + Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(info.filename); + + if (bsaVersion == Bsa::BSAVER_COMPRESSED) + return call(info); + else + return call(info); + } + catch (std::exception& e) + { + std::cerr << "ERROR reading BSA archive\nDetails:\n" << e.what() << std::endl; + return 2; + } +} diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsa_file.hpp index f6c5d03139..83e9ae954c 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsa_file.hpp @@ -128,7 +128,7 @@ public: return Files::openConstrainedFileStream (mFilename.c_str (), file->offset, file->fileSize); } - virtual void addFile(const std::string& filename, std::istream& file); + void addFile(const std::string& filename, std::istream& file); /// Get a list of all files /// @note Thread safe. diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index f19815dcf3..2c0b3c0aac 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -39,7 +39,7 @@ namespace Bsa BSAVER_COMPRESSED = 0x415342 //B, S, A }; - class CompressedBSAFile : public BSAFile + class CompressedBSAFile : private BSAFile { private: //special marker for invalid records, @@ -85,6 +85,10 @@ namespace Bsa static std::uint64_t generateHash(std::string stem, std::string extension) ; Files::IStreamPtr getFile(const FileRecord& fileRecord); public: + using BSAFile::open; + using BSAFile::getList; + using BSAFile::getFilename; + CompressedBSAFile(); virtual ~CompressedBSAFile(); @@ -96,7 +100,7 @@ namespace Bsa Files::IStreamPtr getFile(const char* filePath); 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); }; } diff --git a/components/vfs/bsaarchive.cpp b/components/vfs/bsaarchive.cpp index b0caa5c305..d4d1a5a38b 100644 --- a/components/vfs/bsaarchive.cpp +++ b/components/vfs/bsaarchive.cpp @@ -8,7 +8,7 @@ namespace VFS BsaArchive::BsaArchive(const std::string &filename) { - mFile = std::make_unique(Bsa::BSAFile()); + mFile = std::make_unique(); mFile->open(filename); const Bsa::BSAFile::FileList &filelist = mFile->getList(); @@ -53,17 +53,30 @@ std::string BsaArchive::getDescription() const return std::string{"BSA: "} + mFile->getFilename(); } +// ------------------------------------------------------------------------------ + +BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa) + : mInfo(info) + , mFile(bsa) +{ + +} + +Files::IStreamPtr BsaArchiveFile::open() +{ + return mFile->getFile(mInfo); +} + CompressedBsaArchive::CompressedBsaArchive(const std::string &filename) - : BsaArchive() + : Archive() { - mFile = std::make_unique(Bsa::CompressedBSAFile()); - mFile->open(filename); + mCompressedFile = std::make_unique(); + mCompressedFile->open(filename); - const Bsa::BSAFile::FileList &filelist = mFile->getList(); + const Bsa::BSAFile::FileList &filelist = mCompressedFile->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(mFile.get())); + mCompressedResources.emplace_back(&*it, mCompressedFile.get()); } } @@ -78,22 +91,26 @@ void CompressedBsaArchive::listResources(std::map &out, cha } } -// ------------------------------------------------------------------------------ - -BsaArchiveFile::BsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::BSAFile* bsa) - : mInfo(info) - , mFile(bsa) +bool CompressedBsaArchive::contains(const std::string& file, char (*normalize_function)(char)) const { - + for (const auto& it : mCompressedResources) + { + std::string ent = it.mInfo->name(); + std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function); + if(file == ent) + return true; + } + return false; } -Files::IStreamPtr BsaArchiveFile::open() +std::string CompressedBsaArchive::getDescription() const { - return mFile->getFile(mInfo); + return std::string{"BSA: "} + mCompressedFile->getFilename(); } + CompressedBsaArchiveFile::CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct *info, Bsa::CompressedBSAFile* bsa) - : BsaArchiveFile(info, bsa) + : mInfo(info) , mCompressedFile(bsa) { diff --git a/components/vfs/bsaarchive.hpp b/components/vfs/bsaarchive.hpp index 1015f8d220..1bf9cf4381 100644 --- a/components/vfs/bsaarchive.hpp +++ b/components/vfs/bsaarchive.hpp @@ -19,12 +19,14 @@ namespace VFS Bsa::BSAFile* mFile; }; - class CompressedBsaArchiveFile : public BsaArchiveFile + class CompressedBsaArchiveFile : public File { public: CompressedBsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::CompressedBSAFile* bsa); Files::IStreamPtr open() override; + + const Bsa::BSAFile::FileStruct* mInfo; Bsa::CompressedBSAFile* mCompressedFile; }; @@ -44,12 +46,14 @@ namespace VFS std::vector mResources; }; - class CompressedBsaArchive : public BsaArchive + class CompressedBsaArchive : public Archive { public: CompressedBsaArchive(const std::string& filename); - void listResources(std::map& out, char (*normalize_function) (char)) override; virtual ~CompressedBsaArchive() {} + void listResources(std::map& out, char (*normalize_function) (char)) override; + bool contains(const std::string& file, char (*normalize_function) (char)) const override; + std::string getDescription() const override; private: std::unique_ptr mCompressedFile;