From 58acc1b2eccb4727d287b3a5600a2c4aa56f7d08 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 22 Feb 2025 07:04:04 +0300 Subject: [PATCH] implement ZipFileDevice methods (WIP) --- src/coders/gzip.hpp | 12 +++---- src/io/devices/ZipFileDevice.cpp | 59 ++++++++++++++++++++++++++++---- src/io/devices/ZipFileDevice.hpp | 1 + 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/coders/gzip.hpp b/src/coders/gzip.hpp index f18b1c14..cd14d478 100644 --- a/src/coders/gzip.hpp +++ b/src/coders/gzip.hpp @@ -7,13 +7,13 @@ namespace gzip { const unsigned char MAGIC[] = "\x1F\x8B"; - /* Compress bytes array to GZIP format - @param src source bytes array - @param size length of source bytes array */ + /// Compress bytes array to GZIP format + /// @param src source bytes array + /// @param size length of source bytes array std::vector compress(const ubyte* src, size_t size); - /* Decompress bytes array from GZIP - @param src GZIP data - @param size length of GZIP data */ + /// Decompress bytes array from GZIP + /// @param src GZIP data + /// @param size length of GZIP data std::vector decompress(const ubyte* src, size_t size); } diff --git a/src/io/devices/ZipFileDevice.cpp b/src/io/devices/ZipFileDevice.cpp index 79e3e006..cc54af34 100644 --- a/src/io/devices/ZipFileDevice.cpp +++ b/src/io/devices/ZipFileDevice.cpp @@ -2,7 +2,10 @@ #include #include "debug/Logger.hpp" +#include "io/memory_istream.hpp" +#include "io/deflate_istream.hpp" #include "util/data_io.hpp" +#include "util/Buffer.hpp" static debug::Logger logger("zip-file"); @@ -11,6 +14,8 @@ using namespace io; static constexpr uint32_t EOCD_SIGNATURE = 0x06054b50; static constexpr uint32_t CENTRAL_DIR_SIGNATURE = 0x02014b50; static constexpr uint32_t LOCAL_FILE_SIGNATURE = 0x04034b50; +static constexpr uint32_t COMPRESSION_NONE = 0; +static constexpr uint32_t COMPRESSION_DEFLATE = 8; template static T read_int(std::unique_ptr& file) { @@ -77,7 +82,15 @@ void ZipFileDevice::findBlob(Entry& entry) { file->seekg(nameLength + extraFieldLength, std::ios::cur); entry.blobOffset = file->tellg(); - std::cout << entry.fileName << ": " << entry.blobOffset << " " << entry.compressionMethod << std::endl; + for (size_t i = 0; i < entry.fileName.length(); i++) { + if (entry.fileName[i] == '\\') { + entry.fileName[i] = '/'; + } + } + if (entry.fileName[entry.fileName.length() - 1] == '/') { + entry.isDirectory = true; + entry.fileName = entry.fileName.substr(0, entry.fileName.length() - 1); + } } ZipFileDevice::ZipFileDevice(std::unique_ptr filePtr) @@ -135,23 +148,57 @@ std::unique_ptr ZipFileDevice::write(std::string_view path) { } std::unique_ptr ZipFileDevice::read(std::string_view path) { - return nullptr; + const auto& found = entries.find(std::string(path)); + if (found == entries.end()) { + throw std::runtime_error("could not to open file zip://" + std::string(path)); + } + auto& entry = found->second; + if (entry.isDirectory) { + throw std::runtime_error("zip://" + std::string(path) + " is directory"); + } + if (entry.blobOffset == 0) { + findBlob(entry); + } + file->seekg(entry.blobOffset); + + util::Buffer buffer(entry.compressedSize); + file->read(buffer.data(), buffer.size()); + auto memoryStream = std::make_unique(std::move(buffer)); + if (entry.compressionMethod == COMPRESSION_NONE) { + return memoryStream; + } else if (entry.compressionMethod == COMPRESSION_DEFLATE) { + return std::make_unique(std::move(memoryStream)); + } else { + throw std::runtime_error("unsupported compression method"); + } } size_t ZipFileDevice::size(std::string_view path) { - return 0; + const auto& found = entries.find(std::string(path)); + if (found == entries.end()) { + return false; + } + return found->second.uncompressedSize; } bool ZipFileDevice::exists(std::string_view path) { - return false; + return entries.find(std::string(path)) != entries.end(); } bool ZipFileDevice::isdir(std::string_view path) { - return false; + const auto& found = entries.find(std::string(path)); + if (found == entries.end()) { + return false; + } + return found->second.isDirectory; } bool ZipFileDevice::isfile(std::string_view path) { - return false; + const auto& found = entries.find(std::string(path)); + if (found == entries.end()) { + return false; + } + return !found->second.isDirectory; } bool ZipFileDevice::mkdir(std::string_view path) { diff --git a/src/io/devices/ZipFileDevice.hpp b/src/io/devices/ZipFileDevice.hpp index dba02a98..88d2213c 100644 --- a/src/io/devices/ZipFileDevice.hpp +++ b/src/io/devices/ZipFileDevice.hpp @@ -22,6 +22,7 @@ namespace io { uint32_t localHeaderOffset; std::string fileName; size_t blobOffset = 0; + bool isDirectory = false; }; public: ZipFileDevice(std::unique_ptr file);