From c4a527eb570120d29b573fe987fe0548c986ace4 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Sat, 23 Dec 2023 06:33:35 -0800 Subject: [PATCH 1/4] Add IWD project type. --- src/Linker/Linker.cpp | 35 +++++- src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp | 105 ++++++++++++++++++ src/ObjWriting/ObjContainer/IWD/IWDWriter.h | 24 ++++ 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index c6d2940e9..42090924e 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -9,6 +9,7 @@ #include "LinkerSearchPaths.h" #include "ObjContainer/IPak/IPakWriter.h" #include "ObjContainer/IWD/IWD.h" +#include "ObjContainer/IWD/IWDWriter.h" #include "ObjLoading.h" #include "ObjWriting.h" #include "SearchPath/SearchPaths.h" @@ -45,7 +46,7 @@ enum class ProjectType NONE, FASTFILE, IPAK, - + IWD, MAX }; @@ -53,7 +54,7 @@ constexpr const char* PROJECT_TYPE_NAMES[static_cast(ProjectType::MAX) "none", "fastfile", "ipak", -}; + "iwd"}; class LinkerImpl final : public Linker { @@ -462,6 +463,32 @@ class LinkerImpl final : public Linker return true; } + bool BuildIWD(const std::string& projectName, const ZoneDefinition& zoneDefinition, SearchPaths& assetSearchPaths) const + { + const fs::path iwdFolderPath(m_args.GetOutputFolderPathForProject(projectName)); + auto iwdFilePath(iwdFolderPath); + const auto iwdFileName = zoneDefinition.m_name + ".iwd"; + iwdFilePath.append(iwdFileName); + + fs::create_directories(iwdFolderPath); + + const auto iwdWriter = IWDWriter::Create(iwdFilePath.string(), &assetSearchPaths); + for (const auto& assetEntry : zoneDefinition.m_assets) + { + iwdWriter->AddFile(assetEntry.m_asset_name); + } + + if (!iwdWriter->Write()) + { + std::cout << "Writing iwd failed." << std::endl; + return false; + } + + std::cout << "Created iwd \"" << iwdFilePath.string() << "\"\n"; + + return true; + } + bool BuildReferencedTargets(const std::string& projectName, const std::string& targetName, const ZoneDefinition& zoneDefinition) { return std::all_of(zoneDefinition.m_targets_to_build.begin(), @@ -512,6 +539,10 @@ class LinkerImpl final : public Linker result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths); break; + case ProjectType::IWD: + result = BuildIWD(projectName, *zoneDefinition, assetSearchPaths); + break; + default: assert(false); result = false; diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp index e69de29bb..e75c947e4 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp @@ -0,0 +1,105 @@ +#include "IWDWriter.h" + +#include +#include +#include "../minizip/zip.h" + +class IWDWriterImpl final : public IWDWriter +{ +public: + explicit IWDWriterImpl(const std::string& iwdFileName, ISearchPath* assetSearchPath) + : m_filename(iwdFileName), + m_asset_search_path(assetSearchPath), + m_files(0) + { + m_zipfile = zipOpen(m_filename.c_str(), APPEND_STATUS_CREATE); + if (!m_zipfile) + { + throw std::runtime_error("Error creating IWD file: \"" + m_filename + "\""); + } + } + + void AddFile(std::string fileName) override + { + m_files.emplace_back(std::move(fileName)); + } + + bool AddFileToArchive(const std::string& fileName, const std::unique_ptr& fileData, const size_t& fileSize) + { + zip_fileinfo zi = {}; + + if (zipOpenNewFileInZip(m_zipfile, fileName.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) + { + zipClose(m_zipfile, NULL); + throw std::runtime_error( "Could not open new file in IWD \"" + fileName + "\"\n"); + } + + if (zipWriteInFileInZip(m_zipfile, fileData.get(), fileSize) != ZIP_OK) + { + zipClose(m_zipfile, NULL); + throw std::runtime_error("Could not write file data to IWD \"" + fileName + "\"\n"); + } + + if (zipCloseFileInZip(m_zipfile) != ZIP_OK) + { + zipClose(m_zipfile, NULL); + throw std::runtime_error("Could not close file in IWD \"" + fileName + "\"\n"); + } + + return true; + } + + std::unique_ptr ReadFileDataFromSearchPath(const std::string& fileName, size_t& fileSize) const + { + const auto openFile = m_asset_search_path->Open(fileName); + if (!openFile.IsOpen()) + { + std::cerr << "Could not open file for writing to IWD \"" << fileName << "\"\n"; + return nullptr; + } + + fileSize = static_cast(openFile.m_length); + auto fileData = std::make_unique(fileSize); + openFile.m_stream->read(fileData.get(), fileSize); + + return fileData; + } + + bool WriteFileData(const std::string& fileName) + { + size_t fileSize; + const auto fileData = ReadFileDataFromSearchPath(fileName, fileSize); + if (!fileData) + return false; + + AddFileToArchive(fileName, fileData, fileSize); + + return true; + } + + bool Write() override + { + const auto result = std::all_of(m_files.begin(), + m_files.end(), + [this](const std::string& fileName) + { + return WriteFileData(fileName); + }); + + zipClose(m_zipfile, NULL); + return result; + } + +private: + const std::string m_filename; + + ISearchPath* m_asset_search_path; + std::vector m_files; + + zipFile m_zipfile; +}; + +std::unique_ptr IWDWriter::Create(const std::string& iwdFileName, ISearchPath* assetSearchPath) +{ + return std::make_unique(iwdFileName, assetSearchPath); +} diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h index e69de29bb..bc72ed4f4 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h @@ -0,0 +1,24 @@ +#pragma once +#include "SearchPath/ISearchPath.h" + +#include +#include + +class IWDWriter +{ +public: + static constexpr auto USE_COMPRESSION = true; + + IWDWriter() = default; + virtual ~IWDWriter() = default; + + IWDWriter(const IWDWriter& other) = default; + IWDWriter(IWDWriter&& other) noexcept = default; + IWDWriter& operator=(const IWDWriter& other) = default; + IWDWriter& operator=(IWDWriter&& other) noexcept = default; + + virtual void AddFile(std::string fileName) = 0; + virtual bool Write() = 0; + + static std::unique_ptr Create(const std::string& iwdFileName, ISearchPath* assetSearchPath); +}; \ No newline at end of file From 7fe01b271bb6b8b94904561cac1139d94233e334 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Sat, 23 Dec 2023 06:36:52 -0800 Subject: [PATCH 2/4] Format using clang. --- src/Linker/Linker.cpp | 6 +----- src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp | 7 ++++--- src/ObjWriting/ObjContainer/IWD/IWDWriter.h | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index 42090924e..61fe90723 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -50,11 +50,7 @@ enum class ProjectType MAX }; -constexpr const char* PROJECT_TYPE_NAMES[static_cast(ProjectType::MAX)]{ - "none", - "fastfile", - "ipak", - "iwd"}; +constexpr const char* PROJECT_TYPE_NAMES[static_cast(ProjectType::MAX)]{"none", "fastfile", "ipak", "iwd"}; class LinkerImpl final : public Linker { diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp index e75c947e4..eddf03aba 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp @@ -1,8 +1,9 @@ #include "IWDWriter.h" +#include "../minizip/zip.h" + #include #include -#include "../minizip/zip.h" class IWDWriterImpl final : public IWDWriter { @@ -24,14 +25,14 @@ class IWDWriterImpl final : public IWDWriter m_files.emplace_back(std::move(fileName)); } - bool AddFileToArchive(const std::string& fileName, const std::unique_ptr& fileData, const size_t& fileSize) + bool AddFileToArchive(const std::string& fileName, const std::unique_ptr& fileData, const size_t& fileSize) { zip_fileinfo zi = {}; if (zipOpenNewFileInZip(m_zipfile, fileName.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) { zipClose(m_zipfile, NULL); - throw std::runtime_error( "Could not open new file in IWD \"" + fileName + "\"\n"); + throw std::runtime_error("Could not open new file in IWD \"" + fileName + "\"\n"); } if (zipWriteInFileInZip(m_zipfile, fileData.get(), fileSize) != ZIP_OK) diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h index bc72ed4f4..66c0505e4 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h @@ -21,4 +21,4 @@ class IWDWriter virtual bool Write() = 0; static std::unique_ptr Create(const std::string& iwdFileName, ISearchPath* assetSearchPath); -}; \ No newline at end of file +}; From 6d116d944004d09d8cf4d4a86df2fbb724d3ba00 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Sat, 23 Dec 2023 07:47:28 -0800 Subject: [PATCH 3/4] Address review comments. Handle exceptions properly. --- src/Linker/Linker.cpp | 4 +- src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp | 39 +++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index 61fe90723..0230bfd80 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -50,7 +50,7 @@ enum class ProjectType MAX }; -constexpr const char* PROJECT_TYPE_NAMES[static_cast(ProjectType::MAX)]{"none", "fastfile", "ipak", "iwd"}; +constexpr const char* PROJECT_TYPE_NAMES[static_cast>(ProjectType::MAX)]{"none", "fastfile", "ipak", "iwd"}; class LinkerImpl final : public Linker { @@ -476,7 +476,7 @@ class LinkerImpl final : public Linker if (!iwdWriter->Write()) { - std::cout << "Writing iwd failed." << std::endl; + std::cerr << "Writing iwd failed." << std::endl; return false; } diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp index eddf03aba..1616d7f9e 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp @@ -10,9 +10,10 @@ class IWDWriterImpl final : public IWDWriter public: explicit IWDWriterImpl(const std::string& iwdFileName, ISearchPath* assetSearchPath) : m_filename(iwdFileName), - m_asset_search_path(assetSearchPath), - m_files(0) + m_asset_search_path(assetSearchPath) { + m_files.clear(); + m_added_files.clear(); m_zipfile = zipOpen(m_filename.c_str(), APPEND_STATUS_CREATE); if (!m_zipfile) { @@ -22,10 +23,16 @@ class IWDWriterImpl final : public IWDWriter void AddFile(std::string fileName) override { - m_files.emplace_back(std::move(fileName)); + const auto existingEntry = std::find(m_added_files.cbegin(), m_added_files.cend(), fileName); + if (existingEntry != m_added_files.cend()) + { + std::cerr << "Duplicate entry in " << m_filename << "'s zone definition; ignoring" << "\n"; + return; + } + m_files.emplace_back(fileName); } - bool AddFileToArchive(const std::string& fileName, const std::unique_ptr& fileData, const size_t& fileSize) + void AddFileToArchive(const std::string& fileName, const std::unique_ptr& fileData, const size_t& fileSize) { zip_fileinfo zi = {}; @@ -46,8 +53,6 @@ class IWDWriterImpl final : public IWDWriter zipClose(m_zipfile, NULL); throw std::runtime_error("Could not close file in IWD \"" + fileName + "\"\n"); } - - return true; } std::unique_ptr ReadFileDataFromSearchPath(const std::string& fileName, size_t& fileSize) const @@ -80,12 +85,21 @@ class IWDWriterImpl final : public IWDWriter bool Write() override { - const auto result = std::all_of(m_files.begin(), - m_files.end(), - [this](const std::string& fileName) - { - return WriteFileData(fileName); - }); + auto result = false; + try + { + result = std::all_of(m_files.cbegin(), + m_files.cend(), + [this](const std::string& fileName) + { + return WriteFileData(fileName); + }); + } + catch (const std::exception& e) + { + std::cerr << "Error while creating IWD " << m_filename << " : " << e.what(); + result = false; + } zipClose(m_zipfile, NULL); return result; @@ -96,6 +110,7 @@ class IWDWriterImpl final : public IWDWriter ISearchPath* m_asset_search_path; std::vector m_files; + std::vector m_added_files; zipFile m_zipfile; }; From b8397b5f6e6fa02ea109ae7979edb336dc501c93 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Sat, 23 Dec 2023 08:36:55 -0800 Subject: [PATCH 4/4] Address review comments. Add ability to get the zone definition name for error reporting. --- src/Linker/Linker.cpp | 2 +- src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp | 44 +++++++++---------- src/ObjWriting/ObjContainer/IWD/IWDWriter.h | 4 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index 0230bfd80..a42d9d3e0 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -468,7 +468,7 @@ class LinkerImpl final : public Linker fs::create_directories(iwdFolderPath); - const auto iwdWriter = IWDWriter::Create(iwdFilePath.string(), &assetSearchPaths); + const auto iwdWriter = IWDWriter::Create(zoneDefinition.m_name, iwdFilePath.string(), &assetSearchPaths); for (const auto& assetEntry : zoneDefinition.m_assets) { iwdWriter->AddFile(assetEntry.m_asset_name); diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp index 1616d7f9e..3b1d96fa5 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp @@ -8,25 +8,25 @@ class IWDWriterImpl final : public IWDWriter { public: - explicit IWDWriterImpl(const std::string& iwdFileName, ISearchPath* assetSearchPath) - : m_filename(iwdFileName), + explicit IWDWriterImpl(const std::string& zoneDefinition, const std::string& iwdFileName, ISearchPath* assetSearchPath) + : m_zone_definition(zoneDefinition), + m_filename(iwdFileName), m_asset_search_path(assetSearchPath) { - m_files.clear(); - m_added_files.clear(); m_zipfile = zipOpen(m_filename.c_str(), APPEND_STATUS_CREATE); if (!m_zipfile) { - throw std::runtime_error("Error creating IWD file: \"" + m_filename + "\""); + throw std::runtime_error("Error creating IWD file: \"" + m_zone_definition + "\""); } } - void AddFile(std::string fileName) override + void AddFile(const std::string& fileName) override { - const auto existingEntry = std::find(m_added_files.cbegin(), m_added_files.cend(), fileName); - if (existingEntry != m_added_files.cend()) + const auto existingEntry = std::find(m_files.cbegin(), m_files.cend(), fileName); + if (existingEntry != m_files.cend()) { - std::cerr << "Duplicate entry in " << m_filename << "'s zone definition; ignoring" << "\n"; + std::cerr << "Duplicate entry \"" << fileName << "\" in IWD project " << m_zone_definition << ".zone; ignoring" + << "\n"; return; } m_files.emplace_back(fileName); @@ -39,19 +39,19 @@ class IWDWriterImpl final : public IWDWriter if (zipOpenNewFileInZip(m_zipfile, fileName.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) { zipClose(m_zipfile, NULL); - throw std::runtime_error("Could not open new file in IWD \"" + fileName + "\"\n"); + throw std::runtime_error("Could not open new file in IWD \"" + m_zone_definition + "\"\n"); } if (zipWriteInFileInZip(m_zipfile, fileData.get(), fileSize) != ZIP_OK) { zipClose(m_zipfile, NULL); - throw std::runtime_error("Could not write file data to IWD \"" + fileName + "\"\n"); + throw std::runtime_error("Could not write file data to IWD \"" + m_zone_definition + "\"\n"); } if (zipCloseFileInZip(m_zipfile) != ZIP_OK) { zipClose(m_zipfile, NULL); - throw std::runtime_error("Could not close file in IWD \"" + fileName + "\"\n"); + throw std::runtime_error("Could not close file in IWD \"" + m_zone_definition + "\"\n"); } } @@ -60,7 +60,7 @@ class IWDWriterImpl final : public IWDWriter const auto openFile = m_asset_search_path->Open(fileName); if (!openFile.IsOpen()) { - std::cerr << "Could not open file for writing to IWD \"" << fileName << "\"\n"; + std::cerr << "Could not open file for writing to IWD \"" << m_zone_definition << "\"\n"; return nullptr; } @@ -89,15 +89,15 @@ class IWDWriterImpl final : public IWDWriter try { result = std::all_of(m_files.cbegin(), - m_files.cend(), - [this](const std::string& fileName) - { - return WriteFileData(fileName); - }); + m_files.cend(), + [this](const std::string& fileName) + { + return WriteFileData(fileName); + }); } catch (const std::exception& e) { - std::cerr << "Error while creating IWD " << m_filename << " : " << e.what(); + std::cerr << "Error while creating IWD " << m_zone_definition << " : " << e.what(); result = false; } @@ -107,15 +107,15 @@ class IWDWriterImpl final : public IWDWriter private: const std::string m_filename; + const std::string m_zone_definition; ISearchPath* m_asset_search_path; std::vector m_files; - std::vector m_added_files; zipFile m_zipfile; }; -std::unique_ptr IWDWriter::Create(const std::string& iwdFileName, ISearchPath* assetSearchPath) +std::unique_ptr IWDWriter::Create(const std::string& zoneDefinition, const std::string& iwdFileName, ISearchPath* assetSearchPath) { - return std::make_unique(iwdFileName, assetSearchPath); + return std::make_unique(zoneDefinition, iwdFileName, assetSearchPath); } diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h index 66c0505e4..aa90edfa3 100644 --- a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h +++ b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h @@ -17,8 +17,8 @@ class IWDWriter IWDWriter& operator=(const IWDWriter& other) = default; IWDWriter& operator=(IWDWriter&& other) noexcept = default; - virtual void AddFile(std::string fileName) = 0; + virtual void AddFile(const std::string& fileName) = 0; virtual bool Write() = 0; - static std::unique_ptr Create(const std::string& iwdFileName, ISearchPath* assetSearchPath); + static std::unique_ptr Create(const std::string& zoneDefinition, const std::string& iwdFileName, ISearchPath* assetSearchPath); };