2019-09-27 00:09:09 -07:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <QtEndian>
|
|
|
|
#include <QtGlobal>
|
|
|
|
|
|
|
|
#include <QCoreApplication>
|
2019-09-27 23:09:51 -07:00
|
|
|
#include <QDebug>
|
2019-10-05 16:58:19 -07:00
|
|
|
#include <QMetaEnum>
|
2019-09-27 00:09:09 -07:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <array>
|
|
|
|
#include <filesystem>
|
|
|
|
#include <fstream>
|
|
|
|
#include <ios>
|
|
|
|
#include <istream>
|
|
|
|
#include <iterator>
|
2019-09-28 22:29:31 -07:00
|
|
|
#include <optional>
|
2019-09-27 00:09:09 -07:00
|
|
|
#include <stdexcept>
|
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
2019-09-27 23:09:51 -07:00
|
|
|
#include <variant>
|
2019-09-27 00:09:09 -07:00
|
|
|
|
2019-10-05 16:58:19 -07:00
|
|
|
inline constexpr std::nullopt_t None{std::nullopt};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using Option = std::optional<T>;
|
|
|
|
|
2019-10-08 20:43:35 -07:00
|
|
|
template<typename... Ts>
|
|
|
|
using Variant = std::variant<Ts...>;
|
|
|
|
|
2019-10-04 10:37:34 -07:00
|
|
|
struct Error : public std::runtime_error {
|
|
|
|
using std::runtime_error::runtime_error;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EnumError : public Error {using Error::Error;};
|
|
|
|
struct FileFormatError : public Error {using Error::Error;};
|
|
|
|
struct UnimplementedError : public Error {using Error::Error;};
|
|
|
|
|
2019-10-05 16:58:19 -07:00
|
|
|
struct MemoryStreamBuf : public std::streambuf {
|
|
|
|
MemoryStreamBuf(char *base, std::size_t size) {
|
|
|
|
setg(base, base, base + size);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IMemoryStream : public virtual MemoryStreamBuf, public std::istream {
|
|
|
|
IMemoryStream(char *base, std::size_t size) :
|
|
|
|
MemoryStreamBuf{base, size},
|
|
|
|
std::istream(static_cast<std::streambuf *>(this))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IMemoryStream(char const *base, std::size_t size) :
|
|
|
|
IMemoryStream{const_cast<char *>(base), size}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IMemoryStream(QByteArray &bytes) :
|
|
|
|
IMemoryStream{bytes.data(), std::size_t(bytes.size())}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IMemoryStream(QByteArray const &bytes) :
|
|
|
|
IMemoryStream{bytes.data(), std::size_t(bytes.size())}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-09-27 00:09:09 -07:00
|
|
|
static inline QString trMain(char const *sourceText,
|
|
|
|
char const *disambiguation = nullptr,
|
|
|
|
int n = -1) {
|
|
|
|
return QCoreApplication::translate("main", sourceText, disambiguation, n);
|
|
|
|
}
|
|
|
|
|
2019-10-03 14:06:05 -07:00
|
|
|
static inline quint8 readByte(std::istream &st) {
|
|
|
|
char b;
|
|
|
|
st.read(&b, 1);
|
|
|
|
return quint8(b);
|
|
|
|
}
|
|
|
|
|
2019-09-27 00:09:09 -07:00
|
|
|
template<typename T>
|
|
|
|
static inline T readLE(std::istream &st) {
|
|
|
|
std::array<char, sizeof(T)> b;
|
|
|
|
st.read(b.data(), b.size());
|
|
|
|
return qFromLittleEndian<T>(b.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static inline T readBE(std::istream &st) {
|
|
|
|
std::array<char, sizeof(T)> b;
|
|
|
|
st.read(b.data(), b.size());
|
|
|
|
return qFromBigEndian<T>(b.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<std::size_t N>
|
|
|
|
static inline std::array<char, N> readBytes(std::istream &st) {
|
|
|
|
std::array<char, N> b;
|
|
|
|
st.read(b.data(), b.size());
|
|
|
|
return std::move(b);
|
|
|
|
}
|
|
|
|
|
2019-10-04 10:37:34 -07:00
|
|
|
static inline std::ifstream openReadBin(std::filesystem::path path) {
|
|
|
|
return std::ifstream{path, std::ios_base::in | std::ios_base::binary};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<std::size_t N>
|
|
|
|
static inline std::string ntbsToString(std::array<char, N> const &ntbs) {
|
|
|
|
std::string str;
|
|
|
|
auto zero = std::find(ntbs.cbegin(), ntbs.cend(), '\0');
|
|
|
|
std::copy(ntbs.cbegin(), zero, std::back_inserter(str));
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2019-10-05 16:58:19 -07:00
|
|
|
template<typename T>
|
|
|
|
static inline char const *enumToString(T const t) {
|
|
|
|
return QMetaEnum::fromType<T>().valueToKey(int(t));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static inline int enumMax() {
|
|
|
|
return QMetaEnum::fromType<T>().keyCount();
|
|
|
|
}
|
|
|
|
|
2019-10-09 16:06:14 -07:00
|
|
|
template<typename T>
|
|
|
|
static inline T orThrow(Option<T> opt, Error err) {
|
|
|
|
if(opt) {
|
|
|
|
return *opt;
|
|
|
|
} else {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-27 23:09:51 -07:00
|
|
|
static inline QDebug operator<<(QDebug debug, std::string const &t) {
|
|
|
|
debug << QString::fromStdString(t);
|
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
|
2019-10-08 20:43:35 -07:00
|
|
|
template<typename T0, typename... Ts>
|
|
|
|
static inline QDebug operator<<(QDebug debug, Variant<T0, Ts...> const &t) {
|
|
|
|
std::visit([&](auto &&arg) {debug << arg;}, t);
|
2019-09-27 23:09:51 -07:00
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
|
2019-10-08 20:43:35 -07:00
|
|
|
template<typename T>
|
|
|
|
static inline QDebug operator<<(QDebug debug, Option<T> const &t) {
|
|
|
|
if(t) {
|
|
|
|
debug << *t;
|
|
|
|
} else {
|
|
|
|
debug << "None";
|
|
|
|
}
|
2019-09-27 23:09:51 -07:00
|
|
|
return debug;
|
2019-09-27 00:09:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// EOF
|