Added some SFINAE parameters for smart IO templates

This commit is contained in:
Jack Andersen 2015-08-08 13:25:18 -10:00
parent 9ed090b126
commit 9f0cb1327b
5 changed files with 249 additions and 71 deletions

View File

@ -718,27 +718,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
fileOut << " /* " << fieldName << " */\n";
if (!p)
{
fileOut << " " << fieldName << ".clear();\n"
" " << fieldName << ".reserve(" << sizeExpr << ");\n";
if (isDNAType)
fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" {\n"
" " << fieldName << ".emplace_back();\n"
" " << fieldName << ".back()." << ioOp << "\n"
" }\n";
else
fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" " << fieldName << ".push_back(" << ioOp << ");\n";
}
fileOut << " " ATHENA_DNA_READER ".enumerate(" << fieldName << ", " << sizeExpr << ");\n";
else
{
fileOut << " for (const auto& elem : " << fieldName << ")\n";
if (isDNAType)
fileOut << " elem." << ioOp << "\n";
else
fileOut << " " << ioOp << "\n";
}
fileOut << " " ATHENA_DNA_WRITER ".enumerate(" << fieldName << ");\n";
}
else if (!tsDecl->getName().compare("Buffer"))
@ -1357,42 +1339,9 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
fileOut << " /* " << fieldName << " */\n";
if (!p)
{
fileOut << " " << fieldName << ".clear();\n"
" " << fieldName << ".reserve(" << sizeExpr << ");\n"
" " ATHENA_YAML_READER ".enterSubVector(\"" << fieldNameBare << "\");\n";
if (isDNAType)
fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" {\n"
" " << fieldName << ".emplace_back();\n"
" " ATHENA_YAML_READER ".enterSubRecord(nullptr);\n"
" " << fieldName << ".back()." << ioOp << "\n"
" " ATHENA_YAML_READER ".leaveSubRecord();\n"
" }\n";
else
fileOut << " for (size_t i=0 ; i<(" << sizeExpr << ") ; ++i)\n"
" " << fieldName << ".push_back(" << ioOp << ");\n";
fileOut << " " ATHENA_YAML_READER ".leaveSubVector();\n";
}
fileOut << " " ATHENA_YAML_READER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ", " << sizeExpr << ");\n";
else
{
fileOut << " " ATHENA_YAML_WRITER ".enterSubVector(\"" << fieldNameBare << "\");\n";
if (isDNAType)
{
fileOut << " for (const auto& elem : " << fieldName << ")\n"
" {\n"
" " ATHENA_YAML_WRITER ".enterSubRecord(nullptr);\n"
" elem." << ioOp << "\n"
" " ATHENA_YAML_WRITER ".leaveSubRecord();\n"
" }\n";
}
else
{
fileOut << " for (const auto& elem : " << fieldName << ")\n"
" " << ioOp << "\n";
}
fileOut << " " ATHENA_YAML_WRITER ".leaveSubVector();\n";
}
fileOut << " " ATHENA_YAML_WRITER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n";
}
else if (!tsDecl->getName().compare("Buffer"))
@ -1496,16 +1445,12 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor<ATDNAEmitVisitor>
if (!p)
{
fileOut << " /* " << fieldName << " */\n"
" " ATHENA_YAML_READER ".enterSubRecord(\"" << fieldNameBare << "\");\n"
" " << fieldName << ".fromYAML(" ATHENA_YAML_READER ");\n"
" " ATHENA_YAML_READER ".leaveSubRecord();\n";
" " ATHENA_YAML_READER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n";
}
else
{
fileOut << " /* " << fieldName << " */\n"
" " ATHENA_YAML_WRITER ".enterSubRecord(\"" << fieldNameBare << "\");\n"
" " << fieldName << ".toYAML(" ATHENA_YAML_WRITER ");\n"
" " ATHENA_YAML_WRITER ".leaveSubRecord();\n";
" " ATHENA_YAML_WRITER ".enumerate(\"" << fieldNameBare << "\", " << fieldName << ");\n";
}
break;
}

View File

@ -1,8 +1,3 @@
# Minimal CMake project for building a static library under Windows.
cmake_minimum_required(VERSION 2.8)
project(yaml C)
set(YAML_VERSION_MAJOR 0)
set(YAML_VERSION_MINOR 1)
set(YAML_VERSION_PATCH 6)
@ -12,10 +7,8 @@ file(GLOB SRC src/*.c)
include_directories(include win32)
add_definitions(-DYAML_DECLARE_STATIC)
add_library(yaml STATIC ${SRC} include/yaml.h)
add_library(AthenaLibYaml STATIC ${SRC} include/yaml.h)
set(YAML_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "YAML include path" FORCE)
if(WIN32 AND NOT UNIX)
install(DIRECTORY include/ DESTINATION include COMPONENT yaml)
install(TARGETS yaml DESTINATION lib COMPONENT yaml)
endif()
install(DIRECTORY include/ DESTINATION include/Athena COMPONENT yaml)
install(TARGETS AthenaLibYaml DESTINATION lib COMPONENT yaml)

View File

@ -434,6 +434,14 @@ public:
m_subStack.pop_back();
}
template <class T>
void enumerate(const char* name, T& record)
{
enterSubRecord(name);
record.fromYAML(*this);
leaveSubRecord();
}
void enterSubVector(const char* name)
{
YAMLNode* curSub = m_subStack.back();
@ -458,6 +466,58 @@ public:
}
}
template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count,
typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>::type* = 0)
{
vector.clear();
vector.reserve(count);
enterSubVector(name);
for (int i=0 ; i<count ; ++i)
{
vector.emplace_back();
enterSubRecord(nullptr);
vector.back().fromYAML(*this);
leaveSubRecord();
}
leaveSubVector();
}
template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count,
typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value>::type* = 0)
{
vector.clear();
vector.reserve(count);
enterSubVector(name);
for (int i=0 ; i<count ; ++i)
vector.emplace_back(readVal<T>(name));
leaveSubVector();
}
template <class T>
void enumerate(const char* name, std::vector<T>& vector, size_t count,
std::function<void(YAMLDocReader&, T&)> readf)
{
vector.clear();
vector.reserve(count);
enterSubVector(name);
for (int i=0 ; i<count ; ++i)
{
vector.emplace_back();
enterSubRecord(nullptr);
readf(*this, vector.back());
leaveSubRecord();
}
leaveSubVector();
}
template <typename RETURNTYPE>
RETURNTYPE readVal(const char* name)
{
@ -621,6 +681,14 @@ public:
}
}
template <class T>
void enumerate(const char* name, T& record)
{
enterSubRecord(name);
record.toYAML(*this);
leaveSubRecord();
}
void enterSubVector(const char* name)
{
YAMLNode* curSub = m_subStack.back();
@ -641,6 +709,50 @@ public:
m_subStack.pop_back();
}
template <class T>
void enumerate(const char* name, const std::vector<T>& vector,
typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>::type* = 0)
{
enterSubVector(name);
for (const T& item : vector)
{
enterSubRecord(nullptr);
item.toYAML(*this);
leaveSubRecord();
}
leaveSubVector();
}
template <class T>
void enumerate(const char* name, const std::vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value>::type* = 0)
{
enterSubVector(name);
for (T item : vector)
writeVal<T>(nullptr, item);
leaveSubVector();
}
template <class T>
void enumerate(const char* name, const std::vector<T>& vector,
std::function<void(YAMLDocWriter&, const T&)> writef)
{
enterSubVector(name);
for (const T& item : vector)
{
enterSubRecord(nullptr);
writef(*this, item);
leaveSubRecord();
}
leaveSubVector();
}
bool finish(yaml_emitter_t* docOut)
{
yaml_event_t event = {YAML_DOCUMENT_START_EVENT};

View File

@ -3,6 +3,7 @@
#include <locale>
#include <codecvt>
#include <functional>
#include "IStream.hpp"
namespace Athena
@ -78,12 +79,18 @@ public:
* \return Int8 The value at the current position
*/
inline atInt8 readByte() {atInt8 val; readUBytesToBuf(&val, 1); return val;}
template <class T>
inline atInt8 readVal(typename std::enable_if<std::is_same<T, atInt8>::value>::type* = 0)
{return readByte();}
/*! \brief Reads a byte at the current position and advances the current position
*
* \return Uint8 The value at the current position
*/
inline atUint8 readUByte() {return readByte();}
template <class T>
inline atUint8 readVal(typename std::enable_if<std::is_same<T, atUint8>::value>::type* = 0)
{return readUByte();}
/*! \brief Reads a byte at the current position and advances the current position.
*
@ -124,6 +131,9 @@ public:
readUBytesToBuf(&val, 2);
return m_endian == BigEndian ? utility::BigInt16(val) : utility::LittleInt16(val);
}
template <class T>
inline atInt16 readVal(typename std::enable_if<std::is_same<T, atInt16>::value>::type* = 0)
{return readInt16();}
/*! \brief Reads a Uint16 and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -135,6 +145,9 @@ public:
*/
inline atUint16 readUint16()
{return readInt16();}
template <class T>
inline atUint16 readVal(typename std::enable_if<std::is_same<T, atUint16>::value>::type* = 0)
{return readUint16();}
/*! \brief Reads a Int32 and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -150,6 +163,9 @@ public:
readUBytesToBuf(&val, 4);
return m_endian == BigEndian ? utility::BigInt32(val) : utility::LittleInt32(val);
}
template <class T>
inline atInt32 readVal(typename std::enable_if<std::is_same<T, atInt32>::value>::type* = 0)
{return readInt32();}
/*! \brief Reads a Uint32 and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -161,6 +177,9 @@ public:
*/
inline atUint32 readUint32()
{return readInt32();}
template <class T>
inline atUint32 readVal(typename std::enable_if<std::is_same<T, atUint32>::value>::type* = 0)
{return readUint32();}
/*! \brief Reads a Int64 and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -176,6 +195,9 @@ public:
readUBytesToBuf(&val, 8);
return m_endian == BigEndian ? utility::BigInt64(val) : utility::LittleInt64(val);
}
template <class T>
inline atInt64 readVal(typename std::enable_if<std::is_same<T, atInt64>::value>::type* = 0)
{return readInt64();}
/*! \brief Reads a Uint64 and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -187,6 +209,9 @@ public:
*/
inline atUint64 readUint64()
{return readInt64();}
template <class T>
inline atUint64 readVal(typename std::enable_if<std::is_same<T, atUint64>::value>::type* = 0)
{return readUint64();}
/*! \brief Reads a float and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -202,6 +227,9 @@ public:
readUBytesToBuf(&val, 4);
return m_endian == BigEndian ? utility::BigFloat(val) : utility::LittleFloat(val);
}
template <class T>
inline float readVal(typename std::enable_if<std::is_same<T, float>::value>::type* = 0)
{return readFloat();}
/*! \brief Reads a double and swaps to proper endianness depending on platform
* and Stream settings, and advances the current position
@ -217,6 +245,9 @@ public:
readUBytesToBuf(&val, 8);
return m_endian == BigEndian ? utility::BigDouble(val) : utility::LittleDouble(val);
}
template <class T>
inline double readVal(typename std::enable_if<std::is_same<T, double>::value>::type* = 0)
{return readDouble();}
/*! \brief Reads a bool and advances the current position
*
@ -229,6 +260,9 @@ public:
readUBytesToBuf(&val, 1);
return val != 0;
}
template <class T>
inline bool readVal(typename std::enable_if<std::is_same<T, bool>::value>::type* = 0)
{return readBool();}
/*! \brief Reads an atVec2f (8 bytes) and advances the current position
*
@ -251,6 +285,9 @@ public:
}
return val;
}
template <class T>
inline atVec2f readVal(typename std::enable_if<std::is_same<T, atVec2f>::value>::type* = 0)
{return readVec2f();}
/*! \brief Reads an atVec3f (12 bytes) and advances the current position
*
@ -275,6 +312,9 @@ public:
}
return val;
}
template <class T>
inline atVec3f readVal(typename std::enable_if<std::is_same<T, atVec3f>::value>::type* = 0)
{return readVec3f();}
/*! \brief Reads an atVec4f (16 bytes) and advances the current position
*
@ -301,6 +341,9 @@ public:
}
return val;
}
template <class T>
inline atVec4f readVal(typename std::enable_if<std::is_same<T, atVec4f>::value>::type* = 0)
{return readVec4f();}
/*! \brief Reads a wide-char string, converts to UTF8 and advances the position in the file
*
@ -360,6 +403,9 @@ public:
return ret;
}
template <class T>
inline std::string readVal(typename std::enable_if<std::is_same<T, std::string>::value>::type* = 0)
{return readString();}
/*! \brief Reads a wstring and advances the position in the file
*
@ -388,6 +434,50 @@ public:
return ret;
}
template <class T>
inline std::wstring readVal(typename std::enable_if<std::is_same<T, std::wstring>::value>::type* = 0)
{return readWString();}
template<class T>
void enumerate(std::vector<T>& vector, size_t count,
typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value>::type* = 0)
{
vector.clear();
vector.reserve(count);
for (int i=0 ; i<count ; ++i)
vector.emplace_back(readVal<T>());
}
template<class T>
void enumerate(std::vector<T>& vector, size_t count,
typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>::type* = 0)
{
vector.clear();
vector.reserve(count);
for (int i=0 ; i<count ; ++i)
{
vector.emplace_back();
vector.back().read(*this);
}
}
template<class T>
void enumerate(std::vector<T>& vector, size_t count, std::function<void(IStreamReader&, T&)> readf)
{
vector.clear();
vector.reserve(count);
for (int i=0 ; i<count ; ++i)
{
vector.emplace_back();
readf(*this, vector.back());
}
}
protected:
Endian m_endian;

View File

@ -74,12 +74,14 @@ public:
* \param byte The value to write
*/
inline void writeUByte(atUint8 val) {writeUBytes(&val, 1);}
inline void writeVal(atUint8 val) {return writeUByte(val);}
/*! \brief Writes a byte at the current position and advances the position by one byte.
* \param byte The value to write
* \throw IOException
*/
inline void writeByte(atInt8 val) {writeUByte(val);}
inline void writeVal(atInt8 val) {return writeByte(val);}
/*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length
* however it's undefined behavior to try and write a buffer which is smaller than the given length.
@ -111,6 +113,7 @@ public:
utility::LittleInt16(val);
writeUBytes((atUint8*)&val, 2);
}
inline void writeVal(atInt16 val) {return writeInt16(val);}
/*! \brief Writes an Uint16 to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings
@ -119,6 +122,7 @@ public:
* \param val The value to write to the buffer
*/
inline void writeUint16(atUint16 val) {writeInt16(val);}
inline void writeVal(atUint16 val) {return writeUint16(val);}
/*! \brief Writes an Int32 to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -134,6 +138,7 @@ public:
utility::LittleInt32(val);
writeUBytes((atUint8*)&val, 4);
}
inline void writeVal(atInt32 val) {return writeInt32(val);}
/*! \brief Writes an Uint32 to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -142,6 +147,7 @@ public:
* \param val The value to write to the buffer
*/
inline void writeUint32(atUint32 val) {writeInt32(val);}
inline void writeVal(atUint32 val) {return writeUint32(val);}
/*! \brief Writes an Int64 to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -157,6 +163,7 @@ public:
utility::LittleInt64(val);
writeUBytes((atUint8*)&val, 8);
}
inline void writeVal(atInt64 val) {return writeInt64(val);}
/*! \brief Writes an Uint64 to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -165,6 +172,7 @@ public:
* \param val The value to write to the buffer
*/
inline void writeUint64(atUint64 val) {writeInt64(val);}
inline void writeVal(atUint64 val) {return writeUint64(val);}
/*! \brief Writes an float to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -180,6 +188,7 @@ public:
utility::LittleFloat(val);
writeUBytes((atUint8*)&val, 4);
}
inline void writeVal(float val) {return writeFloat(val);}
/*! \brief Writes an double to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -195,6 +204,7 @@ public:
utility::LittleDouble(val);
writeUBytes((atUint8*)&val, 8);
}
inline void writeVal(double val) {return writeDouble(val);}
/*! \brief Writes an bool to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -203,6 +213,7 @@ public:
* \param val The value to write to the buffer
*/
inline void writeBool(bool val) {writeUBytes((atUint8*)&val, 1);}
inline void writeVal(bool val) {return writeBool(val);}
/*! \brief Writes an atVec2f (8 bytes) to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -224,6 +235,7 @@ public:
}
writeUBytes((atUint8*)&vec, 8);
}
inline void writeVal(atVec2f val) {return writeVec2f(val);}
/*! \brief Writes an atVec3f (12 bytes) to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -247,6 +259,7 @@ public:
}
writeUBytes((atUint8*)&vec, 12);
}
inline void writeVal(atVec3f val) {return writeVec3f(val);}
/*! \brief Writes an atVec4f (16 bytes) to the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -272,6 +285,7 @@ public:
}
writeUBytes((atUint8*)&vec, 16);
}
inline void writeVal(atVec4f val) {return writeVec4f(val);}
/*! \brief Converts a UTF8 string to a wide-char string in the buffer and advances the buffer.
* It also swaps the bytes depending on the platform and Stream settings.
@ -351,6 +365,7 @@ public:
}
}
}
inline void writeVal(const std::string& val) {return writeString(val);}
/*! \brief Writes an wstring to the buffer and advances the buffer.
*
@ -385,12 +400,35 @@ public:
}
}
}
inline void writeVal(const std::wstring& val) {return writeWString(val);}
inline void fill(atUint8 val, atUint64 length)
{for (atUint64 l=0 ; l<length ; ++l) writeUBytes(&val, 1);}
inline void fill(atInt8 val, atUint64 length)
{fill((atUint8)val, length);}
template <class T>
void enumerate(const std::vector<T>& vector,
typename std::enable_if<std::is_arithmetic<T>::value ||
std::is_same<T, atVec2f>::value ||
std::is_same<T, atVec3f>::value ||
std::is_same<T, atVec4f>::value>::type* = 0)
{
for (const T& item : vector)
writeVal(item);
}
template <class T>
void enumerate(const std::vector<T>& vector,
typename std::enable_if<!std::is_arithmetic<T>::value &&
!std::is_same<T, atVec2f>::value &&
!std::is_same<T, atVec3f>::value &&
!std::is_same<T, atVec4f>::value>::type* = 0)
{
for (const T& item : vector)
item.write(*this);
}
protected:
Endian m_endian;
};