11 if (!std::filesystem::exists(path)) {
16 auto* rez =
new REZ{path};
17 auto packFile = std::unique_ptr<PackFile>(rez);
19 FileStream reader{rez->fullFilePath};
22 if (
const auto c = reader.read<uint8_t>(); c !=
'\r' && c !=
'&') {
25 if (
const auto c = reader.read<uint8_t>(); c !=
'\n' && c !=
'#') {
28 reader.read(rez->fileType, 60,
false);
31 if (
const auto c = reader.read<uint8_t>(); c !=
'\r' && c !=
'!') {
34 if (
const auto c = reader.read<uint8_t>(); c !=
'\n' && c !=
'\"') {
37 reader.read(rez->userTitle, 60,
false);
40 if (
const auto c = reader.read<uint8_t>(); c !=
'\r' && c !=
'%') {
43 if (
const auto c = reader.read<uint8_t>(); c !=
'\n' && c !=
'\'') {
46 rez->version = reader.read<uint8_t>();
48 switch (rez->version) {
50 reader.read(rez->version);
51 if (rez->version != 1) {
52 reader.skip_in(7).read(rez->version);
53 if (rez->version != 2) {
59 reader.skip_in(68).read(rez->version);
60 if (rez->version != 1) {
68 const auto rootDirOffset = reader.read<uint32_t>();
69 const auto rootDirSize = reader.read<uint32_t>();
70 reader.skip_in<uint32_t>();
71 reader.skip_in<uint32_t>();
72 reader.skip_in<uint32_t>();
73 reader.skip_in<uint32_t>();
74 reader.skip_in<uint32_t>();
75 reader.skip_in<uint32_t>();
76 reader.skip_in<uint32_t>();
77 reader.skip_in<uint8_t>();
80 std::function<bool(
const std::string&, std::span<const std::byte>)> readBlock;
81 readBlock = [&callback, &rez, &reader, &readBlock](
const std::string& parentPath, std::span<const std::byte> blockData) {
82 BufferStreamReadOnly blockStream{blockData.data(), blockData.size()};
84 while (blockStream.tell() != blockStream.size()) {
85 const auto blockType = blockStream.read<uint32_t>();
86 const auto blockOffset = blockStream.read<uint32_t>();
87 const auto blockLength = blockStream.read<uint32_t>();
88 blockStream.skip<uint32_t>();
95 blockStream.skip<uint32_t>();
96 auto resourceExtension = blockStream.read_string(4);
97 const auto resourceKeyCount = blockStream.read<uint32_t>();
98 const auto resourceName = blockStream.read_string();
99 const auto resourceDesc = blockStream.read_string();
100 blockStream.skip<uint32_t>(resourceKeyCount);
102 auto entryPath = parentPath;
103 entryPath +=
'/' + resourceName;
104 if (!resourceExtension.empty()) {
105 std::ranges::reverse(resourceExtension);
106 entryPath +=
'.' + resourceExtension;
108 entryPath = rez->cleanEntryPath(entryPath);
110 entry.
length = blockLength;
111 entry.
offset = blockOffset;
113 rez->entries.emplace(entryPath, entry);
116 callback(entryPath, entry);
118 }
else if (blockType == 1) {
120 const auto dirName = blockStream.read_string();
122 std::string newParentPath;
123 if (!parentPath.empty()) {
124 newParentPath = parentPath;
125 newParentPath +=
'/' + dirName;
127 newParentPath = dirName;
129 readBlock(newParentPath, reader.seek_in(blockOffset).read_bytes(blockLength));
138 if (!readBlock(
"", reader.seek_in(rootDirOffset).read_bytes(rootDirSize))) {
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).