#ifndef DNA_HPP #define DNA_HPP /* 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' */ #include "Global.hpp" #include "IStreamReader.hpp" #include "IStreamWriter.hpp" #include #include namespace Athena { namespace io { /* forward-declaration dance for recursively-derived types */ template struct Buffer; template struct String; template struct WString; template struct WStringAsString; /** * @brief Base DNA class used against 'atdna' * * Athena bundles a build-tool called 'atdna'. This tool functions * 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 */ template struct DNA { virtual void read(IStreamReader&)=0; virtual void write(IStreamWriter&) const=0; template using Value = T; template using Vector = std::vector; template using Buffer = struct Athena::io::Buffer; template using String = struct Athena::io::String; template using WString = struct Athena::io::WString; template using WStringAsString = struct Athena::io::WStringAsString; template struct Seek {}; template struct Align {}; struct Delete {}; }; template struct Buffer : public DNA, public std::unique_ptr { typename DNA::Delete expl; inline void read(IStreamReader& reader) { reset(new atUint8[sizeVar]); reader.readUBytesToBuf(get(), sizeVar); } inline void write(IStreamWriter& writer) const { writer.writeUBytes(get(), sizeVar); } }; template struct String : public DNA, public std::string { typename DNA::Delete expl; inline void read(IStreamReader& reader) {this->assign(std::move(reader.readString(sizeVar)));} inline void write(IStreamWriter& writer) const {writer.writeString(*this, sizeVar);} inline std::string& operator=(const std::string& __str) {return this->assign(__str);} inline std::string& operator=(std::string&& __str) {this->swap(__str); return *this;} }; template struct WString : public DNA, public std::wstring { typename DNA::Delete expl; inline void read(IStreamReader& reader) { reader.setEndian(VE); this->assign(std::move(reader.readWString(sizeVar))); } inline void write(IStreamWriter& writer) const { writer.setEndian(VE); writer.writeWString(*this, sizeVar); } inline std::wstring& operator=(const std::wstring& __str) {return this->assign(__str);} inline std::wstring& operator=(std::wstring&& __str) {this->swap(__str); return *this;} }; template struct WStringAsString : public DNA, public std::string { typename DNA::Delete expl; inline void read(IStreamReader& reader) {*this = reader.readWStringAsString(sizeVar);} inline void write(IStreamWriter& writer) const {writer.writeStringAsWString(*this, sizeVar);} inline std::string& operator=(const std::string& __str) {return this->assign(__str);} inline std::string& operator=(std::string&& __str) {this->swap(__str); return *this;} }; /** Macro to automatically declare read/write methods in subclasses */ #define DECL_DNA \ void read(Athena::io::IStreamReader&); \ void write(Athena::io::IStreamWriter&) const; \ /** 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; \ Delete __dna_delete; /** 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 } } #endif // DNA_HPP