athena/include/Athena/DNA.hpp

258 lines
8.1 KiB
C++
Raw Permalink Normal View History

2015-06-15 02:49:02 +00:00
#ifndef DNA_HPP
#define DNA_HPP
2015-06-17 02:50:12 +00:00
/* BIG FAT WARNING!!!
*
* The type-structure of this file is expected to remain consistent for 'atdna'
* Any changes to the types or namespacing must be reflected in 'atdna/main.cpp'
*/
2015-06-16 02:29:53 +00:00
#include "Global.hpp"
#include "IStreamReader.hpp"
#include "IStreamWriter.hpp"
2015-06-15 02:49:02 +00:00
#include <vector>
#include <memory>
2015-06-15 02:49:02 +00:00
namespace Athena
{
namespace io
{
/* forward-declaration dance for recursively-derived types */
template <size_t sizeVar, Endian VE>
struct Buffer;
template <atInt32 sizeVar, Endian VE>
struct String;
template <atInt32 sizeVar, Endian VE>
struct WString;
template <atInt32 sizeVar, Endian VE>
struct WStringAsString;
2015-06-16 02:29:53 +00:00
/**
* @brief Base DNA class used against 'atdna'
2015-09-08 03:02:58 +00:00
* @tparam DNAE Default-endianness for contained DNA values
2015-06-16 02:29:53 +00:00
*
* Athena bundles a build-tool called 'atdna'. This tool functions
2015-06-17 02:50:12 +00:00
* just like the 'clang' compiler, except it emits a full .cpp implementation
* with all read/write calls necessary to marshal the DNA structure to/from
* a streamed medium
2015-06-16 02:29:53 +00:00
*/
2015-06-17 00:25:48 +00:00
template <Endian DNAE>
2015-06-15 02:49:02 +00:00
struct DNA
{
2015-10-18 04:05:35 +00:00
virtual ~DNA() {}
2015-09-08 03:02:58 +00:00
/**
* @brief Common virtual read function for all DNA types
*/
2015-07-07 03:23:37 +00:00
virtual void read(IStreamReader&)=0;
2015-09-08 03:02:58 +00:00
/**
* @brief Common virtual write function for all DNA types
*/
2015-07-07 03:23:37 +00:00
virtual void write(IStreamWriter&) const=0;
2015-10-18 04:05:35 +00:00
/**
* @brief Common virtual binary size computation for all DNA types
* @param __isz initial cumulative value to add result to
* @return Cumulative size
*/
virtual size_t binarySize(size_t __isz) const=0;
2015-07-07 03:23:37 +00:00
2015-09-08 03:02:58 +00:00
/**
* @brief Template type signaling atdna to capture the value where it's used
* @tparam T The type of the value. Can be any numeric type or atVec* type
* @tparam VE Endianness of the value
*/
2015-06-16 07:11:56 +00:00
template <typename T, Endian VE = DNAE>
2015-06-16 02:29:53 +00:00
using Value = T;
2015-06-15 02:49:02 +00:00
2015-09-08 03:02:58 +00:00
/**
* @brief Template type wrapping std::vector and signaling atdna to manipulate it where it's used
* @tparam T The type of contained elements. Can be any numeric type, atVec* type, or another DNA subclass
* @tparam cntVar C++ expression wrapped in DNA_COUNT macro to determine number of elements for vector
* @tparam VE Endianness of the contained values
*/
2015-06-17 00:25:48 +00:00
template <typename T, size_t cntVar, Endian VE = DNAE>
2015-06-16 02:29:53 +00:00
using Vector = std::vector<T>;
2015-06-15 02:49:02 +00:00
2015-09-08 03:02:58 +00:00
/**
* @brief Template type wrapping std::unique_ptr<atUint8[]> and signaling atdna to read a
* raw byte-buffer where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of bytes for buffer
*/
template <size_t sizeVar>
using Buffer = struct Athena::io::Buffer<sizeVar, DNAE>;
2015-09-08 03:02:58 +00:00
/**
* @brief Template type wrapping std::string and signaling atdna to read string data where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string
* -1 literal indicates null-terminated string
*/
template <atInt32 sizeVar = -1>
using String = struct Athena::io::String<sizeVar, DNAE>;
2015-09-08 03:02:58 +00:00
/**
* @brief Template type wrapping std::wstring and signaling atdna to read wstring data where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for wstring
* -1 literal indicates null-terminated wstring
*/
template <atInt32 sizeVar = -1, Endian VE = DNAE>
using WString = struct Athena::io::WString<sizeVar, VE>;
2015-09-08 03:02:58 +00:00
/**
* @brief Template type wrapping std::string and signaling atdna to read wstring data where it's used
* @tparam sizeVar C++ expression wrapped in DNA_COUNT macro to determine number of characters for string
* -1 literal indicates null-terminated string
*/
template <atInt32 sizeVar = -1>
using WStringAsString = struct Athena::io::WStringAsString<sizeVar, DNAE>;
2015-09-08 03:02:58 +00:00
/**
* @brief Meta Template signaling atdna to insert a stream seek where it's used
* @tparam offset C++ expression wrapped in DNA_COUNT macro to determine number of bytes to seek
* @tparam direction SeekOrigin to seek relative to
*/
template <off_t offset, SeekOrigin direction>
struct Seek {};
2015-09-08 03:02:58 +00:00
/**
* @brief Meta Template signaling atdna to insert an aligning stream seek where it's used
* @tparam align Number of bytes to align to
*/
template <size_t align>
struct Align {};
2015-09-08 03:02:58 +00:00
/**
* @brief Meta Template preventing atdna from emitting read/write implementations
*/
struct Delete {};
2015-10-18 04:05:35 +00:00
/**
* @brief Internal DNA helper for accumulating binarySize
* @param __isz initial size value
* @param v Vector to enumerate
* @return Cumulative total
*/
template <typename T>
static size_t __EnumerateSize(size_t __isz, const T& v)
{
for (const auto& val : v)
__isz = val.binarySize(__isz);
return __isz;
}
};
2015-09-08 03:02:58 +00:00
/**
* @brief Concrete buffer type used by DNA::Buffer
*/
template <size_t sizeVar, Endian VE>
struct Buffer : public DNA<VE>, public std::unique_ptr<atUint8[]>
{
typename DNA<VE>::Delete expl;
2015-10-18 04:05:35 +00:00
void read(IStreamReader& reader)
{
reset(new atUint8[sizeVar]);
reader.readUBytesToBuf(get(), sizeVar);
}
2015-10-18 04:05:35 +00:00
void write(IStreamWriter& writer) const
{
writer.writeUBytes(get(), sizeVar);
}
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const
{
return __isz + sizeVar;
}
};
2015-09-08 03:02:58 +00:00
/**
* @brief Concrete string type used by DNA::String
*/
template <atInt32 sizeVar, Endian VE>
struct String : public DNA<VE>, public std::string
{
typename DNA<VE>::Delete expl;
2015-10-18 04:05:35 +00:00
void read(IStreamReader& reader)
2015-07-30 06:09:37 +00:00
{this->assign(std::move(reader.readString(sizeVar)));}
2015-10-18 04:05:35 +00:00
void write(IStreamWriter& writer) const
{writer.writeString(*this, sizeVar);}
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const
{return __isz + ((sizeVar<0)?(this->size()+1):sizeVar);}
std::string& operator=(const std::string& __str)
{return this->assign(__str);}
2015-10-18 04:05:35 +00:00
std::string& operator=(std::string&& __str)
{this->swap(__str); return *this;}
};
2015-09-08 03:02:58 +00:00
/**
* @brief Concrete wstring type used by DNA::WString
*/
template <atInt32 sizeVar, Endian VE>
struct WString : public DNA<VE>, public std::wstring
{
typename DNA<VE>::Delete expl;
2015-10-18 04:05:35 +00:00
void read(IStreamReader& reader)
{
reader.setEndian(VE);
2015-07-30 06:09:37 +00:00
this->assign(std::move(reader.readWString(sizeVar)));
}
2015-10-18 04:05:35 +00:00
void write(IStreamWriter& writer) const
{
writer.setEndian(VE);
writer.writeWString(*this, sizeVar);
}
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const
{return __isz + (((sizeVar<0)?(this->size()+1):sizeVar)*2);}
std::wstring& operator=(const std::wstring& __str)
{return this->assign(__str);}
2015-10-18 04:05:35 +00:00
std::wstring& operator=(std::wstring&& __str)
{this->swap(__str); return *this;}
};
2015-09-08 03:02:58 +00:00
/**
* @brief Concrete converting-wstring type used by DNA::WStringAsString
*/
template <atInt32 sizeVar, Endian VE>
struct WStringAsString : public DNA<VE>, public std::string
{
typename DNA<VE>::Delete expl;
2015-10-18 04:05:35 +00:00
void read(IStreamReader& reader)
{*this = reader.readWStringAsString(sizeVar);}
2015-10-18 04:05:35 +00:00
void write(IStreamWriter& writer) const
{writer.writeStringAsWString(*this, sizeVar);}
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const
{return __isz + (((sizeVar<0)?(this->size()+1):sizeVar)*2);}
std::string& operator=(const std::string& __str)
{return this->assign(__str);}
2015-10-18 04:05:35 +00:00
std::string& operator=(std::string&& __str)
{this->swap(__str); return *this;}
2015-06-16 02:29:53 +00:00
};
2015-06-15 02:49:02 +00:00
2015-06-17 00:25:48 +00:00
/** Macro to automatically declare read/write methods in subclasses */
#define DECL_DNA \
void read(Athena::io::IStreamReader&); \
void write(Athena::io::IStreamWriter&) const; \
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const;
2015-06-17 00:25:48 +00:00
/** Macro to automatically declare read/write methods and prevent outputting implementation */
#define DECL_EXPLICIT_DNA \
void read(Athena::io::IStreamReader&); \
void write(Athena::io::IStreamWriter&) const; \
2015-10-18 04:05:35 +00:00
size_t binarySize(size_t __isz) const; \
Delete __dna_delete;
2015-06-20 04:40:15 +00:00
/** Macro to supply count variable to atdna and mute it for other compilers */
#ifdef __clang__
#define DNA_COUNT(cnt) sizeof(cnt)
#else
#define DNA_COUNT(cnt) 0
#endif
2015-06-15 02:49:02 +00:00
}
}
#endif // DNA_HPP