quake-tools/source/common.h

169 lines
3.8 KiB
C++

#pragma once
#include <QtEndian>
#include <QtGlobal>
#include <QCoreApplication>
#include <QDebug>
#include <QMetaEnum>
#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <functional>
#include <ios>
#include <istream>
#include <iterator>
#include <optional>
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>
inline constexpr std::nullopt_t None{std::nullopt};
template<typename T>
using Option = std::optional<T>;
template<typename... Ts>
using Variant = std::variant<Ts...>;
template<typename T>
using UniquePtr = std::unique_ptr<T>;
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 FileSystemError : public Error {using Error::Error;};
struct UnimplementedError : public Error {using Error::Error;};
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())}
{
}
};
static inline QString trMain(char const *sourceText,
char const *disambiguation = nullptr,
int n = -1) {
return QCoreApplication::translate("main", sourceText, disambiguation, n);
}
static inline quint8 readByte(std::istream &st) {
char b;
st.read(&b, 1);
return quint8(b);
}
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);
}
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;
}
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();
}
template<typename T>
static inline T orThrow(Option<T> opt, Error err) {
if(opt) {
return *opt;
} else {
throw err;
}
}
static inline QDebug operator<<(QDebug debug, std::string const &t) {
debug << QString::fromStdString(t);
return debug;
}
template<typename T0, typename... Ts>
static inline QDebug operator<<(QDebug debug, Variant<T0, Ts...> const &t) {
std::visit([&](auto &&arg) {debug << arg;}, t);
return debug;
}
template<typename T>
static inline QDebug operator<<(QDebug debug, Option<T> const &t) {
if(t) {
debug << *t;
} else {
debug << "None";
}
return debug;
}
template<typename T>
static inline QDebug operator<<(QDebug debug, UniquePtr<T> const &t) {
if(t) {
debug << *t;
} else {
debug << "nullptr";
}
return debug;
}
// EOF