Skip to content

Commit b31be1d

Browse files
feat(vpkpp): cache read-only pack file handles
1 parent 514a708 commit b31be1d

File tree

18 files changed

+341
-316
lines changed

18 files changed

+341
-316
lines changed

include/vpkpp/PackFile.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <unordered_map>
1111
#include <vector>
1212

13+
#include <FileStream.h>
1314
#include <sourcepp/math/Integer.h>
1415
#include <sourcepp/Macros.h>
1516
#include <tsl/htrie_map.h>
@@ -63,21 +64,21 @@ class PackFile {
6364

6465
/// Verify the checksums of each file, if a file fails the check its path will be added to the vector
6566
/// If there is no checksum ability in the format, it will return an empty vector
66-
[[nodiscard]] virtual std::vector<std::string> verifyEntryChecksums() const;
67+
[[nodiscard]] virtual std::vector<std::string> verifyEntryChecksums();
6768

6869
/// Returns true if the entire file has a checksum
6970
[[nodiscard]] virtual bool hasPackFileChecksum() const;
7071

7172
/// Verify the checksum of the entire file, returns true on success
7273
/// Will return true if there is no checksum ability in the format
73-
[[nodiscard]] virtual bool verifyPackFileChecksum() const;
74+
[[nodiscard]] virtual bool verifyPackFileChecksum();
7475

7576
/// Returns true if the file is signed
7677
[[nodiscard]] virtual bool hasPackFileSignature() const;
7778

7879
/// Verify the file signature, returns true on success
7980
/// Will return true if there is no signature ability in the format
80-
[[nodiscard]] virtual bool verifyPackFileSignature() const;
81+
[[nodiscard]] virtual bool verifyPackFileSignature();
8182

8283
/// Does the format support case-sensitive file names?
8384
[[nodiscard]] virtual constexpr bool isCaseSensitive() const noexcept {
@@ -91,10 +92,10 @@ class PackFile {
9192
[[nodiscard]] std::optional<Entry> findEntry(const std::string& path_, bool includeUnbaked = true) const;
9293

9394
/// Try to read the entry's data to a bytebuffer
94-
[[nodiscard]] virtual std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const = 0;
95+
[[nodiscard]] virtual std::optional<std::vector<std::byte>> readEntry(const std::string& path_) = 0;
9596

9697
/// Try to read the entry's data to a string
97-
[[nodiscard]] std::optional<std::string> readEntryText(const std::string& path) const;
98+
[[nodiscard]] std::optional<std::string> readEntryText(const std::string& path);
9899

99100
[[nodiscard]] virtual constexpr bool isReadOnly() const noexcept {
100101
return false;
@@ -131,16 +132,16 @@ class PackFile {
131132
virtual bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) = 0;
132133

133134
/// Extract the given entry to disk at the given file path
134-
bool extractEntry(const std::string& entryPath, const std::string& filepath) const; // NOLINT(*-use-nodiscard)
135+
bool extractEntry(const std::string& entryPath, const std::string& filepath); // NOLINT(*-use-nodiscard)
135136

136137
/// Extract the given directory to disk under the given output directory
137-
bool extractDirectory(const std::string& dir_, const std::string& outputDir) const; // NOLINT(*-use-nodiscard)
138+
bool extractDirectory(const std::string& dir_, const std::string& outputDir); // NOLINT(*-use-nodiscard)
138139

139140
/// Extract the contents of the pack file to disk at the given directory
140-
bool extractAll(const std::string& outputDir, bool createUnderPackFileDir = true) const; // NOLINT(*-use-nodiscard)
141+
bool extractAll(const std::string& outputDir, bool createUnderPackFileDir = true); // NOLINT(*-use-nodiscard)
141142

142143
/// Extract the contents of the pack file to disk at the given directory - only entries which match the predicate are extracted
143-
bool extractAll(const std::string& outputDir, const EntryPredicate& predicate, bool stripSharedDirs = true) const; // NOLINT(*-use-nodiscard)
144+
bool extractAll(const std::string& outputDir, const EntryPredicate& predicate, bool stripSharedDirs = true); // NOLINT(*-use-nodiscard)
144145

145146
/// Get entries saved to disk
146147
[[nodiscard]] const EntryTrie& getBakedEntries() const;
@@ -187,10 +188,14 @@ class PackFile {
187188
protected:
188189
explicit PackFile(std::string fullFilePath_);
189190

191+
[[nodiscard]] bool isReadHandleOpen() const;
192+
190193
void runForAllEntriesInternal(const std::function<void(const std::string&, Entry&)>& operation, bool includeUnbaked = true);
191194

192195
void runForAllEntriesInternal(const std::string& parentDir, const std::function<void(const std::string&, Entry&)>& operation, bool recursive = true, bool includeUnbaked = true);
193196

197+
[[nodiscard]] std::vector<std::string> verifyEntryChecksumsUsingCRC32();
198+
194199
[[nodiscard]] std::vector<std::string> verifyEntryChecksumsUsingCRC32() const;
195200

196201
virtual void addEntryInternal(Entry& entry, const std::string& path, std::vector<std::byte>& buffer, EntryOptions options) = 0;
@@ -214,6 +219,7 @@ class PackFile {
214219
static const OpenFactoryFunction& registerOpenExtensionForTypeFactory(std::string_view extension, const OpenFactoryFunction& factory);
215220

216221
std::string fullFilePath;
222+
std::optional<FileStream> readHandle;
217223

218224
PackFileType type = PackFileType::UNKNOWN;
219225

include/vpkpp/format/GCF.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ class GCF : public PackFileReadOnly {
116116
return true;
117117
}
118118

119-
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() const override;
119+
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() override;
120120

121-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
121+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
122122

123123
[[nodiscard]] Attribute getSupportedEntryAttributes() const override;
124124

include/vpkpp/format/GMA.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ class GMA : public PackFile {
3131
return true;
3232
}
3333

34-
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() const override;
34+
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() override;
3535

3636
[[nodiscard]] bool hasPackFileChecksum() const override;
3737

38-
[[nodiscard]] bool verifyPackFileChecksum() const override;
38+
[[nodiscard]] bool verifyPackFileChecksum() override;
3939

40-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
40+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
4141

4242
bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) override;
4343

include/vpkpp/format/PAK.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class PAK : public PackFile {
1818
/// Open a PAK file
1919
[[nodiscard]] static std::unique_ptr<PackFile> open(const std::string& path, const EntryCallback& callback = nullptr);
2020

21-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
21+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
2222

2323
bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) override;
2424

include/vpkpp/format/PCK.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class PCK : public PackFile {
3737
return true;
3838
}
3939

40-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
40+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
4141

4242
bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) override;
4343

include/vpkpp/format/VPK.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#pragma once
22

33
#include <array>
4-
#include <tuple>
54

65
#include "../PackFile.h"
76

@@ -75,17 +74,17 @@ class VPK : public PackFile {
7574
return true;
7675
}
7776

78-
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() const override;
77+
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() override;
7978

8079
[[nodiscard]] bool hasPackFileChecksum() const override;
8180

82-
[[nodiscard]] bool verifyPackFileChecksum() const override;
81+
[[nodiscard]] bool verifyPackFileChecksum() override;
8382

8483
[[nodiscard]] bool hasPackFileSignature() const override;
8584

86-
[[nodiscard]] bool verifyPackFileSignature() const override;
85+
[[nodiscard]] bool verifyPackFileSignature() override;
8786

88-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
87+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
8988

9089
bool removeEntry(const std::string& filename_) override;
9190

include/vpkpp/format/VPK_VTMB.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class VPK_VTMB : public PackFile {
1717
/// Open Vampire: The Masquerade - Bloodlines VPK files
1818
[[nodiscard]] static std::unique_ptr<PackFile> open(const std::string& path, const EntryCallback& callback = nullptr);
1919

20-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
20+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
2121

2222
bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) override;
2323

include/vpkpp/format/ZIP.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ class ZIP : public PackFile {
2727
return true;
2828
}
2929

30-
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() const override;
30+
[[nodiscard]] std::vector<std::string> verifyEntryChecksums() override;
3131

3232
[[nodiscard]] constexpr bool isCaseSensitive() const noexcept override {
3333
return true;
3434
}
3535

36-
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) const override;
36+
[[nodiscard]] std::optional<std::vector<std::byte>> readEntry(const std::string& path_) override;
3737

3838
bool bake(const std::string& outputDir_ /*= ""*/, BakeOptions options /*= {}*/, const EntryCallback& callback /*= nullptr*/) override;
3939

src/vpkpp/PackFile.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,23 @@ PackFileType PackFile::getType() const {
146146
return this->type;
147147
}
148148

149-
std::vector<std::string> PackFile::verifyEntryChecksums() const {
149+
std::vector<std::string> PackFile::verifyEntryChecksums() {
150150
return {};
151151
}
152152

153153
bool PackFile::hasPackFileChecksum() const {
154154
return false;
155155
}
156156

157-
bool PackFile::verifyPackFileChecksum() const {
157+
bool PackFile::verifyPackFileChecksum() {
158158
return true;
159159
}
160160

161161
bool PackFile::hasPackFileSignature() const {
162162
return false;
163163
}
164164

165-
bool PackFile::verifyPackFileSignature() const {
165+
bool PackFile::verifyPackFileSignature() {
166166
return true;
167167
}
168168

@@ -183,7 +183,7 @@ std::optional<Entry> PackFile::findEntry(const std::string& path_, bool includeU
183183
return std::nullopt;
184184
}
185185

186-
std::optional<std::string> PackFile::readEntryText(const std::string& path) const {
186+
std::optional<std::string> PackFile::readEntryText(const std::string& path) {
187187
auto bytes = this->readEntry(path);
188188
if (!bytes) {
189189
return std::nullopt;
@@ -358,7 +358,7 @@ std::size_t PackFile::removeDirectory(const std::string& dirName_) {
358358
return count;
359359
}
360360

361-
bool PackFile::extractEntry(const std::string& entryPath, const std::string& filepath) const {
361+
bool PackFile::extractEntry(const std::string& entryPath, const std::string& filepath) {
362362
if (filepath.empty()) {
363363
return false;
364364
}
@@ -377,7 +377,7 @@ bool PackFile::extractEntry(const std::string& entryPath, const std::string& fil
377377
return true;
378378
}
379379

380-
bool PackFile::extractDirectory(const std::string& dir_, const std::string& outputDir) const {
380+
bool PackFile::extractDirectory(const std::string& dir_, const std::string& outputDir) {
381381
auto dir = this->cleanEntryPath(dir_);
382382
dir += '/';
383383
if (dir == "/") {
@@ -402,7 +402,7 @@ bool PackFile::extractDirectory(const std::string& dir_, const std::string& outp
402402
return noneFailed;
403403
}
404404

405-
bool PackFile::extractAll(const std::string& outputDir, bool createUnderPackFileDir) const {
405+
bool PackFile::extractAll(const std::string& outputDir, bool createUnderPackFileDir) {
406406
if (outputDir.empty()) {
407407
return false;
408408
}
@@ -424,7 +424,7 @@ bool PackFile::extractAll(const std::string& outputDir, bool createUnderPackFile
424424
return noneFailed;
425425
}
426426

427-
bool PackFile::extractAll(const std::string& outputDir, const EntryPredicate& predicate, bool stripSharedDirs) const {
427+
bool PackFile::extractAll(const std::string& outputDir, const EntryPredicate& predicate, bool stripSharedDirs) {
428428
if (outputDir.empty() || !predicate) {
429429
return false;
430430
}
@@ -633,7 +633,11 @@ std::string PackFile::escapeEntryPathForWrite(const std::string& path) {
633633
#endif
634634
}
635635

636-
std::vector<std::string> PackFile::verifyEntryChecksumsUsingCRC32() const {
636+
bool PackFile::isReadHandleOpen() const {
637+
return this->readHandle && *this->readHandle;
638+
}
639+
640+
std::vector<std::string> PackFile::verifyEntryChecksumsUsingCRC32() {
637641
std::vector<std::string> out;
638642
this->runForAllEntries([this, &out](const std::string& path, const Entry& entry) {
639643
if (!entry.crc32) {

src/vpkpp/format/BSP.cpp

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ std::unique_ptr<PackFile> BSP::open(const std::string& path, const EntryCallback
3131
}
3232

3333
auto* bsp = new BSP{path};
34-
auto packFile = std::unique_ptr<PackFile>(bsp);
34+
auto packFile = std::unique_ptr<PackFile>{bsp};
3535

3636
if (!(*bsp)) {
3737
// File failed to load, or has an invalid signature
@@ -44,22 +44,7 @@ std::unique_ptr<PackFile> BSP::open(const std::string& path, const EntryCallback
4444
writer.write(*pakFileLump);
4545
} else {
4646
// No paklump, create an empty zip
47-
void* writeStreamHandle = mz_stream_os_create();
48-
if (mz_stream_os_open(writeStreamHandle, bsp->tempBSPPakLumpPath.c_str(), MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE)) {
49-
return nullptr;
50-
}
51-
void* writeZipHandle = mz_zip_writer_create();
52-
if (mz_zip_writer_open(writeZipHandle, writeStreamHandle, 0)) {
53-
return nullptr;
54-
}
55-
if (mz_zip_writer_close(writeZipHandle)) {
56-
return nullptr;
57-
}
58-
mz_zip_writer_delete(&writeZipHandle);
59-
if (mz_stream_os_close(writeStreamHandle)) {
60-
return nullptr;
61-
}
62-
mz_stream_os_delete(&writeStreamHandle);
47+
ZIP::create(bsp->tempBSPPakLumpPath);
6348
}
6449

6550
if (!bsp->openZIP(bsp->tempBSPPakLumpPath)) {

0 commit comments

Comments
 (0)