summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-08-20 22:41:02 +0200
committerAki <please@ignore.pl>2022-08-20 22:41:02 +0200
commite4bb06e7a22d766e7c0c689a9fa392346f5a3daa (patch)
tree8eee01e71a11816c9fc144057ff7731633f4704a
parentbc5e7b154c0160c7f512f9d0a1ad85de9b38edbe (diff)
downloadstarshatter-e4bb06e7a22d766e7c0c689a9fa392346f5a3daa.zip
starshatter-e4bb06e7a22d766e7c0c689a9fa392346f5a3daa.tar.gz
starshatter-e4bb06e7a22d766e7c0c689a9fa392346f5a3daa.tar.bz2
Merged on-demand Archive creation to constructor
-rw-r--r--ArchiveEx/Archive.cpp50
-rw-r--r--ArchiveEx/Archive.h7
2 files changed, 18 insertions, 39 deletions
diff --git a/ArchiveEx/Archive.cpp b/ArchiveEx/Archive.cpp
index 0313eda..808b6fc 100644
--- a/ArchiveEx/Archive.cpp
+++ b/ArchiveEx/Archive.cpp
@@ -38,44 +38,19 @@ static constexpr int UNUSED_BLOCK {-1};
static constexpr int DIRECTORY_BLOCK {-2};
-Archive
-CreateEmpty(const char* path)
-{
- Header header = {VERSION, 0, {0, 0, 0}};
- std::vector<Entry> entries;
- entries.reserve(DIRECTORY_MARGIN);
- const std::size_t uncompressed_size = DIRECTORY_MARGIN * sizeof(Entry);
- uLongf compressed_size = uncompressed_size * 1.1 + 12;
- auto compressed = std::make_unique<Bytef[]>(compressed_size);
- int err = compress(
- compressed.get(),
- &compressed_size,
- reinterpret_cast<Bytef*>(entries.data()),
- uncompressed_size);
- if (Z_OK != err)
- throw "could not compress directory metadata";
- header.directory.compressed_size = compressed_size;
- UniqueFileHandle archive {std::fopen(path, "wb"), &std::fclose};
- err = std::fwrite(&header, sizeof(Header), 1, archive.get());
- if (1 != err)
- throw "could not write header (write)";
- err = std::fwrite(compressed.get(), 1, compressed_size, archive.get());
- if (static_cast<int>(compressed_size) != err)
- throw "could not write directory (write)";
- archive.reset();
- return Archive(path);
-}
-
-
-Archive::Archive(const char* p) :
+Archive::Archive(const char* p, bool create) :
path {p},
directory_offset {0},
entries {},
- blocks {}
+ blocks {DIRECTORY_BLOCK}
{
UniqueFileHandle file {std::fopen(path, "rb"), &std::fclose};
- if (!file)
- throw "could not open archive";
+ if (!file) {
+ if (!create)
+ throw "could not open archive";
+ WriteMeta(true);
+ return;
+ }
Header header {};
std::size_t length = std::fread(&header, sizeof(Header), 1, file.get());
if (1 != length)
@@ -218,7 +193,7 @@ Archive::Insert(const char* filepath)
void
-Archive::WriteMeta()
+Archive::WriteMeta(bool create)
{
const std::size_t total_entries = entries.size();
const std::size_t dirsize = total_entries + DIRECTORY_MARGIN;
@@ -251,6 +226,13 @@ Archive::WriteMeta()
header.directory.compressed_size = compressed_size;
header.directory.offset = directory_offset;
UniqueFileHandle archive {std::fopen(path, "rb+"), &std::fclose};
+ if (!archive) {
+ if (!create)
+ throw "could not open archive file";
+ archive.reset(std::fopen(path, "wb"));
+ if (!archive)
+ throw "could not create archive file";
+ }
err = std::fseek(archive.get(), 0, SEEK_SET);
if (-1 == err)
throw "could not write header (seek)";
diff --git a/ArchiveEx/Archive.h b/ArchiveEx/Archive.h
index 189cdbe..7ba32e4 100644
--- a/ArchiveEx/Archive.h
+++ b/ArchiveEx/Archive.h
@@ -24,12 +24,12 @@ struct Entry
class Archive
{
public:
- explicit Archive(const char* path);
+ explicit Archive(const char* path, bool create=false);
int Extract(int index, std::uint8_t*& buffer, bool null_terminated=false) const;
int Extract(const char* filepath, std::uint8_t*& buffer, bool null_terminated=false) const;
int Find(const char* filepath) const;
int Insert(const char* filepath);
- void WriteMeta();
+ void WriteMeta(bool create=false);
void GenerateBlockMap();
std::size_t FindFreeSpot(std::size_t bytes) const;
void PrintNamesOfEntries() const;
@@ -43,7 +43,4 @@ private:
};
-Archive CreateEmpty(const char* path);
-
-
} // namespace ArchiveEx