#include "quam/pack.h" static constexpr quint32 sizeOfPackEntry = 64; static std::pair readPackHeader(std::istream &st) { auto magic = readBytes<4>(st); if(magic != std::array{'P', 'A', 'C', 'K'}) { throw FileFormatError("not a pak file (invalid magic number)"); } auto dirOffset = readLE(st); auto dirSize = readLE(st); if(dirSize % sizeOfPackEntry != 0) { throw FileFormatError("invalid directory size"); } return std::make_pair(dirOffset, dirSize / sizeOfPackEntry); } static Arc::File readPackEntry(std::istream &st) { auto entName = readBytes<56>(st); auto entOffset = readLE(st); auto entSize = readLE(st); if(entName.front() == '/') { throw FileFormatError("empty root directory name"); } auto pos = st.tellg(); st.seekg(entOffset); QByteArray data; data.resize(entSize); st.read(data.data(), entSize); st.seekg(pos); return Arc::File{ntbsToString(entName), std::move(data)}; } static void insertFile(Arc::Dir &dir, Arc::File &file, std::string name) { Option next; if(auto slash = name.find('/'); slash != std::string::npos) { next = name.substr(slash + 1); name = name.substr(0, slash); } auto existing = dir.findNode(name); if(next) { Arc::Node *ref; if(existing) { ref = existing; } else { ref = new Arc::Dir(name); dir.emplaceBack(ref); } insertFile(*ref->getDir(), file, *next); } else if(!existing) { file.name = name; file.parent = &dir; dir.emplaceBack(new Arc::File(std::move(file))); } else { throw FileFormatError("duplicate file"); } } Arc::Dir readPack(std::istream &st) { auto hdr = readPackHeader(st); st.seekg(hdr.first); Arc::Dir root{std::string{}}; for(quint32 i = 0; i < hdr.second; i++) { auto file = readPackEntry(st); insertFile(root, file, file.name); } return root; } PackValidator::PackValidator(QObject *parent) : QValidator{parent} { } QValidator::State PackValidator::validate(QString &input, int &pos) const { return QValidator::Acceptable; } // EOF