diff options
author | Aki <please@ignore.pl> | 2022-08-07 22:38:21 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2022-08-07 22:38:21 +0200 |
commit | c5657b5cf6e72df9f573f149fe027374bf634fa7 (patch) | |
tree | 7b69d550e3b591bc31530c33437e6a5107af65bd /ArchiveEx | |
parent | 9ae3b193c461b168336d1d9e272aa834705633d7 (diff) | |
download | starshatter-c5657b5cf6e72df9f573f149fe027374bf634fa7.zip starshatter-c5657b5cf6e72df9f573f149fe027374bf634fa7.tar.gz starshatter-c5657b5cf6e72df9f573f149fe027374bf634fa7.tar.bz2 |
Added method to expand stored files
Diffstat (limited to 'ArchiveEx')
-rw-r--r-- | ArchiveEx/Archive.cpp | 37 | ||||
-rw-r--r-- | ArchiveEx/Archive.h | 1 |
2 files changed, 35 insertions, 3 deletions
diff --git a/ArchiveEx/Archive.cpp b/ArchiveEx/Archive.cpp index d714e46..3eea0fe 100644 --- a/ArchiveEx/Archive.cpp +++ b/ArchiveEx/Archive.cpp @@ -1,5 +1,6 @@ #include "Archive.h" +#include <cstdint> #include <cstdio> #include <memory> #include <vector> @@ -28,7 +29,7 @@ Archive::Archive(const char* p) : UniqueFileHandle file {std::fopen(path, "rb"), &std::fclose}; if (!file) throw "could not open archive"; - std::size_t length = fread(&header, sizeof(Header), 1, file.get()); + std::size_t length = std::fread(&header, sizeof(Header), 1, file.get()); if (1 != length) throw "could not read"; if (VERSION != header.version) @@ -36,7 +37,7 @@ Archive::Archive(const char* p) : int err = std::fseek(file.get(), sizeof(Header) + header.directory.offset, SEEK_SET); if (-1 == err) throw "could not find directory in archive"; - std::vector<std::uint8_t> compressed(header.directory.compressed_size); + std::vector<Bytef> compressed(header.directory.compressed_size); length = std::fread(compressed.data(), 1, header.directory.compressed_size, file.get()); if (header.directory.compressed_size != length) throw "could not read compressed directory"; @@ -44,7 +45,7 @@ Archive::Archive(const char* p) : entries.resize(header.total_entries); entries.reserve(total_entries); // In original impl entries were switched on/off with their uncompressed size value. uLongf uncompressed_size = sizeof(Entry) * total_entries; - err = ::uncompress( + err = uncompress( reinterpret_cast<Bytef*>(entries.data()), &uncompressed_size, compressed.data(), @@ -54,6 +55,36 @@ Archive::Archive(const char* p) : } +int +Archive::Expand(const int index, std::uint8_t*& buffer, const bool null_terminated) const +{ + if (0 > index && static_cast<int>(header.total_entries) <= index) + return -1; // Can be replaced by error-checked access to std::vector holding entries. + UniqueFileHandle file {std::fopen(path, "rb"), &std::fclose}; + if (!file) + return -1; + const auto& entry = entries[index]; + std::vector<Bytef> compressed(entry.compressed_size); + int err = std::fseek(file.get(), sizeof(Header) + entry.offset, SEEK_SET); + if (-1 == err) + return -1; + std::size_t length = std::fread(compressed.data(), 1, entry.compressed_size, file.get()); + if (entry.compressed_size != length) + return -1; + uLongf output_length = entry.original_size + static_cast<uLongf>(null_terminated); + std::unique_ptr<std::uint8_t[]> uncompressed(new std::uint8_t[output_length]); + if (!uncompressed) + return -1; + err = uncompress(uncompressed.get(), &output_length, compressed.data(), entry.compressed_size); + if (Z_OK != err) + return -1; + buffer = uncompressed.release(); + if (null_terminated) + buffer[output_length - 1] = 0; + return output_length; +} + + void Archive::PrintNamesOfEntries() const { diff --git a/ArchiveEx/Archive.h b/ArchiveEx/Archive.h index cc06dc4..6870194 100644 --- a/ArchiveEx/Archive.h +++ b/ArchiveEx/Archive.h @@ -39,6 +39,7 @@ class Archive { public: explicit Archive(const char* path); + int Expand(int index, std::uint8_t*& buffer, bool null_terminated=false) const; void PrintNamesOfEntries() const; std::size_t DirectoryBlocks() const; private: |