summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ArchiveEx/Archive.cpp45
-rw-r--r--ArchiveEx/Archive.h3
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;
};