From 1cd06668e006ed25e25ebd851887ecd70104fbe8 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 3 Mar 2021 14:04:35 +0100 Subject: [PATCH] Replace FileAPI with c++ streams and std::filesystem --- premake5.lua | 5 + src/ObjCommon/Utils/FileToZlibWrapper.cpp | 141 +++++++-- src/ObjCommon/Utils/FileToZlibWrapper.h | 10 +- src/ObjCommon/Utils/ObjFileStream.h | 103 +++++++ src/ObjCommon/Utils/ObjStream.h | 222 ++++++++++++++ src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp | 17 +- src/ObjLoading/Game/T6/ObjLoaderT6.cpp | 51 ++-- src/ObjLoading/Image/IwiLoader.cpp | 61 ++-- src/ObjLoading/Image/IwiLoader.h | 8 +- src/ObjLoading/ObjContainer/IPak/IPak.cpp | 79 ++--- src/ObjLoading/ObjContainer/IPak/IPak.h | 13 +- .../ObjContainer/IPak/IPakEntryReadStream.cpp | 287 ++++++++++-------- .../ObjContainer/IPak/IPakEntryReadStream.h | 38 +-- .../ObjContainer/IPak/IPakStreamManager.cpp | 51 ++-- .../ObjContainer/IPak/IPakStreamManager.h | 11 +- src/ObjLoading/ObjContainer/IWD/IWD.cpp | 245 ++++++++------- src/ObjLoading/ObjContainer/IWD/IWD.h | 10 +- .../ObjContainer/ObjContainerRepository.h | 73 +++-- src/ObjLoading/ObjLoading.cpp | 39 ++- src/ObjLoading/SearchPath/ISearchPath.h | 9 +- .../SearchPath/SearchPathFilesystem.cpp | 17 +- .../SearchPath/SearchPathFilesystem.h | 5 +- src/ObjLoading/SearchPath/SearchPaths.cpp | 28 +- src/ObjLoading/SearchPath/SearchPaths.h | 9 +- src/ObjWriting/Dumping/AbstractAssetDumper.h | 26 +- src/ObjWriting/Dumping/CsvWriter.cpp | 32 +- src/ObjWriting/Dumping/CsvWriter.h | 11 +- .../Dumping/Localize/StringFileDumper.cpp | 38 ++- .../Dumping/Localize/StringFileDumper.h | 7 +- .../AssetDumpers/AssetDumperAddonMapEnts.cpp | 4 +- .../AssetDumpers/AssetDumperAddonMapEnts.h | 2 +- .../IW4/AssetDumpers/AssetDumperGfxImage.cpp | 4 +- .../IW4/AssetDumpers/AssetDumperGfxImage.h | 2 +- .../AssetDumpers/AssetDumperLoadedSound.cpp | 22 +- .../IW4/AssetDumpers/AssetDumperLoadedSound.h | 4 +- .../AssetDumpers/AssetDumperLocalizeEntry.cpp | 26 +- .../IW4/AssetDumpers/AssetDumperRawFile.cpp | 6 +- .../IW4/AssetDumpers/AssetDumperRawFile.h | 2 +- .../AssetDumpers/AssetDumperStringTable.cpp | 8 +- .../IW4/AssetDumpers/AssetDumperStringTable.h | 2 +- .../IW4/AssetDumpers/AssetDumperVehicle.cpp | 4 +- .../IW4/AssetDumpers/AssetDumperVehicle.h | 2 +- .../IW4/AssetDumpers/AssetDumperWeapon.cpp | 4 +- .../Game/IW4/AssetDumpers/AssetDumperWeapon.h | 2 +- .../T6/AssetDumpers/AssetDumperFontIcon.cpp | 8 +- .../T6/AssetDumpers/AssetDumperFontIcon.h | 2 +- .../T6/AssetDumpers/AssetDumperGfxImage.cpp | 4 +- .../T6/AssetDumpers/AssetDumperGfxImage.h | 2 +- .../AssetDumpers/AssetDumperLocalizeEntry.cpp | 26 +- .../AssetDumperPhysConstraints.cpp | 4 +- .../AssetDumpers/AssetDumperPhysConstraints.h | 2 +- .../T6/AssetDumpers/AssetDumperPhysPreset.cpp | 4 +- .../T6/AssetDumpers/AssetDumperPhysPreset.h | 2 +- .../Game/T6/AssetDumpers/AssetDumperQdb.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperQdb.h | 2 +- .../T6/AssetDumpers/AssetDumperRawFile.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperRawFile.h | 2 +- .../AssetDumperScriptParseTree.cpp | 4 +- .../AssetDumpers/AssetDumperScriptParseTree.h | 2 +- .../Game/T6/AssetDumpers/AssetDumperSlug.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperSlug.h | 2 +- .../AssetDumpers/AssetDumperStringTable.cpp | 8 +- .../T6/AssetDumpers/AssetDumperStringTable.h | 2 +- .../T6/AssetDumpers/AssetDumperTracer.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperTracer.h | 2 +- .../T6/AssetDumpers/AssetDumperVehicle.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperVehicle.h | 2 +- .../T6/AssetDumpers/AssetDumperWeapon.cpp | 4 +- .../Game/T6/AssetDumpers/AssetDumperWeapon.h | 2 +- .../T6/AssetDumpers/AssetDumperZBarrier.cpp | 4 +- .../T6/AssetDumpers/AssetDumperZBarrier.h | 2 +- src/ObjWriting/Image/DdsWriter.cpp | 22 +- src/ObjWriting/Image/DdsWriter.h | 2 +- src/ObjWriting/Image/IImageWriter.h | 7 +- src/ObjWriting/Image/IwiWriter27.cpp | 45 +-- src/ObjWriting/Image/IwiWriter27.h | 4 +- src/ObjWriting/Image/IwiWriter8.cpp | 34 ++- src/ObjWriting/Image/IwiWriter8.h | 4 +- src/Unlinker/ContentLister/ZoneDefWriter.cpp | 16 +- src/Unlinker/ContentLister/ZoneDefWriter.h | 10 +- src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp | 8 +- src/Unlinker/Game/IW4/ZoneDefWriterIW4.h | 2 +- src/Unlinker/Game/T6/ZoneDefWriterT6.cpp | 8 +- src/Unlinker/Game/T6/ZoneDefWriterT6.h | 2 +- src/Unlinker/Unlinker.cpp | 56 ++-- src/Utils/Utils/ClassUtils.h | 6 +- src/Utils/Utils/FileAPI.cpp | 145 --------- src/Utils/Utils/FileAPI.h | 63 ---- src/Utils/Utils/PathUtils.cpp | 41 --- src/Utils/Utils/PathUtils.h | 16 - src/ZoneLoading/Loading/LoadingFileStream.cpp | 9 +- src/ZoneLoading/Loading/LoadingFileStream.h | 8 +- .../Loading/Steps/StepDumpData.cpp | 10 +- src/ZoneLoading/Loading/ZoneLoader.cpp | 16 +- src/ZoneLoading/Loading/ZoneLoader.h | 4 +- src/ZoneLoading/ZoneLoading.cpp | 26 +- 96 files changed, 1355 insertions(+), 1061 deletions(-) create mode 100644 src/ObjCommon/Utils/ObjFileStream.h create mode 100644 src/ObjCommon/Utils/ObjStream.h delete mode 100644 src/Utils/Utils/FileAPI.cpp delete mode 100644 src/Utils/Utils/FileAPI.h delete mode 100644 src/Utils/Utils/PathUtils.cpp delete mode 100644 src/Utils/Utils/PathUtils.h diff --git a/premake5.lua b/premake5.lua index 17613bb2..f7118fc6 100644 --- a/premake5.lua +++ b/premake5.lua @@ -103,6 +103,11 @@ workspace "OpenAssetTools" } filter {} + defines { + "__STDC_LIB_EXT1__", + "__STDC_WANT_LIB_EXT1__=1" + } + -- ======================== -- ThirdParty -- ======================== diff --git a/src/ObjCommon/Utils/FileToZlibWrapper.cpp b/src/ObjCommon/Utils/FileToZlibWrapper.cpp index 804b88c6..02eebde9 100644 --- a/src/ObjCommon/Utils/FileToZlibWrapper.cpp +++ b/src/ObjCommon/Utils/FileToZlibWrapper.cpp @@ -1,49 +1,74 @@ #include "FileToZlibWrapper.h" + #include +#include voidpf Wrapper_Zlib_FileOpen(voidpf opaque, const char*, int) { return opaque; } -uLong Wrapper_Zlib_FileRead(voidpf, voidpf stream, void* buf, const uLong size) +template +uLong Wrapper_Zlib_FileRead(voidpf opaque, voidpf stream, void* buf, const uLong size) { - auto* file = reinterpret_cast(stream); + auto* file = static_cast(stream); - return file->Read(buf, 1, size); + file->read(static_cast(buf), size); + + return static_cast(file->gcount()); } +uLong Wrapper_Zlib_NoFileRead(voidpf opaque, voidpf stream, void* buf, const uLong size) +{ + return 0; +} + +template uLong Wrapper_Zlib_FileWrite(voidpf opaque, voidpf stream, const void* buf, const uLong size) { - auto* file = reinterpret_cast(stream); - - return file->Write(buf, 1, size); + auto* file = static_cast(stream); + file->write(static_cast(buf), size); + return size; } -long Wrapper_Zlib_FileTell(voidpf opaque, voidpf stream) +uLong Wrapper_Zlib_NoFileWrite(voidpf opaque, voidpf stream, const void* buf, const uLong size) { - auto* file = reinterpret_cast(stream); - - return static_cast(file->Pos()); + return 0; } -long Wrapper_Zlib_FileSeek(voidpf opaque, voidpf stream, const uLong offset, const int origin) +template +long Wrapper_Zlib_FileTellRead(voidpf opaque, voidpf stream) { - auto* file = reinterpret_cast(stream); + auto* file = static_cast(stream); + + return static_cast(file->tellg()); +} + +template +long Wrapper_Zlib_FileTellWrite(voidpf opaque, voidpf stream) +{ + auto* file = static_cast(stream); + + return static_cast(file->tellp()); +} + +template +long Wrapper_Zlib_FileSeekRead(voidpf opaque, voidpf stream, const uLong offset, const int origin) +{ + auto* file = static_cast(stream); switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR: - file->Skip(offset); + file->seekg(offset, SEEK_CUR); break; case ZLIB_FILEFUNC_SEEK_END: - assert(offset == 0); - file->GotoEnd(); + file->seekg(offset, SEEK_END); break; case ZLIB_FILEFUNC_SEEK_SET: - file->Goto(offset); + file->seekg(offset, SEEK_SET); break; default: @@ -53,17 +78,45 @@ long Wrapper_Zlib_FileSeek(voidpf opaque, voidpf stream, const uLong offset, con return 0; } -int Wrapper_Zlib_FileClose(voidpf opaque, voidpf stream) +template +long Wrapper_Zlib_FileSeekWrite(voidpf opaque, voidpf stream, const uLong offset, const int origin) { - auto* file = reinterpret_cast(stream); + auto* file = static_cast(stream); - if (file->IsOpen()) + switch (origin) { - file->Close(); - return 0; + case ZLIB_FILEFUNC_SEEK_CUR: + file->seekp(offset, SEEK_CUR); + break; + + case ZLIB_FILEFUNC_SEEK_END: + file->seekp(offset, SEEK_END); + break; + + case ZLIB_FILEFUNC_SEEK_SET: + file->seekp(offset, SEEK_SET); + break; + + default: + return -1; } - return -1; + return 0; +} + +template +int Wrapper_Zlib_FileClose(voidpf opaque, voidpf stream) +{ + return 0; + // auto* file = static_cast(stream); + // + // if (file->is_open()) + // { + // file->close(); + // return 0; + // } + // + // return -1; } int Wrapper_Zlib_FileError(voidpf opaque, voidpf stream) @@ -71,17 +124,47 @@ int Wrapper_Zlib_FileError(voidpf opaque, voidpf stream) return 0; } -zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(FileAPI::IFile* file) +zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(std::iostream* stream) { return zlib_filefunc_def_s { Wrapper_Zlib_FileOpen, - Wrapper_Zlib_FileRead, - Wrapper_Zlib_FileWrite, - Wrapper_Zlib_FileTell, - Wrapper_Zlib_FileSeek, - Wrapper_Zlib_FileClose, + Wrapper_Zlib_FileRead, + Wrapper_Zlib_FileWrite, + Wrapper_Zlib_FileTellRead, + Wrapper_Zlib_FileSeekRead, + Wrapper_Zlib_FileClose, Wrapper_Zlib_FileError, - file + stream + }; +} + +zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(std::istream* stream) +{ + return zlib_filefunc_def_s + { + Wrapper_Zlib_FileOpen, + Wrapper_Zlib_FileRead, + Wrapper_Zlib_NoFileWrite, + Wrapper_Zlib_FileTellRead, + Wrapper_Zlib_FileSeekRead, + Wrapper_Zlib_FileClose, + Wrapper_Zlib_FileError, + stream + }; +} + +zlib_filefunc_def FileToZlibWrapper::CreateFunctions32ForFile(std::ostream* stream) +{ + return zlib_filefunc_def_s + { + Wrapper_Zlib_FileOpen, + Wrapper_Zlib_NoFileRead, + Wrapper_Zlib_FileWrite, + Wrapper_Zlib_FileTellWrite, + Wrapper_Zlib_FileSeekWrite, + Wrapper_Zlib_FileClose, + Wrapper_Zlib_FileError, + stream }; } diff --git a/src/ObjCommon/Utils/FileToZlibWrapper.h b/src/ObjCommon/Utils/FileToZlibWrapper.h index 6c2094f5..b5fc4251 100644 --- a/src/ObjCommon/Utils/FileToZlibWrapper.h +++ b/src/ObjCommon/Utils/FileToZlibWrapper.h @@ -1,10 +1,16 @@ #pragma once #include -#include "Utils/FileAPI.h" +#include +#include +#include + +#include "ObjStream.h" class FileToZlibWrapper { public: - static zlib_filefunc_def CreateFunctions32ForFile(FileAPI::IFile* file); + static zlib_filefunc_def CreateFunctions32ForFile(std::iostream* stream); + static zlib_filefunc_def CreateFunctions32ForFile(std::istream* stream); + static zlib_filefunc_def CreateFunctions32ForFile(std::ostream* stream); }; diff --git a/src/ObjCommon/Utils/ObjFileStream.h b/src/ObjCommon/Utils/ObjFileStream.h new file mode 100644 index 00000000..993609fc --- /dev/null +++ b/src/ObjCommon/Utils/ObjFileStream.h @@ -0,0 +1,103 @@ +// ReSharper disable CppHidingFunction +// ReSharper disable IdentifierTypo +// ReSharper disable CppInconsistentNaming +#pragma once + +// #include +// +// #include "ObjStream.h" +// +// template +// class basic_fobjbuf final : public basic_objbuf, public std::basic_filebuf +// { +// public: +// using myfb = std::basic_filebuf; +// +// explicit basic_fobjbuf(myfb* fb) +// { +// m_fb.swap(*fb); +// } +// +// _NODISCARD bool is_open() const override +// { +// return m_fb.is_open(); +// } +// +// bool close() override +// { +// return m_fb.close(); +// } +// +// private: +// myfb m_fb; +// }; +// +// template +// class basic_fobjstream final : public basic_objstream +// { +// public: +// using mybase = basic_objstream; +// using myfb = basic_fobjbuf; +// +// using mybase::m_ob; +// +// explicit basic_fobjstream(std::fstream&& stream) +// : mybase(std::make_unique(std::move(*stream.rdbuf()))) +// { +// // reinterpret_cast(m_ob.get())->swapp(*stream.rdbuf()); +// // reinterpret_cast(m_ob.get())->swap(*stream.rdbuf()); +// } +// +// basic_fobjstream(const basic_fobjstream& other) = delete; +// basic_fobjstream(basic_fobjstream&& other) noexcept = default; +// basic_fobjstream& operator=(const basic_fobjstream& other) = delete; +// basic_fobjstream& operator=(basic_fobjstream&& other) noexcept = default; +// }; +// +// template +// class basic_ifobjstream final : public basic_iobjstream +// { +// public: +// using mybase = basic_iobjstream; +// using myfb = basic_fobjbuf; +// +// using mybase::m_ob; +// +// explicit basic_ifobjstream(std::ifstream&& stream) +// : mybase(std::make_unique(std::move(*stream.rdbuf()))) +// { +// // reinterpret_cast(m_ob.get())->swapp(*stream.rdbuf()); +// // m_ob->swapp(*stream.rdbuf()); +// } +// ~basic_ifobjstream() = default; +// +// basic_ifobjstream(const basic_ifobjstream& other) = delete; +// basic_ifobjstream(basic_ifobjstream&& other) noexcept = default; +// basic_ifobjstream& operator=(const basic_ifobjstream& other) = delete; +// basic_ifobjstream& operator=(basic_ifobjstream&& other) noexcept = default; +// }; +// +// template +// class basic_ofobjstream final : public basic_oobjstream +// { +// public: +// using mybase = basic_oobjstream; +// using myfb = basic_fobjbuf; +// +// using mybase::m_ob; +// +// explicit basic_ofobjstream(std::ofstream file) +// : mybase(std::make_unique(file.rdbuf())) +// { +// } +// +// basic_ofobjstream(const basic_ofobjstream& other) = delete; +// basic_ofobjstream(basic_ofobjstream&& other) noexcept = default; +// basic_ofobjstream& operator=(const basic_ofobjstream& other) = delete; +// basic_ofobjstream& operator=(basic_ofobjstream&& other) noexcept = default; +// }; +// +// using fobjbuf = basic_fobjbuf>; +// using fobjstream = basic_fobjstream>; +// using ifobjstream = basic_ifobjstream>; +// using ofobjstream = basic_ofobjstream>; \ No newline at end of file diff --git a/src/ObjCommon/Utils/ObjStream.h b/src/ObjCommon/Utils/ObjStream.h new file mode 100644 index 00000000..9393fc1a --- /dev/null +++ b/src/ObjCommon/Utils/ObjStream.h @@ -0,0 +1,222 @@ +// ReSharper disable CppInconsistentNaming +// ReSharper disable IdentifierTypo +#pragma once + +#include + +#include "Utils/ClassUtils.h" +#include +#include +#include + +template +class basic_objbuf : public std::basic_streambuf +{ +public: + _NODISCARD virtual bool is_open() const = 0; + virtual bool close() = 0; +}; + +template +class basic_objstream : public std::basic_iostream +{ +public: + using mybase = std::basic_iostream; + using myob = basic_objbuf; + using myios = std::basic_ios; + + explicit basic_objstream(std::unique_ptr objbuf) + : std::basic_iostream(objbuf.get()), + m_ob(std::move(objbuf)) + { + assert(m_ob); + } + + explicit basic_objstream(basic_objstream&& right) noexcept + : std::basic_iostream(right), + m_ob(std::move(right.m_ob)) + { + assert(m_ob != nullptr); + } + + basic_objstream(const basic_objstream& other) = delete; + basic_objstream& operator=(const basic_objstream& other) = delete; + + ~basic_objstream() override + { + if(m_ob) + m_ob->close(); + } + + void swap(basic_objstream& right) noexcept + { + if (this != _STD addressof(right)) + { + mybase::swap(right); + m_ob = std::move(right.m_ob); + } + } + + basic_objstream& operator=(basic_objstream&& other) noexcept + { + swap(other); + return *this; + } + + // ReSharper disable once CppHidingFunction + _NODISCARD myob* rdbuf() const + { + return const_cast(m_ob.get()); + } + + _NODISCARD bool is_open() const + { + return m_ob->is_open(); + } + + void close() + { + if (!m_ob->close()) + { + myios::setstate(std::ios_base::failbit); + } + } + +protected: + std::unique_ptr m_ob; +}; + +template +class basic_iobjstream : public std::basic_istream +{ +public: + using mybase = std::basic_istream; + using myob = basic_objbuf; + using myios = std::basic_ios; + + explicit basic_iobjstream(std::unique_ptr objbuf) + : std::basic_istream(objbuf.get()), + m_ob(std::move(objbuf)) + { + assert(m_ob); + } + + explicit basic_iobjstream(basic_iobjstream&& right) noexcept + : std::basic_istream(right), + m_ob(std::move(right.m_ob)) + { + assert(m_ob != nullptr); + } + + basic_iobjstream(const basic_iobjstream& other) = delete; + basic_iobjstream& operator=(const basic_iobjstream& other) = delete; + + ~basic_iobjstream() override = default; + + void swap(basic_iobjstream& right) noexcept + { + if (this != _STD addressof(right)) + { + mybase::swap(right); + m_ob = std::move(right.m_ob); + } + } + + basic_iobjstream& operator=(basic_iobjstream&& other) noexcept + { + swap(other); + return *this; + } + + // ReSharper disable once CppHidingFunction + _NODISCARD myob* rdbuf() const + { + return const_cast(m_ob.get()); + } + + _NODISCARD bool is_open() const + { + return m_ob->is_open(); + } + + void close() + { + if (!m_ob->close()) + { + myios::setstate(std::ios_base::failbit); + } + } + +protected: + std::unique_ptr m_ob; +}; + +template +class basic_oobjstream : public std::basic_ostream +{ +public: + using mybase = std::basic_ostream; + using myob = basic_objbuf; + using myios = std::basic_ios; + + explicit basic_oobjstream(std::unique_ptr objbuf) + : std::basic_ostream(objbuf.get()), + m_ob(std::move(objbuf)) + { + assert(m_ob); + } + + explicit basic_oobjstream(basic_oobjstream&& right) noexcept + : std::basic_ostream(right), + m_ob(std::move(right.m_ob)) + { + assert(m_ob != nullptr); + } + + ~basic_oobjstream() override = default; + + basic_oobjstream(const basic_oobjstream& other) = delete; + basic_oobjstream& operator=(const basic_oobjstream& other) = delete; + + void swap(basic_oobjstream& right) noexcept + { + if (this != _STD addressof(right)) + { + mybase::swap(right); + m_ob = std::move(right.m_ob); + } + } + + basic_oobjstream& operator=(basic_oobjstream&& other) noexcept + { + swap(other); + return *this; + } + + // ReSharper disable once CppHidingFunction + _NODISCARD myob* rdbuf() const + { + return const_cast(m_ob.get()); + } + + _NODISCARD bool is_open() const + { + return m_ob->is_open(); + } + + void close() + { + if (!m_ob->close()) + { + myios::setstate(std::ios_base::failbit); + } + } + +protected: + std::unique_ptr m_ob; +}; + +using objbuf = basic_objbuf>; +using objstream = basic_objstream>; +using iobjstream = basic_iobjstream>; +using oobjstream = basic_oobjstream>; diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp index 1beb111a..652a2416 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp @@ -43,15 +43,14 @@ namespace IW4 Texture* loadedTexture = nullptr; IwiLoader loader(zone->GetMemory()); - const std::string imageFileName = "images/" + std::string(image->name) + ".iwi"; - auto* filePathImage = searchPath->Open(imageFileName); + const auto imageFileName = "images/" + std::string(image->name) + ".iwi"; - if (filePathImage != nullptr) { - loadedTexture = loader.LoadIwi(filePathImage); - - filePathImage->Close(); - delete filePathImage; + const auto filePathImage = searchPath->Open(imageFileName); + if (filePathImage != nullptr) + { + loadedTexture = loader.LoadIwi(*filePathImage); + } } if (loadedTexture != nullptr) @@ -59,8 +58,8 @@ namespace IW4 image->texture.texture = loadedTexture; image->cardMemory.platform[0] = 0; - const int textureMipCount = loadedTexture->GetMipMapCount(); - for (int mipLevel = 0; mipLevel < textureMipCount; mipLevel++) + const auto textureMipCount = loadedTexture->GetMipMapCount(); + for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++) image->cardMemory.platform[0] += static_cast(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount()); } else diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index eddc055e..5311bb2a 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -1,4 +1,5 @@ #include "ObjLoaderT6.h" + #include "Game/T6/GameT6.h" #include "Game/T6/GameAssetPoolT6.h" #include "ObjContainer/IPak/IPak.h" @@ -22,36 +23,32 @@ namespace T6 if (ObjLoading::Configuration.Verbose) printf("Trying to load ipak '%s' for zone '%s'\n", ipakName.c_str(), zone->m_name.c_str()); - IPak* existingIPak = IPak::Repository.GetContainerByName(ipakName); + auto* existingIPak = IPak::Repository.GetContainerByName(ipakName); if (existingIPak != nullptr) { if (ObjLoading::Configuration.Verbose) printf("Referencing loaded ipak '%s'.\n", ipakName.c_str()); - IPak::Repository.AddContainer(existingIPak, zone); + IPak::Repository.AddContainerReference(existingIPak, zone); return; } - const std::string ipakFilename = ipakName + ".ipak"; + const auto ipakFilename = ipakName + ".ipak"; - auto* file = searchPath->Open(ipakFilename); - if (file && file->IsOpen()) + auto file = searchPath->Open(ipakFilename); + if (file) { - IPak* ipak = new IPak(ipakFilename, file); + auto ipak = std::make_unique(ipakFilename, std::move(file)); if (ipak->Initialize()) { - IPak::Repository.AddContainer(ipak, zone); + IPak::Repository.AddContainer(std::move(ipak), zone); if (ObjLoading::Configuration.Verbose) printf("Found and loaded ipak '%s'.\n", ipakFilename.c_str()); } else { - delete ipak; - file->Close(); - delete file; - printf("Failed to load ipak '%s'!\n", ipakFilename.c_str()); } } @@ -108,7 +105,7 @@ namespace T6 void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const { auto* assetPoolT6 = dynamic_cast(zone->m_pools.get()); - const int zoneNameHash = CommonT6::Com_HashKey(zone->m_name.c_str(), 64); + const auto zoneNameHash = CommonT6::Com_HashKey(zone->m_name.c_str(), 64); LoadCommonIPaks(searchPath, zone); @@ -117,9 +114,9 @@ namespace T6 for (auto* keyValuePairsEntry : *assetPoolT6->m_key_value_pairs) { auto* keyValuePairs = keyValuePairsEntry->Asset(); - for (int variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++) + for (auto variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++) { - KeyValuePair* variable = &keyValuePairs->keyValuePairs[variableIndex]; + auto* variable = &keyValuePairs->keyValuePairs[variableIndex]; if (variable->namespaceHash == zoneNameHash && variable->keyHash == IPAK_READ_HASH) { @@ -149,14 +146,13 @@ namespace T6 { for (auto* ipak : IPak::Repository) { - auto* ipakStream = ipak->GetEntryStream(image->hash, image->streamedParts[0].hash); + auto ipakStream = ipak->GetEntryStream(image->hash, image->streamedParts[0].hash); - if (ipakStream != nullptr) + if (ipakStream) { - loadedTexture = loader.LoadIwi(ipakStream); + loadedTexture = loader.LoadIwi(*ipakStream); - ipakStream->Close(); - delete ipakStream; + ipakStream->close(); if (loadedTexture != nullptr) { @@ -168,15 +164,14 @@ namespace T6 if (loadedTexture == nullptr) { - const std::string imageFileName = "images/" + std::string(image->name) + ".iwi"; - auto* filePathImage = searchPath->Open(imageFileName); + const auto imageFileName = "images/" + std::string(image->name) + ".iwi"; - if (filePathImage != nullptr) { - loadedTexture = loader.LoadIwi(filePathImage); - - filePathImage->Close(); - delete filePathImage; + const auto filePathImage = searchPath->Open(imageFileName); + if (filePathImage) + { + loadedTexture = loader.LoadIwi(*filePathImage); + } } } @@ -185,8 +180,8 @@ namespace T6 image->texture.texture = loadedTexture; image->loadedSize = 0; - const int textureMipCount = loadedTexture->GetMipMapCount(); - for (int mipLevel = 0; mipLevel < textureMipCount; mipLevel++) + const auto textureMipCount = loadedTexture->GetMipMapCount(); + for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++) image->loadedSize += loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount(); } else diff --git a/src/ObjLoading/Image/IwiLoader.cpp b/src/ObjLoading/Image/IwiLoader.cpp index 8a8a310b..87acf744 100644 --- a/src/ObjLoading/Image/IwiLoader.cpp +++ b/src/ObjLoading/Image/IwiLoader.cpp @@ -52,21 +52,22 @@ const ImageFormat* IwiLoader::GetFormat8(int8_t format) return nullptr; } -Texture* IwiLoader::LoadIwi8(FileAPI::IFile* file) +Texture* IwiLoader::LoadIwi8(std::istream& stream) const { iwi8::IwiHeader header{}; - if (file->Read(&header, sizeof header, 1) != 1) + stream.read(reinterpret_cast(&header), sizeof header); + if (stream.gcount() != sizeof header) return nullptr; - const ImageFormat* format = GetFormat8(header.format); + const auto* format = GetFormat8(header.format); if (format == nullptr) return nullptr; - uint16_t width = header.dimensions[0]; - uint16_t height = header.dimensions[1]; - uint16_t depth = header.dimensions[2]; - bool hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS); + auto width = header.dimensions[0]; + auto height = header.dimensions[1]; + auto depth = header.dimensions[2]; + auto hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS); Texture* texture; if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_CUBE) @@ -94,12 +95,12 @@ Texture* IwiLoader::LoadIwi8(FileAPI::IFile* file) texture->Allocate(); - size_t currentFileSize = sizeof iwi8::IwiHeader + sizeof IwiVersion; - const int mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; + auto currentFileSize = sizeof iwi8::IwiHeader + sizeof IwiVersion; + const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; - for (int currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) + for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) { - const size_t sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); currentFileSize += sizeOfMipLevel; if (currentMipLevel < static_cast(_countof(iwi8::IwiHeader::fileSizeForPicmip)) @@ -111,7 +112,8 @@ Texture* IwiLoader::LoadIwi8(FileAPI::IFile* file) return nullptr; } - if (file->Read(texture->GetBufferForMipLevel(currentMipLevel), 1, sizeOfMipLevel) != sizeOfMipLevel) + stream.read(reinterpret_cast(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel); + if (stream.gcount() != sizeOfMipLevel) { printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel); @@ -167,21 +169,22 @@ const ImageFormat* IwiLoader::GetFormat27(int8_t format) return nullptr; } -Texture* IwiLoader::LoadIwi27(FileAPI::IFile* file) +Texture* IwiLoader::LoadIwi27(std::istream& stream) const { iwi27::IwiHeader header{}; - if (file->Read(&header, sizeof header, 1) != 1) + stream.read(reinterpret_cast(&header), sizeof header); + if (stream.gcount() != sizeof header) return nullptr; - const ImageFormat* format = GetFormat27(header.format); + const auto* format = GetFormat27(header.format); if (format == nullptr) return nullptr; - uint16_t width = header.dimensions[0]; - uint16_t height = header.dimensions[1]; - uint16_t depth = header.dimensions[2]; - bool hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS); + auto width = header.dimensions[0]; + auto height = header.dimensions[1]; + auto depth = header.dimensions[2]; + auto hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS); Texture* texture; if (header.flags & iwi27::IwiFlags::IMG_FLAG_CUBEMAP) @@ -199,12 +202,12 @@ Texture* IwiLoader::LoadIwi27(FileAPI::IFile* file) texture->Allocate(); - size_t currentFileSize = sizeof iwi27::IwiHeader + sizeof IwiVersion; - const int mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; + auto currentFileSize = sizeof iwi27::IwiHeader + sizeof IwiVersion; + const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; - for (int currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) + for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) { - const size_t sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); currentFileSize += sizeOfMipLevel; if (currentMipLevel < static_cast(_countof(iwi27::IwiHeader::fileSizeForPicmip)) @@ -216,7 +219,8 @@ Texture* IwiLoader::LoadIwi27(FileAPI::IFile* file) return nullptr; } - if (file->Read(texture->GetBufferForMipLevel(currentMipLevel), 1, sizeOfMipLevel) != sizeOfMipLevel) + stream.read(reinterpret_cast(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel); + if (stream.gcount() != sizeOfMipLevel) { printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel); @@ -228,11 +232,12 @@ Texture* IwiLoader::LoadIwi27(FileAPI::IFile* file) return texture; } -Texture* IwiLoader::LoadIwi(FileAPI::IFile* file) +Texture* IwiLoader::LoadIwi(std::istream& stream) { IwiVersion iwiVersion{}; - if (file->Read(&iwiVersion, sizeof iwiVersion, 1) != 1) + stream.read(reinterpret_cast(&iwiVersion), sizeof iwiVersion); + if (stream.gcount() != sizeof iwiVersion) return nullptr; if (iwiVersion.tag[0] != 'I' @@ -245,10 +250,10 @@ Texture* IwiLoader::LoadIwi(FileAPI::IFile* file) switch (iwiVersion.version) { case 8: - return LoadIwi8(file); + return LoadIwi8(stream); case 27: - return LoadIwi27(file); + return LoadIwi27(stream); default: break; diff --git a/src/ObjLoading/Image/IwiLoader.h b/src/ObjLoading/Image/IwiLoader.h index b377f03e..18940009 100644 --- a/src/ObjLoading/Image/IwiLoader.h +++ b/src/ObjLoading/Image/IwiLoader.h @@ -1,6 +1,6 @@ #pragma once -#include "Utils/FileAPI.h" +#include #include "Utils/MemoryManager.h" #include "Image/Texture.h" @@ -9,13 +9,13 @@ class IwiLoader MemoryManager* m_memory_manager; static const ImageFormat* GetFormat8(int8_t format); - Texture* LoadIwi8(FileAPI::IFile* file); + Texture* LoadIwi8(std::istream& stream) const; static const ImageFormat* GetFormat27(int8_t format); - Texture* LoadIwi27(FileAPI::IFile* file); + Texture* LoadIwi27(std::istream& stream) const; public: explicit IwiLoader(MemoryManager* memoryManager); - Texture* LoadIwi(FileAPI::IFile* file); + Texture* LoadIwi(std::istream& stream); }; diff --git a/src/ObjLoading/ObjContainer/IPak/IPak.cpp b/src/ObjLoading/ObjContainer/IPak/IPak.cpp index 9e296411..e9923c6a 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPak.cpp +++ b/src/ObjLoading/ObjContainer/IPak/IPak.cpp @@ -1,27 +1,33 @@ #include "IPak.h" -#include "zlib.h" -#include "Exception/IPakLoadException.h" -#include "ObjContainer/IPak/IPakTypes.h" -#include "Utils/PathUtils.h" -#include "IPakStreamManager.h" #include #include +#include +#include + +#include "zlib.h" + +#include "Utils/FileUtils.h" +#include "Exception/IPakLoadException.h" +#include "ObjContainer/IPak/IPakTypes.h" +#include "IPakStreamManager.h" + +namespace fs = std::filesystem; ObjContainerRepository IPak::Repository; class IPak::Impl : public ObjContainerReferenceable { - static const uint32_t MAGIC = 'IPAK'; + static const uint32_t MAGIC = MakeMagic32('K', 'A', 'P', 'I'); static const uint32_t VERSION = 0x50000; std::string m_path; - FileAPI::IFile* m_file; + std::unique_ptr m_stream; bool m_initialized; - IPakSection* m_index_section; - IPakSection* m_data_section; + std::unique_ptr m_index_section; + std::unique_ptr m_data_section; std::vector m_index_entries; @@ -29,7 +35,7 @@ class IPak::Impl : public ObjContainerReferenceable static uint32_t R_HashString(const char* str, uint32_t hash) { - for (const char* pos = str; *pos; pos++) + for (const auto* pos = str; *pos; pos++) { hash = 33 * hash ^ (*pos | 0x20); } @@ -39,12 +45,13 @@ class IPak::Impl : public ObjContainerReferenceable bool ReadIndexSection() { - m_file->Goto(m_index_section->offset); + m_stream->seekg(m_index_section->offset); IPakIndexEntry indexEntry{}; for (unsigned itemIndex = 0; itemIndex < m_index_section->itemCount; itemIndex++) { - if (m_file->Read(&indexEntry, sizeof indexEntry, 1) != 1) + m_stream->read(reinterpret_cast(&indexEntry), sizeof indexEntry); + if (m_stream->gcount() != sizeof indexEntry) { printf("Unexpected eof when trying to load index entry %u.\n", itemIndex); return false; @@ -66,7 +73,8 @@ class IPak::Impl : public ObjContainerReferenceable { IPakSection section{}; - if (m_file->Read(§ion, sizeof section, 1) != 1) + m_stream->read(reinterpret_cast(§ion), sizeof section); + if (m_stream->gcount() != sizeof section) { printf("Unexpected eof when trying to load section.\n"); return false; @@ -75,11 +83,11 @@ class IPak::Impl : public ObjContainerReferenceable switch (section.type) { case 1: - m_index_section = new IPakSection(section); + m_index_section = std::make_unique(section); break; case 2: - m_data_section = new IPakSection(section); + m_data_section = std::make_unique(section); break; default: @@ -93,7 +101,8 @@ class IPak::Impl : public ObjContainerReferenceable { IPakHeader header{}; - if (m_file->Read(&header, sizeof header, 1) != 1) + m_stream->read(reinterpret_cast(&header), sizeof header); + if (m_stream->gcount() != sizeof header) { printf("Unexpected eof when trying to load header.\n"); return false; @@ -136,28 +145,22 @@ class IPak::Impl : public ObjContainerReferenceable } public: - Impl(std::string path, FileAPI::IFile* file) - : m_stream_manager(file) + Impl(std::string path, std::unique_ptr stream) + : m_path(std::move(path)), + m_stream(std::move(stream)), + m_initialized(false), + m_index_section(nullptr), + m_data_section(nullptr), + m_stream_manager(*m_stream) { - m_path = std::move(path); - m_file = file; - m_initialized = false; - m_index_section = nullptr; - m_data_section = nullptr; } - ~Impl() - { - delete m_index_section; - m_index_section = nullptr; - - delete m_data_section; - m_data_section = nullptr; - } + ~Impl() override + = default; std::string GetName() override { - return utils::Path::GetFilenameWithoutExtension(m_path); + return fs::path(m_path).filename().replace_extension("").string(); } bool Initialize() @@ -172,7 +175,7 @@ public: return true; } - FileAPI::IFile* GetEntryData(const Hash nameHash, const Hash dataHash) + std::unique_ptr GetEntryData(const Hash nameHash, const Hash dataHash) { IPakIndexEntryKey wantedKey{}; wantedKey.nameHash = nameHash; @@ -182,7 +185,7 @@ public: { if (entry.key.combinedKey == wantedKey.combinedKey) { - return m_stream_manager.OpenStream(m_data_section->offset + entry.offset, entry.size); + return m_stream_manager.OpenStream(static_cast(m_data_section->offset) + entry.offset, entry.size); } else if (entry.key.combinedKey > wantedKey.combinedKey) { @@ -205,9 +208,9 @@ public: } }; -IPak::IPak(std::string path, FileAPI::IFile* file) +IPak::IPak(std::string path, std::unique_ptr stream) { - m_impl = new Impl(std::move(path), file); + m_impl = new Impl(std::move(path), std::move(stream)); } IPak::~IPak() @@ -221,12 +224,12 @@ std::string IPak::GetName() return m_impl->GetName(); } -bool IPak::Initialize() const +bool IPak::Initialize() { return m_impl->Initialize(); } -FileAPI::IFile* IPak::GetEntryStream(const Hash nameHash, const Hash dataHash) const +std::unique_ptr IPak::GetEntryStream(const Hash nameHash, const Hash dataHash) const { return m_impl->GetEntryData(nameHash, dataHash); } diff --git a/src/ObjLoading/ObjContainer/IPak/IPak.h b/src/ObjLoading/ObjContainer/IPak/IPak.h index 9506e28f..1c16633b 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPak.h +++ b/src/ObjLoading/ObjContainer/IPak/IPak.h @@ -1,8 +1,11 @@ #pragma once -#include "Utils/FileAPI.h" +#include + +#include "Utils/ClassUtils.h" #include "ObjContainer/ObjContainerReferenceable.h" #include "ObjContainer/ObjContainerRepository.h" +#include "Utils/ObjStream.h" #include "Zone/Zone.h" class IPak final : public ObjContainerReferenceable @@ -15,13 +18,13 @@ public: static ObjContainerRepository Repository; - IPak(std::string path, FileAPI::IFile* file); - ~IPak(); + IPak(std::string path, std::unique_ptr stream); + ~IPak() override; std::string GetName() override; - bool Initialize() const; - FileAPI::IFile* GetEntryStream(Hash nameHash, Hash dataHash) const; + bool Initialize(); + _NODISCARD std::unique_ptr GetEntryStream(Hash nameHash, Hash dataHash) const; static Hash HashString(const std::string& str); static Hash HashData(const void* data, size_t dataSize); diff --git a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp index 9d7ef7ae..075723de 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp +++ b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.cpp @@ -1,48 +1,47 @@ #include "IPakEntryReadStream.h" -#include "ObjContainer/IPak/IPakTypes.h" + #include -#include + #include +#include "ObjContainer/IPak/IPakTypes.h" + using namespace ipak_consts; -IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, +IPakEntryReadStream::IPakEntryReadStream(std::istream& stream, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, const int64_t startOffset, const size_t entrySize) - : m_decompress_buffer{} + : m_chunk_buffer(chunkBuffer), + m_stream(stream), + m_stream_manager_actions(streamManagerActions), + m_file_offset(0), + m_file_head(0), + m_entry_size(entrySize), + m_decompress_buffer{}, + m_current_block(nullptr), + m_next_command(0), + m_current_command_buffer(nullptr), + m_current_command_length(0), + m_current_command_offset(0), + m_pos(startOffset), + m_base_pos(startOffset), + m_end_pos(startOffset + entrySize), + m_buffer_start_pos(0), + m_buffer_end_pos(0) { - m_file = file; - m_stream_manager_actions = streamManagerActions; - m_chunk_buffer = chunkBuffer; - - m_file_offset = 0; - m_file_head = 0; - m_entry_size = entrySize; - - m_base_pos = startOffset; - m_end_pos = startOffset + entrySize; - m_pos = m_base_pos; - m_buffer_start_pos = 0; - m_buffer_end_pos = 0; - - m_current_block = nullptr; - m_next_command = 0; - m_current_command_buffer = nullptr; - m_current_command_length = 0; - m_current_command_offset = 0; - lzo_init(); } IPakEntryReadStream::~IPakEntryReadStream() { - Close(); + close(); } size_t IPakEntryReadStream::ReadChunks(uint8_t* buffer, const int64_t startPos, const size_t chunkCount) const { m_stream_manager_actions->StartReading(); - m_file->Goto(startPos); - const auto readSize = m_file->Read(buffer, 1, chunkCount * IPAK_CHUNK_SIZE); + m_stream.seekg(startPos); + m_stream.read(reinterpret_cast(buffer), static_cast(chunkCount) * IPAK_CHUNK_SIZE); + const auto readSize = static_cast(m_stream.gcount()); m_stream_manager_actions->StopReading(); return readSize / IPAK_CHUNK_SIZE; @@ -66,47 +65,42 @@ bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, size_t ch return true; } - const int64_t endPos = startPos + static_cast(chunkCount) * IPAK_CHUNK_SIZE; + const auto endPos = startPos + static_cast(chunkCount) * IPAK_CHUNK_SIZE; if (startPos >= m_buffer_start_pos && startPos < m_buffer_end_pos) { if (m_buffer_start_pos != startPos) { - const int64_t moveEnd = endPos < m_buffer_end_pos ? endPos : m_buffer_end_pos; - memmove_s(m_chunk_buffer, - IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ, - &m_chunk_buffer[startPos - m_buffer_start_pos], + const auto moveEnd = endPos < m_buffer_end_pos ? endPos : m_buffer_end_pos; + memmove_s(m_chunk_buffer, IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ, &m_chunk_buffer[startPos - m_buffer_start_pos], static_cast(moveEnd - startPos)); m_buffer_start_pos = startPos; } if (endPos > m_buffer_end_pos) { - const size_t readChunkCount = ReadChunks(&m_chunk_buffer[m_buffer_end_pos - startPos], - m_buffer_end_pos, - static_cast(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE); + const auto readChunkCount = ReadChunks(&m_chunk_buffer[m_buffer_end_pos - startPos], m_buffer_end_pos, + static_cast(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE); m_buffer_end_pos += static_cast(readChunkCount) * IPAK_CHUNK_SIZE; return m_buffer_end_pos == endPos; } - else - { - m_buffer_end_pos = endPos; - return true; - } + m_buffer_end_pos = endPos; + return true; } - else if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos) + + if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos) { memmove_s(&m_chunk_buffer[m_buffer_start_pos - startPos], IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ - static_cast(m_buffer_start_pos - startPos), m_chunk_buffer, static_cast(endPos - m_buffer_start_pos)); - const size_t readChunkCount = ReadChunks(m_chunk_buffer, - startPos, - static_cast(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE); + const auto readChunkCount = ReadChunks(m_chunk_buffer, + startPos, + static_cast(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE); m_buffer_start_pos = startPos; m_buffer_end_pos = readChunkCount == (m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE @@ -116,9 +110,7 @@ bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, size_t ch return m_buffer_end_pos == endPos; } - const size_t readChunkCount = ReadChunks(m_chunk_buffer, - startPos, - chunkCount); + const auto readChunkCount = ReadChunks(m_chunk_buffer, startPos, chunkCount); m_buffer_start_pos = startPos; m_buffer_end_pos = startPos + static_cast(readChunkCount) * IPAK_CHUNK_SIZE; @@ -136,12 +128,12 @@ bool IPakEntryReadStream::ValidateBlockHeader(IPakDataBlockHeader* blockHeader) if (blockHeader->offset != m_file_head) { // A matching offset is only relevant if a command contains data. - for(unsigned currentCommand = 0; currentCommand < blockHeader->count; currentCommand++) + for (unsigned currentCommand = 0; currentCommand < blockHeader->count; currentCommand++) { - if(blockHeader->_commands[currentCommand].compressed == 0 + if (blockHeader->_commands[currentCommand].compressed == 0 || blockHeader->_commands[currentCommand].compressed == 1) { - printf("IPak block offset is not the file head: %u != %u -> Invalid\n", blockHeader->offset, m_file_head); + printf("IPak block offset is not the file head: %u != %lld -> Invalid\n", blockHeader->offset, m_file_head); return false; } } @@ -190,8 +182,8 @@ bool IPakEntryReadStream::NextBlock() const auto chunkStartPos = AlignBackwards(m_pos, IPAK_CHUNK_SIZE); const auto blockOffsetInChunk = static_cast(m_pos - chunkStartPos); - const size_t sizeLeftToRead = m_entry_size - m_file_head; - size_t estimatedChunksToRead = AlignForward(m_entry_size - static_cast(m_pos - m_base_pos), IPAK_CHUNK_SIZE) + const auto sizeLeftToRead = m_entry_size - m_file_head; + auto estimatedChunksToRead = AlignForward(m_entry_size - static_cast(m_pos - m_base_pos), IPAK_CHUNK_SIZE) / IPAK_CHUNK_SIZE; if (estimatedChunksToRead > IPAK_CHUNK_COUNT_PER_READ) @@ -263,18 +255,29 @@ bool IPakEntryReadStream::AdvanceStream() return true; } -bool IPakEntryReadStream::IsOpen() +bool IPakEntryReadStream::is_open() const { - return m_file != nullptr; + return !m_stream.eof(); } -size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const size_t elementCount) +bool IPakEntryReadStream::close() { - auto* destBuffer = static_cast(buffer); - const size_t bufferSize = elementCount * elementSize; - size_t countRead = 0; + if (is_open()) + { + m_stream_manager_actions->CloseStream(this); + } - while (countRead < bufferSize) + return true; +} + +std::streamsize IPakEntryReadStream::showmanyc() +{ + return m_end_pos - m_pos; +} + +std::streambuf::int_type IPakEntryReadStream::underflow() +{ + while (true) { if (m_current_command_offset >= m_current_command_length) { @@ -282,68 +285,93 @@ size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const s break; } - size_t sizeToRead = bufferSize - countRead; + if (m_current_command_length - m_current_command_offset < 1) + continue; + + return m_current_command_buffer[m_current_command_offset]; + } + + return EOF; +} + +std::streambuf::int_type IPakEntryReadStream::uflow() +{ + while (true) + { + if (m_current_command_offset >= m_current_command_length) + { + if (!AdvanceStream()) + break; + } + + if (m_current_command_length - m_current_command_offset < 1) + continue; + + const auto result = m_current_command_buffer[m_current_command_offset]; + m_current_command_offset++; + m_file_offset++; + + return result; + } + + return EOF; +} + +std::streamsize IPakEntryReadStream::xsgetn(char* ptr, const std::streamsize count) +{ + auto* destBuffer = reinterpret_cast(ptr); + int64_t countRead = 0; + + while (countRead < count) + { + if (m_current_command_offset >= m_current_command_length) + { + if (!AdvanceStream()) + break; + } + + auto sizeToRead = count - countRead; if (sizeToRead > m_current_command_length - m_current_command_offset) sizeToRead = m_current_command_length - m_current_command_offset; if (sizeToRead > 0) { - memcpy_s(&destBuffer[countRead], bufferSize - countRead, - &m_current_command_buffer[m_current_command_offset], sizeToRead); + memcpy_s(&destBuffer[countRead], static_cast(count - countRead), + &m_current_command_buffer[m_current_command_offset], static_cast(sizeToRead)); countRead += sizeToRead; m_current_command_offset += sizeToRead; m_file_offset += sizeToRead; } } - return countRead / elementSize; + return countRead; } -size_t IPakEntryReadStream::Write(const void* data, size_t elementSize, size_t elementCount) +std::streambuf::pos_type IPakEntryReadStream::seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) { - // This is not meant for writing. - assert(false); - throw std::runtime_error("This is not a stream for output!"); -} - -void IPakEntryReadStream::Skip(const int64_t amount) -{ - if (amount > 0) + pos_type pos; + if (dir == std::ios_base::beg) { - const size_t targetOffset = m_file_offset + static_cast(amount); - - while (m_file_head < targetOffset) - { - if (!AdvanceStream()) - break; - } - - if (targetOffset <= m_file_head) - { - m_current_command_offset = m_current_command_length - (m_file_head - targetOffset); - m_file_offset = targetOffset; - } - else - { - m_current_command_offset = m_current_command_length; - m_file_offset = m_file_head; - } + pos = off; } + else if (dir == std::ios_base::cur) + { + pos = off + m_file_offset; + } + else + { + pos = -1; + } + + if (pos == 0 || pos > m_file_offset) + { + return seekpos(pos, mode); + } + + return std::streampos(-1); } -size_t IPakEntryReadStream::Printf(const char* fmt, ...) -{ - // This is not meant for writing. - assert(false); - throw std::runtime_error("This is not a stream for output!"); -} - -int64_t IPakEntryReadStream::Pos() -{ - return m_file_offset; -} - -void IPakEntryReadStream::Goto(const int64_t pos) +std::streambuf::pos_type IPakEntryReadStream::seekpos(const pos_type pos, std::ios_base::openmode mode) { if (pos == 0) { @@ -357,34 +385,31 @@ void IPakEntryReadStream::Goto(const int64_t pos) m_current_command_buffer = nullptr; m_current_command_length = 0; m_current_command_offset = 0; - } - else if (pos > m_file_offset) - { - Skip(pos - m_file_offset); - } - else - { - // Not implemented due to being too time consuming. - // Can be added if necessary. - assert(false); - throw std::runtime_error("Operation not supported!"); - } -} -void IPakEntryReadStream::GotoEnd() -{ - // Not implemented due to being too time consuming. - // Can be added if necessary. - assert(false); - throw std::runtime_error("Operation not supported!"); -} - -void IPakEntryReadStream::Close() -{ - if (IsOpen()) - { - m_file = nullptr; - - m_stream_manager_actions->CloseStream(this); + return pos; } + + if (pos > m_file_offset) + { + while (m_file_head < pos) + { + if (!AdvanceStream()) + break; + } + + if (pos <= m_file_head) + { + m_current_command_offset = m_current_command_length - (m_file_head - pos); + m_file_offset = pos; + } + else + { + m_current_command_offset = m_current_command_length; + m_file_offset = m_file_head; + } + + return pos; + } + + return std::streampos(-1); } diff --git a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h index b89ca8a8..f6b13a1c 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h +++ b/src/ObjLoading/ObjContainer/IPak/IPakEntryReadStream.h @@ -1,21 +1,22 @@ #pragma once -#include "IPakStreamManager.h" -#include "Utils/FileAPI.h" -#include "ObjContainer/IPak/IPakTypes.h" -#include +#include -class IPakEntryReadStream final : public FileAPI::IFile +#include "Utils/ObjStream.h" +#include "IPakStreamManager.h" +#include "ObjContainer/IPak/IPakTypes.h" + +class IPakEntryReadStream final : public objbuf { static constexpr size_t IPAK_DECOMPRESS_BUFFER_SIZE = 0x8000; uint8_t* m_chunk_buffer; - IFile* m_file; + std::istream& m_stream; IPakStreamManagerActions* m_stream_manager_actions; - size_t m_file_offset; - size_t m_file_head; + int64_t m_file_offset; + int64_t m_file_head; size_t m_entry_size; @@ -53,16 +54,17 @@ class IPakEntryReadStream final : public FileAPI::IFile bool AdvanceStream(); public: - IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t entrySize); + IPakEntryReadStream(std::istream& stream, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t entrySize); ~IPakEntryReadStream() override; - bool IsOpen() override; - size_t Read(void* buffer, size_t elementSize, size_t elementCount) override; - size_t Write(const void* data, size_t elementSize, size_t elementCount) override; - void Skip(int64_t amount) override; - size_t Printf(const char* fmt, ...) override; - int64_t Pos() override; - void Goto(int64_t pos) override; - void GotoEnd() override; - void Close() override; + _NODISCARD bool is_open() const override; + bool close() override; + +protected: + std::streamsize showmanyc() override; + int_type underflow() override; + int_type uflow() override; + std::streamsize xsgetn(char* ptr, std::streamsize count) override; + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode) override; + pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override; }; \ No newline at end of file diff --git a/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.cpp b/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.cpp index 8e4eec08..71e2e824 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.cpp +++ b/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.cpp @@ -1,9 +1,11 @@ #include "IPakStreamManager.h" -#include "IPakEntryReadStream.h" -#include "ObjContainer/IPak/IPakTypes.h" + #include #include +#include "IPakEntryReadStream.h" +#include "ObjContainer/IPak/IPakTypes.h" + using namespace ipak_consts; class IPakStreamManager::Impl final : public IPakStreamManagerActions @@ -30,7 +32,7 @@ class IPakStreamManager::Impl final : public IPakStreamManagerActions } }; - FileAPI::IFile* m_file; + std::istream& m_stream; std::mutex m_read_mutex; std::mutex m_stream_mutex; @@ -39,10 +41,9 @@ class IPakStreamManager::Impl final : public IPakStreamManagerActions std::vector m_chunk_buffers; public: - explicit Impl(FileAPI::IFile* file) + explicit Impl(std::istream& stream) + : m_stream(stream) { - m_file = file; - m_chunk_buffers.push_back(new ChunkBuffer()); } @@ -55,7 +56,7 @@ public: for (const auto& openStream : m_open_streams) { - openStream.m_stream->Close(); + openStream.m_stream->close(); } m_open_streams.clear(); @@ -65,16 +66,15 @@ public: Impl& operator=(const Impl& other) = delete; Impl& operator=(Impl&& other) noexcept = delete; - FileAPI::IFile* OpenStream(const int64_t startPosition, const size_t length) + std::unique_ptr OpenStream(const int64_t startPosition, const size_t length) { m_stream_mutex.lock(); ChunkBuffer* reservedChunkBuffer; - const auto freeChunkBuffer = std::find_if(m_chunk_buffers.begin(), m_chunk_buffers.end(), - [](ChunkBuffer* chunkBuffer) - { - return chunkBuffer->m_using_stream == nullptr; - }); + const auto freeChunkBuffer = std::find_if(m_chunk_buffers.begin(), m_chunk_buffers.end(), [](ChunkBuffer* chunkBuffer) + { + return chunkBuffer->m_using_stream == nullptr; + }); if (freeChunkBuffer == m_chunk_buffers.end()) { @@ -84,15 +84,15 @@ public: else reservedChunkBuffer = *freeChunkBuffer; - auto* stream = new IPakEntryReadStream(m_file, this, reservedChunkBuffer->m_buffer, startPosition, length); + auto ipakEntryStream = std::make_unique(m_stream, this, reservedChunkBuffer->m_buffer, startPosition, length); - reservedChunkBuffer->m_using_stream = stream; + reservedChunkBuffer->m_using_stream = ipakEntryStream.get(); - m_open_streams.emplace_back(stream, reservedChunkBuffer); + m_open_streams.emplace_back(ipakEntryStream.get(), reservedChunkBuffer); m_stream_mutex.unlock(); - return stream; + return std::make_unique(std::move(ipakEntryStream)); } void StartReading() override @@ -105,15 +105,14 @@ public: m_read_mutex.unlock(); } - void CloseStream(FileAPI::IFile* stream) override + void CloseStream(objbuf* stream) override { m_stream_mutex.lock(); - const auto openStreamEntry = std::find_if(m_open_streams.begin(), m_open_streams.end(), - [stream](const ManagedStream& managedStream) - { - return managedStream.m_stream == stream; - }); + const auto openStreamEntry = std::find_if(m_open_streams.begin(), m_open_streams.end(), [stream](const ManagedStream& managedStream) + { + return managedStream.m_stream == stream; + }); if (openStreamEntry != m_open_streams.end()) { @@ -138,9 +137,9 @@ public: } }; -IPakStreamManager::IPakStreamManager(FileAPI::IFile* file) +IPakStreamManager::IPakStreamManager(std::istream& stream) + : m_impl(new Impl(stream)) { - m_impl = new Impl(file); } IPakStreamManager::~IPakStreamManager() @@ -149,7 +148,7 @@ IPakStreamManager::~IPakStreamManager() m_impl = nullptr; } -FileAPI::IFile* IPakStreamManager::OpenStream(const int64_t startPosition, const size_t length) const +std::unique_ptr IPakStreamManager::OpenStream(const int64_t startPosition, const size_t length) const { return m_impl->OpenStream(startPosition, length); } diff --git a/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.h b/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.h index 00ecf6b5..9de19c5c 100644 --- a/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.h +++ b/src/ObjLoading/ObjContainer/IPak/IPakStreamManager.h @@ -1,8 +1,11 @@ #pragma once -#include "Utils/FileAPI.h" #include #include +#include + +#include "Utils/ClassUtils.h" +#include "Utils/ObjStream.h" class IPakStreamManagerActions { @@ -10,7 +13,7 @@ public: virtual void StartReading() = 0; virtual void StopReading() = 0; - virtual void CloseStream(FileAPI::IFile* stream) = 0; + virtual void CloseStream(objbuf* stream) = 0; }; class IPakStreamManager @@ -19,7 +22,7 @@ class IPakStreamManager Impl* m_impl; public: - explicit IPakStreamManager(FileAPI::IFile* file); + explicit IPakStreamManager(std::istream& stream); IPakStreamManager(const IPakStreamManager& other) = delete; IPakStreamManager(IPakStreamManager&& other) noexcept = delete; ~IPakStreamManager(); @@ -27,5 +30,5 @@ public: IPakStreamManager& operator=(const IPakStreamManager& other) = delete; IPakStreamManager& operator=(IPakStreamManager&& other) noexcept = delete; - FileAPI::IFile* OpenStream(int64_t startPosition, size_t length) const; + _NODISCARD std::unique_ptr OpenStream(int64_t startPosition, size_t length) const; }; \ No newline at end of file diff --git a/src/ObjLoading/ObjContainer/IWD/IWD.cpp b/src/ObjLoading/ObjContainer/IWD/IWD.cpp index 36deceab..9bb31330 100644 --- a/src/ObjLoading/ObjContainer/IWD/IWD.cpp +++ b/src/ObjLoading/ObjContainer/IWD/IWD.cpp @@ -1,6 +1,5 @@ #include "IWD.h" -#include "Utils/PathUtils.h" #include "ObjLoading.h" #include "Utils/FileToZlibWrapper.h" @@ -8,10 +7,14 @@ #include #include #include +#include +#include + +namespace fs = std::filesystem; ObjContainerRepository IWD::Repository; -class IWDFile final : public FileAPI::IFile +class IWDFile final : public objbuf { public: class IParent @@ -25,99 +28,135 @@ public: private: IParent* m_parent; bool m_open; - size_t m_size; + int64_t m_size; unzFile m_container; + bool m_peeked; + int_type m_peek_symbol; public: - IWDFile(IParent* parent, const unzFile container, const size_t size) + 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) { - m_parent = parent; - m_container = container; - m_size = size; - m_open = true; } ~IWDFile() override { - if(m_open) + if (m_open) { - Close(); + close(); } } - bool IsOpen() override +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(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(m_peek_symbol) : EOF; + } + + std::streamsize xsgetn(char* ptr, std::streamsize count) override + { + if (m_peeked && count >= 1) + { + *ptr = static_cast(m_peek_symbol); + ptr++; + count--; + } + + const auto result = unzReadCurrentFile(m_container, ptr, static_cast(count)); + + return result >= 0 ? static_cast(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(currentPos) < pos) + { + auto skipAmount = pos - static_cast(currentPos); + while (skipAmount > 0) + { + char temp[1024]; + const auto toRead = skipAmount > sizeof temp ? sizeof temp : static_cast(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; } - size_t Read(void* buffer, const size_t elementSize, const size_t elementCount) override - { - const auto result = unzReadCurrentFile(m_container, buffer, elementSize * elementCount); - - return result >= 0 ? static_cast(result) / elementSize : 0; - } - - size_t Write(const void* data, size_t elementSize, size_t elementCount) override - { - // This is not meant for writing. - assert(false); - throw std::runtime_error("This is not a stream for output!"); - } - - void Skip(int64_t amount) override - { - while (amount > 0) - { - char temp[1024]; - const size_t toRead = amount > sizeof temp ? sizeof temp : static_cast(amount); - unzReadCurrentFile(m_container, temp, toRead); - amount -= toRead; - } - } - - size_t Printf(const char* fmt, ...) override - { - // This is not meant for writing. - assert(false); - throw std::runtime_error("This is not a stream for output!"); - } - - int64_t Pos() override - { - return unztell(m_container); - } - - void Goto(const int64_t pos) override - { - const auto current = Pos(); - - if(pos > current) - { - Skip(pos - current); - } - else if(pos == current) - { - // This is fine. - } - else - { - // Unsupported for zip entries - assert(false); - throw std::runtime_error("Going backwards is not supported in IWD files!"); - } - } - - void GotoEnd() override - { - Goto(m_size); - } - - void Close() override + bool close() override { unzCloseCurrentFile(m_container); m_open = false; m_parent->OnIWDFileClose(); + + return true; } }; @@ -126,12 +165,12 @@ class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IPar class IWDEntry { public: - size_t m_size{}; + int64_t m_size{}; unz_file_pos m_file_pos{}; }; std::string m_path; - FileAPI::IFile* m_file; + std::unique_ptr m_stream; unzFile m_unz_file; IWDFile* m_last_file; @@ -139,12 +178,12 @@ class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IPar std::map m_entry_map; public: - Impl(std::string path, FileAPI::IFile* file) + Impl(std::string path, std::unique_ptr stream) + : m_path(std::move(path)), + m_stream(std::move(stream)), + m_unz_file(nullptr), + m_last_file(nullptr) { - m_unz_file = nullptr; - m_path = std::move(path); - m_file = file; - m_last_file = nullptr; } ~Impl() override @@ -152,13 +191,7 @@ public: if (m_unz_file != nullptr) { unzClose(m_unz_file); - } - - if (m_file) - { - m_file->Close(); - delete m_file; - m_file = nullptr; + m_unz_file = nullptr; } } @@ -169,7 +202,7 @@ public: bool Initialize() { - auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_file); + auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_stream.get()); m_unz_file = unzOpen2("", &ioFunctions); if (m_unz_file == nullptr) @@ -181,9 +214,9 @@ public: auto ret = unzGoToFirstFile(m_unz_file); while (ret == Z_OK) { - unz_file_info info; + unz_file_info64 info; char fileNameBuffer[256]; - unzGetCurrentFileInfo(m_unz_file, &info, fileNameBuffer, sizeof fileNameBuffer, nullptr, 0, nullptr, 0); + unzGetCurrentFileInfo64(m_unz_file, &info, fileNameBuffer, sizeof fileNameBuffer, nullptr, 0, nullptr, 0); std::string fileName(fileNameBuffer); std::filesystem::path path(fileName); @@ -207,21 +240,21 @@ public: return true; } - FileAPI::IFile* Open(const std::string& fileName) override + std::unique_ptr Open(const std::string& fileName) override { if (m_unz_file == nullptr) { return nullptr; } - std::string iwdFilename = fileName; + auto iwdFilename = fileName; std::replace(iwdFilename.begin(), iwdFilename.end(), '\\', '/'); const auto iwdEntry = m_entry_map.find(iwdFilename); if (iwdEntry != m_entry_map.end()) { - if(m_last_file != nullptr) + if (m_last_file != nullptr) { throw std::runtime_error("Trying to open new IWD file while last one was not yet closed."); } @@ -231,10 +264,12 @@ public: if (unzOpenCurrentFile(m_unz_file) == UNZ_OK) { - m_last_file = new IWDFile(this, m_unz_file, iwdEntry->second.m_size); + auto result = std::make_unique(this, m_unz_file, iwdEntry->second.m_size); + m_last_file = result.get(); + return std::make_unique(std::move(result)); } - return m_last_file; + return nullptr; } return nullptr; @@ -247,24 +282,24 @@ public: std::string GetName() override { - return utils::Path::GetFilename(m_path); + return fs::path(m_path).filename().string(); } void Find(const SearchPathSearchOptions& options, const std::function& callback) override { - if(options.m_disk_files_only) + if (options.m_disk_files_only) { return; } - for(auto& [entryName, entry] : m_entry_map) + for (auto& [entryName, entry] : m_entry_map) { std::filesystem::path entryPath(entryName); - if(!options.m_should_include_subdirectories && entryPath.has_parent_path()) + if (!options.m_should_include_subdirectories && entryPath.has_parent_path()) continue; - if(options.m_filter_extensions && options.m_extension != entryPath.extension().string()) + if (options.m_filter_extensions && options.m_extension != entryPath.extension().string()) continue; callback(entryName); @@ -277,9 +312,9 @@ public: } }; -IWD::IWD(std::string path, FileAPI::IFile* file) +IWD::IWD(std::string path, std::unique_ptr stream) { - m_impl = new Impl(std::move(path), file); + m_impl = new Impl(std::move(path), std::move(stream)); } IWD::~IWD() @@ -302,12 +337,12 @@ IWD& IWD::operator=(IWD&& other) noexcept return *this; } -bool IWD::Initialize() const +bool IWD::Initialize() { return m_impl->Initialize(); } -FileAPI::IFile* IWD::Open(const std::string& fileName) +std::unique_ptr IWD::Open(const std::string& fileName) { return m_impl->Open(fileName); } diff --git a/src/ObjLoading/ObjContainer/IWD/IWD.h b/src/ObjLoading/ObjContainer/IWD/IWD.h index 6a5ef2c6..a3b386d3 100644 --- a/src/ObjLoading/ObjContainer/IWD/IWD.h +++ b/src/ObjLoading/ObjContainer/IWD/IWD.h @@ -1,5 +1,9 @@ #pragma once +#include + +#include "Utils/ClassUtils.h" +#include "Utils/ObjStream.h" #include "SearchPath/ISearchPath.h" #include "ObjContainer/ObjContainerRepository.h" @@ -11,7 +15,7 @@ class IWD final : public ISearchPath, IObjContainer public: static ObjContainerRepository Repository; - IWD(std::string path, FileAPI::IFile* file); + IWD(std::string path, std::unique_ptr stream); ~IWD(); IWD(const IWD& other) = delete; @@ -23,9 +27,9 @@ public: * \brief Initializes the IWD container. * \return \c true when initialization was successful. */ - bool Initialize() const; + bool Initialize(); - FileAPI::IFile* Open(const std::string& fileName) override; + std::unique_ptr Open(const std::string& fileName) override; std::string GetPath() override; std::string GetName() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; diff --git a/src/ObjLoading/ObjContainer/ObjContainerRepository.h b/src/ObjLoading/ObjContainer/ObjContainerRepository.h index eb9668f8..f7b13470 100644 --- a/src/ObjLoading/ObjContainer/ObjContainerRepository.h +++ b/src/ObjLoading/ObjContainer/ObjContainerRepository.h @@ -7,6 +7,7 @@ #include #include #include +#include template class ObjContainerRepository @@ -14,51 +15,67 @@ class ObjContainerRepository class ObjContainerEntry { public: - ContainerType* m_container; + std::unique_ptr m_container; std::set m_references; - explicit ObjContainerEntry(ContainerType* container) + explicit ObjContainerEntry(std::unique_ptr container) + : m_container(std::move(container)) { - m_container = container; } + + ~ObjContainerEntry() = default; + ObjContainerEntry(const ObjContainerEntry& other) = delete; + ObjContainerEntry(ObjContainerEntry&& other) noexcept = default; + ObjContainerEntry& operator=(const ObjContainerEntry& other) = delete; + ObjContainerEntry& operator=(ObjContainerEntry&& other) noexcept = default; }; std::vector m_containers; public: - void AddContainer(ContainerType* container, ReferencerType* referencer) - { - auto firstEntry = std::find_if(m_containers.begin(), m_containers.end(), - [container](ObjContainerEntry& entry) -> bool - { - return entry.m_container == container; - }); + ObjContainerRepository() = default; + ~ObjContainerRepository() = default; + ObjContainerRepository(const ObjContainerRepository& other) = delete; + ObjContainerRepository(ObjContainerRepository&& other) noexcept = default; + ObjContainerRepository& operator=(const ObjContainerRepository& other) = delete; + ObjContainerRepository& operator=(ObjContainerRepository&& other) noexcept = default; - if(firstEntry != m_containers.end()) + void AddContainer(std::unique_ptr container, ReferencerType* referencer) + { + ObjContainerEntry entry(std::move(container)); + entry.m_references.insert(referencer); + m_containers.emplace_back(std::move(entry)); + } + + bool AddContainerReference(ContainerType* container, ReferencerType* referencer) + { + auto firstEntry = std::find_if(m_containers.begin(), m_containers.end(), [container](const ObjContainerEntry& entry) + { + return entry.m_container.get() == container; + }); + + if (firstEntry != m_containers.end()) { firstEntry->m_references.insert(referencer); - return; + return true; } - ObjContainerEntry entry(container); - entry.m_references.insert(referencer); - m_containers.push_back(entry); + return false; } void RemoveContainerReferences(ReferencerType* referencer) { - for(auto iEntry = m_containers.begin(); iEntry != m_containers.end();) + for (auto iEntry = m_containers.begin(); iEntry != m_containers.end();) { auto foundReference = iEntry->m_references.find(referencer); - if(foundReference != iEntry->m_references.end()) + if (foundReference != iEntry->m_references.end()) { iEntry->m_references.erase(foundReference); } - if(iEntry->m_references.empty()) + if (iEntry->m_references.empty()) { - delete iEntry->m_container; iEntry = m_containers.erase(iEntry); } else @@ -70,14 +87,14 @@ public: ContainerType* GetContainerByName(const std::string& name) { - auto foundEntry = std::find_if(m_containers.begin(), m_containers.end(), [name](ObjContainerEntry& entry) -> bool - { - return entry.m_container->GetName() == name; - }); - - if(foundEntry != m_containers.end()) + auto foundEntry = std::find_if(m_containers.begin(), m_containers.end(), [name](ObjContainerEntry& entry) { - return foundEntry->m_container; + return entry.m_container->GetName() == name; + }); + + if (foundEntry != m_containers.end()) + { + return foundEntry->m_container.get(); } return nullptr; @@ -86,12 +103,12 @@ public: TransformIterator::iterator, ObjContainerEntry&, ContainerType*> begin() { return TransformIterator::iterator, ObjContainerEntry&, ContainerType*>( - m_containers.begin(), [](ObjContainerEntry& entry) -> ContainerType* { return entry.m_container; }); + m_containers.begin(), [](ObjContainerEntry& entry) { return entry.m_container.get(); }); } TransformIterator::iterator, ObjContainerEntry&, ContainerType*> end() { return TransformIterator::iterator, ObjContainerEntry&, ContainerType*>( - m_containers.end(), [](ObjContainerEntry& entry) -> ContainerType* { return entry.m_container; }); + m_containers.end(), [](ObjContainerEntry& entry){ return entry.m_container.get(); }); } }; diff --git a/src/ObjLoading/ObjLoading.cpp b/src/ObjLoading/ObjLoading.cpp index 85eaa2b6..79ced6b6 100644 --- a/src/ObjLoading/ObjLoading.cpp +++ b/src/ObjLoading/ObjLoading.cpp @@ -1,9 +1,13 @@ #include "ObjLoading.h" + +#include + #include "IObjLoader.h" #include "Game/IW4/ObjLoaderIW4.h" #include "Game/T6/ObjLoaderT6.h" #include "ObjContainer/IWD/IWD.h" #include "SearchPath/SearchPaths.h" +#include "Utils/ObjFileStream.h" ObjLoading::Configuration_t ObjLoading::Configuration; @@ -51,29 +55,20 @@ void ObjLoading::UnloadContainersOfZone(Zone* zone) void ObjLoading::LoadIWDsInSearchPath(ISearchPath* searchPath) { - searchPath->Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"), - [searchPath](const std::string& path) -> void - { - auto file = FileAPI::Open(path, FileAPI::Mode::MODE_READ); + searchPath->Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"), [searchPath](const std::string& path) + { + auto file = std::make_unique(path, std::fstream::in | std::fstream::binary); - if (file.IsOpen()) - { - auto* fileP = new FileAPI::File(std::move(file)); - IWD* iwd = new IWD(path, fileP); - - if (iwd->Initialize()) - { - IWD::Repository.AddContainer(iwd, searchPath); - } - else - { - delete iwd; - - fileP->Close(); - delete fileP; - } - } - }); + if (file->is_open()) + { + auto iwd = std::make_unique(path, std::move(file)); + + if (iwd->Initialize()) + { + IWD::Repository.AddContainer(std::move(iwd), searchPath); + } + } + }); } void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath) diff --git a/src/ObjLoading/SearchPath/ISearchPath.h b/src/ObjLoading/SearchPath/ISearchPath.h index fb559e81..d5e31000 100644 --- a/src/ObjLoading/SearchPath/ISearchPath.h +++ b/src/ObjLoading/SearchPath/ISearchPath.h @@ -1,8 +1,11 @@ #pragma once -#include "SearchPathSearchOptions.h" -#include "Utils/FileAPI.h" #include +#include +#include + +#include "Utils/ObjStream.h" +#include "SearchPathSearchOptions.h" class ISearchPath { @@ -14,7 +17,7 @@ public: * \param fileName The relative path to the file to open. * \return A pointer to an \c IFile object to read the found file or \c nullptr when no file could be found. */ - virtual FileAPI::IFile* Open(const std::string& fileName) = 0; + virtual std::unique_ptr Open(const std::string& fileName) = 0; /** * \brief Returns the path to the search path. diff --git a/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp b/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp index 8d2e992c..f0f92a89 100644 --- a/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp +++ b/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp @@ -1,7 +1,11 @@ #include "SearchPathFilesystem.h" -#include "Utils/PathUtils.h" #include +#include + +#include "Utils/ObjFileStream.h" + +namespace fs = std::filesystem; SearchPathFilesystem::SearchPathFilesystem(std::string path) { @@ -13,20 +17,19 @@ std::string SearchPathFilesystem::GetPath() return m_path; } -FileAPI::IFile* SearchPathFilesystem::Open(const std::string& fileName) +std::unique_ptr SearchPathFilesystem::Open(const std::string& fileName) { - FileAPI::File file = FileAPI::Open(utils::Path::Combine(m_path, fileName), FileAPI::Mode::MODE_READ); + auto file = std::make_unique(fs::path(m_path).append(fileName).string(), std::fstream::in | std::fstream::binary); - if (file.IsOpen()) + if (file->is_open()) { - return new FileAPI::File(std::move(file)); + return std::move(file); } return nullptr; } -void SearchPathFilesystem::Find(const SearchPathSearchOptions& options, - const std::function& callback) +void SearchPathFilesystem::Find(const SearchPathSearchOptions& options, const std::function& callback) { try { diff --git a/src/ObjLoading/SearchPath/SearchPathFilesystem.h b/src/ObjLoading/SearchPath/SearchPathFilesystem.h index 82e827a1..6a5f1e3c 100644 --- a/src/ObjLoading/SearchPath/SearchPathFilesystem.h +++ b/src/ObjLoading/SearchPath/SearchPathFilesystem.h @@ -1,8 +1,9 @@ #pragma once -#include "ISearchPath.h" #include +#include "ISearchPath.h" + class SearchPathFilesystem final : public ISearchPath { std::string m_path; @@ -10,7 +11,7 @@ class SearchPathFilesystem final : public ISearchPath public: explicit SearchPathFilesystem(std::string path); - FileAPI::IFile* Open(const std::string& fileName) override; + std::unique_ptr Open(const std::string& fileName) override; std::string GetPath() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; }; \ No newline at end of file diff --git a/src/ObjLoading/SearchPath/SearchPaths.cpp b/src/ObjLoading/SearchPath/SearchPaths.cpp index b28346b2..aaf681ac 100644 --- a/src/ObjLoading/SearchPath/SearchPaths.cpp +++ b/src/ObjLoading/SearchPath/SearchPaths.cpp @@ -5,15 +5,7 @@ SearchPaths::SearchPaths() = default; SearchPaths::~SearchPaths() -{ - for(auto searchPathToFree : m_to_free) - { - delete searchPathToFree; - } - m_to_free.clear(); - - m_search_paths.clear(); -} += default; SearchPaths::SearchPaths(const SearchPaths& other) : m_search_paths(other.m_search_paths) @@ -41,15 +33,15 @@ SearchPaths& SearchPaths::operator=(SearchPaths&& other) noexcept return *this; } -FileAPI::IFile* SearchPaths::Open(const std::string& fileName) +std::unique_ptr SearchPaths::Open(const std::string& fileName) { - for(auto searchPathEntry : m_search_paths) + for(auto* searchPathEntry : m_search_paths) { - auto* file = searchPathEntry->Open(fileName); + auto file = searchPathEntry->Open(fileName); - if(file != nullptr) + if(file) { - return file; + return std::move(file); } } @@ -63,16 +55,16 @@ std::string SearchPaths::GetPath() void SearchPaths::Find(const SearchPathSearchOptions& options, const std::function& callback) { - for (auto searchPathEntry : m_search_paths) + for (auto* searchPathEntry : m_search_paths) { searchPathEntry->Find(options, callback); } } -void SearchPaths::CommitSearchPath(ISearchPath* searchPath) +void SearchPaths::CommitSearchPath(std::unique_ptr searchPath) { - m_search_paths.push_back(searchPath); - m_to_free.push_back(searchPath); + m_search_paths.push_back(searchPath.get()); + m_owned_search_paths.emplace_back(std::move(searchPath)); } void SearchPaths::IncludeSearchPath(ISearchPath* searchPath) diff --git a/src/ObjLoading/SearchPath/SearchPaths.h b/src/ObjLoading/SearchPath/SearchPaths.h index 918cafc5..01b7989c 100644 --- a/src/ObjLoading/SearchPath/SearchPaths.h +++ b/src/ObjLoading/SearchPath/SearchPaths.h @@ -1,12 +1,13 @@ #pragma once -#include "ISearchPath.h" #include +#include "ISearchPath.h" + class SearchPaths final : public ISearchPath { std::vector m_search_paths; - std::vector m_to_free; + std::vector> m_owned_search_paths; public: using iterator = std::vector::iterator; @@ -14,7 +15,7 @@ public: SearchPaths(); ~SearchPaths() override; - FileAPI::IFile* Open(const std::string& fileName) override; + std::unique_ptr Open(const std::string& fileName) override; std::string GetPath() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; @@ -27,7 +28,7 @@ public: * \brief Adds a search path that gets deleted upon destruction of the \c SearchPaths object. * \param searchPath The search path to add. */ - void CommitSearchPath(ISearchPath* searchPath); + void CommitSearchPath(std::unique_ptr searchPath); /** * \brief Adds a search path that does \b NOT get deleted upon destruction of the \c SearchPaths object. diff --git a/src/ObjWriting/Dumping/AbstractAssetDumper.h b/src/ObjWriting/Dumping/AbstractAssetDumper.h index 2cebdf8b..8a324475 100644 --- a/src/ObjWriting/Dumping/AbstractAssetDumper.h +++ b/src/ObjWriting/Dumping/AbstractAssetDumper.h @@ -1,10 +1,10 @@ #pragma once #include "IAssetDumper.h" -#include "Utils/FileAPI.h" -#include "Utils/PathUtils.h" -#include +#include +#include +#include template class AbstractAssetDumper : public IAssetDumper @@ -12,7 +12,7 @@ class AbstractAssetDumper : public IAssetDumper protected: virtual bool ShouldDump(XAssetInfo* asset) = 0; virtual std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) = 0; - virtual void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) = 0; + virtual void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) = 0; public: void DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) override @@ -25,21 +25,23 @@ public: continue; } - std::string assetFilePath = utils::Path::Combine(basePath, GetFileNameForAsset(zone, assetInfo)); + std::filesystem::path assetFilePath(basePath); + assetFilePath.append(GetFileNameForAsset(zone, assetInfo)); - FileAPI::DirectoryCreate(utils::Path::GetDirectory(assetFilePath)); + auto assetFileFolder(assetFilePath); + assetFileFolder.replace_filename(""); + create_directories(assetFileFolder); - auto file = FileAPI::Open(assetFilePath, FileAPI::Mode::MODE_WRITE); - - if(file.IsOpen()) + std::ofstream file(assetFilePath, std::fstream::out | std::fstream::binary); + if(file.is_open()) { - DumpAsset(zone, assetInfo, &file); + DumpAsset(zone, assetInfo, file); - file.Close(); + file.close(); } else { - printf("Failed to open file '%s' to dump asset '%s'\n", assetFilePath.c_str(), assetInfo->m_name.c_str()); + std::cout << "Failed to open file '" << assetFilePath.string() << "' to dump asset '" << assetInfo->m_name.c_str() << "'\n"; } } } diff --git a/src/ObjWriting/Dumping/CsvWriter.cpp b/src/ObjWriting/Dumping/CsvWriter.cpp index 9c5dfad8..51909685 100644 --- a/src/ObjWriting/Dumping/CsvWriter.cpp +++ b/src/ObjWriting/Dumping/CsvWriter.cpp @@ -2,23 +2,21 @@ #include -const std::string CsvWriter::LINE_BREAK = "\n"; - -CsvWriter::CsvWriter(FileAPI::IFile* file) +CsvWriter::CsvWriter(std::ostream& stream) + : m_stream(stream), + m_column_count(0), + m_current_column(0), + m_first_row(true) { - m_file = file; - m_first_row = true; - m_current_column = 0; - m_column_count = 0; } void CsvWriter::WriteColumn(const std::string& value) { if (m_current_column++ > 0) - m_file->Printf(","); + m_stream << ","; - bool containsSeparator = false; - bool containsQuote = false; + auto containsSeparator = false; + auto containsQuote = false; for (const auto& c : value) { if (c == '"') @@ -35,7 +33,7 @@ void CsvWriter::WriteColumn(const std::string& value) { std::ostringstream str; - for(const auto& c : value) + for (const auto& c : value) { if (c == '"') str << "\"\""; @@ -43,15 +41,15 @@ void CsvWriter::WriteColumn(const std::string& value) str << c; } - m_file->Printf("\"%s\"", str.str().c_str()); + m_stream << "\"" << str.str() << "\""; } else if (containsSeparator) { - m_file->Printf("\"%s\"", value.c_str()); + m_stream << "\"" << value << "\""; } else { - m_file->Printf("%s", value.c_str()); + m_stream << value; } } @@ -64,13 +62,13 @@ void CsvWriter::NextRow() } else { - while(m_current_column < m_column_count) + while (m_current_column < m_column_count) { - m_file->Printf(","); + m_stream << ","; m_current_column++; } } - m_file->Printf("\n"); + m_stream << "\n"; m_current_column = 0; } diff --git a/src/ObjWriting/Dumping/CsvWriter.h b/src/ObjWriting/Dumping/CsvWriter.h index 6bdcd979..0181f2f5 100644 --- a/src/ObjWriting/Dumping/CsvWriter.h +++ b/src/ObjWriting/Dumping/CsvWriter.h @@ -1,18 +1,19 @@ #pragma once -#include "Utils/FileAPI.h" + +#include +#include class CsvWriter { static constexpr char SEPARATOR = ','; - static const std::string LINE_BREAK; - - FileAPI::IFile* m_file; + + std::ostream& m_stream; unsigned m_column_count; unsigned m_current_column; bool m_first_row; public: - explicit CsvWriter(FileAPI::IFile* file); + explicit CsvWriter(std::ostream& stream); void WriteColumn(const std::string& value); void NextRow(); diff --git a/src/ObjWriting/Dumping/Localize/StringFileDumper.cpp b/src/ObjWriting/Dumping/Localize/StringFileDumper.cpp index 682f9118..c3741fdc 100644 --- a/src/ObjWriting/Dumping/Localize/StringFileDumper.cpp +++ b/src/ObjWriting/Dumping/Localize/StringFileDumper.cpp @@ -1,16 +1,12 @@ #include "StringFileDumper.h" #include -StringFileDumper::StringFileDumper(Zone* zone, FileAPI::File* file) +StringFileDumper::StringFileDumper(Zone* zone, std::ostream& stream) + : m_zone(zone), + m_stream(stream), + m_language_caps("ENGLISH"), + m_wrote_header(false) { - m_zone = zone; - m_file = file; - - m_config_file = ""; - m_notes = ""; - m_language_caps = "ENGLISH"; - - m_wrote_header = false; } void StringFileDumper::SetLanguageName(std::string language) @@ -31,11 +27,11 @@ void StringFileDumper::SetNotes(std::string notes) void StringFileDumper::WriteHeader() { - m_file->Printf("// Dumped from fastfile \"%s\".\n", m_zone->m_name.c_str()); - m_file->Printf("// In their original format the strings might have been separated in multiple files.\n"); - m_file->Printf("VERSION \"1\"\n"); - m_file->Printf("CONFIG \"%s\"\n", m_config_file.c_str()); - m_file->Printf("FILENOTES \"%s\"\n", m_notes.c_str()); + m_stream << "// Dumped from fastfile \"" << m_zone->m_name << "\".\n"; + m_stream << "// In their original format the strings might have been separated in multiple files.\n"; + m_stream << "VERSION \"1\"\n"; + m_stream << "CONFIG \"" << m_config_file << "\"\n"; + m_stream << "FILENOTES \"" << m_notes << "\"\n"; m_wrote_header = true; } @@ -45,13 +41,13 @@ void StringFileDumper::WriteLocalizeEntry(const std::string& reference, const st if (!m_wrote_header) WriteHeader(); - m_file->Printf("\n"); - m_file->Printf("REFERENCE %s\n", reference.c_str()); + m_stream << "\n"; + m_stream << "REFERENCE " << reference <<"\n"; - const std::string escapedValue = std::regex_replace(value, std::regex("\n"), "\\n"); + const auto escapedValue = std::regex_replace(value, std::regex("\n"), "\\n"); - const std::string valueSpacing = std::string(15 - m_language_caps.length(), ' '); - m_file->Printf("LANG_%s%s\"%s\"\n", m_language_caps.c_str(), valueSpacing.c_str(), escapedValue.c_str()); + const auto valueSpacing = std::string(15 - m_language_caps.length(), ' '); + m_stream << "LANG_" << m_language_caps << valueSpacing << "\"" << escapedValue << "\"\n"; } void StringFileDumper::Finalize() @@ -59,5 +55,5 @@ void StringFileDumper::Finalize() if (!m_wrote_header) WriteHeader(); - m_file->Printf("\nENDMARKER"); -} \ No newline at end of file + m_stream << "\nENDMARKER"; +} diff --git a/src/ObjWriting/Dumping/Localize/StringFileDumper.h b/src/ObjWriting/Dumping/Localize/StringFileDumper.h index 0e7315de..23d0cf5d 100644 --- a/src/ObjWriting/Dumping/Localize/StringFileDumper.h +++ b/src/ObjWriting/Dumping/Localize/StringFileDumper.h @@ -1,12 +1,13 @@ #pragma once +#include + #include "Zone/Zone.h" -#include "Utils/FileAPI.h" class StringFileDumper { Zone* m_zone; - FileAPI::File* m_file; + std::ostream& m_stream; std::string m_config_file; std::string m_notes; @@ -17,7 +18,7 @@ class StringFileDumper void WriteHeader(); public: - StringFileDumper(Zone* zone, FileAPI::File* file); + StringFileDumper(Zone* zone, std::ostream& stream); void SetConfigFile(std::string configFile); void SetNotes(std::string notes); diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp index 0569a01f..3732d444 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp @@ -15,8 +15,8 @@ std::string AssetDumperAddonMapEnts::GetFileNameForAsset(Zone* zone, XAssetInfo< return asset->m_name; } -void AssetDumperAddonMapEnts::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperAddonMapEnts::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* addonMapEnts = asset->Asset(); - out->Write(addonMapEnts->entityString, 1, std::max(addonMapEnts->numEntityChars - 1, 0)); + stream.write(addonMapEnts->entityString, std::max(addonMapEnts->numEntityChars - 1, 0)); } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h index cdaeca5d..a4d80823 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h @@ -10,6 +10,6 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp index 834342d0..83005ab6 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp @@ -42,8 +42,8 @@ std::string AssetDumperGfxImage::GetFileNameForAsset(Zone* zone, XAssetInfom_name + m_writer->GetFileExtension(); } -void AssetDumperGfxImage::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperGfxImage::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* image = asset->Asset(); - m_writer->DumpImage(out, image->texture.texture); + m_writer->DumpImage(stream, image->texture.texture); } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h index cba50f79..04fb383f 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h @@ -13,7 +13,7 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; public: AssetDumperGfxImage(); diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp index 9515db79..9a5f18c9 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp @@ -14,9 +14,9 @@ std::string AssetDumperLoadedSound::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperLoadedSound::DumpWavPcm(Zone* zone, const LoadedSound* asset, FileAPI::File* out) +void AssetDumperLoadedSound::DumpWavPcm(Zone* zone, const LoadedSound* asset, std::ostream& stream) { - const uint32_t riffMasterChunkSize = sizeof WAV_CHUNK_ID_RIFF + const auto riffMasterChunkSize = sizeof WAV_CHUNK_ID_RIFF + sizeof uint32_t + sizeof WAV_WAVE_ID + sizeof WavChunkHeader @@ -24,16 +24,16 @@ void AssetDumperLoadedSound::DumpWavPcm(Zone* zone, const LoadedSound* asset, Fi + sizeof WavChunkHeader + sizeof asset->sound.info.data_len; - out->Write(&WAV_CHUNK_ID_RIFF, sizeof WAV_CHUNK_ID_RIFF, 1); - out->Write(&riffMasterChunkSize, sizeof riffMasterChunkSize, 1); - out->Write(&WAV_WAVE_ID, sizeof WAV_WAVE_ID, 1); + stream.write(reinterpret_cast(&WAV_CHUNK_ID_RIFF), sizeof WAV_CHUNK_ID_RIFF); + stream.write(reinterpret_cast(&riffMasterChunkSize), sizeof riffMasterChunkSize); + stream.write(reinterpret_cast(&WAV_WAVE_ID), sizeof WAV_WAVE_ID); const WavChunkHeader formatChunkHeader { WAV_CHUNK_ID_FMT, sizeof WavFormatChunkPcm }; - out->Write(&formatChunkHeader, sizeof formatChunkHeader, 1); + stream.write(reinterpret_cast(&formatChunkHeader), sizeof formatChunkHeader); WavFormatChunkPcm formatChunk { @@ -44,24 +44,24 @@ void AssetDumperLoadedSound::DumpWavPcm(Zone* zone, const LoadedSound* asset, Fi static_cast(asset->sound.info.block_size), static_cast(asset->sound.info.bits) }; - out->Write(&formatChunk, sizeof formatChunk, 1); + stream.write(reinterpret_cast(&formatChunk), sizeof formatChunk); const WavChunkHeader dataChunkHeader { WAV_CHUNK_ID_DATA, asset->sound.info.data_len }; - out->Write(&dataChunkHeader, sizeof dataChunkHeader, 1); - out->Write(asset->sound.data, 1, asset->sound.info.data_len); + stream.write(reinterpret_cast(&dataChunkHeader), sizeof dataChunkHeader); + stream.write(asset->sound.data, asset->sound.info.data_len); } -void AssetDumperLoadedSound::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperLoadedSound::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* loadedSound = asset->Asset(); switch (static_cast(loadedSound->sound.info.format)) { case WavFormat::PCM: - DumpWavPcm(zone, loadedSound, out); + DumpWavPcm(zone, loadedSound, stream); break; default: diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h index 356146bf..2958d823 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h @@ -7,10 +7,10 @@ namespace IW4 { class AssetDumperLoadedSound final : public AbstractAssetDumper { - static void DumpWavPcm(Zone* zone, const LoadedSound* asset, FileAPI::File* out); + static void DumpWavPcm(Zone* zone, const LoadedSound* asset, std::ostream& stream); protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp index fe98a9f9..5ac42440 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp @@ -1,25 +1,35 @@ #include "AssetDumperLocalizeEntry.h" +#include +#include + #include "Dumping/Localize/LocalizeCommon.h" #include "Dumping/Localize/StringFileDumper.h" using namespace IW4; +namespace fs = std::filesystem; void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) { if (pool->m_asset_lookup.empty()) return; - const std::string language = LocalizeCommon::GetNameOfLanguage(zone->m_language); - const std::string stringsPath = utils::Path::Combine(basePath, language + "/localizedstrings"); + const auto language = LocalizeCommon::GetNameOfLanguage(zone->m_language); + fs::path stringsPath(basePath); + stringsPath.append(language); + stringsPath.append("/localizedstrings"); - FileAPI::DirectoryCreate(stringsPath); + create_directories(stringsPath); - FileAPI::File stringFile = FileAPI::Open(utils::Path::Combine(stringsPath, zone->m_name + ".str"), FileAPI::Mode::MODE_WRITE); + auto stringFilePath(stringsPath); + stringFilePath.append(zone->m_name); + stringFilePath.append(".str"); - if (stringFile.IsOpen()) + std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary); + + if (stringFile.is_open()) { - StringFileDumper stringFileDumper(zone, &stringFile); + StringFileDumper stringFileDumper(zone, stringFile); stringFileDumper.SetLanguageName(language); @@ -28,14 +38,14 @@ void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* po stringFileDumper.SetNotes(""); - for (auto localizeEntry : *pool) + for (auto* localizeEntry : *pool) { stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); } stringFileDumper.Finalize(); - stringFile.Close(); + stringFile.close(); } else { diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp index 095cb0f4..e1bdd422 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp @@ -14,7 +14,7 @@ std::string AssetDumperRawFile::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperRawFile::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperRawFile::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* rawFile = asset->Asset(); if (rawFile->compressedLen > 0) @@ -52,13 +52,13 @@ void AssetDumperRawFile::DumpAsset(Zone* zone, XAssetInfo* asset, FileA return; } - out->Write(buffer, 1, sizeof buffer - zs.avail_out); + stream.write(reinterpret_cast(buffer), sizeof buffer - zs.avail_out); } inflateEnd(&zs); } else if (rawFile->len > 0) { - out->Write(rawFile->data.buffer, 1, rawFile->len); + stream.write(rawFile->data.buffer, rawFile->len); } } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h index 4296ecc2..fd5dc274 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h @@ -10,6 +10,6 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp index 4e94ca4e..a94f786f 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp @@ -14,14 +14,14 @@ std::string AssetDumperStringTable::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperStringTable::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperStringTable::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* stringTable = asset->Asset(); - CsvWriter csv(out); + CsvWriter csv(stream); - for (int row = 0; row < stringTable->rowCount; row++) + for (auto row = 0; row < stringTable->rowCount; row++) { - for (int column = 0; column < stringTable->columnCount; column++) + for (auto column = 0; column < stringTable->columnCount; column++) { const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; csv.WriteColumn(cell->string); diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h index a69b79e6..6dbb8ba3 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h @@ -10,6 +10,6 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp index 76c84f49..86cb015c 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp @@ -240,7 +240,7 @@ std::string AssetDumperVehicle::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { InfoStringFromVehicleConverter converter(asset->Asset(), vehicle_fields, _countof(vehicle_fields), [asset](const scr_string_t scrStr) -> std::string { @@ -253,5 +253,5 @@ void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, Fi const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("VEHICLEFILE"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); } \ No newline at end of file diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h index 510d11cf..71c410fa 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h @@ -13,6 +13,6 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp index 2ee5f46e..425a23da 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp @@ -1162,7 +1162,7 @@ std::string AssetDumperWeapon::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { auto* fullDef = new WeaponFullDef; memset(fullDef, 0, sizeof WeaponFullDef); @@ -1179,7 +1179,7 @@ void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* ass const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("WEAPONFILE"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); delete fullDef; } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h index 940671ff..d871236b 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h @@ -14,6 +14,6 @@ namespace IW4 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.cpp index 255ce8ea..4f0c1b7e 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.cpp @@ -241,8 +241,8 @@ class AssetDumperFontIconInternal } public: - explicit AssetDumperFontIconInternal(FileAPI::IFile* file) - : m_csv(file) + explicit AssetDumperFontIconInternal(std::ostream& stream) + : m_csv(stream) { } @@ -265,8 +265,8 @@ std::string AssetDumperFontIcon::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperFontIcon::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperFontIcon::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { - AssetDumperFontIconInternal dumper(out); + AssetDumperFontIconInternal dumper(stream); dumper.DumpFontIcon(asset->Asset()); } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h index af6ebc2e..23d1d7e3 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperFontIcon.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp index 3f3e813b..6af52202 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp @@ -42,8 +42,8 @@ std::string AssetDumperGfxImage::GetFileNameForAsset(Zone* zone, XAssetInfom_name + m_writer->GetFileExtension(); } -void AssetDumperGfxImage::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperGfxImage::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* image = asset->Asset(); - m_writer->DumpImage(out, image->texture.texture); + m_writer->DumpImage(stream, image->texture.texture); } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h index 84109c77..bd49cdf1 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h @@ -13,7 +13,7 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; public: AssetDumperGfxImage(); diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp index 7e9e7b51..d7fc8e12 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp @@ -1,25 +1,35 @@ #include "AssetDumperLocalizeEntry.h" +#include +#include + #include "Dumping/Localize/LocalizeCommon.h" #include "Dumping/Localize/StringFileDumper.h" using namespace T6; +namespace fs = std::filesystem; void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* pool, const std::string& basePath) { if (pool->m_asset_lookup.empty()) return; - const std::string language = LocalizeCommon::GetNameOfLanguage(zone->m_language); - const std::string stringsPath = utils::Path::Combine(basePath, language + "/localizedstrings"); + const auto language = LocalizeCommon::GetNameOfLanguage(zone->m_language); + fs::path stringsPath(basePath); + stringsPath.append(language); + stringsPath.append("/localizedstrings"); - FileAPI::DirectoryCreate(stringsPath); + create_directories(stringsPath); - FileAPI::File stringFile = FileAPI::Open(utils::Path::Combine(stringsPath, zone->m_name + ".str"), FileAPI::Mode::MODE_WRITE); + auto stringFilePath(stringsPath); + stringFilePath.append(zone->m_name); + stringFilePath.append(".str"); - if(stringFile.IsOpen()) + std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary); + + if(stringFile.is_open()) { - StringFileDumper stringFileDumper(zone, &stringFile); + StringFileDumper stringFileDumper(zone, stringFile); stringFileDumper.SetLanguageName(language); @@ -28,14 +38,14 @@ void AssetDumperLocalizeEntry::DumpPool(Zone* zone, AssetPool* po stringFileDumper.SetNotes(""); - for(auto localizeEntry : *pool) + for(auto* localizeEntry : *pool) { stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); } stringFileDumper.Finalize(); - stringFile.Close(); + stringFile.close(); } else { diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp index e3c4afe1..81fb7499 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp @@ -138,7 +138,7 @@ std::string AssetDumperPhysConstraints::GetFileNameForAsset(Zone* zone, XAssetIn return "physconstraints/" + asset->m_name; } -void AssetDumperPhysConstraints::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperPhysConstraints::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { assert(asset->Asset()->count <= 4); @@ -153,5 +153,5 @@ void AssetDumperPhysConstraints::DumpAsset(Zone* zone, XAssetInfoWrite(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h index 54bb1046..555b5537 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h @@ -12,6 +12,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp index 1e2cae48..2d747dea 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp @@ -86,7 +86,7 @@ std::string AssetDumperPhysPreset::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperPhysPreset::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperPhysPreset::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { auto* physPresetInfo = new PhysPresetInfo; CopyToPhysPresetInfo(asset->Asset(), physPresetInfo); @@ -102,7 +102,7 @@ void AssetDumperPhysPreset::DumpAsset(Zone* zone, XAssetInfo* asset, const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("PHYSIC"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); delete physPresetInfo; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h index 9ee991d5..3c62325b 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h @@ -14,6 +14,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp index f9e1311a..4140f80a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp @@ -12,8 +12,8 @@ std::string AssetDumperQdb::GetFileNameForAsset(Zone* zone, XAssetInfo* ass return asset->m_name; } -void AssetDumperQdb::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperQdb::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* qdb = asset->Asset(); - out->Write(qdb->buffer, 1, qdb->len); + stream.write(qdb->buffer, qdb->len); } \ No newline at end of file diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h index 30bf1848..42b0027a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp index 403cd0b2..4c6f1e1b 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp @@ -12,8 +12,8 @@ std::string AssetDumperRawFile::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperRawFile::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperRawFile::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* rawFile = asset->Asset(); - out->Write(rawFile->buffer, 1, rawFile->len); + stream.write(rawFile->buffer, rawFile->len); } \ No newline at end of file diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h index 9ae92f78..36bf8bb9 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp index 18bcdee2..5b212de6 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp @@ -12,8 +12,8 @@ std::string AssetDumperScriptParseTree::GetFileNameForAsset(Zone* zone, XAssetIn return asset->m_name; } -void AssetDumperScriptParseTree::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperScriptParseTree::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* scriptParseTree = asset->Asset(); - out->Write(scriptParseTree->buffer, 1, scriptParseTree->len); + stream.write(scriptParseTree->buffer, scriptParseTree->len); } \ No newline at end of file diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h index d5bb2280..0d6bb007 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp index c0c19357..ba8a1ef8 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp @@ -12,8 +12,8 @@ std::string AssetDumperSlug::GetFileNameForAsset(Zone* zone, XAssetInfo* a return asset->m_name; } -void AssetDumperSlug::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperSlug::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* slug = asset->Asset(); - out->Write(slug->buffer, 1, slug->len); + stream.write(slug->buffer, slug->len); } \ No newline at end of file diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h index 098bbce2..77f32820 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp index 4a6c1caa..305087e6 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp @@ -14,14 +14,14 @@ std::string AssetDumperStringTable::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperStringTable::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperStringTable::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { const auto* stringTable = asset->Asset(); - CsvWriter csv(out); + CsvWriter csv(stream); - for(int row = 0; row < stringTable->rowCount; row++) + for(auto row = 0; row < stringTable->rowCount; row++) { - for(int column = 0; column < stringTable->columnCount; column++) + for(auto column = 0; column < stringTable->columnCount; column++) { const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; csv.WriteColumn(cell->string); diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h index 5272b62c..54f33393 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h @@ -10,6 +10,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp index 2aacc25a..42bfde7b 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp @@ -85,7 +85,7 @@ std::string AssetDumperTracer::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperTracer::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperTracer::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { InfoStringFromTracerConverter converter(asset->Asset(), tracer_fields, _countof(tracer_fields), [asset](const scr_string_t scrStr) -> std::string { @@ -98,7 +98,7 @@ void AssetDumperTracer::DumpAsset(Zone* zone, XAssetInfo* asset, File const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("TRACER"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); } //void AssetDumperTracer::CheckFields() diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h index 61e16c9a..ce664756 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h @@ -12,6 +12,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp index 5867a0ba..3c1ea563 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp @@ -680,7 +680,7 @@ std::string AssetDumperVehicle::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { InfoStringFromVehicleConverter converter(asset->Asset(), vehicle_fields, _countof(vehicle_fields), [asset](const scr_string_t scrStr) -> std::string { @@ -693,5 +693,5 @@ void AssetDumperVehicle::DumpAsset(Zone* zone, XAssetInfo* asset, Fi const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("VEHICLEFILE"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h index 164f6707..d5b5d3f3 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h @@ -12,6 +12,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp index 6828f8bb..af93bd22 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp @@ -1620,7 +1620,7 @@ std::string AssetDumperWeapon::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { auto* fullDef = new WeaponFullDef; memset(fullDef, 0, sizeof WeaponFullDef); @@ -1637,7 +1637,7 @@ void AssetDumperWeapon::DumpAsset(Zone* zone, XAssetInfo* asse const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("WEAPONFILE"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); delete fullDef; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h index 074d704d..ddb93ae5 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h @@ -14,6 +14,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp index de03e58b..276ea319 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp @@ -183,7 +183,7 @@ std::string AssetDumperZBarrier::GetFileNameForAsset(Zone* zone, XAssetInfom_name; } -void AssetDumperZBarrier::DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) +void AssetDumperZBarrier::DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) { InfoStringFromZBarrierConverter converter(asset->Asset(), zbarrier_fields, _countof(zbarrier_fields), [asset](const scr_string_t scrStr) -> std::string { @@ -196,7 +196,7 @@ void AssetDumperZBarrier::DumpAsset(Zone* zone, XAssetInfo* asset, const auto infoString = converter.Convert(); const auto stringValue = infoString.ToString("ZBARRIER"); - out->Write(stringValue.c_str(), 1, stringValue.length()); + stream.write(stringValue.c_str(), stringValue.size()); } //void AssetDumperZBarrier::CheckFields() diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h index 59888e44..8ea1f15c 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h @@ -12,6 +12,6 @@ namespace T6 protected: bool ShouldDump(XAssetInfo* asset) override; std::string GetFileNameForAsset(Zone* zone, XAssetInfo* asset) override; - void DumpAsset(Zone* zone, XAssetInfo* asset, FileAPI::File* out) override; + void DumpAsset(Zone* zone, XAssetInfo* asset, std::ostream& stream) override; }; } diff --git a/src/ObjWriting/Image/DdsWriter.cpp b/src/ObjWriting/Image/DdsWriter.cpp index 86568375..5934ce7e 100644 --- a/src/ObjWriting/Image/DdsWriter.cpp +++ b/src/ObjWriting/Image/DdsWriter.cpp @@ -15,7 +15,7 @@ const std::map DDS_CONVERSION_TABLE class DdsWriterInternal { - FileAPI::IFile* m_file; + std::ostream& m_stream; Texture* m_texture; std::unique_ptr m_converted_texture; bool m_use_dx10_extension; @@ -190,8 +190,8 @@ public: return ".dds"; } - DdsWriterInternal(FileAPI::IFile* file, Texture* texture) - : m_file(file), + DdsWriterInternal(std::ostream& stream, Texture* texture) + : m_stream(stream), m_texture(texture), m_use_dx10_extension(false) { @@ -204,24 +204,24 @@ public: DDS_HEADER header{}; PopulateDdsHeader(header); - constexpr uint32_t magic = MakeFourCc('D', 'D', 'S', ' '); + constexpr auto magic = MakeFourCc('D', 'D', 'S', ' '); - m_file->Write(&magic, sizeof magic, 1); - m_file->Write(&header, sizeof header, 1); + m_stream.write(reinterpret_cast(&magic), sizeof magic); + m_stream.write(reinterpret_cast(&header), sizeof header); if (m_use_dx10_extension) { DDS_HEADER_DXT10 dxt10{}; PopulateDxt10Header(dxt10); - m_file->Write(&dxt10, sizeof dxt10, 1); + m_stream.write(reinterpret_cast(&dxt10), sizeof dxt10); } - const int mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1; + const auto mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1; for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++) { const auto* buffer = m_texture->GetBufferForMipLevel(mipLevel); const auto mipLevelSize = m_texture->GetSizeOfMipLevel(mipLevel) * m_texture->GetFaceCount(); - m_file->Write(buffer, 1, mipLevelSize); + m_stream.write(reinterpret_cast(buffer), mipLevelSize); } } }; @@ -239,8 +239,8 @@ std::string DdsWriter::GetFileExtension() return DdsWriterInternal::GetFileExtension(); } -void DdsWriter::DumpImage(FileAPI::IFile* file, Texture* texture) +void DdsWriter::DumpImage(std::ostream& stream, Texture* texture) { - DdsWriterInternal internal(file, texture); + DdsWriterInternal internal(stream, texture); internal.DumpImage(); } diff --git a/src/ObjWriting/Image/DdsWriter.h b/src/ObjWriting/Image/DdsWriter.h index 6b7003c3..a2a01001 100644 --- a/src/ObjWriting/Image/DdsWriter.h +++ b/src/ObjWriting/Image/DdsWriter.h @@ -8,5 +8,5 @@ public: bool SupportsImageFormat(const ImageFormat * imageFormat) override; std::string GetFileExtension() override; - void DumpImage(FileAPI::IFile* file, Texture* texture) override; + void DumpImage(std::ostream& stream, Texture* texture) override; }; diff --git a/src/ObjWriting/Image/IImageWriter.h b/src/ObjWriting/Image/IImageWriter.h index 60f1b773..1886b9e4 100644 --- a/src/ObjWriting/Image/IImageWriter.h +++ b/src/ObjWriting/Image/IImageWriter.h @@ -1,9 +1,10 @@ #pragma once -#include "Image/Texture.h" -#include "Utils/FileAPI.h" +#include #include +#include "Image/Texture.h" + class IImageWriter { public: @@ -11,5 +12,5 @@ public: virtual bool SupportsImageFormat(const ImageFormat* imageFormat) = 0; virtual std::string GetFileExtension() = 0; - virtual void DumpImage(FileAPI::IFile* file, Texture* texture) = 0; + virtual void DumpImage(std::ostream& stream, Texture* texture) = 0; }; \ No newline at end of file diff --git a/src/ObjWriting/Image/IwiWriter27.cpp b/src/ObjWriting/Image/IwiWriter27.cpp index 3095bf40..c318f846 100644 --- a/src/ObjWriting/Image/IwiWriter27.cpp +++ b/src/ObjWriting/Image/IwiWriter27.cpp @@ -1,5 +1,6 @@ #include "IwiWriter27.h" #include +#include using namespace iwi27; @@ -52,7 +53,7 @@ std::string IwiWriter::GetFileExtension() return ".iwi"; } -void IwiWriter::WriteVersion(FileAPI::IFile* file) +void IwiWriter::WriteVersion(std::ostream& stream) { IwiVersion version{}; version.tag[0] = 'I'; @@ -60,7 +61,7 @@ void IwiWriter::WriteVersion(FileAPI::IFile* file) version.tag[2] = 'i'; version.version = 27; - file->Write(&version, sizeof IwiVersion, 1); + stream.write(reinterpret_cast(&version), sizeof IwiVersion); } void IwiWriter::FillHeader2D(IwiHeader* header, Texture2D* texture) @@ -86,12 +87,11 @@ void IwiWriter::FillHeader3D(IwiHeader* header, Texture3D* texture) header->flags |= IMG_FLAG_VOLMAP; } -void IwiWriter::DumpImage(FileAPI::IFile* file, Texture* texture) +void IwiWriter::DumpImage(std::ostream& stream, Texture* texture) { - assert(file != nullptr); assert(texture != nullptr); - WriteVersion(file); + WriteVersion(stream); IwiHeader header{}; header.flags = 0; @@ -102,39 +102,44 @@ void IwiWriter::DumpImage(FileAPI::IFile* file, Texture* texture) if (!texture->HasMipMaps()) header.flags |= IMG_FLAG_NOMIPMAPS; - for (signed char& i : header.maxGlossForMip) + for (auto& i : header.maxGlossForMip) i = 0; - size_t currentFileSize = sizeof IwiVersion + sizeof IwiHeader; + auto currentFileSize = sizeof IwiVersion + sizeof IwiHeader; - const int textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; - for (int currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; + for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) { - const size_t mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); currentFileSize += mipLevelSize; - if(currentMipLevel < static_cast(_countof(iwi27::IwiHeader::fileSizeForPicmip))) + if (currentMipLevel < static_cast(_countof(iwi27::IwiHeader::fileSizeForPicmip))) header.fileSizeForPicmip[currentMipLevel] = currentFileSize; } - if(auto* texture2D = dynamic_cast(texture)) + if (auto* texture2D = dynamic_cast(texture)) { FillHeader2D(&header, texture2D); } - else if(auto* textureCube = dynamic_cast(texture)) + else if (auto* textureCube = dynamic_cast(texture)) { FillHeaderCube(&header, textureCube); } - else if(auto* texture3D = dynamic_cast(texture)) + else if (auto* texture3D = dynamic_cast(texture)) { FillHeader3D(&header, texture3D); } - - file->Write(&header, sizeof IwiHeader, 1); - - for (int currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + else { - const size_t mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); - file->Write(texture->GetBufferForMipLevel(currentMipLevel), 1, mipLevelSize); + assert(false); + return; + } + + stream.write(reinterpret_cast(&header), sizeof IwiHeader); + + for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + { + const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + stream.write(reinterpret_cast(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize); } } diff --git a/src/ObjWriting/Image/IwiWriter27.h b/src/ObjWriting/Image/IwiWriter27.h index de139870..88bbc834 100644 --- a/src/ObjWriting/Image/IwiWriter27.h +++ b/src/ObjWriting/Image/IwiWriter27.h @@ -9,7 +9,7 @@ namespace iwi27 { static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); - static void WriteVersion(FileAPI::IFile* file); + static void WriteVersion(std::ostream& stream); static void FillHeader2D(IwiHeader* header, Texture2D* texture); static void FillHeaderCube(IwiHeader* header, TextureCube* texture); static void FillHeader3D(IwiHeader* header, Texture3D* texture); @@ -25,6 +25,6 @@ namespace iwi27 bool SupportsImageFormat(const ImageFormat* imageFormat) override; std::string GetFileExtension() override; - void DumpImage(FileAPI::IFile* file, Texture* texture) override; + void DumpImage(std::ostream& stream, Texture* texture) override; }; } diff --git a/src/ObjWriting/Image/IwiWriter8.cpp b/src/ObjWriting/Image/IwiWriter8.cpp index 312e6143..8378de20 100644 --- a/src/ObjWriting/Image/IwiWriter8.cpp +++ b/src/ObjWriting/Image/IwiWriter8.cpp @@ -40,7 +40,7 @@ IwiFormat IwiWriter::GetIwiFormatForImageFormat(const ImageFormat* imageFormat) } } -void IwiWriter::WriteVersion(FileAPI::IFile* file) +void IwiWriter::WriteVersion(std::ostream& stream) { IwiVersion version{}; version.tag[0] = 'I'; @@ -48,7 +48,7 @@ void IwiWriter::WriteVersion(FileAPI::IFile* file) version.tag[2] = 'i'; version.version = 8; - file->Write(&version, sizeof IwiVersion, 1); + stream.write(reinterpret_cast(&version), sizeof IwiVersion); } void IwiWriter::FillHeader2D(IwiHeader* header, Texture2D* texture) @@ -84,12 +84,11 @@ std::string IwiWriter::GetFileExtension() return ".iwi"; } -void IwiWriter::DumpImage(FileAPI::IFile* file, Texture* texture) +void IwiWriter::DumpImage(std::ostream& stream, Texture* texture) { - assert(file != nullptr); assert(texture != nullptr); - WriteVersion(file); + WriteVersion(stream); IwiHeader header{}; header.flags = 0; @@ -99,12 +98,12 @@ void IwiWriter::DumpImage(FileAPI::IFile* file, Texture* texture) if (!texture->HasMipMaps()) header.flags |= IMG_FLAG_NOMIPMAPS; - size_t currentFileSize = sizeof IwiVersion + sizeof IwiHeader; + auto currentFileSize = sizeof IwiVersion + sizeof IwiHeader; - const int textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; - for (int currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; + for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) { - const size_t mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); currentFileSize += mipLevelSize; if (currentMipLevel < static_cast(_countof(iwi27::IwiHeader::fileSizeForPicmip))) @@ -123,12 +122,17 @@ void IwiWriter::DumpImage(FileAPI::IFile* file, Texture* texture) { FillHeader3D(&header, texture3D); } - - file->Write(&header, sizeof iwi27::IwiHeader, 1); - - for (int currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + else { - const size_t mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); - file->Write(texture->GetBufferForMipLevel(currentMipLevel), 1, mipLevelSize); + assert(false); + return; + } + + stream.write(reinterpret_cast(&header), sizeof IwiHeader); + + for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) + { + const auto mipLevelSize = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount(); + stream.write(reinterpret_cast(texture->GetBufferForMipLevel(currentMipLevel)), mipLevelSize); } } diff --git a/src/ObjWriting/Image/IwiWriter8.h b/src/ObjWriting/Image/IwiWriter8.h index ee60524e..1d354293 100644 --- a/src/ObjWriting/Image/IwiWriter8.h +++ b/src/ObjWriting/Image/IwiWriter8.h @@ -9,7 +9,7 @@ namespace iwi8 { static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); - static void WriteVersion(FileAPI::IFile* file); + static void WriteVersion(std::ostream& stream); static void FillHeader2D(IwiHeader* header, Texture2D* texture); static void FillHeaderCube(IwiHeader* header, TextureCube* texture); static void FillHeader3D(IwiHeader* header, Texture3D* texture); @@ -25,6 +25,6 @@ namespace iwi8 bool SupportsImageFormat(const ImageFormat* imageFormat) override; std::string GetFileExtension() override; - void DumpImage(FileAPI::IFile* file, Texture* texture) override; + void DumpImage(std::ostream& stream, Texture* texture) override; }; } diff --git a/src/Unlinker/ContentLister/ZoneDefWriter.cpp b/src/Unlinker/ContentLister/ZoneDefWriter.cpp index 7888a47f..4cf15d6a 100644 --- a/src/Unlinker/ContentLister/ZoneDefWriter.cpp +++ b/src/Unlinker/ContentLister/ZoneDefWriter.cpp @@ -2,28 +2,28 @@ const std::string AbstractZoneDefWriter::META_DATA_KEY_GAME = "game"; -AbstractZoneDefWriter::AbstractZoneDefWriter(Zone* zone, FileAPI::IFile* file) +AbstractZoneDefWriter::AbstractZoneDefWriter(Zone* zone, std::ostream& stream) + : m_zone(zone), + m_stream(stream) { - m_zone = zone; - m_file = file; } void AbstractZoneDefWriter::EmptyLine() const { - m_file->Printf("\n"); + m_stream << "\n"; } void AbstractZoneDefWriter::WriteComment(const std::string& comment) const { - m_file->Printf("// %s\n", comment.c_str()); + m_stream << "// " << comment << "\n"; } void AbstractZoneDefWriter::WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const { - m_file->Printf(">%s,%s\n", metaDataKey.c_str(), metaDataValue.c_str()); + m_stream << ">" << metaDataKey << "," << metaDataValue << "\n"; } void AbstractZoneDefWriter::WriteEntry(const std::string& entryKey, const std::string& entryValue) const { - m_file->Printf("%s,%s\n", entryKey.c_str(), entryValue.c_str()); -} \ No newline at end of file + m_stream << entryKey << "," << entryValue << "\n"; +} diff --git a/src/Unlinker/ContentLister/ZoneDefWriter.h b/src/Unlinker/ContentLister/ZoneDefWriter.h index c378d115..88bbce50 100644 --- a/src/Unlinker/ContentLister/ZoneDefWriter.h +++ b/src/Unlinker/ContentLister/ZoneDefWriter.h @@ -1,12 +1,14 @@ #pragma once -#include "Utils/FileAPI.h" + +#include + #include "Zone/Zone.h" class AbstractZoneDefWriter { protected: Zone* m_zone; - FileAPI::IFile* m_file; + std::ostream& m_stream; static const std::string META_DATA_KEY_GAME; @@ -15,7 +17,7 @@ protected: void WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const; void WriteEntry(const std::string& entryKey, const std::string& entryValue) const; - AbstractZoneDefWriter(Zone* zone, FileAPI::IFile* file); + AbstractZoneDefWriter(Zone* zone, std::ostream& stream); public: virtual void WriteZoneDef() = 0; @@ -25,5 +27,5 @@ class IZoneDefWriter { public: virtual bool CanHandleZone(Zone* zone) const = 0; - virtual void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const = 0; + virtual void WriteZoneDef(Zone* zone, std::ostream& stream) const = 0; }; \ No newline at end of file diff --git a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp index 3e8281dc..b7c65dfc 100644 --- a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp +++ b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.cpp @@ -42,8 +42,8 @@ namespace IW4 } public: - ZoneDefWriterInternal(Zone* zone, FileAPI::IFile* file) - : AbstractZoneDefWriter(zone, file) + ZoneDefWriterInternal(Zone* zone, std::ostream& stream) + : AbstractZoneDefWriter(zone, stream) { } @@ -63,8 +63,8 @@ bool ZoneDefWriter::CanHandleZone(Zone* zone) const return zone->m_game == &g_GameIW4; } -void ZoneDefWriter::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const +void ZoneDefWriter::WriteZoneDef(Zone* zone, std::ostream& stream) const { - ZoneDefWriterInternal writer(zone, file); + ZoneDefWriterInternal writer(zone, stream); writer.WriteZoneDef(); } diff --git a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h index 719f9be2..750d2cb1 100644 --- a/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h +++ b/src/Unlinker/Game/IW4/ZoneDefWriterIW4.h @@ -8,6 +8,6 @@ namespace IW4 { public: bool CanHandleZone(Zone* zone) const override; - void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override; + void WriteZoneDef(Zone* zone, std::ostream& stream) const override; }; } \ No newline at end of file diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp index 6e71bda2..067879ac 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp @@ -80,8 +80,8 @@ namespace T6 } public: - ZoneDefWriterInternal(Zone* zone, FileAPI::IFile* file) - : AbstractZoneDefWriter(zone, file) + ZoneDefWriterInternal(Zone* zone, std::ostream& stream) + : AbstractZoneDefWriter(zone, stream) { } @@ -117,8 +117,8 @@ bool ZoneDefWriter::CanHandleZone(Zone* zone) const return zone->m_game == &g_GameT6; } -void ZoneDefWriter::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const +void ZoneDefWriter::WriteZoneDef(Zone* zone, std::ostream& stream) const { - ZoneDefWriterInternal writer(zone, file); + ZoneDefWriterInternal writer(zone, stream); writer.WriteZoneDef(); } diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.h b/src/Unlinker/Game/T6/ZoneDefWriterT6.h index 26202574..d12e65dc 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.h +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.h @@ -8,6 +8,6 @@ namespace T6 { public: bool CanHandleZone(Zone* zone) const override; - void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override; + void WriteZoneDef(Zone* zone, std::ostream& stream) const override; }; } \ No newline at end of file diff --git a/src/Unlinker/Unlinker.cpp b/src/Unlinker/Unlinker.cpp index 16af34cb..01fd082e 100644 --- a/src/Unlinker/Unlinker.cpp +++ b/src/Unlinker/Unlinker.cpp @@ -3,13 +3,13 @@ #include #include #include +#include +#include "Utils/ClassUtils.h" #include "Utils/Arguments/ArgumentParser.h" #include "ZoneLoading.h" #include "ObjWriting.h" #include "ContentLister/ContentPrinter.h" -#include "Utils/PathUtils.h" -#include "Utils/FileAPI.h" #include "ObjLoading.h" #include "SearchPath/SearchPaths.h" #include "SearchPath/SearchPathFilesystem.h" @@ -19,6 +19,9 @@ #include "Game/IW4/ZoneDefWriterIW4.h" #include "Game/T6/ZoneDefWriterT6.h" +#include "Utils/ObjFileStream.h" + +namespace fs = std::filesystem; const IZoneDefWriter* const ZONE_DEF_WRITERS[] { @@ -33,7 +36,7 @@ class Unlinker::Impl SearchPathFilesystem* m_last_zone_search_path; std::set m_absolute_search_paths; - bool ShouldLoadObj() const + _NODISCARD bool ShouldLoadObj() const { return m_args.m_task != UnlinkerArgs::ProcessingTask::LIST; } @@ -80,7 +83,7 @@ class Unlinker::Impl SearchPaths GetSearchPathsForZone(const std::string& zonePath) { SearchPaths searchPathsForZone; - const std::string absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string(); + const auto absoluteZoneDirectory = fs::absolute(std::filesystem::path(zonePath).remove_filename()).string(); if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory) { @@ -115,19 +118,19 @@ class Unlinker::Impl { for (const auto& path : m_args.m_user_search_paths) { - std::string absolutePath = std::filesystem::absolute(path).string(); + auto absolutePath = fs::absolute(path); - if (!FileAPI::DirectoryExists(absolutePath)) + if (!fs::is_directory(absolutePath)) { printf("Could not find directory of search path: \"%s\"\n", path.c_str()); return false; } - auto* searchPath = new SearchPathFilesystem(absolutePath); - LoadSearchPath(searchPath); - m_search_paths.CommitSearchPath(searchPath); + auto searchPath = std::make_unique(absolutePath.string()); + LoadSearchPath(searchPath.get()); + m_search_paths.CommitSearchPath(std::move(searchPath)); - m_absolute_search_paths.insert(absolutePath); + m_absolute_search_paths.insert(absolutePath.string()); } if (m_args.m_verbose) @@ -161,23 +164,26 @@ class Unlinker::Impl } else if (m_args.m_task == UnlinkerArgs::ProcessingTask::DUMP) { - const std::string outputFolderPath = m_args.GetOutputFolderPathForZone(zone); - FileAPI::DirectoryCreate(outputFolderPath); + const auto outputFolderPath = m_args.GetOutputFolderPathForZone(zone); + fs::create_directories(outputFolderPath); - const std::string zoneDefinitionFileFolder = utils::Path::Combine(outputFolderPath, "zone_source"); - FileAPI::DirectoryCreate(zoneDefinitionFileFolder); + fs::path zoneDefinitionFileFolder(outputFolderPath); + zoneDefinitionFileFolder.append("zone_source"); + fs::create_directories(zoneDefinitionFileFolder); - FileAPI::File zoneDefinitionFile = FileAPI::Open( - utils::Path::Combine(zoneDefinitionFileFolder, zone->m_name + ".zone"), - FileAPI::Mode::MODE_WRITE); + auto zoneDefinitionFilePath(zoneDefinitionFileFolder); + zoneDefinitionFilePath.append(zone->m_name); + zoneDefinitionFilePath.replace_extension(".zone"); - if (zoneDefinitionFile.IsOpen()) + std::ofstream zoneDefinitionFile(zoneDefinitionFilePath, std::fstream::out | std::fstream::binary); + + if (zoneDefinitionFile.is_open()) { - for (auto zoneDefWriter : ZONE_DEF_WRITERS) + for (const auto* zoneDefWriter : ZONE_DEF_WRITERS) { if (zoneDefWriter->CanHandleZone(zone)) { - zoneDefWriter->WriteZoneDef(zone, &zoneDefinitionFile); + zoneDefWriter->WriteZoneDef(zone, zoneDefinitionFile); break; } } @@ -189,7 +195,7 @@ class Unlinker::Impl return false; } - zoneDefinitionFile.Close(); + zoneDefinitionFile.close(); } return true; @@ -214,18 +220,18 @@ public: for (const auto& zonePath : m_args.m_zones_to_load) { - if (!FileAPI::FileExists(zonePath)) + if (!fs::is_regular_file(zonePath)) { printf("Could not find file \"%s\".\n", zonePath.c_str()); continue; } - std::string absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string(); + auto absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string(); - SearchPaths searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory); + auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory); searchPathsForZone.IncludeSearchPath(&m_search_paths); - Zone* zone = ZoneLoading::LoadZone(zonePath); + auto* zone = ZoneLoading::LoadZone(zonePath); if (zone == nullptr) { printf("Failed to load zone \"%s\".\n", zonePath.c_str()); diff --git a/src/Utils/Utils/ClassUtils.h b/src/Utils/Utils/ClassUtils.h index 899eb12b..f8792858 100644 --- a/src/Utils/Utils/ClassUtils.h +++ b/src/Utils/Utils/ClassUtils.h @@ -10,13 +10,15 @@ #define _CPP_VERSION 0 #endif -#ifndef _NODISCARD +#ifdef _NODISCARD +#undef _NODISCARD +#endif + #if _CPP_VERSION >= 201703L #define _NODISCARD [[nodiscard]] #else #define _NODISCARD #endif -#endif template struct Movable diff --git a/src/Utils/Utils/FileAPI.cpp b/src/Utils/Utils/FileAPI.cpp deleted file mode 100644 index 7704fe3b..00000000 --- a/src/Utils/Utils/FileAPI.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "FileAPI.h" - -#include -#include -#include - -bool FileAPI::FileExists(const std::string& fileName) -{ - return std::filesystem::exists(fileName); -} - -uint64_t FileAPI::FileSize(const std::string& fileName) -{ - return std::filesystem::file_size(fileName); -} - -bool FileAPI::DirectoryCreate(const std::string& directoryPath) -{ - return std::filesystem::create_directories(directoryPath); -} - -bool FileAPI::DirectoryExists(const std::string& directoryName) -{ - return std::filesystem::is_directory(directoryName); -} - -FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode) -{ - const char* modeStr; - switch (mode) - { - default: - case Mode::MODE_READ: - modeStr = "rb"; - break; - - case Mode::MODE_WRITE: - modeStr = "wb"; - break; - } - - FILE* handle; - if (fopen_s(&handle, filename.c_str(), modeStr) != 0) - { - return File(nullptr); - } - - return File(handle); -} - -FileAPI::File::File() -{ - this->m_handle = nullptr; -} - -FileAPI::File::File(void* handle) -{ - this->m_handle = handle; -} - -FileAPI::File::File(File&& f) noexcept -{ - m_handle = f.m_handle; - f.m_handle = nullptr; -} - -FileAPI::File::~File() -{ - this->Close(); -} - -FileAPI::File& FileAPI::File::operator=(File&& f) noexcept -{ - m_handle = f.m_handle; - f.m_handle = nullptr; - - return *this; -} - -bool FileAPI::File::IsOpen() -{ - return this->m_handle != nullptr; -} - -size_t FileAPI::File::Read(void* buffer, const size_t elementSize, const size_t elementCount) -{ - if (!this->IsOpen()) - return 0; - - return fread(buffer, elementSize, elementCount, static_cast(m_handle)); -} - -size_t FileAPI::File::Write(const void* data, const size_t elementSize, const size_t elementCount) -{ - if (!this->IsOpen()) - return 0; - - return fwrite(data, elementSize, elementCount, static_cast(m_handle)); -} - -void FileAPI::File::Skip(const int64_t amount) -{ - if (!this->IsOpen()) - return; - - _fseeki64(static_cast(m_handle), amount, SEEK_CUR); -} - -void FileAPI::File::GotoEnd() -{ - _fseeki64(static_cast(m_handle), 0, SEEK_END); -} - -size_t FileAPI::File::Printf(const char* fmt, ...) -{ - va_list ap; - - if (!this->IsOpen()) - return 0; - - va_start(ap, fmt); - const int result = vfprintf(static_cast(m_handle), fmt, ap); - va_end(ap); - - return result; -} - -int64_t FileAPI::File::Pos() -{ - return _ftelli64(static_cast(m_handle)); -} - -void FileAPI::File::Goto(const int64_t pos) -{ - _fseeki64(static_cast(m_handle), pos, SEEK_SET); -} - -void FileAPI::File::Close() -{ - if (this->m_handle != nullptr) - { - fclose(static_cast(m_handle)); - this->m_handle = nullptr; - } -} diff --git a/src/Utils/Utils/FileAPI.h b/src/Utils/Utils/FileAPI.h deleted file mode 100644 index 9ce9a44e..00000000 --- a/src/Utils/Utils/FileAPI.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include -#include - -class FileAPI -{ -public: - enum class Mode - { - MODE_READ = 0, - MODE_WRITE = 1 - }; - - class IFile - { - public: - virtual ~IFile() = default; - - virtual bool IsOpen() = 0; - virtual size_t Read(void* buffer, size_t elementSize, size_t elementCount) = 0; - virtual size_t Write(const void* data, size_t elementSize, size_t elementCount) = 0; - virtual void Skip(int64_t amount) = 0; - virtual size_t Printf(const char* fmt, ...) = 0; - virtual int64_t Pos() = 0; - virtual void Goto(int64_t pos) = 0; - virtual void GotoEnd() = 0; - virtual void Close() = 0; - }; - - class File final : public IFile - { - void* m_handle; - - public: - File(); - explicit File(void* handle); - File(File&) = delete; - File(File&& f) noexcept; - ~File() override; - - File& operator=(File&) = delete; - File& operator=(File&& f) noexcept; - - bool IsOpen() override; - size_t Read(void* buffer, size_t elementSize, size_t elementCount) override; - size_t Write(const void* data, size_t elementSize, size_t elementCount) override; - void Skip(int64_t amount) override; - size_t Printf(const char* fmt, ...) override; - int64_t Pos() override; - void Goto(int64_t pos) override; - void GotoEnd() override; - void Close() override; - }; - - static bool FileExists(const std::string& fileName); - static uint64_t FileSize(const std::string& fileName); - - static bool DirectoryCreate(const std::string& directoryPath); - static bool DirectoryExists(const std::string& directoryName); - - static File Open(const std::string& filename, Mode mode); -}; \ No newline at end of file diff --git a/src/Utils/Utils/PathUtils.cpp b/src/Utils/Utils/PathUtils.cpp deleted file mode 100644 index 6b5c1355..00000000 --- a/src/Utils/Utils/PathUtils.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "PathUtils.h" - -#include - -namespace utils -{ - std::string Path::GetFilename(const std::string& pathInput) - { - const std::filesystem::path path(pathInput); - - return path.filename().string(); - } - - std::string Path::GetFilenameWithoutExtension(const std::string& pathInput) - { - const std::filesystem::path path(pathInput); - - return path.filename().replace_extension().string(); - } - - std::string Path::GetExtension(const std::string& pathInput) - { - const std::filesystem::path path(pathInput); - - return path.extension().string(); - } - - std::string Path::GetDirectory(const std::string& pathInput) - { - std::filesystem::path path(pathInput); - - return path.remove_filename().string(); - } - - std::string Path::Combine(const std::string& p1, const std::string& p2) - { - std::filesystem::path path(p1); - - return path.append(p2).string(); - } -} diff --git a/src/Utils/Utils/PathUtils.h b/src/Utils/Utils/PathUtils.h deleted file mode 100644 index 81b8e01f..00000000 --- a/src/Utils/Utils/PathUtils.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -namespace utils -{ - class Path - { - public: - static std::string GetFilename(const std::string& pathInput); - static std::string GetFilenameWithoutExtension(const std::string& pathInput); - static std::string GetExtension(const std::string& pathInput); - static std::string GetDirectory(const std::string& pathInput); - static std::string Combine(const std::string& p1, const std::string& p2); - }; -} \ No newline at end of file diff --git a/src/ZoneLoading/Loading/LoadingFileStream.cpp b/src/ZoneLoading/Loading/LoadingFileStream.cpp index 1d6cc4ff..807db569 100644 --- a/src/ZoneLoading/Loading/LoadingFileStream.cpp +++ b/src/ZoneLoading/Loading/LoadingFileStream.cpp @@ -1,16 +1,17 @@ #include "LoadingFileStream.h" -LoadingFileStream::LoadingFileStream(FileAPI::File* file) +LoadingFileStream::LoadingFileStream(std::istream& stream) + : m_stream(stream) { - m_file = file; } size_t LoadingFileStream::Load(void* buffer, const size_t length) { - return m_file->Read(buffer, 1, length); + m_stream.read(static_cast(buffer), length); + return static_cast(m_stream.gcount()); } int64_t LoadingFileStream::Pos() { - return m_file->Pos(); + return m_stream.tellg(); } \ No newline at end of file diff --git a/src/ZoneLoading/Loading/LoadingFileStream.h b/src/ZoneLoading/Loading/LoadingFileStream.h index ceec1f42..cd334855 100644 --- a/src/ZoneLoading/Loading/LoadingFileStream.h +++ b/src/ZoneLoading/Loading/LoadingFileStream.h @@ -1,13 +1,15 @@ #pragma once + +#include + #include "ILoadingStream.h" -#include "Utils/FileAPI.h" class LoadingFileStream final : public ILoadingStream { - FileAPI::File* m_file; + std::istream& m_stream; public: - explicit LoadingFileStream(FileAPI::File* file); + explicit LoadingFileStream(std::istream& stream); size_t Load(void* buffer, size_t length) override; int64_t Pos() override; diff --git a/src/ZoneLoading/Loading/Steps/StepDumpData.cpp b/src/ZoneLoading/Loading/Steps/StepDumpData.cpp index 2a56a244..960227ef 100644 --- a/src/ZoneLoading/Loading/Steps/StepDumpData.cpp +++ b/src/ZoneLoading/Loading/Steps/StepDumpData.cpp @@ -1,5 +1,7 @@ #include "StepDumpData.h" +#include + StepDumpData::StepDumpData(const unsigned int dumpCount) { m_dump_count = dumpCount; @@ -10,7 +12,7 @@ void StepDumpData::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) uint8_t tempBuffer[128]; unsigned int dumpedBytes = 0; - FileAPI::File tempFile = FileAPI::Open("dump.dat", FileAPI::Mode::MODE_WRITE); + std::ofstream tempFile("dump.dat", std::fstream::out | std::fstream::binary); while (dumpedBytes < m_dump_count) { @@ -25,14 +27,14 @@ void StepDumpData::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) toDump = sizeof(tempBuffer); } - const size_t loadedSize = stream->Load(tempBuffer, toDump); + const auto loadedSize = stream->Load(tempBuffer, toDump); dumpedBytes += loadedSize; if (loadedSize == 0) break; - tempFile.Write(tempBuffer, 1, loadedSize); + tempFile.write(reinterpret_cast(tempBuffer), loadedSize); } - tempFile.Close(); + tempFile.close(); } \ No newline at end of file diff --git a/src/ZoneLoading/Loading/ZoneLoader.cpp b/src/ZoneLoading/Loading/ZoneLoader.cpp index 16f7621b..1f5669c8 100644 --- a/src/ZoneLoading/Loading/ZoneLoader.cpp +++ b/src/ZoneLoading/Loading/ZoneLoader.cpp @@ -12,13 +12,13 @@ ZoneLoader::ZoneLoader(Zone* zone) ZoneLoader::~ZoneLoader() { - for(auto step : m_steps) + for(auto* step : m_steps) { delete step; } m_steps.clear(); - for(auto processor : m_processors) + for(auto* processor : m_processors) { delete processor; } @@ -27,9 +27,9 @@ ZoneLoader::~ZoneLoader() ILoadingStream* ZoneLoader::BuildLoadingChain(ILoadingStream* rootStream) { - ILoadingStream* currentStream = rootStream; + auto* currentStream = rootStream; - for(auto processor : m_processors) + for(auto* processor : m_processors) { processor->SetBaseStream(currentStream); @@ -74,14 +74,14 @@ void ZoneLoader::RemoveStreamProcessor(StreamProcessor* streamProcessor) } } -Zone* ZoneLoader::LoadZone(FileAPI::File* file) +Zone* ZoneLoader::LoadZone(std::istream& stream) { - LoadingFileStream fileStream(file); - ILoadingStream* endStream = BuildLoadingChain(&fileStream); + LoadingFileStream fileStream(stream); + auto* endStream = BuildLoadingChain(&fileStream); try { - for(auto step : m_steps) + for(auto* step : m_steps) { step->PerformStep(this, endStream); diff --git a/src/ZoneLoading/Loading/ZoneLoader.h b/src/ZoneLoading/Loading/ZoneLoader.h index c77e3fc1..f9d2d642 100644 --- a/src/ZoneLoading/Loading/ZoneLoader.h +++ b/src/ZoneLoading/Loading/ZoneLoader.h @@ -3,10 +3,10 @@ #include "ILoadingStep.h" #include "Zone/Zone.h" #include "Zone/XBlock.h" -#include "Utils/FileAPI.h" #include "StreamProcessor.h" #include +#include class ILoadingStep; @@ -33,5 +33,5 @@ public: void RemoveStreamProcessor(StreamProcessor* streamProcessor); - Zone* LoadZone(FileAPI::File* file); + Zone* LoadZone(std::istream& stream); }; diff --git a/src/ZoneLoading/ZoneLoading.cpp b/src/ZoneLoading/ZoneLoading.cpp index 20819c55..531f54da 100644 --- a/src/ZoneLoading/ZoneLoading.cpp +++ b/src/ZoneLoading/ZoneLoading.cpp @@ -1,8 +1,14 @@ #include "ZoneLoading.h" -#include "Utils/PathUtils.h" +#include +#include +#include + #include "Game/IW4/ZoneLoaderFactoryIW4.h" #include "Game/T6/ZoneLoaderFactoryT6.h" +#include "Utils/ObjFileStream.h" + +namespace fs = std::filesystem; IZoneLoaderFactory* ZoneLoaderFactories[] { @@ -12,17 +18,22 @@ IZoneLoaderFactory* ZoneLoaderFactories[] Zone* ZoneLoading::LoadZone(const std::string& path) { - std::string zoneName = utils::Path::GetFilenameWithoutExtension(path); - FileAPI::File file = FileAPI::Open(path, FileAPI::Mode::MODE_READ); + auto zoneName = fs::path(path).filename().replace_extension("").string(); + std::ifstream file(path, std::fstream::in | std::fstream::binary); - if(!file.IsOpen()) + if(!file.is_open()) { printf("Could not open file '%s'.\n", path.c_str()); return nullptr; } ZoneHeader header{}; - file.Read(&header, sizeof(ZoneHeader), 1); + file.read(reinterpret_cast(&header), sizeof header); + if(file.gcount() != sizeof header) + { + std::cout << "Failed to read zone header from file '" << path << "'.\n"; + return nullptr; + } ZoneLoader* zoneLoader = nullptr; for(auto* factory : ZoneLoaderFactories) @@ -39,8 +50,9 @@ Zone* ZoneLoading::LoadZone(const std::string& path) return nullptr; } - Zone* loadedZone = zoneLoader->LoadZone(&file); + auto* loadedZone = zoneLoader->LoadZone(file); + delete zoneLoader; - file.Close(); + file.close(); return loadedZone; } \ No newline at end of file