5 #include "MpqArchive.h"
7 #include <fmt/format.h>
13 MpqArchive::MpqArchive(MpqArchive&& toMove) { *
this = std::move(toMove); }
15 MpqArchive& MpqArchive::operator=(MpqArchive&& toMove)
17 std::swap(mpqHandle, toMove.mpqHandle);
18 std::swap(mpqFileName, toMove.mpqFileName);
19 std::swap(_state, toMove._state);
22 MpqArchive::MpqArchive(
const char* MpqFileName,
const char* listFilePath) : mpqFileName(MpqFileName)
24 static_assert(std::is_same<MpqArchive::HANDLE, ::HANDLE>(),
25 "Make sure we correctly defined HANDLE type");
26 if (load() && listFilePath) {
27 addListFile(listFilePath);
31 MpqArchive::~MpqArchive() { unload(); }
33 void MpqArchive::addListFile(
const char* listFilePath)
35 if (!mpqHandle)
return;
36 if (SFileAddListFile(mpqHandle, listFilePath) != ERROR_SUCCESS) setstate(failbit);
39 std::vector<MpqArchive::Path> MpqArchive::findFiles(
const Path& searchMask)
41 if (!mpqHandle)
return {};
42 std::vector<Path> list;
43 SFILE_FIND_DATA findFileData;
44 HANDLE findHandle = SFileFindFirstFile(mpqHandle, searchMask.c_str(), &findFileData,
nullptr);
45 if (!findHandle)
return {};
48 list.emplace_back(findFileData.cFileName);
49 }
while (SFileFindNextFile(findHandle, &findFileData));
51 SFileFindClose(findHandle);
55 bool MpqArchive::load()
57 if (mpqHandle)
throw std::runtime_error(
"tried to reopen mpq archive");
58 if (!SFileOpenArchive(mpqFileName.c_str(), 0, STREAM_FLAG_READ_ONLY, &mpqHandle))
63 bool MpqArchive::is_loaded() {
return mpqHandle !=
nullptr; }
65 bool MpqArchive::unload()
67 if (!(mpqHandle && SFileCloseArchive(mpqHandle))) setstate(failbit);
72 bool MpqArchive::exists(
const Path& filePath) {
return SFileHasFile(mpqHandle, filePath.c_str()); }
74 StreamPtr MpqArchive::open(
const Path& filePath)
76 StreamPtr tmp = std::make_unique<MpqFileStream>(*
this, filePath);
77 return tmp->good() ? std::move(tmp) : nullptr;
80 MpqFileStream::MpqFileStream(MpqArchive& archive,
const Path& filename) { open(archive, filename); }
82 MpqFileStream::~MpqFileStream() { close(); }
84 bool MpqFileStream::open(MpqArchive& archive,
const Path& filename)
86 if (!archive || !SFileOpenFileEx(archive.getInternalHandle(), filename.c_str(), 0, &file))
91 bool MpqFileStream::close()
93 if (!(file && SFileCloseFile(file))) setstate(failbit);
102 bool success = SFileReadFile(file, buffer, static_cast<DWORD>(size), &readBytes,
nullptr);
104 const DWORD lastError = GetLastError();
105 if (lastError == ERROR_HANDLE_EOF) {
115 const DWORD
size = SFileSetFilePointer(file, 0,
nullptr, FILE_CURRENT);
116 if (size == SFILE_INVALID_SIZE) setstate(failbit);
117 return static_cast<long>(
size);
121 static_assert(MpqFileStream::beg == FILE_BEGIN,
"");
122 static_assert(MpqFileStream::cur == FILE_CURRENT,
"");
123 static_assert(MpqFileStream::end == FILE_END,
"");
126 if (SFileSetFilePointer(file, static_cast<LONG>(offset),
nullptr, origin) == SFILE_INVALID_SIZE)
133 DWORD sizeLower32bits = SFileGetFileSize(file,
nullptr);
134 if (sizeLower32bits == SFILE_INVALID_SIZE) setstate(failbit);
135 return static_cast<long>(sizeLower32bits);
bool seek(long offset, seekdir origin) override
long size() override
Compute the size of the file.
long tell() override
Return the current position of the stream pointer.
size_t read(void *buffer, size_t size) override
Read data from the stream.