athena/include/athena/DNAOp.hpp

1188 lines
70 KiB
C++

#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <type_traits>
#include <vector>
#include "athena/ChecksumsLiterals.hpp"
#include "athena/IStreamReader.hpp"
#include "athena/IStreamWriter.hpp"
#include "athena/YAMLDocReader.hpp"
#include "athena/YAMLDocWriter.hpp"
namespace athena::io {
struct PropId {
std::string_view name;
uint32_t rcrc32 = 0xffffffff;
uint64_t crc64 = 0x0;
template <class T>
constexpr T opget() const;
constexpr PropId() = default;
constexpr explicit PropId(std::string_view name, uint32_t rcrc32, uint64_t crc64)
: name(name), rcrc32(rcrc32), crc64(crc64) {}
constexpr explicit PropId(std::string_view name)
: name(name)
, rcrc32(athena::checksums::literals::rcrc32_rec(0xFFFFFFFF, name.data()))
, crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name.data())) {}
constexpr PropId(std::string_view name, uint32_t rcrc32)
: name(name), rcrc32(rcrc32), crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name.data())) {}
};
template <>
constexpr uint32_t PropId::opget<uint32_t>() const {
return rcrc32;
}
template <>
constexpr uint64_t PropId::opget<uint64_t>() const {
return crc64;
}
namespace literals {
constexpr PropId operator"" _propid(const char* s, size_t len) { return PropId{s}; }
} // namespace literals
#define AT_PROP_CASE(...) case athena::io::PropId(__VA_ARGS__).opget<typename Op::PropT>()
#if defined(__atdna__)
#define AT_OVERRIDE_RCRC32(rcrc32) __attribute__((annotate("rcrc32=" #rcrc32)))
#else
#define AT_OVERRIDE_RCRC32(rcrc32)
#endif
#if defined(__atdna__)
#define AT_SPECIALIZE_PARMS(...) __attribute__((annotate("specparms=" #__VA_ARGS__)))
#else
#define AT_SPECIALIZE_PARMS(...)
#endif
enum class PropType { None, CRC32, CRC64 };
template <class T>
using __IsPODType = std::disjunction<
std::is_arithmetic<std::remove_cv_t<T>>, std::is_convertible<std::remove_cv_t<T>&, atVec2f&>,
std::is_convertible<std::remove_cv_t<T>&, atVec3f&>, std::is_convertible<std::remove_cv_t<T>&, atVec4f&>,
std::is_convertible<std::remove_cv_t<T>&, atVec2d&>, std::is_convertible<std::remove_cv_t<T>&, atVec3d&>,
std::is_convertible<std::remove_cv_t<T>&, atVec4d&>>;
template <class T>
constexpr bool __IsPODType_v = __IsPODType<T>::value;
template <class T>
using __CastPODType = std::conditional_t<
std::is_convertible_v<std::remove_cv_t<T>&, atVec2f&>, atVec2f,
std::conditional_t<
std::is_convertible_v<std::remove_cv_t<T>&, atVec3f&>, atVec3f,
std::conditional_t<
std::is_convertible_v<std::remove_cv_t<T>&, atVec4f&>, atVec4f,
std::conditional_t<
std::is_convertible_v<std::remove_cv_t<T>&, atVec2d&>, atVec2d,
std::conditional_t<std::is_convertible_v<std::remove_cv_t<T>&, atVec3d&>, atVec3d,
std::conditional_t<std::is_convertible_v<std::remove_cv_t<T>&, atVec4d&>, atVec4d,
std::remove_cv_t<T>>>>>>>;
template <Endian DNAE>
uint16_t __Read16(IStreamReader& r) {
return DNAE == Endian::Big ? r.readUint16Big() : r.readUint16Little();
}
template <Endian DNAE>
void __Write16(IStreamWriter& w, uint16_t v) {
DNAE == Endian::Big ? w.writeUint16Big(v) : w.writeUint16Little(v);
}
template <Endian DNAE>
uint32_t __Read32(IStreamReader& r) {
return DNAE == Endian::Big ? r.readUint32Big() : r.readUint32Little();
}
template <Endian DNAE>
void __Write32(IStreamWriter& w, uint32_t v) {
DNAE == Endian::Big ? w.writeUint32Big(v) : w.writeUint32Little(v);
}
template <Endian DNAE>
uint64_t __Read64(IStreamReader& r) {
return DNAE == Endian::Big ? r.readUint64Big() : r.readUint64Little();
}
template <Endian DNAE>
void __Write64(IStreamWriter& w, uint64_t v) {
DNAE == Endian::Big ? w.writeUint64Big(v) : w.writeUint64Little(v);
}
template <PropType PropOp>
struct BinarySize {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = size_t;
template <class T, Endian DNAE>
static std::enable_if_t<std::is_enum_v<T>> Do(const PropId& id, T& var, StreamT& s) {
if (PropOp != PropType::None) {
/* Accessed via Enumerate, header */
s += 6;
}
using PODType = std::underlying_type_t<T>;
BinarySize<PropType::None>::Do<PODType, DNAE>(id, *reinterpret_cast<PODType*>(&var), s);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsPODType_v<T>> Do(const PropId& id, T& var, StreamT& s) {
if (PropOp != PropType::None) {
/* Accessed via Enumerate, header */
s += 6;
}
using CastT = __CastPODType<T>;
BinarySize<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(const_cast<std::remove_cv_t<T>&>(var)), s);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord_v<T> && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& s) {
/* Accessed via Enumerate, header */
s += 6;
var.template Enumerate<BinarySize<PropOp>>(s);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord_v<T> && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& s) {
var.template Enumerate<BinarySize<PropType::None>>(s);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_array_v<T>> Do(const PropId& id, T& var, StreamT& s) {
for (auto& v : var) {
BinarySize<PropOp>::template Do<std::remove_reference_t<decltype(v)>, DNAE>(id, v, s);
}
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
BinarySize<PropOp>::template Do<T, DNAE>(id, var, s);
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<!std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& s) {
for (T& v : vector) {
BinarySize<PropOp>::template Do<T, DNAE>(id, v, s);
}
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& s) {
/* libc++ specializes vector<bool> as a bitstream */
s += vector.size();
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& s) {
if (buf)
s += count;
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, T& str, StreamT& s) {
s += str.size() + 1;
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) {
if (count < 0)
s += str.size() + 1;
else
s += count;
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, T& str, StreamT& s) {
s += str.size() * 2 + 2;
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) {
if (count < 0)
s += str.size() * 2 + 2;
else
s += count * 2;
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) {
switch (whence) {
case SeekOrigin::Begin:
s = amount;
break;
case SeekOrigin::Current:
s += amount;
break;
default:
break;
}
}
static void DoAlign(atInt64 amount, StreamT& s) { s = (s + amount - 1) / amount * amount; }
};
#define __BINARY_SIZE_S(type, endian) \
template <> \
template <> \
inline void BinarySize<PropType::None>::Do<type, endian>(const PropId& id, type& var, BinarySize::StreamT& s)
__BINARY_SIZE_S(bool, Endian::Big) { s += 1; }
__BINARY_SIZE_S(atInt8, Endian::Big) { s += 1; }
__BINARY_SIZE_S(atUint8, Endian::Big) { s += 1; }
__BINARY_SIZE_S(atInt16, Endian::Big) { s += 2; }
__BINARY_SIZE_S(atUint16, Endian::Big) { s += 2; }
__BINARY_SIZE_S(atInt32, Endian::Big) { s += 4; }
__BINARY_SIZE_S(atUint32, Endian::Big) { s += 4; }
__BINARY_SIZE_S(atInt64, Endian::Big) { s += 8; }
__BINARY_SIZE_S(atUint64, Endian::Big) { s += 8; }
__BINARY_SIZE_S(float, Endian::Big) { s += 4; }
__BINARY_SIZE_S(double, Endian::Big) { s += 8; }
__BINARY_SIZE_S(atVec2f, Endian::Big) { s += 8; }
__BINARY_SIZE_S(atVec2d, Endian::Big) { s += 16; }
__BINARY_SIZE_S(atVec3f, Endian::Big) { s += 12; }
__BINARY_SIZE_S(atVec3d, Endian::Big) { s += 24; }
__BINARY_SIZE_S(atVec4f, Endian::Big) { s += 16; }
__BINARY_SIZE_S(atVec4d, Endian::Big) { s += 32; }
__BINARY_SIZE_S(bool, Endian::Little) { s += 1; }
__BINARY_SIZE_S(atInt8, Endian::Little) { s += 1; }
__BINARY_SIZE_S(atUint8, Endian::Little) { s += 1; }
__BINARY_SIZE_S(atInt16, Endian::Little) { s += 2; }
__BINARY_SIZE_S(atUint16, Endian::Little) { s += 2; }
__BINARY_SIZE_S(atInt32, Endian::Little) { s += 4; }
__BINARY_SIZE_S(atUint32, Endian::Little) { s += 4; }
__BINARY_SIZE_S(atInt64, Endian::Little) { s += 8; }
__BINARY_SIZE_S(atUint64, Endian::Little) { s += 8; }
__BINARY_SIZE_S(float, Endian::Little) { s += 4; }
__BINARY_SIZE_S(double, Endian::Little) { s += 8; }
__BINARY_SIZE_S(atVec2f, Endian::Little) { s += 8; }
__BINARY_SIZE_S(atVec2d, Endian::Little) { s += 16; }
__BINARY_SIZE_S(atVec3f, Endian::Little) { s += 12; }
__BINARY_SIZE_S(atVec3d, Endian::Little) { s += 24; }
__BINARY_SIZE_S(atVec4f, Endian::Little) { s += 16; }
__BINARY_SIZE_S(atVec4d, Endian::Little) { s += 32; }
template <PropType PropOp>
struct PropCount {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = size_t;
template <class T, Endian DNAE>
static void Do(const PropId& id, T& var, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
PropCount<PropOp>::template Do<T, DNAE>(id, var, s);
}
template <class T, class S, Endian DNAE>
static void Do(const PropId& id, std::vector<T>& vector, const S& count, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, T& str, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, T& str, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& s) {
/* Only reports one level of properties */
s += 1;
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& s) {}
static void DoAlign(atInt64 amount, StreamT& s) {}
};
template <PropType PropOp>
struct Read {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = IStreamReader;
template <class T, Endian DNAE>
static std::enable_if_t<std::is_enum_v<T>> Do(const PropId& id, T& var, StreamT& r) {
using PODType = std::underlying_type_t<T>;
Read<PropType::None>::Do<PODType, DNAE>(id, *reinterpret_cast<PODType*>(&var), r);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsPODType_v<T>> Do(const PropId& id, T& var, StreamT& r) {
using CastT = __CastPODType<T>;
Read<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(var), r);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord<T>() && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& r) {
var.template Enumerate<Read<PropType::None>>(r);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord<T>() && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& r) {
/* Accessed via Lookup, no header */
atUint16 propCount = __Read16<T::DNAEndian>(r);
for (atUint32 i = 0; i < propCount; ++i) {
atUint64 hash;
if (PropOp == PropType::CRC64)
hash = __Read64<T::DNAEndian>(r);
else
hash = __Read32<T::DNAEndian>(r);
atInt64 size = __Read16<T::DNAEndian>(r);
atInt64 start = r.position();
var.template Lookup<Read<PropOp>>(hash, r);
atInt64 actualRead = r.position() - start;
if (actualRead != size)
r.seek(size - actualRead);
}
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_array_v<T>> Do(const PropId& id, T& var, StreamT& s) {
for (auto& v : var) {
Read<PropOp>::template Do<std::remove_reference_t<decltype(v)>, DNAE>(id, v, s);
}
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
Read<PropOp>::template Do<T, DNAE>(id, var, s);
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<!std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& r) {
vector.clear();
vector.reserve(count);
for (size_t i = 0; i < static_cast<size_t>(count); ++i) {
vector.emplace_back();
Read<PropOp>::template Do<T, DNAE>(id, vector.back(), r);
}
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& r) {
/* libc++ specializes vector<bool> as a bitstream */
vector.clear();
vector.reserve(count);
for (size_t i = 0; i < count; ++i)
vector.push_back(r.readBool());
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& r) {
buf.reset(new atUint8[count]);
r.readUBytesToBuf(buf.get(), count);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, T& str, StreamT& r) {
str = r.readString();
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(count); }
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, T& str, StreamT& r) {
Read<PropType::None>::Do<DNAE>(id, str, r);
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) {
Read<PropType::None>::Do<DNAE>(id, str, count, r);
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) { r.seek(amount, whence); }
static void DoAlign(atInt64 amount, StreamT& r) {
r.seek((r.position() + amount - 1) / amount * amount, athena::SeekOrigin::Begin);
}
};
#define __READ_S(type, endian) \
template <> \
template <> \
inline void Read<PropType::None>::Do<type, endian>(const PropId& id, type& var, Read::StreamT& r)
#define __READ_WSTR_S(endian) \
template <> \
template <> \
inline void Read<PropType::None>::Do<std::wstring, endian>(const PropId& id, std::wstring& str, Read::StreamT& r)
#define __READ_WSTRC_S(endian) \
template <> \
template <> \
inline void Read<PropType::None>::Do<endian>(const PropId& id, std::wstring& str, atInt32 count, Read::StreamT& r)
__READ_S(bool, Endian::Big) { var = r.readBool(); }
__READ_S(atInt8, Endian::Big) { var = r.readByte(); }
__READ_S(atUint8, Endian::Big) { var = r.readUByte(); }
__READ_S(atInt16, Endian::Big) { var = r.readInt16Big(); }
__READ_S(atUint16, Endian::Big) { var = r.readUint16Big(); }
__READ_S(atInt32, Endian::Big) { var = r.readInt32Big(); }
__READ_S(atUint32, Endian::Big) { var = r.readUint32Big(); }
__READ_S(atInt64, Endian::Big) { var = r.readInt64Big(); }
__READ_S(atUint64, Endian::Big) { var = r.readUint64Big(); }
__READ_S(float, Endian::Big) { var = r.readFloatBig(); }
__READ_S(double, Endian::Big) { var = r.readDoubleBig(); }
__READ_S(atVec2f, Endian::Big) { var = r.readVec2fBig(); }
__READ_S(atVec2d, Endian::Big) { var = r.readVec2dBig(); }
__READ_S(atVec3f, Endian::Big) { var = r.readVec3fBig(); }
__READ_S(atVec3d, Endian::Big) { var = r.readVec3dBig(); }
__READ_S(atVec4f, Endian::Big) { var = r.readVec4fBig(); }
__READ_S(atVec4d, Endian::Big) { var = r.readVec4dBig(); }
__READ_WSTR_S(Endian::Big) { str = r.readWStringBig(); }
__READ_WSTRC_S(Endian::Big) { str = r.readWStringBig(count); }
__READ_S(bool, Endian::Little) { var = r.readBool(); }
__READ_S(atInt8, Endian::Little) { var = r.readByte(); }
__READ_S(atUint8, Endian::Little) { var = r.readUByte(); }
__READ_S(atInt16, Endian::Little) { var = r.readInt16Little(); }
__READ_S(atUint16, Endian::Little) { var = r.readUint16Little(); }
__READ_S(atInt32, Endian::Little) { var = r.readInt32Little(); }
__READ_S(atUint32, Endian::Little) { var = r.readUint32Little(); }
__READ_S(atInt64, Endian::Little) { var = r.readInt64Little(); }
__READ_S(atUint64, Endian::Little) { var = r.readUint64Little(); }
__READ_S(float, Endian::Little) { var = r.readFloatLittle(); }
__READ_S(double, Endian::Little) { var = r.readDoubleLittle(); }
__READ_S(atVec2f, Endian::Little) { var = r.readVec2fLittle(); }
__READ_S(atVec2d, Endian::Little) { var = r.readVec2dLittle(); }
__READ_S(atVec3f, Endian::Little) { var = r.readVec3fLittle(); }
__READ_S(atVec3d, Endian::Little) { var = r.readVec3dLittle(); }
__READ_S(atVec4f, Endian::Little) { var = r.readVec4fLittle(); }
__READ_S(atVec4d, Endian::Little) { var = r.readVec4dLittle(); }
__READ_WSTR_S(Endian::Little) { str = r.readWStringLittle(); }
__READ_WSTRC_S(Endian::Little) { str = r.readWStringLittle(count); }
template <PropType PropOp>
struct Write {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = IStreamWriter;
template <class T, Endian DNAE>
static std::enable_if_t<std::is_enum_v<T>> Do(const PropId& id, T& var, StreamT& w) {
if (PropOp != PropType::None) {
/* Accessed via Enumerate, header */
if (PropOp == PropType::CRC64)
__Write64<DNAE>(w, id.crc64);
else
__Write32<DNAE>(w, id.rcrc32);
size_t binarySize = 0;
BinarySize<PropType::None>::Do<T, DNAE>(id, var, binarySize);
DNAE == Endian::Big ? w.writeUint16Big(atUint16(binarySize)) : w.writeUint16Little(atUint16(binarySize));
}
using PODType = std::underlying_type_t<T>;
Write<PropType::None>::Do<PODType, DNAE>(id, *reinterpret_cast<PODType*>(&var), w);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsPODType_v<T>> Do(const PropId& id, T& var, StreamT& w) {
using CastT = __CastPODType<T>;
if (PropOp != PropType::None) {
/* Accessed via Enumerate, header */
if (PropOp == PropType::CRC64)
__Write64<DNAE>(w, id.crc64);
else
__Write32<DNAE>(w, id.rcrc32);
size_t binarySize = 0;
BinarySize<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(const_cast<std::remove_cv_t<T>&>(var)),
binarySize);
__Write16<DNAE>(w, atUint16(binarySize));
}
Write<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(const_cast<std::remove_cv_t<T>&>(var)), w);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord<T>() && PropOp != PropType::None> Do(const PropId& id, T& var, StreamT& w) {
/* Accessed via Enumerate, header */
if (PropOp == PropType::CRC64)
__Write64<T::DNAEndian>(w, id.crc64);
else
__Write32<T::DNAEndian>(w, id.rcrc32);
size_t binarySize = 0;
var.template Enumerate<BinarySize<PropOp>>(binarySize);
__Write16<T::DNAEndian>(w, atUint16(binarySize));
size_t propCount = 0;
var.template Enumerate<PropCount<PropOp>>(propCount);
__Write16<T::DNAEndian>(w, atUint16(propCount));
var.template Enumerate<Write<PropOp>>(w);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord<T>() && PropOp == PropType::None> Do(const PropId& id, T& var, StreamT& w) {
var.template Enumerate<Write<PropType::None>>(w);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_array_v<T>> Do(const PropId& id, T& var, StreamT& s) {
for (auto& v : var) {
Write<PropOp>::template Do<std::remove_reference_t<decltype(v)>, DNAE>(id, v, s);
}
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
Write<PropOp>::template Do<T, DNAE>(id, var, s);
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<!std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& w) {
for (T& v : vector) {
Write<PropOp>::template Do<T, DNAE>(id, v, w);
}
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& w) {
/* libc++ specializes vector<bool> as a bitstream */
for (const T v : vector)
w.writeBool(v);
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& w) {
if (buf)
w.writeUBytes(buf.get(), count);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, std::string& str, StreamT& w) {
w.writeString(str);
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(str, count); }
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, std::wstring& str, StreamT& w) {
Write<PropType::None>::Do<DNAE>(id, str, w);
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) {
Write<PropType::None>::Do<DNAE>(id, str, count, w);
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) { w.seek(amount, whence); }
static void DoAlign(atInt64 amount, StreamT& w) { w.writeZeroTo((w.position() + amount - 1) / amount * amount); }
};
#define __WRITE_S(type, endian) \
template <> \
template <> \
inline void Write<PropType::None>::Do<type, endian>(const PropId& id, type& var, Write::StreamT& w)
#define __WRITE_WSTR_S(endian) \
template <> \
template <> \
inline void Write<PropType::None>::Do<std::wstring, endian>(const PropId& id, std::wstring& str, Write::StreamT& w)
#define __WRITE_WSTRC_S(endian) \
template <> \
template <> \
inline void Write<PropType::None>::Do<endian>(const PropId& id, std::wstring& str, atInt32 count, Write::StreamT& w)
__WRITE_S(bool, Endian::Big) { w.writeBool(var); }
__WRITE_S(atInt8, Endian::Big) { w.writeByte(var); }
__WRITE_S(atUint8, Endian::Big) { w.writeUByte(var); }
__WRITE_S(atInt16, Endian::Big) { w.writeInt16Big(var); }
__WRITE_S(atUint16, Endian::Big) { w.writeUint16Big(var); }
__WRITE_S(atInt32, Endian::Big) { w.writeInt32Big(var); }
__WRITE_S(atUint32, Endian::Big) { w.writeUint32Big(var); }
__WRITE_S(atInt64, Endian::Big) { w.writeInt64Big(var); }
__WRITE_S(atUint64, Endian::Big) { w.writeUint64Big(var); }
__WRITE_S(float, Endian::Big) { w.writeFloatBig(var); }
__WRITE_S(double, Endian::Big) { w.writeDoubleBig(var); }
__WRITE_S(atVec2f, Endian::Big) { w.writeVec2fBig(var); }
__WRITE_S(atVec2d, Endian::Big) { w.writeVec2dBig(var); }
__WRITE_S(atVec3f, Endian::Big) { w.writeVec3fBig(var); }
__WRITE_S(atVec3d, Endian::Big) { w.writeVec3dBig(var); }
__WRITE_S(atVec4f, Endian::Big) { w.writeVec4fBig(var); }
__WRITE_S(atVec4d, Endian::Big) { w.writeVec4dBig(var); }
__WRITE_WSTR_S(Endian::Big) { w.writeWStringBig(str); }
__WRITE_WSTRC_S(Endian::Big) { w.writeWStringBig(str, count); }
__WRITE_S(bool, Endian::Little) { w.writeBool(var); }
__WRITE_S(atInt8, Endian::Little) { w.writeByte(var); }
__WRITE_S(atUint8, Endian::Little) { w.writeUByte(var); }
__WRITE_S(atInt16, Endian::Little) { w.writeInt16Little(var); }
__WRITE_S(atUint16, Endian::Little) { w.writeUint16Little(var); }
__WRITE_S(atInt32, Endian::Little) { w.writeInt32Little(var); }
__WRITE_S(atUint32, Endian::Little) { w.writeUint32Little(var); }
__WRITE_S(atInt64, Endian::Little) { w.writeInt64Little(var); }
__WRITE_S(atUint64, Endian::Little) { w.writeUint64Little(var); }
__WRITE_S(float, Endian::Little) { w.writeFloatLittle(var); }
__WRITE_S(double, Endian::Little) { w.writeDoubleLittle(var); }
__WRITE_S(atVec2f, Endian::Little) { w.writeVec2fLittle(var); }
__WRITE_S(atVec2d, Endian::Little) { w.writeVec2dLittle(var); }
__WRITE_S(atVec3f, Endian::Little) { w.writeVec3fLittle(var); }
__WRITE_S(atVec3d, Endian::Little) { w.writeVec3dLittle(var); }
__WRITE_S(atVec4f, Endian::Little) { w.writeVec4fLittle(var); }
__WRITE_S(atVec4d, Endian::Little) { w.writeVec4dLittle(var); }
__WRITE_WSTR_S(Endian::Little) { w.writeWStringLittle(str); }
__WRITE_WSTRC_S(Endian::Little) { w.writeWStringLittle(str, count); }
template <PropType PropOp>
struct ReadYaml {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = YAMLDocReader;
template <class T, Endian DNAE>
static std::enable_if_t<std::is_enum_v<T>> Do(const PropId& id, T& var, StreamT& r) {
using PODType = std::underlying_type_t<T>;
ReadYaml<PropType::None>::Do<PODType, DNAE>(id, *reinterpret_cast<PODType*>(&var), r);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsPODType_v<T>> Do(const PropId& id, T& var, StreamT& r) {
using CastT = __CastPODType<T>;
ReadYaml<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(var), r);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord_v<T>> Do(const PropId& id, T& var, StreamT& r) {
if (auto rec = r.enterSubRecord(id.name))
var.template Enumerate<ReadYaml<PropOp>>(r);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_array_v<T>> Do(const PropId& id, T& var, StreamT& r) {
size_t _count;
if (auto __v = r.enterSubVector(id.name, _count)) {
for (size_t i = 0; i < _count && i < std::extent_v<T>; ++i) {
ReadYaml<PropOp>::template Do<std::remove_reference_t<decltype(var[i])>, DNAE>({}, var[i], r);
}
}
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
/* Squelch size field access */
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<!std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& r) {
size_t _count;
vector.clear();
if (auto __v = r.enterSubVector(id.name, _count)) {
vector.reserve(_count);
for (size_t i = 0; i < _count; ++i) {
vector.emplace_back();
ReadYaml<PropOp>::template Do<T, DNAE>({}, vector.back(), r);
}
}
/* Horrible reference abuse (but it works) */
const_cast<S&>(count) = vector.size();
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& r) {
/* libc++ specializes vector<bool> as a bitstream */
size_t _count;
vector.clear();
if (auto __v = r.enterSubVector(id.name, _count)) {
vector.reserve(_count);
for (size_t i = 0; i < _count; ++i)
vector.push_back(r.readBool());
}
/* Horrible reference abuse (but it works) */
const_cast<S&>(count) = vector.size();
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& r) {
buf = r.readUBytes(id.name);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, T& str, StreamT& r) {
str = r.readString(id.name);
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& r) { str = r.readString(id.name); }
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, T& str, StreamT& r) {
str = r.readWString(id.name);
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& r) {
str = r.readWString(id.name);
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& r) {}
static void DoAlign(atInt64 amount, StreamT& r) {}
};
#define __READ_YAML_S(type, endian) \
template <> \
template <> \
inline void ReadYaml<PropType::None>::Do<type, endian>(const PropId& id, type& var, ReadYaml::StreamT& r)
__READ_YAML_S(bool, Endian::Big) { var = r.readBool(id.name); }
__READ_YAML_S(atInt8, Endian::Big) { var = r.readByte(id.name); }
__READ_YAML_S(atUint8, Endian::Big) { var = r.readUByte(id.name); }
__READ_YAML_S(atInt16, Endian::Big) { var = r.readInt16(id.name); }
__READ_YAML_S(atUint16, Endian::Big) { var = r.readUint16(id.name); }
__READ_YAML_S(atInt32, Endian::Big) { var = r.readInt32(id.name); }
__READ_YAML_S(atUint32, Endian::Big) { var = r.readUint32(id.name); }
__READ_YAML_S(atInt64, Endian::Big) { var = r.readInt64(id.name); }
__READ_YAML_S(atUint64, Endian::Big) { var = r.readUint64(id.name); }
__READ_YAML_S(float, Endian::Big) { var = r.readFloat(id.name); }
__READ_YAML_S(double, Endian::Big) { var = r.readDouble(id.name); }
__READ_YAML_S(atVec2f, Endian::Big) { var = r.readVec2f(id.name); }
__READ_YAML_S(atVec2d, Endian::Big) { var = r.readVec2d(id.name); }
__READ_YAML_S(atVec3f, Endian::Big) { var = r.readVec3f(id.name); }
__READ_YAML_S(atVec3d, Endian::Big) { var = r.readVec3d(id.name); }
__READ_YAML_S(atVec4f, Endian::Big) { var = r.readVec4f(id.name); }
__READ_YAML_S(atVec4d, Endian::Big) { var = r.readVec4d(id.name); }
__READ_YAML_S(bool, Endian::Little) { var = r.readBool(id.name); }
__READ_YAML_S(atInt8, Endian::Little) { var = r.readByte(id.name); }
__READ_YAML_S(atUint8, Endian::Little) { var = r.readUByte(id.name); }
__READ_YAML_S(atInt16, Endian::Little) { var = r.readInt16(id.name); }
__READ_YAML_S(atUint16, Endian::Little) { var = r.readUint16(id.name); }
__READ_YAML_S(atInt32, Endian::Little) { var = r.readInt32(id.name); }
__READ_YAML_S(atUint32, Endian::Little) { var = r.readUint32(id.name); }
__READ_YAML_S(atInt64, Endian::Little) { var = r.readInt64(id.name); }
__READ_YAML_S(atUint64, Endian::Little) { var = r.readUint64(id.name); }
__READ_YAML_S(float, Endian::Little) { var = r.readFloat(id.name); }
__READ_YAML_S(double, Endian::Little) { var = r.readDouble(id.name); }
__READ_YAML_S(atVec2f, Endian::Little) { var = r.readVec2f(id.name); }
__READ_YAML_S(atVec2d, Endian::Little) { var = r.readVec2d(id.name); }
__READ_YAML_S(atVec3f, Endian::Little) { var = r.readVec3f(id.name); }
__READ_YAML_S(atVec3d, Endian::Little) { var = r.readVec3d(id.name); }
__READ_YAML_S(atVec4f, Endian::Little) { var = r.readVec4f(id.name); }
__READ_YAML_S(atVec4d, Endian::Little) { var = r.readVec4d(id.name); }
template <PropType PropOp>
struct WriteYaml {
using PropT = std::conditional_t<PropOp == PropType::CRC64, uint64_t, uint32_t>;
using StreamT = YAMLDocWriter;
template <class T, Endian DNAE>
static std::enable_if_t<std::is_enum_v<T>> Do(const PropId& id, T& var, StreamT& w) {
using PODType = std::underlying_type_t<T>;
WriteYaml<PropType::None>::Do<PODType, DNAE>(id, *reinterpret_cast<PODType*>(&var), w);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsPODType_v<T>> Do(const PropId& id, T& var, StreamT& w) {
using CastT = __CastPODType<T>;
WriteYaml<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(const_cast<std::remove_cv_t<T>&>(var)), w);
}
template <class T, Endian DNAE>
static std::enable_if_t<__IsDNARecord_v<T>> Do(const PropId& id, T& var, StreamT& w) {
if (auto rec = w.enterSubRecord(id.name))
var.template Enumerate<WriteYaml<PropOp>>(w);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_array_v<T>> Do(const PropId& id, T& var, StreamT& w) {
if (auto __v = w.enterSubVector(id.name)) {
for (auto& v : var) {
WriteYaml<PropOp>::template Do<std::remove_reference_t<decltype(v)>, DNAE>({}, v, w);
}
}
}
template <class T, Endian DNAE>
static void DoSize(const PropId& id, T& var, StreamT& s) {
/* Squelch size field access */
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<!std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& w) {
if (auto __v = w.enterSubVector(id.name)) {
for (T& v : vector) {
WriteYaml<PropOp>::template Do<T, DNAE>(id, v, w);
}
}
}
template <class T, class S, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, bool>> Do(const PropId& id, std::vector<T>& vector, const S& count,
StreamT& w) {
/* libc++ specializes vector<bool> as a bitstream */
if (auto __v = w.enterSubVector(id.name))
for (const T v : vector)
w.writeBool(v);
}
static void Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, StreamT& w) {
w.writeUBytes(id.name, buf, count);
}
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::string>> Do(const PropId& id, T& str, StreamT& w) {
w.writeString(id.name, str);
}
static void Do(const PropId& id, std::string& str, atInt32 count, StreamT& w) { w.writeString(id.name, str); }
template <class T, Endian DNAE>
static std::enable_if_t<std::is_same_v<T, std::wstring>> Do(const PropId& id, T& str, StreamT& w) {
w.writeWString(id.name, str);
}
template <Endian DNAE>
static void Do(const PropId& id, std::wstring& str, atInt32 count, StreamT& w) {
w.writeWString(id.name, str);
}
static void DoSeek(atInt64 amount, SeekOrigin whence, StreamT& w) {}
static void DoAlign(atInt64 amount, StreamT& w) {}
};
#define __WRITE_YAML_S(type, endian) \
template <> \
template <> \
inline void WriteYaml<PropType::None>::Do<type, endian>(const PropId& id, type& var, WriteYaml::StreamT& w)
__WRITE_YAML_S(bool, Endian::Big) { w.writeBool(id.name, var); }
__WRITE_YAML_S(atInt8, Endian::Big) { w.writeByte(id.name, var); }
__WRITE_YAML_S(atUint8, Endian::Big) { w.writeUByte(id.name, var); }
__WRITE_YAML_S(atInt16, Endian::Big) { w.writeInt16(id.name, var); }
__WRITE_YAML_S(atUint16, Endian::Big) { w.writeUint16(id.name, var); }
__WRITE_YAML_S(atInt32, Endian::Big) { w.writeInt32(id.name, var); }
__WRITE_YAML_S(atUint32, Endian::Big) { w.writeUint32(id.name, var); }
__WRITE_YAML_S(atInt64, Endian::Big) { w.writeInt64(id.name, var); }
__WRITE_YAML_S(atUint64, Endian::Big) { w.writeUint64(id.name, var); }
__WRITE_YAML_S(float, Endian::Big) { w.writeFloat(id.name, var); }
__WRITE_YAML_S(double, Endian::Big) { w.writeDouble(id.name, var); }
__WRITE_YAML_S(atVec2f, Endian::Big) { w.writeVec2f(id.name, var); }
__WRITE_YAML_S(atVec2d, Endian::Big) { w.writeVec2d(id.name, var); }
__WRITE_YAML_S(atVec3f, Endian::Big) { w.writeVec3f(id.name, var); }
__WRITE_YAML_S(atVec3d, Endian::Big) { w.writeVec3d(id.name, var); }
__WRITE_YAML_S(atVec4f, Endian::Big) { w.writeVec4f(id.name, var); }
__WRITE_YAML_S(atVec4d, Endian::Big) { w.writeVec4d(id.name, var); }
__WRITE_YAML_S(bool, Endian::Little) { w.writeBool(id.name, var); }
__WRITE_YAML_S(atInt8, Endian::Little) { w.writeByte(id.name, var); }
__WRITE_YAML_S(atUint8, Endian::Little) { w.writeUByte(id.name, var); }
__WRITE_YAML_S(atInt16, Endian::Little) { w.writeInt16(id.name, var); }
__WRITE_YAML_S(atUint16, Endian::Little) { w.writeUint16(id.name, var); }
__WRITE_YAML_S(atInt32, Endian::Little) { w.writeInt32(id.name, var); }
__WRITE_YAML_S(atUint32, Endian::Little) { w.writeUint32(id.name, var); }
__WRITE_YAML_S(atInt64, Endian::Little) { w.writeInt64(id.name, var); }
__WRITE_YAML_S(atUint64, Endian::Little) { w.writeUint64(id.name, var); }
__WRITE_YAML_S(float, Endian::Little) { w.writeFloat(id.name, var); }
__WRITE_YAML_S(double, Endian::Little) { w.writeDouble(id.name, var); }
__WRITE_YAML_S(atVec2f, Endian::Little) { w.writeVec2f(id.name, var); }
__WRITE_YAML_S(atVec2d, Endian::Little) { w.writeVec2d(id.name, var); }
__WRITE_YAML_S(atVec3f, Endian::Little) { w.writeVec3f(id.name, var); }
__WRITE_YAML_S(atVec3d, Endian::Little) { w.writeVec3d(id.name, var); }
__WRITE_YAML_S(atVec4f, Endian::Little) { w.writeVec4f(id.name, var); }
__WRITE_YAML_S(atVec4d, Endian::Little) { w.writeVec4d(id.name, var); }
template <class Op, class T, Endian DNAE>
void __Do(const PropId& id, T& var, typename Op::StreamT& s) {
Op::template Do<T, DNAE>(id, var, s);
}
template <class Op, class T, Endian DNAE>
void __DoSize(const PropId& id, T& var, typename Op::StreamT& s) {
Op::template DoSize<T, DNAE>(id, var, s);
}
template <class Op, class T, class S, Endian DNAE>
void __Do(const PropId& id, std::vector<T>& vector, const S& count, typename Op::StreamT& s) {
Op::template Do<T, S, DNAE>(id, vector, count, s);
}
template <class Op>
void __Do(const PropId& id, std::unique_ptr<atUint8[]>& buf, size_t count, typename Op::StreamT& s) {
Op::Do(id, buf, count, s);
}
template <class Op>
void __Do(const PropId& id, std::string& str, atInt32 count, typename Op::StreamT& s) {
Op::Do(id, str, count, s);
}
template <class Op, Endian DNAE>
void __Do(const PropId& id, std::wstring& str, atInt32 count, typename Op::StreamT& s) {
Op::template Do<DNAE>(id, str, count, s);
}
template <class Op>
void __DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) {
Op::DoSeek(delta, whence, s);
}
template <class Op>
void __DoAlign(atInt64 amount, typename Op::StreamT& s) {
Op::DoAlign(amount, s);
}
template <class T>
void __Read(T& obj, athena::io::IStreamReader& r) {
__Do<Read<PropType::None>, T, T::DNAEndian>({}, obj, r);
}
template <class T>
void __Write(const T& obj, athena::io::IStreamWriter& w) {
__Do<Write<PropType::None>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
}
template <class T>
void __BinarySize(const T& obj, size_t& s) {
__Do<BinarySize<PropType::None>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
}
template <class T>
void __PropCount(const T& obj, size_t& s) {
const_cast<T&>(obj).template Enumerate<PropCount<PropType::None>>(s);
}
template <class T>
void __ReadYaml(T& obj, athena::io::YAMLDocReader& r) {
obj.template Enumerate<ReadYaml<PropType::None>>(r);
}
template <class T>
void __WriteYaml(const T& obj, athena::io::YAMLDocWriter& w) {
const_cast<T&>(obj).template Enumerate<WriteYaml<PropType::None>>(w);
}
template <class T>
void __ReadProp(T& obj, athena::io::IStreamReader& r) {
/* Read root 0xffffffff hash (hashed empty string) */
T::DNAEndian == Endian::Big ? r.readUint32Big() : r.readUint32Little();
atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little();
atInt64 start = r.position();
__Do<Read<PropType::CRC32>, T, T::DNAEndian>({}, obj, r);
atInt64 actualRead = r.position() - start;
if (actualRead != size)
r.seek(size - actualRead);
}
template <class T>
void __WriteProp(const T& obj, athena::io::IStreamWriter& w) {
__Do<Write<PropType::CRC32>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
}
template <class T>
void __BinarySizeProp(const T& obj, size_t& s) {
__Do<BinarySize<PropType::CRC32>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
}
template <class T>
void __ReadProp64(T& obj, athena::io::IStreamReader& r) {
/* Read root 0x0 hash (hashed empty string) */
T::DNAEndian == Endian::Big ? r.readUint64Big() : r.readUint64Little();
atInt64 size = T::DNAEndian == Endian::Big ? r.readUint16Big() : r.readUint16Little();
atInt64 start = r.position();
__Do<Read<PropType::CRC64>, T, T::DNAEndian>({}, obj, r);
atInt64 actualRead = r.position() - start;
if (actualRead != size)
r.seek(size - actualRead);
}
template <class T>
void __WriteProp64(const T& obj, athena::io::IStreamWriter& w) {
__Do<Write<PropType::CRC64>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
}
template <class T>
void __BinarySizeProp64(const T& obj, size_t& s) {
__Do<BinarySize<PropType::CRC64>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
}
} // namespace athena::io
#define AT_DECL_DNA_DO \
template <class Op, athena::Endian DNAE = DNAEndian, class T> \
void Do(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \
athena::io::__Do<Op, T, DNAE>(_id, var, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian, class T> \
void DoSize(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \
athena::io::__DoSize<Op, T, DNAE>(_id, var, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian, class T, class S> \
void Do(const athena::io::PropId& _id, std::vector<T>& var, const S& count, typename Op::StreamT& s) { \
athena::io::__Do<Op, T, S, DNAE>(_id, var, count, s); \
} \
template <class Op> \
void Do(const athena::io::PropId& _id, std::unique_ptr<atUint8[]>& buf, size_t count, typename Op::StreamT& s) { \
athena::io::__Do<Op>(_id, buf, count, s); \
} \
template <class Op> \
void Do(const athena::io::PropId& _id, std::string& str, atInt32 count, typename Op::StreamT& s) { \
athena::io::__Do<Op>(_id, str, count, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian> \
void Do(const athena::io::PropId& _id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \
athena::io::__Do<Op, DNAE>(_id, str, count, s); \
} \
template <class Op> \
void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \
athena::io::__DoSeek<Op>(delta, whence, s); \
} \
template <class Op> \
void DoAlign(atInt64 amount, typename Op::StreamT& s) { \
athena::io::__DoAlign<Op>(amount, s); \
} \
template <class Op> \
void Enumerate(typename Op::StreamT& s); \
static std::string_view DNAType();
#define AT_DECL_DNA \
AT_DECL_DNA_DO \
void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \
void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \
void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); }
#define AT_DECL_DNA_YAML \
AT_DECL_DNA \
void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \
void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); }
#define AT_DECL_EXPLICIT_DNA \
AT_DECL_DNA \
Delete __d;
#define AT_DECL_EXPLICIT_DNAV \
AT_DECL_DNAV \
Delete __d;
#define AT_DECL_EXPLICIT_DNAV_NO_TYPE \
AT_DECL_DNAV_NO_TYPE \
Delete __d;
#define AT_DECL_EXPLICIT_DNA_YAML \
AT_DECL_DNA_YAML \
Delete __d;
#define AT_DECL_EXPLICIT_DNA_YAMLV \
AT_DECL_DNA_YAMLV \
Delete __d;
#define AT_DECL_EXPLICIT_DNA_YAMLV_NO_TYPE \
AT_DECL_DNA_YAMLV_NO_TYPE \
Delete __d;
#define AT_DECL_DNAV \
AT_DECL_DNA_DO \
void read(athena::io::IStreamReader& r) override { athena::io::__Read(*this, r); } \
void write(athena::io::IStreamWriter& w) const override { athena::io::__Write(*this, w); } \
void binarySize(size_t& s) const override { athena::io::__BinarySize(*this, s); } \
std::string_view DNATypeV() const override { return DNAType(); }
#define AT_DECL_DNAV_NO_TYPE \
AT_DECL_DNA_DO \
void read(athena::io::IStreamReader& r) override { athena::io::__Read(*this, r); } \
void write(athena::io::IStreamWriter& w) const override { athena::io::__Write(*this, w); } \
void binarySize(size_t& s) const override { athena::io::__BinarySize(*this, s); }
#define AT_DECL_DNA_YAMLV \
AT_DECL_DNAV \
void read(athena::io::YAMLDocReader& r) override { athena::io::__ReadYaml(*this, r); } \
void write(athena::io::YAMLDocWriter& w) const override { athena::io::__WriteYaml(*this, w); }
#define AT_DECL_DNA_YAMLV_NO_TYPE \
AT_DECL_DNAV_NO_TYPE \
void read(athena::io::YAMLDocReader& r) override { athena::io::__ReadYaml(*this, r); } \
void write(athena::io::YAMLDocWriter& w) const override { athena::io::__WriteYaml(*this, w); }
#define AT_SPECIALIZE_DNA(...) \
template void __VA_ARGS__::Enumerate<athena::io::Read<athena::io::PropType::None>>( \
athena::io::Read<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Write<athena::io::PropType::None>>( \
athena::io::Write<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::BinarySize<athena::io::PropType::None>>( \
athena::io::BinarySize<athena::io::PropType::None>::StreamT & s);
#define AT_SPECIALIZE_DNA_YAML(...) \
AT_SPECIALIZE_DNA(__VA_ARGS__) \
template void __VA_ARGS__::Enumerate<athena::io::ReadYaml<athena::io::PropType::None>>( \
athena::io::ReadYaml<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::WriteYaml<athena::io::PropType::None>>( \
athena::io::WriteYaml<athena::io::PropType::None>::StreamT & s);
#define AT_DECL_PROPDNA \
template <class Op, athena::Endian DNAE = DNAEndian, class T> \
void Do(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \
athena::io::__Do<Op, T, DNAE>(_id, var, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian, class T> \
void DoSize(const athena::io::PropId& _id, T& var, typename Op::StreamT& s) { \
athena::io::__DoSize<Op, T, DNAE>(_id, var, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian, class T, class S> \
void Do(const athena::io::PropId& _id, std::vector<T>& var, const S& count, typename Op::StreamT& s) { \
athena::io::__Do<Op, T, S, DNAE>(_id, var, count, s); \
} \
template <class Op> \
void Do(const athena::io::PropId& _id, std::unique_ptr<atUint8[]>& buf, size_t count, typename Op::StreamT& s) { \
athena::io::__Do<Op>(_id, buf, count, s); \
} \
template <class Op> \
void Do(const athena::io::PropId& _id, std::string& str, atInt32 count, typename Op::StreamT& s) { \
athena::io::__Do<Op>(_id, str, count, s); \
} \
template <class Op, athena::Endian DNAE = DNAEndian> \
void Do(const athena::io::PropId& _id, std::wstring& str, atInt32 count, typename Op::StreamT& s) { \
athena::io::__Do<Op, DNAE>(_id, str, count, s); \
} \
template <class Op> \
void DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s) { \
athena::io::__DoSeek<Op>(delta, whence, s); \
} \
template <class Op> \
void DoAlign(atInt64 amount, typename Op::StreamT& s) { \
athena::io::__DoAlign<Op>(amount, s); \
} \
template <class Op> \
void Enumerate(typename Op::StreamT& s); \
template <class Op> \
bool Lookup(uint64_t hash, typename Op::StreamT& s); \
static std::string_view DNAType(); \
void read(athena::io::IStreamReader& r) { athena::io::__Read(*this, r); } \
void write(athena::io::IStreamWriter& w) const { athena::io::__Write(*this, w); } \
void binarySize(size_t& s) const { athena::io::__BinarySize(*this, s); } \
void read(athena::io::YAMLDocReader& r) { athena::io::__ReadYaml(*this, r); } \
void write(athena::io::YAMLDocWriter& w) const { athena::io::__WriteYaml(*this, w); } \
void readProp(athena::io::IStreamReader& r) { athena::io::__ReadProp(*this, r); } \
void writeProp(athena::io::IStreamWriter& w) const { athena::io::__WriteProp(*this, w); } \
void binarySizeProp(size_t& s) const { athena::io::__BinarySizeProp(*this, s); } \
void propCount(size_t& s) const { athena::io::__PropCount(*this, s); } \
void readProp64(athena::io::IStreamReader& r) { athena::io::__ReadProp64(*this, r); } \
void writeProp64(athena::io::IStreamWriter& w) const { athena::io::__WriteProp64(*this, w); } \
void binarySizeProp64(size_t& s) const { athena::io::__BinarySizeProp64(*this, s); }
#define AT_DECL_EXPLICIT_PROPDNA \
AT_DECL_PROPDNA \
Delete __d;
#define AT_SPECIALIZE_PROPDNA(...) \
template void __VA_ARGS__::Enumerate<athena::io::Read<athena::io::PropType::None>>( \
athena::io::Read<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Write<athena::io::PropType::None>>( \
athena::io::Write<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::BinarySize<athena::io::PropType::None>>( \
athena::io::BinarySize<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::ReadYaml<athena::io::PropType::None>>( \
athena::io::ReadYaml<athena::io::PropType::None>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::WriteYaml<athena::io::PropType::None>>( \
athena::io::WriteYaml<athena::io::PropType::None>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::Read<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::Read<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Read<athena::io::PropType::CRC32>>( \
athena::io::Read<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::Write<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::Write<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Write<athena::io::PropType::CRC32>>( \
athena::io::Write<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::BinarySize<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::BinarySize<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::BinarySize<athena::io::PropType::CRC32>>( \
athena::io::BinarySize<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::PropCount<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::PropCount<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::PropCount<athena::io::PropType::CRC32>>( \
athena::io::PropCount<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::ReadYaml<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::ReadYaml<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::ReadYaml<athena::io::PropType::CRC32>>( \
athena::io::ReadYaml<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::WriteYaml<athena::io::PropType::CRC32>>( \
uint64_t hash, athena::io::WriteYaml<athena::io::PropType::CRC32>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::WriteYaml<athena::io::PropType::CRC32>>( \
athena::io::WriteYaml<athena::io::PropType::CRC32>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::Read<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::Read<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Read<athena::io::PropType::CRC64>>( \
athena::io::Read<athena::io::PropType::CRC64>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::Write<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::Write<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::Write<athena::io::PropType::CRC64>>( \
athena::io::Write<athena::io::PropType::CRC64>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::BinarySize<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::BinarySize<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::BinarySize<athena::io::PropType::CRC64>>( \
athena::io::BinarySize<athena::io::PropType::CRC64>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::PropCount<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::PropCount<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::PropCount<athena::io::PropType::CRC64>>( \
athena::io::PropCount<athena::io::PropType::CRC64>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::ReadYaml<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::ReadYaml<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::ReadYaml<athena::io::PropType::CRC64>>( \
athena::io::ReadYaml<athena::io::PropType::CRC64>::StreamT & s); \
template bool __VA_ARGS__::Lookup<athena::io::WriteYaml<athena::io::PropType::CRC64>>( \
uint64_t hash, athena::io::WriteYaml<athena::io::PropType::CRC64>::StreamT & s); \
template void __VA_ARGS__::Enumerate<athena::io::WriteYaml<athena::io::PropType::CRC64>>( \
athena::io::WriteYaml<athena::io::PropType::CRC64>::StreamT & s);
#define AT_SUBDECL_DNA \
void _read(athena::io::IStreamReader& r); \
void _write(athena::io::IStreamWriter& w) const; \
void _binarySize(size_t& s) const; \
void _read(athena::io::YAMLDocReader& r); \
void _write(athena::io::YAMLDocWriter& w) const;
#define AT_SUBDECL_DNA_YAML \
AT_SUBDECL_DNA \
void _read(athena::io::YAMLDocReader& r); \
void _write(athena::io::YAMLDocWriter& w) const;
#define AT_SUBSPECIALIZE_DNA(...) \
template <> \
template <> \
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::BinarySize>(typename BinarySize::StreamT & s) { \
_binarySize(s); \
} \
template <> \
template <> \
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::Read>(typename Read::StreamT & r) { \
_read(r); \
} \
template <> \
template <> \
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::Write>(typename Write::StreamT & w) { \
_write(w); \
}
#define AT_SUBSPECIALIZE_DNA_YAML(...) \
template <> \
template <> \
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::ReadYaml>(typename ReadYaml::StreamT & r) { \
_read(r); \
} \
template <> \
template <> \
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Endian::Big>::WriteYaml>(typename WriteYaml::StreamT & w) { \
_write(w); \
} \
AT_SUBSPECIALIZE_DNA(__VA_ARGS__)