add separateFunc ZipFileDevice constructor argument

This commit is contained in:
MihailRis 2025-02-24 20:06:55 +03:00
parent 310bef1723
commit 9cc55e30e3
2 changed files with 35 additions and 15 deletions

View File

@ -94,9 +94,10 @@ void ZipFileDevice::findBlob(Entry& entry) {
} }
} }
ZipFileDevice::ZipFileDevice(std::unique_ptr<std::istream> filePtr) ZipFileDevice::ZipFileDevice(
: file(std::move(filePtr)) { std::unique_ptr<std::istream> filePtr, FileSeparateFunc separateFunc
)
: file(std::move(filePtr)), separateFunc(std::move(separateFunc)) {
// Searching for EOCD // Searching for EOCD
file->seekg(0, std::ios::end); file->seekg(0, std::ios::end);
std::streampos fileSize = file->tellg(); std::streampos fileSize = file->tellg();
@ -139,7 +140,6 @@ ZipFileDevice::ZipFileDevice(std::unique_ptr<std::istream> filePtr)
} }
} }
std::filesystem::path ZipFileDevice::resolve(std::string_view path) { std::filesystem::path ZipFileDevice::resolve(std::string_view path) {
throw std::runtime_error("unable to resolve filesystem path"); throw std::runtime_error("unable to resolve filesystem path");
} }
@ -160,17 +160,27 @@ std::unique_ptr<std::istream> ZipFileDevice::read(std::string_view path) {
if (entry.blobOffset == 0) { if (entry.blobOffset == 0) {
findBlob(entry); findBlob(entry);
} }
std::unique_ptr<std::istream> srcStream;
if (separateFunc) {
// Create new istream for concurrent data reading
srcStream = separateFunc();
srcStream->seekg(entry.blobOffset);
} else {
// Read compressed data to memory if istream cannot be separated
file->seekg(entry.blobOffset); file->seekg(entry.blobOffset);
util::Buffer<char> buffer(entry.compressedSize); util::Buffer<char> buffer(entry.compressedSize);
file->read(buffer.data(), buffer.size()); file->read(buffer.data(), buffer.size());
auto memoryStream = std::make_unique<memory_istream>(std::move(buffer)); srcStream = std::make_unique<memory_istream>(std::move(buffer));
}
if (entry.compressionMethod == COMPRESSION_NONE) { if (entry.compressionMethod == COMPRESSION_NONE) {
return memoryStream; return srcStream;
} else if (entry.compressionMethod == COMPRESSION_DEFLATE) { } else if (entry.compressionMethod == COMPRESSION_DEFLATE) {
return std::make_unique<deflate_istream>(std::move(memoryStream)); return std::make_unique<deflate_istream>(std::move(srcStream));
} else { } else {
throw std::runtime_error("unsupported compression method"); throw std::runtime_error(
"unsupported compression method [" +
std::to_string(entry.compressionMethod) + "]"
);
} }
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <functional>
#include <unordered_map> #include <unordered_map>
#include "Device.hpp" #include "Device.hpp"
@ -25,7 +26,15 @@ namespace io {
bool isDirectory = false; bool isDirectory = false;
}; };
public: public:
ZipFileDevice(std::unique_ptr<std::istream> file); using FileSeparateFunc = std::function<std::unique_ptr<std::istream>()>;
/// @param file ZIP file seekable istream
/// @param separateFunc Optional function that creates new seekable
/// istream for the ZIP file.
ZipFileDevice(
std::unique_ptr<std::istream> file,
FileSeparateFunc separateFunc = nullptr
);
std::filesystem::path resolve(std::string_view path) override; std::filesystem::path resolve(std::string_view path) override;
std::unique_ptr<std::ostream> write(std::string_view path) override; std::unique_ptr<std::ostream> write(std::string_view path) override;
@ -41,6 +50,7 @@ namespace io {
std::unique_ptr<PathsGenerator> list(std::string_view path) override; std::unique_ptr<PathsGenerator> list(std::string_view path) override;
private: private:
std::unique_ptr<std::istream> file; std::unique_ptr<std::istream> file;
FileSeparateFunc separateFunc;
std::unordered_map<std::string, Entry> entries; std::unordered_map<std::string, Entry> entries;
Entry readEntry(); Entry readEntry();