mirror of https://github.com/libAthena/athena.git
1277 lines
53 KiB
C++
1277 lines
53 KiB
C++
#ifndef AT_DNAOP_HPP
|
|
#define AT_DNAOP_HPP
|
|
|
|
#include "IStreamReader.hpp"
|
|
#include "IStreamWriter.hpp"
|
|
#include "YAMLDocReader.hpp"
|
|
#include "YAMLDocWriter.hpp"
|
|
#include "ChecksumsLiterals.hpp"
|
|
#include <type_traits>
|
|
|
|
namespace athena::io
|
|
{
|
|
|
|
struct PropId
|
|
{
|
|
const char* name = nullptr;
|
|
uint32_t rcrc32 = 0xffffffff;
|
|
uint64_t crc64 = 0x0;
|
|
template <class T> constexpr T opget() const;
|
|
constexpr PropId() = default;
|
|
constexpr PropId(const char* name, uint32_t rcrc32, uint64_t crc64)
|
|
: name(name), rcrc32(rcrc32), crc64(crc64) {}
|
|
constexpr PropId(const char* name)
|
|
: name(name),
|
|
rcrc32(athena::checksums::literals::rcrc32_rec(0xFFFFFFFF, name)),
|
|
crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {}
|
|
constexpr PropId(const char* name, uint32_t rcrc32)
|
|
: name(name),
|
|
rcrc32(rcrc32),
|
|
crc64(athena::checksums::literals::crc64_rec(0xFFFFFFFFFFFFFFFF, name)) {}
|
|
};
|
|
|
|
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 {s};
|
|
}
|
|
}
|
|
|
|
#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 = typename std::disjunction<std::is_arithmetic<T>,
|
|
std::is_convertible<T&, atVec2f&>,
|
|
std::is_convertible<T&, atVec3f&>,
|
|
std::is_convertible<T&, atVec4f&>,
|
|
std::is_convertible<T&, atVec2d&>,
|
|
std::is_convertible<T&, atVec3d&>,
|
|
std::is_convertible<T&, atVec4d&>>;
|
|
template <class T>
|
|
inline constexpr bool __IsPODType_v = __IsPODType<T>::value;
|
|
|
|
template <class T>
|
|
using __CastPODType = typename std::conditional_t<std::is_convertible_v<T&, atVec2f&>, atVec2f,
|
|
std::conditional_t<std::is_convertible_v<T&, atVec3f&>, atVec3f,
|
|
std::conditional_t<std::is_convertible_v<T&, atVec4f&>, atVec4f,
|
|
std::conditional_t<std::is_convertible_v<T&, atVec2d&>, atVec2d,
|
|
std::conditional_t<std::is_convertible_v<T&, atVec3d&>, atVec3d,
|
|
std::conditional_t<std::is_convertible_v<T&, atVec4d&>, atVec4d,
|
|
T>>>>>>;
|
|
|
|
template <Endian DNAE>
|
|
static inline uint16_t __Read16(IStreamReader& r)
|
|
{
|
|
return DNAE == Endian::Big ? r.readUint16Big() : r.readUint16Little();
|
|
}
|
|
|
|
template <Endian DNAE>
|
|
static inline void __Write16(IStreamWriter& w, uint16_t v)
|
|
{
|
|
DNAE == Endian::Big ? w.writeUint16Big(v) : w.writeUint16Little(v);
|
|
}
|
|
|
|
template <Endian DNAE>
|
|
static inline uint32_t __Read32(IStreamReader& r)
|
|
{
|
|
return DNAE == Endian::Big ? r.readUint32Big() : r.readUint32Little();
|
|
}
|
|
|
|
template <Endian DNAE>
|
|
static inline void __Write32(IStreamWriter& w, uint32_t v)
|
|
{
|
|
DNAE == Endian::Big ? w.writeUint32Big(v) : w.writeUint32Little(v);
|
|
}
|
|
|
|
template <Endian DNAE>
|
|
static inline uint64_t __Read64(IStreamReader& r)
|
|
{
|
|
return DNAE == Endian::Big ? r.readUint64Big() : r.readUint64Little();
|
|
}
|
|
|
|
template <Endian DNAE>
|
|
static inline 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 typename 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 typename 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&>(var), s);
|
|
}
|
|
template <class T, Endian DNAE>
|
|
static typename 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 typename 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 typename std::enable_if_t<std::is_array_v<T>>
|
|
Do(const PropId& id, T& var, StreamT& s)
|
|
{
|
|
for (auto& v : var)
|
|
BinarySize<PropOp>::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>::Do<T, DNAE>(id, var, s);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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>::Do<T, DNAE>(id, v, s);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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 typename 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 typename 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>::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 typename 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 typename 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 typename 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 typename 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 typename 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 typename 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 typename std::enable_if_t<std::is_array_v<T>>
|
|
Do(const PropId& id, T& var, StreamT& s)
|
|
{
|
|
for (auto& v : var)
|
|
Read<PropOp>::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>::Do<T, DNAE>(id, var, s);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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>::Do<T, DNAE>(id, vector.back(), r);
|
|
}
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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 typename 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 typename 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::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 typename 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 typename 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&>(var), binarySize);
|
|
__Write16<DNAE>(w, atUint16(binarySize));
|
|
}
|
|
Write<PropType::None>::Do<CastT, DNAE>(id, static_cast<CastT&>(var), w);
|
|
}
|
|
template <class T, Endian DNAE>
|
|
static typename 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 typename 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 typename std::enable_if_t<std::is_array_v<T>>
|
|
Do(const PropId& id, T& var, StreamT& s)
|
|
{
|
|
for (auto& v : var)
|
|
Write<PropOp>::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>::Do<T, DNAE>(id, var, s);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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>::Do<T, DNAE>(id, v, w);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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 typename 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 typename 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 typename 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 typename 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 typename 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 typename 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>::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 typename 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>::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 typename 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(nullptr));
|
|
}
|
|
/* 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 typename 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 typename 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 typename 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 typename 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&>(var), w);
|
|
}
|
|
template <class T, Endian DNAE>
|
|
static typename 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 typename 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>::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 typename 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>::Do<T, DNAE>(id, v, w);
|
|
}
|
|
template <class T, class S, Endian DNAE>
|
|
static typename 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(nullptr, 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 typename 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 typename 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>
|
|
static inline 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>
|
|
static inline 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>
|
|
static inline 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>
|
|
static inline 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>
|
|
static inline 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>
|
|
static inline 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>
|
|
static inline void __DoSeek(atInt64 delta, athena::SeekOrigin whence, typename Op::StreamT& s)
|
|
{
|
|
Op::DoSeek(delta, whence, s);
|
|
}
|
|
|
|
template <class Op>
|
|
static inline void __DoAlign(atInt64 amount, typename Op::StreamT& s)
|
|
{
|
|
Op::DoAlign(amount, s);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __Read(T& obj, athena::io::IStreamReader& r)
|
|
{
|
|
__Do<Read<PropType::None>, T, T::DNAEndian>({}, obj, r);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __Write(const T& obj, athena::io::IStreamWriter& w)
|
|
{
|
|
__Do<Write<PropType::None>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __BinarySize(const T& obj, size_t& s)
|
|
{
|
|
__Do<BinarySize<PropType::None>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __PropCount(const T& obj, size_t& s)
|
|
{
|
|
const_cast<T&>(obj).template Enumerate<PropCount<PropType::None>>(s);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __ReadYaml(T& obj, athena::io::YAMLDocReader& r)
|
|
{
|
|
obj.template Enumerate<ReadYaml<PropType::None>>(r);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __WriteYaml(const T& obj, athena::io::YAMLDocWriter& w)
|
|
{
|
|
const_cast<T&>(obj).template Enumerate<WriteYaml<PropType::None>>(w);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __ReadProp(T& obj, athena::io::IStreamReader& r)
|
|
{
|
|
/* Read root 0xffffffff hash (hashed empty string) */
|
|
atUint32 hash = 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>
|
|
static inline void __WriteProp(const T& obj, athena::io::IStreamWriter& w)
|
|
{
|
|
__Do<Write<PropType::CRC32>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __BinarySizeProp(const T& obj, size_t& s)
|
|
{
|
|
__Do<BinarySize<PropType::CRC32>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __ReadProp64(T& obj, athena::io::IStreamReader& r)
|
|
{
|
|
/* Read root 0x0 hash (hashed empty string) */
|
|
atUint64 hash = 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>
|
|
static inline void __WriteProp64(const T& obj, athena::io::IStreamWriter& w)
|
|
{
|
|
__Do<Write<PropType::CRC64>, T, T::DNAEndian>({}, const_cast<T&>(obj), w);
|
|
}
|
|
|
|
template <class T>
|
|
static inline void __BinarySizeProp64(const T& obj, size_t& s)
|
|
{
|
|
__Do<BinarySize<PropType::CRC64>, T, T::DNAEndian>({}, const_cast<T&>(obj), s);
|
|
}
|
|
|
|
}
|
|
|
|
#define AT_DECL_DNA \
|
|
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 const char* 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); }
|
|
|
|
#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_DNA_YAML \
|
|
AT_DECL_DNA_YAML \
|
|
Delete __d;
|
|
|
|
#define AT_DECL_DNAV const char* DNATypeV() const {return DNAType();}
|
|
|
|
#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 const char* 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::Big>::BinarySize>(typename BinarySize::StreamT& s) \
|
|
{ \
|
|
_binarySize(s); \
|
|
} \
|
|
template <> template <> \
|
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT& r) \
|
|
{ \
|
|
_read(r); \
|
|
} \
|
|
template <> template <> \
|
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT& w) \
|
|
{ \
|
|
_write(w); \
|
|
}
|
|
|
|
#define AT_SUBSPECIALIZE_DNA_YAML(...) \
|
|
template <> template <> \
|
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::ReadYaml>(typename ReadYaml::StreamT& r) \
|
|
{ \
|
|
_read(r); \
|
|
} \
|
|
template <> template <> \
|
|
void __VA_ARGS__::Enumerate<athena::io::DNA<athena::Big>::WriteYaml>(typename WriteYaml::StreamT& w) \
|
|
{ \
|
|
_write(w); \
|
|
} \
|
|
AT_SUBSPECIALIZE_DNA(__VA_ARGS__)
|
|
|
|
#endif // AT_DNAOP_HPP
|