finish pak loader
This commit is contained in:
		
							parent
							
								
									0df35fc0c9
								
							
						
					
					
						commit
						e5cf9ec68c
					
				|  | @ -4,18 +4,20 @@ | ||||||
| #include <QtGlobal> | #include <QtGlobal> | ||||||
| 
 | 
 | ||||||
| #include <QCoreApplication> | #include <QCoreApplication> | ||||||
|  | #include <QDebug> | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <array> | #include <array> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| #include <ios> | #include <ios> | ||||||
| #include <iostream> |  | ||||||
| #include <istream> | #include <istream> | ||||||
| #include <iterator> | #include <iterator> | ||||||
|  | #include <memory> | ||||||
| #include <stdexcept> | #include <stdexcept> | ||||||
| #include <string> | #include <string> | ||||||
| #include <utility> | #include <utility> | ||||||
|  | #include <variant> | ||||||
| 
 | 
 | ||||||
| static inline QString trMain(char const *sourceText, | static inline QString trMain(char const *sourceText, | ||||||
|                              char const *disambiguation = nullptr, |                              char const *disambiguation = nullptr, | ||||||
|  | @ -44,33 +46,22 @@ static inline std::array<char, N> readBytes(std::istream &st) { | ||||||
| 	return std::move(b); | 	return std::move(b); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename It> | static inline QDebug operator<<(QDebug debug, std::string const &t) { | ||||||
| static inline std::string escapeText(It begin, It end) { | 	debug << QString::fromStdString(t); | ||||||
| 	std::stringstream out; | 	return debug; | ||||||
| 	out << std::hex << std::uppercase; | } | ||||||
| 	for(auto it = begin; it != end; ++it) { | 
 | ||||||
| 		unsigned char c = *it; | template<typename T> | ||||||
| 		switch(c) { | static inline QDebug operator<<(QDebug debug, std::unique_ptr<T> const &t) { | ||||||
| 			case '"':  out << "\\\""; break; | 	debug << *t; | ||||||
| 			case '\0': out << "\\0";  break; | 	return debug; | ||||||
| 			case '\\': out << "\\\\"; break; | } | ||||||
| 			case '\a': out << "\\a";  break; | 
 | ||||||
| 			case '\b': out << "\\b";  break; | template<typename T0, typename... Ts> | ||||||
| 			case '\f': out << "\\f";  break; | static inline QDebug operator <<(QDebug debug, | ||||||
| 			case '\n': out << "\\n";  break; |                                  std::variant<T0, Ts...> const &t) { | ||||||
| 			case '\r': out << "\\r";  break; | 	std::visit([&](auto &&arg) {debug << arg;}, t); | ||||||
| 			case '\t': out << "\\t";  break; | 	return debug; | ||||||
| 			case '\v': out << "\\v";  break; |  | ||||||
| 			default: |  | ||||||
| 				if(c >= ' ' && c <= '~') { |  | ||||||
| 					out << c; |  | ||||||
| 				} else { |  | ||||||
| 					out << "\\x" << int(c); |  | ||||||
| 				} |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return out.str(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // EOF
 | // EOF
 | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ static int modeText(int argc, char *argv[]) { | ||||||
| 
 | 
 | ||||||
| 	auto fileName = par.value(fileNameOpt).toStdString(); | 	auto fileName = par.value(fileNameOpt).toStdString(); | ||||||
| 	std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary}; | 	std::ifstream st{fileName, std::ios_base::in | std::ios_base::binary}; | ||||||
| 	readPakFile(st); | 	auto pak = readPak(st); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ struct PakHeader { | ||||||
| 
 | 
 | ||||||
| struct PakEntry { | struct PakEntry { | ||||||
| 	std::string name; | 	std::string name; | ||||||
| 	QByteArray  data; | 	PakFile     data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static constexpr quint32 sizeOfPakEntry = 64; | static constexpr quint32 sizeOfPakEntry = 64; | ||||||
|  | @ -42,7 +42,7 @@ static PakEntry readPakEntry(std::istream &st) { | ||||||
| 
 | 
 | ||||||
| 	st.seekg(entOffset); | 	st.seekg(entOffset); | ||||||
| 
 | 
 | ||||||
| 	QByteArray bytes; | 	PakFile bytes; | ||||||
| 	bytes.resize(entSize); | 	bytes.resize(entSize); | ||||||
| 	st.read(bytes.data(), 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'); | 	auto zero = std::find(entName.cbegin(), entName.cend(), '\0'); | ||||||
| 
 | 
 | ||||||
| 	std::string out; | 	std::string name; | ||||||
| 	std::copy(entName.cbegin(), zero, std::back_inserter(out)); | 	std::copy(entName.cbegin(), zero, std::back_inserter(name)); | ||||||
|  | 
 | ||||||
|  | 	if(name.front() == '/') { | ||||||
|  | 		name.erase(0, 1); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	PakEntry ent; | 	PakEntry ent; | ||||||
| 	ent.name = std::move(out); | 	ent.name = std::move(name); | ||||||
| 	ent.data = std::move(bytes); | 	ent.data = std::move(bytes); | ||||||
| 	return ent; | 	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<PakNode>(PakDir{}); | ||||||
|  | 		insertFile(std::get<PakDir>(*dir[folder]), | ||||||
|  | 		           std::move(next), | ||||||
|  | 		           std::move(file)); | ||||||
|  | 	} else { | ||||||
|  | 		dir[name] = std::make_unique<PakNode>(std::move(file)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PakDir readPak(std::istream &st) { | ||||||
| 	auto hdr = readPakHeader(st); | 	auto hdr = readPakHeader(st); | ||||||
| 	st.seekg(hdr.dirOffset); | 	st.seekg(hdr.dirOffset); | ||||||
| 
 | 
 | ||||||
| 	PakFile pak; | 	PakDir root; | ||||||
| 
 | 
 | ||||||
| 	for(quint32 i = 0; i < hdr.dirNum; i++) { | 	for(quint32 i = 0; i < hdr.dirNum; i++) { | ||||||
| 		auto ent = readPakEntry(st); | 		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
 | // EOF
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,19 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| class PakFile : public std::map<std::string, QByteArray> { | struct PakNode; | ||||||
|  | 
 | ||||||
|  | struct PakDir : public std::map<std::string, std::unique_ptr<PakNode>> { | ||||||
|  | 	using std::map<std::string, std::unique_ptr<PakNode>>::map; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PakFile readPakFile(std::istream &st); | struct PakFile : public QByteArray { | ||||||
|  | 	using QByteArray::QByteArray; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct PakNode : public std::variant<PakDir, PakFile> { | ||||||
|  | 	using std::variant<PakDir, PakFile>::variant; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PakDir readPak(std::istream &st); | ||||||
| 
 | 
 | ||||||
| // EOF
 | // EOF
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user