10std::unique_ptr<PackFile>
PAK::create(
const std::string& path,
bool hrot) {
12 FileStream stream{path, FileStream::OPT_TRUNCATE | FileStream::OPT_CREATE_IF_NONEXISTENT};
22 if (!std::filesystem::exists(path)) {
27 auto* pak =
new PAK{path};
28 auto packFile = std::unique_ptr<PackFile>(pak);
30 FileStream reader{pak->fullFilePath};
33 if (
auto signature = reader.read<uint32_t>(); signature ==
PAK_SIGNATURE) {
42 auto directoryOffset = reader.read<uint32_t>();
44 auto fileCount = reader.read<uint32_t>() / (pak->isHROT() ? 128 : 64);
46 reader.seek_in(directoryOffset);
47 for (uint32_t i = 0; i < fileCount; i++) {
52 entry.
offset = reader.read<uint32_t>();
53 entry.
length = reader.read<uint32_t>();
55 pak->entries.emplace(entryPath, entry);
58 callback(entryPath, entry);
65std::optional<std::vector<std::byte>>
PAK::readEntry(
const std::string& path_)
const {
80 stream.seek_in_u(entry->offset);
81 return stream.read_bytes(entry->length);
85 entry.
length = buffer.size();
94 std::string outputPath = outputDir +
'/' + this->
getFilename();
97 std::vector<std::pair<std::string, Entry*>> entriesToBake;
99 entriesToBake.emplace_back(path, &entry);
103 std::vector<std::byte> fileData;
104 for (
auto& [path, entry] : entriesToBake) {
105 if (
auto binData = this->
readEntry(path)) {
106 entry->
offset = fileData.size();
108 fileData.insert(fileData.end(), binData->begin(), binData->end());
116 FileStream stream{outputPath, FileStream::OPT_TRUNCATE | FileStream::OPT_CREATE_IF_NONEXISTENT};
123 static constexpr uint32_t DIRECTORY_INDEX =
sizeof(
PAK_SIGNATURE) +
sizeof(uint32_t) * 2;
124 stream.write(DIRECTORY_INDEX);
125 const uint32_t directorySize = entriesToBake.size() * (this->
isHROT() ? 128 : 64);
126 stream.write(directorySize);
129 for (
const auto& [path, entry] : entriesToBake) {
131 stream.write(
static_cast<uint32_t
>(entry->
offset + DIRECTORY_INDEX + directorySize));
132 stream.write(
static_cast<uint32_t
>(entry->
length));
135 callback(path, *entry);
140 stream.write(fileData);
This class represents the metadata that a file has inside a PackFile.
uint64_t offset
Offset, format-specific meaning - 0 if unused, or if the offset genuinely is 0.
uint64_t length
Length in bytes (in formats with compression, this is the uncompressed length)
static std::unique_ptr< PackFile > open(const std::string &path, const EntryCallback &callback=nullptr)
Open a PAK file.
static std::unique_ptr< PackFile > create(const std::string &path, bool forHROT=false)
Create a PAK file.
std::optional< std::vector< std::byte > > readEntry(const std::string &path_) const override
Try to read the entry's data to a bytebuffer.
Attribute getSupportedEntryAttributes() const override
Returns a list of supported entry attributes Mostly for GUI programs that show entries and their meta...
void addEntryInternal(Entry &entry, const std::string &path, std::vector< std::byte > &buffer, EntryOptions options) override
bool bake(const std::string &outputDir_, BakeOptions options, const EntryCallback &callback) override
If output folder is an empty string, it will overwrite the original.
EntryCallbackBase< void > EntryCallback
void mergeUnbakedEntries()
std::optional< Entry > findEntry(const std::string &path_, bool includeUnbaked=true) const
Try to find an entry given the file path.
void runForAllEntriesInternal(const std::function< void(const std::string &, Entry &)> &operation, bool includeUnbaked=true)
std::string getFilename() const
/home/user/pak01_dir.vpk -> pak01_dir.vpk
std::string getBakeOutputDir(const std::string &outputDir) const
void setFullFilePath(const std::string &outputDir)
std::string cleanEntryPath(const std::string &path) const
static Entry createNewEntry()
static std::optional< std::vector< std::byte > > readUnbakedEntry(const Entry &entry)
constexpr auto PAK_HROT_SIGNATURE
constexpr int8_t PAK_FILENAME_MAX_SIZE
constexpr auto PAK_SIGNATURE
constexpr int8_t PAK_HROT_FILENAME_MAX_SIZE