diff --git a/openVulkanoCpp/Host/ExeAppendedZipLoader.cpp b/openVulkanoCpp/Host/ExeAppendedZipLoader.cpp new file mode 100644 index 0000000..1ab4c03 --- /dev/null +++ b/openVulkanoCpp/Host/ExeAppendedZipLoader.cpp @@ -0,0 +1,56 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ExeAppendedZipLoader.hpp" +#include "Base/Logger.hpp" +#include "IO/Archive/ArchiveReader.hpp" +#include +#include + +namespace OpenVulkano +{ + std::string ExeAppendedZipLoader::GetResourcePath(const std::string& resourceName) + { + return GetCurrentExecutablePath(); + } + + Array ExeAppendedZipLoader::GetResource(const std::string& exeName) + { + std::string ext = std::filesystem::path(exeName).extension().string(); + if (ext != ".exe" && ext != "") + { + Logger::DATA->debug("Given file {} is not a valid executable", exeName); + return {}; + } + + std::ifstream ifs(exeName, std::ios::in | std::ios::binary); + if (!ifs.is_open()) + { + Logger::DATA->debug("Could not open file {}.", exeName); + return {}; + } + ifs.seekg(0, std::ios_base::end); + size_t zipSize = ifs.tellg(); + ifs.seekg(0, std::ios_base::beg); + Array zipData(zipSize); + ifs.read(zipData.Data(), zipSize); + ifs.close(); + return zipData; + } + + std::vector>> ExeAppendedZipLoader::GetZipArchiveFiles(const std::string& exePath) + { + Array zipData = GetResource(exePath); + ArchiveReader reader(zipData.Data(), zipData.Size(), nullptr, ArchiveType::ZIP); + std::vector>> filesFromZip; + while (reader.HasNext()) + { + filesFromZip.push_back(*reader.GetNextFile()); + } + return filesFromZip; + } + +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/ExeAppendedZipLoader.hpp b/openVulkanoCpp/Host/ExeAppendedZipLoader.hpp new file mode 100644 index 0000000..9adede4 --- /dev/null +++ b/openVulkanoCpp/Host/ExeAppendedZipLoader.hpp @@ -0,0 +1,24 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Host/ResourceLoader.hpp" +#include "IO/FileDescription.hpp" +#include +#include + +namespace OpenVulkano +{ + class ExeAppendedZipLoader : public ResourceLoader + { + public: + std::string GetResourcePath(const std::string& resourceName) override; + Array GetResource(const std::string& exePath) override; + std::vector>> GetZipArchiveFiles(const std::string& exePath); + virtual std::string GetCurrentExecutablePath() const = 0; + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.cpp b/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.cpp new file mode 100644 index 0000000..90332b9 --- /dev/null +++ b/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.cpp @@ -0,0 +1,30 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ExeAppendedZipLoaderLinux.hpp" +#include +#include + +namespace OpenVulkano +{ + namespace + { + void* HANDLE = ResourceLoader::RegisterResourceLoader(std::make_unique()); + } + + std::string OpenVulkano::ExeAppendedZipLoaderLinux::GetCurrentExecutablePath() const + { + char dest[PATH_MAX]; + memset(dest, 0, sizeof(dest)); // readlink does not null terminate! + size_t sz = 0; + if ((sz = readlink("/proc/self/exe", dest, PATH_MAX)) != -1) + { + return std::string(dest, sz); + } + return ""; + } + +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.hpp b/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.hpp new file mode 100644 index 0000000..c1ce15e --- /dev/null +++ b/openVulkanoCpp/Host/Linux/ExeAppendedZipLoaderLinux.hpp @@ -0,0 +1,18 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Host/ExeAppendedZipLoader.hpp" + +namespace OpenVulkano +{ + class ExeAppendedZipLoaderLinux final : public ExeAppendedZipLoader + { + public: + std::string GetCurrentExecutablePath() const override; + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.cpp b/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.cpp new file mode 100644 index 0000000..30e1238 --- /dev/null +++ b/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.cpp @@ -0,0 +1,24 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ExeAppendedZipLoaderWindows.hpp" +#include + +namespace OpenVulkano +{ + namespace + { + void* HANDLE = ResourceLoader::RegisterResourceLoader(std::make_unique()); + } + + std::string OpenVulkano::ExeAppendedZipLoaderWindows::GetCurrentExecutablePath() const + { + CHAR nameBuf[MAX_PATH] = {}; + DWORD len = GetModuleFileNameA(NULL, nameBuf, MAX_PATH); + return std::string(nameBuf, len); + } + +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.hpp b/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.hpp new file mode 100644 index 0000000..4e89e2e --- /dev/null +++ b/openVulkanoCpp/Host/Windows/ExeAppendedZipLoaderWindows.hpp @@ -0,0 +1,18 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Host/ExeAppendedZipLoader.hpp" + +namespace OpenVulkano +{ + class ExeAppendedZipLoaderWindows final : public ExeAppendedZipLoader + { + public: + std::string GetCurrentExecutablePath() const override; + }; +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 71523b6..19d78dc 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,11 +10,22 @@ FilterPlatformPaths(SOURCES) if (NOT ENABLE_CURL) list(FILTER SOURCES EXCLUDE REGEX "WebResourceLoader") endif() + +if (APPLE) + list(FILTER SOURCES EXCLUDE REGEX "ExeAppendedZipLoader") +endif() + source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES}) file(GLOB_RECURSE RESOURCES "${ROOT_FOLDER}/resources/*.rc" "${ROOT_FOLDER}/resources/*.h") list(APPEND SOURCES ${RESOURCES}) add_executable(OpenVulkano_Tests ${SOURCES}) +# append zip file at the end of executable file +if (WIN32 OR (LINUX AND NOT APPLE)) + set(ZIP_FILE ${ROOT_FOLDER}/resources/arch.zip) + add_custom_command(TARGET OpenVulkano_Tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E cat ${ZIP_FILE} >> $) +endif() + target_include_directories(OpenVulkano_Tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(OpenVulkano_Tests PRIVATE openVulkanoCpp) diff --git a/tests/Host/ExeAppendedZipLoaderTests.cpp b/tests/Host/ExeAppendedZipLoaderTests.cpp new file mode 100644 index 0000000..5923cef --- /dev/null +++ b/tests/Host/ExeAppendedZipLoaderTests.cpp @@ -0,0 +1,52 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#ifdef _WIN32 + #include "Host/Windows/ExeAppendedZipLoaderWindows.hpp" +#else + #include "Host/Linux/ExeAppendedZipLoaderLinux.hpp" +#endif + +#include "Base/Logger.hpp" +#include +#include +#include + +using namespace OpenVulkano; + +TEST_CASE("Load zip from exe") +{ + Logger::SetupLogger("", "tests.log"); +#ifdef _WIN32 + ExeAppendedZipLoaderWindows loader; +#else + ExeAppendedZipLoaderLinux loader; +#endif + Array zipData = loader.GetResource(loader.GetCurrentExecutablePath()); + REQUIRE(!zipData.Empty()); + + auto files = loader.GetZipArchiveFiles(loader.GetCurrentExecutablePath()); + REQUIRE(files.size() == 2); + + int i = 0; + for (const auto& [fileDesc, fileData] : files) + { + if (i == 0) + { + REQUIRE(fileDesc.path == "madvoxel_icon.ico"); + } + else if (i == 1) + { + REQUIRE(fileDesc.path == "text.txt"); + std::string s(fileData.Data(), fileData.Size()); + REQUIRE(s == "Hello world!"); + } + i++; + } + +}