14 if (!std::filesystem::exists(path)) {
19 auto* oo7 =
new OO7{path};
20 auto packFile = std::unique_ptr<PackFile>(oo7);
22 FileStream reader{oo7->fullFilePath};
25 reader >> oo7->majorVersion >> oo7->minorVersion;
26 if (oo7->majorVersion != 1 || (oo7->minorVersion != 1 && oo7->minorVersion != 3)) {
31 std::vector<std::string> v3EntriesFixup;
34 std::function<void(
const std::string&,
bool)> readDir;
35 readDir = [&callback, &oo7, &reader, &v3EntriesFixup, &readDir](
const std::string& parentPath,
bool root) {
36 auto currentPath = parentPath +
'/' + reader.read_string(reader.read<uint32_t>(),
false);
40 auto subDirCount = reader.read<uint32_t>();
41 if (oo7->minorVersion == 3) {
42 reader.skip_in<uint32_t>();
45 auto filenameSize = reader.read<uint32_t>();
52 auto entryPath = oo7->cleanEntryPath(currentPath +
'/' + reader.read_string(filenameSize,
false));
54 bool compressed = reader.read<uint8_t>();
55 entry.
length = reader.read<uint32_t>();
59 reader.skip_in<uint32_t>();
62 if (oo7->minorVersion == 1) {
63 entry.
offset = reader.tell_in();
68 reader.skip_in(entry.
length);
71 v3EntriesFixup.push_back(entryPath);
74 oo7->entries.emplace(entryPath, entry);
77 callback(entryPath, entry);
80 for (uint32_t i = 0; i < subDirCount; i++) {
81 readDir(currentPath,
false);
86 for (
const auto& entryPath : v3EntriesFixup) {
87 auto& entry = oo7->entries.at(entryPath);
88 entry.offset = reader.tell_in();
89 if (!entry.compressedLength) {
90 reader.skip_in(entry.length);
92 reader.skip_in(entry.compressedLength);
99 if (oo7->minorVersion == 3 && reader.read<uint32_t>() == 16) {
100 oo7->hasChecksum =
true;
101 reader >> oo7->checksum;
130std::optional<std::vector<std::byte>>
OO7::readEntry(
const std::string& path_)
const {
136 if (entry->unbaked) {
145 stream.seek_in_u(entry->offset);
146 if (!entry->compressedLength) {
147 return stream.read_bytes(entry->length);
151 auto compressedData = stream.read_bytes(entry->compressedLength);
152 mz_ulong uncompressedLength = entry->length;
153 std::vector<std::byte> uncompressedData(uncompressedLength);
154 if (mz_uncompress(
reinterpret_cast<unsigned char*
>(uncompressedData.data()), &uncompressedLength,
reinterpret_cast<const unsigned char*
>(compressedData.data()), entry->compressedLength) != MZ_OK) {
157 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).