13 if (!std::filesystem::exists(path)) {
18 auto* oo7 =
new OO7{path};
19 auto packFile = std::unique_ptr<PackFile>(oo7);
21 FileStream reader{oo7->fullFilePath};
24 reader >> oo7->majorVersion >> oo7->minorVersion;
25 if (oo7->majorVersion != 1 || (oo7->minorVersion != 1 && oo7->minorVersion != 3)) {
30 std::vector<std::string> v3EntriesFixup;
33 std::function<void(
const std::string&,
bool)> readDir;
34 readDir = [&callback, &oo7, &reader, &v3EntriesFixup, &readDir](
const std::string& parentPath,
bool root) {
35 auto currentPath = parentPath +
'/' + reader.read_string(reader.read<uint32_t>(),
false);
39 auto subDirCount = reader.read<uint32_t>();
40 if (oo7->minorVersion == 3) {
41 reader.skip_in<uint32_t>();
44 auto filenameSize = reader.read<uint32_t>();
51 auto entryPath = oo7->cleanEntryPath(currentPath +
'/' + reader.read_string(filenameSize,
false));
53 bool compressed = reader.read<uint8_t>();
54 entry.
length = reader.read<uint32_t>();
58 reader.skip_in<uint32_t>();
61 if (oo7->minorVersion == 1) {
62 entry.
offset = reader.tell_in();
67 reader.skip_in(entry.
length);
70 v3EntriesFixup.push_back(entryPath);
73 oo7->entries.emplace(entryPath, entry);
76 callback(entryPath, entry);
79 for (uint32_t i = 0; i < subDirCount; i++) {
80 readDir(currentPath,
false);
85 for (
const auto& entryPath : v3EntriesFixup) {
86 auto& entry = oo7->entries.at(entryPath);
87 entry.offset = reader.tell_in();
88 if (!entry.compressedLength) {
89 reader.skip_in(entry.length);
91 reader.skip_in(entry.compressedLength);
98 if (oo7->minorVersion == 3 && reader.read<uint32_t>() == 16) {
99 oo7->hasChecksum =
true;
100 reader >> oo7->checksum;
129std::optional<std::vector<std::byte>>
OO7::readEntry(
const std::string& path_)
const {
135 if (entry->unbaked) {
144 stream.seek_in_u(entry->offset);
145 if (!entry->compressedLength) {
146 return stream.read_bytes(entry->length);
150 auto compressedData = stream.read_bytes(entry->compressedLength);
151 mz_ulong uncompressedLength = entry->length;
152 std::vector<std::byte> uncompressedData(uncompressedLength);
153 if (mz_uncompress(
reinterpret_cast<unsigned char*
>(uncompressedData.data()), &uncompressedLength,
reinterpret_cast<const unsigned char*
>(compressedData.data()), entry->compressedLength) != MZ_OK) {
156 return uncompressedData;
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 compressedLength
If the format supports compression, this is the compressed length.
uint64_t length
Length in bytes (in formats with compression, this is the uncompressed length)