diff --git a/source/common.h b/source/common.h index 2bda765..446c548 100644 --- a/source/common.h +++ b/source/common.h @@ -4,18 +4,20 @@ #include #include +#include #include #include #include #include #include -#include #include #include +#include #include #include #include +#include static inline QString trMain(char const *sourceText, char const *disambiguation = nullptr, @@ -44,33 +46,22 @@ static inline std::array readBytes(std::istream &st) { return std::move(b); } -template -static inline std::string escapeText(It begin, It end) { - std::stringstream out; - out << std::hex << std::uppercase; - for(auto it = begin; it != end; ++it) { - unsigned char c = *it; - switch(c) { - case '"': out << "\\\""; break; - case '\0': out << "\\0"; break; - case '\\': out << "\\\\"; break; - case '\a': out << "\\a"; break; - case '\b': out << "\\b"; break; - case '\f': out << "\\f"; break; - case '\n': out << "\\n"; break; - case '\r': out << "\\r"; break; - case '\t': out << "\\t"; break; - case '\v': out << "\\v"; break; - default: - if(c >= ' ' && c <= '~') { - out << c; - } else { - out << "\\x" << int(c); - } - break; - } - } - return out.str(); +static inline QDebug operator<<(QDebug debug, std::string const &t) { + debug << QString::fromStdString(t); + return debug; +} + +template +static inline QDebug operator<<(QDebug debug, std::unique_ptr const &t) { + debug << *t; + return debug; +} + +template +static inline QDebug operator <<(QDebug debug, + std::variant const &t) { + std::visit([&](auto &&arg) {debug << arg;}, t); + return debug; } // EOF diff --git a/source/quam/main.cc b/source/quam/main.cc index fbf2d5b..7feefc2 100644 --- a/source/quam/main.cc +++ b/source/quam/main.cc @@ -43,7 +43,7 @@ static int modeText(int argc, char *argv[]) { auto fileName = par.value(fileNameOpt).toStdString(); std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary}; - readPakFile(st); + auto pak = readPak(st); return 0; } diff --git a/source/quam/pak.cc b/source/quam/pak.cc index 609d429..06a71cb 100644 --- a/source/quam/pak.cc +++ b/source/quam/pak.cc @@ -8,7 +8,7 @@ struct PakHeader { struct PakEntry { std::string name; - QByteArray data; + PakFile data; }; static constexpr quint32 sizeOfPakEntry = 64; @@ -42,7 +42,7 @@ static PakEntry readPakEntry(std::istream &st) { st.seekg(entOffset); - QByteArray bytes; + PakFile bytes; bytes.resize(entSize); st.read(bytes.data(), entSize); @@ -50,27 +50,44 @@ static PakEntry readPakEntry(std::istream &st) { auto zero = std::find(entName.cbegin(), entName.cend(), '\0'); - std::string out; - std::copy(entName.cbegin(), zero, std::back_inserter(out)); + std::string name; + std::copy(entName.cbegin(), zero, std::back_inserter(name)); + + if(name.front() == '/') { + name.erase(0, 1); + } PakEntry ent; - ent.name = std::move(out); + ent.name = std::move(name); ent.data = std::move(bytes); return ent; } -PakFile readPakFile(std::istream &st) { +void insertFile(PakDir &dir, std::string name, PakFile file) { + if(auto slash = name.find('/'); slash != std::string::npos) { + auto folder = name.substr(0, slash); + auto next = name.substr(slash + 1); + dir[folder] = std::make_unique(PakDir{}); + insertFile(std::get(*dir[folder]), + std::move(next), + std::move(file)); + } else { + dir[name] = std::make_unique(std::move(file)); + } +} + +PakDir readPak(std::istream &st) { auto hdr = readPakHeader(st); st.seekg(hdr.dirOffset); - PakFile pak; + PakDir root; for(quint32 i = 0; i < hdr.dirNum; i++) { auto ent = readPakEntry(st); - pak.emplace(std::move(ent.name), std::move(ent.data)); + insertFile(root, std::move(ent.name), std::move(ent.data)); } - return pak; + return root; } // EOF diff --git a/source/quam/pak.h b/source/quam/pak.h index 66c9b9d..b6145aa 100644 --- a/source/quam/pak.h +++ b/source/quam/pak.h @@ -1,8 +1,19 @@ #pragma once -class PakFile : public std::map { +struct PakNode; + +struct PakDir : public std::map> { + using std::map>::map; }; -PakFile readPakFile(std::istream &st); +struct PakFile : public QByteArray { + using QByteArray::QByteArray; +}; + +struct PakNode : public std::variant { + using std::variant::variant; +}; + +PakDir readPak(std::istream &st); // EOF