diff options
-rw-r--r-- | ArchiveEx/Archive.cpp | 45 | ||||
-rw-r--r-- | ArchiveEx/Archive.h | 3 |
2 files changed, 48 insertions, 0 deletions
diff --git a/ArchiveEx/Archive.cpp b/ArchiveEx/Archive.cpp index 134404c..8ca7b71 100644 --- a/ArchiveEx/Archive.cpp +++ b/ArchiveEx/Archive.cpp @@ -23,6 +23,8 @@ static inline std::size_t ConvertPathSeparator(const char* src, char* dest); static constexpr std::uint32_t VERSION {0x0010}; static constexpr std::size_t BLOCK_SIZE {1024}; static constexpr std::size_t DIRECTORY_MARGIN {64}; +static constexpr int UNUSED_BLOCK {-1}; +static constexpr int DIRECTORY_BLOCK {-2}; Archive::Archive(const char* p) : @@ -56,6 +58,7 @@ Archive::Archive(const char* p) : header.directory.compressed_size); if (Z_OK != err) throw "could not uncompress directory"; + UpdateBlockMap(); } @@ -111,6 +114,29 @@ Archive::Find(const char* filepath) const void +Archive::UpdateBlockMap() +{ + const std::size_t last_directory_block = header.directory.offset / BLOCK_SIZE + DirectoryBlocks() - 1; + std::size_t last_block = last_directory_block; + for (const auto& entry : entries) { + const std::size_t block = entry.offset / BLOCK_SIZE + BytesToBlocks(entry.compressed_size) - 1; + if (last_block < block) + last_block = block; + } + blocks.clear(); + blocks.resize(last_block + 1, UNUSED_BLOCK); + for (std::size_t n = header.directory.offset / BLOCK_SIZE; n <= last_directory_block; ++n) + blocks[n] = DIRECTORY_BLOCK; + for (std::size_t i = 0; i < entries.size(); ++i) { + const std::size_t from = entries[i].offset / BLOCK_SIZE; + const std::size_t exclusive_to = from + BytesToBlocks(entries[i].compressed_size); + for (std::size_t n = from; n < exclusive_to; ++n) + blocks[n] = i; + } +} + + +void Archive::PrintNamesOfEntries() const { for (const auto& entry : entries) @@ -118,6 +144,25 @@ Archive::PrintNamesOfEntries() const } +void +Archive::PrintBlocks() const +{ + for (std::size_t i = 0; i < blocks.size(); ++i) { + std::printf("%ld\t", i); + switch (blocks[i]) { + case UNUSED_BLOCK: + std::printf("(unused)\n"); + break; + case DIRECTORY_BLOCK: + std::printf("(dir)\n"); + break; + default: + std::printf("%s\n", entries[blocks[i]].name); + } + } +} + + std::size_t Archive::DirectoryBlocks() const { diff --git a/ArchiveEx/Archive.h b/ArchiveEx/Archive.h index cbaf571..e19c718 100644 --- a/ArchiveEx/Archive.h +++ b/ArchiveEx/Archive.h @@ -40,12 +40,15 @@ public: int Expand(int index, std::uint8_t*& buffer, bool null_terminated=false) const; int Expand(const char* filepath, std::uint8_t*& buffer, bool null_terminated=false) const; int Find(const char* filepath) const; + void UpdateBlockMap(); void PrintNamesOfEntries() const; + void PrintBlocks() const; std::size_t DirectoryBlocks() const; private: const char* path; Header header; std::vector<Entry> entries; + std::vector<int> blocks; }; |