diff --git a/atdna/main.cpp b/atdna/main.cpp index 6f0044a..df27aa2 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "clang/AST/ASTConsumer.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" @@ -218,15 +219,31 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (vType->isVectorType()) { const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + const uint64_t width = context.getTypeInfo(eType).Width; if (!eType->isBuiltinType() || !eType->isFloatingPoint() || - context.getTypeInfo(eType).Width != 32) + (width != 32 && width != 64)) continue; if (vType->getNumElements() == 2) - return ATHENA_DNA_WRITER ".writeVec2f" + funcPrefix + "(" + fieldName + ");"; + { + if (width == 32) + return ATHENA_DNA_WRITER ".writeVec2f" + funcPrefix + "(" + fieldName + ");"; + else if (width == 64) + return ATHENA_DNA_WRITER ".writeVec2d" + funcPrefix + "(" + fieldName + ");"; + } else if (vType->getNumElements() == 3) - return ATHENA_DNA_WRITER ".writeVec3f" + funcPrefix + "(" + fieldName + ");"; + { + if (width == 32) + return ATHENA_DNA_WRITER ".writeVec3f" + funcPrefix + "(" + fieldName + ");"; + else if (width == 64) + return ATHENA_DNA_WRITER ".writeVec3d" + funcPrefix + "(" + fieldName + ");"; + } else if (vType->getNumElements() == 4) - return ATHENA_DNA_WRITER ".writeVec4f" + funcPrefix + "(" + fieldName + ");"; + { + if (width == 32) + return ATHENA_DNA_WRITER ".writeVec4f" + funcPrefix + "(" + fieldName + ");"; + else if (width == 64) + return ATHENA_DNA_WRITER ".writeVec4d" + funcPrefix + "(" + fieldName + ");"; + } } } } @@ -323,15 +340,31 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (vType->isVectorType()) { const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + const uint64_t width = context.getTypeInfo(eType).Width; if (!eType->isBuiltinType() || !eType->isFloatingPoint() || - context.getTypeInfo(eType).Width != 32) + (width != 32 && width != 64)) continue; if (vType->getNumElements() == 2) - return ATHENA_DNA_READER ".readVec2f" + funcPrefix + "()"; + { + if (width == 32) + return ATHENA_DNA_READER ".readVec2f" + funcPrefix + "()"; + else if (width == 64) + return ATHENA_DNA_READER ".readVec2d" + funcPrefix + "()"; + } else if (vType->getNumElements() == 3) - return ATHENA_DNA_READER ".readVec3f" + funcPrefix + "()"; + { + if (width == 32) + return ATHENA_DNA_READER ".readVec3f" + funcPrefix + "()"; + else if (width == 64) + return ATHENA_DNA_READER ".readVec3d" + funcPrefix + "()"; + } else if (vType->getNumElements() == 4) - return ATHENA_DNA_READER ".readVec4f" + funcPrefix + "()"; + { + if (width == 32) + return ATHENA_DNA_READER ".readVec4f" + funcPrefix + "()"; + else if (width == 64) + return ATHENA_DNA_READER ".readVec4d" + funcPrefix + "()"; + } } } } @@ -436,15 +469,31 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (vType->isVectorType()) { const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + const uint64_t width = context.getTypeInfo(eType).Width; if (!eType->isBuiltinType() || !eType->isFloatingPoint() || - context.getTypeInfo(eType).Width != 32) + (width != 32 && width != 64)) continue; if (vType->getNumElements() == 2) - return ATHENA_YAML_WRITER ".writeVec2f(\"" + bareFieldName + "\", " + fieldName + ");"; + { + if (width == 32) + return ATHENA_YAML_WRITER ".writeVec2f(\"" + bareFieldName + "\", " + fieldName + ");"; + else if (width == 64) + return ATHENA_YAML_WRITER ".writeVec2d(\"" + bareFieldName + "\", " + fieldName + ");"; + } else if (vType->getNumElements() == 3) - return ATHENA_YAML_WRITER ".writeVec3f(\"" + bareFieldName + "\", " + fieldName + ");"; + { + if (width == 32) + return ATHENA_YAML_WRITER ".writeVec3f(\"" + bareFieldName + "\", " + fieldName + ");"; + else if (width == 64) + return ATHENA_YAML_WRITER ".writeVec3d(\"" + bareFieldName + "\", " + fieldName + ");"; + } else if (vType->getNumElements() == 4) - return ATHENA_YAML_WRITER ".writeVec4f(\"" + bareFieldName + "\", " + fieldName + ");"; + { + if (width == 32) + return ATHENA_YAML_WRITER ".writeVec4f(\"" + bareFieldName + "\", " + fieldName + ");"; + else if (width == 64) + return ATHENA_YAML_WRITER ".writeVec4d(\"" + bareFieldName + "\", " + fieldName + ");"; + } } } } @@ -541,15 +590,31 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor if (vType->isVectorType()) { const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + const uint64_t width = context.getTypeInfo(eType).Width; if (!eType->isBuiltinType() || !eType->isFloatingPoint() || - context.getTypeInfo(eType).Width != 32) + (width != 32 && width != 64)) continue; if (vType->getNumElements() == 2) - return ATHENA_YAML_READER ".readVec2f(\"" + bareFieldName + "\")"; + { + if (width == 32) + return ATHENA_YAML_READER ".readVec2f(\"" + bareFieldName + "\")"; + else if (width == 64) + return ATHENA_YAML_READER ".readVec2d(\"" + bareFieldName + "\")"; + } else if (vType->getNumElements() == 3) - return ATHENA_YAML_READER ".readVec3f(\"" + bareFieldName + "\")"; + { + if (width == 32) + return ATHENA_YAML_READER ".readVec3f(\"" + bareFieldName + "\")"; + else if (width == 64) + return ATHENA_YAML_READER ".readVec3d(\"" + bareFieldName + "\")"; + } else if (vType->getNumElements() == 4) - return ATHENA_YAML_READER ".readVec4f(\"" + bareFieldName + "\")"; + { + if (width == 32) + return ATHENA_YAML_READER ".readVec4f(\"" + bareFieldName + "\")"; + else if (width == 64) + return ATHENA_YAML_READER ".readVec4d(\"" + bareFieldName + "\")"; + } } } } diff --git a/include/Athena/DNAYaml.hpp b/include/Athena/DNAYaml.hpp index ebeb2e0..6294ae3 100644 --- a/include/Athena/DNAYaml.hpp +++ b/include/Athena/DNAYaml.hpp @@ -263,7 +263,14 @@ inline RETURNTYPE NodeToVec(const YAMLNode* node) { YAMLNode* snode = it->get(); if (snode->m_type == YAML_SCALAR_NODE) - retval.vec[i] = NodeToVal(snode); + { + if (std::is_same::value || + std::is_same::value || + std::is_same::value) + retval.vec[i] = NodeToVal(snode); + else + retval.vec[i] = NodeToVal(snode); + } else retval.vec[i] = 0.0; } @@ -336,6 +343,72 @@ inline std::unique_ptr ValToNode(const atVec4f& val) return std::unique_ptr(ret); } +template <> +inline atVec2d NodeToVal(const YAMLNode* node) +{ + return NodeToVec(node); +} + +template <> +inline std::unique_ptr ValToNode(const atVec2d& val) +{ + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(2); + for (size_t i=0 ; i<2 ; ++i) + { + char str[64]; + snprintf(str, 64, "%f", val.vec[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); +} + +template <> +inline atVec3d NodeToVal(const YAMLNode* node) +{ + return NodeToVec(node); +} + +template <> +inline std::unique_ptr ValToNode(const atVec3d& val) +{ + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(3); + for (size_t i=0 ; i<3 ; ++i) + { + char str[64]; + snprintf(str, 64, "%f", val.vec[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); +} + +template <> +inline atVec4d NodeToVal(const YAMLNode* node) +{ + return NodeToVec(node); +} + +template <> +inline std::unique_ptr ValToNode(const atVec4d& val) +{ + YAMLNode* ret = new YAMLNode(YAML_SEQUENCE_NODE); + ret->m_seqChildren.reserve(4); + for (size_t i=0 ; i<4 ; ++i) + { + char str[64]; + snprintf(str, 64, "%f", val.vec[i]); + YAMLNode* comp = new YAMLNode(YAML_SCALAR_NODE); + comp->m_scalarString = str; + ret->m_seqChildren.emplace_back(comp); + } + return std::unique_ptr(ret); +} + template <> inline std::unique_ptr NodeToVal(const YAMLNode* node) { @@ -643,12 +716,26 @@ public: { return readVal(name); } - inline atVec4f readVec4f(const char* name) { return readVal(name); } + inline atVec2d readVec2d(const char* name) + { + return readVal(name); + } + + inline atVec3d readVec3d(const char* name) + { + return readVal(name); + } + + inline atVec4d readVec4d(const char* name) + { + return readVal(name); + } + inline std::unique_ptr readUBytes(const char* name) { return readVal>(name); @@ -751,7 +838,10 @@ public: typename std::enable_if::value && !std::is_same::value && !std::is_same::value && - !std::is_same::value>::type* = 0) + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value>::type* = 0) { enterSubVector(name); for (const T& item : vector) @@ -768,7 +858,10 @@ public: typename std::enable_if::value || std::is_same::value || std::is_same::value || - std::is_same::value>::type* = 0) + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type* = 0) { enterSubVector(name); for (T item : vector) @@ -898,6 +991,21 @@ public: writeVal(name, val); } + inline void writeVec2d(const char* name, const atVec2d& val) + { + writeVal(name, val); + } + + inline void writeVec3d(const char* name, const atVec3d& val) + { + writeVal(name, val); + } + + inline void writeVec4d(const char* name, const atVec4d& val) + { + writeVal(name, val); + } + inline void writeUBytes(const char* name, const std::unique_ptr& val, size_t byteCount) { writeVal&>(name, val, byteCount); diff --git a/include/Athena/IStreamReader.hpp b/include/Athena/IStreamReader.hpp index b126f72..b29801b 100644 --- a/include/Athena/IStreamReader.hpp +++ b/include/Athena/IStreamReader.hpp @@ -686,6 +686,195 @@ public: inline atVec4f readValBig(typename std::enable_if::value>::type* = 0) {return readVec4fBig();} + /** @brief Reads an atVec2d (16 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec2d readVec2d() + { + atVec2d val; + readUBytesToBuf(&val, 16); + if (m_endian == BigEndian) + { + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + } + else + { + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + } + return val; + } + template + inline atVec2d readVal(typename std::enable_if::value>::type* = 0) + {return readVec2d();} + + /** @brief Reads an atVec2d (16 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec2d readVec2dLittle() + { + atVec2d val; + readUBytesToBuf(&val, 16); + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + return val; + } + template + inline atVec2d readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec2dLittle();} + + /** @brief Reads an atVec2d (16 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec2d readVec2dBig() + { + atVec2d val; + readUBytesToBuf(&val, 16); + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + return val; + } + template + inline atVec2d readValBig(typename std::enable_if::value>::type* = 0) + {return readVec2dBig();} + + /** @brief Reads an atVec3d (24 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec3d readVec3d() + { + atVec3d val; + readUBytesToBuf(&val, 24); + if (m_endian == BigEndian) + { + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + utility::BigDouble(val.vec[2]); + } + else + { + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + utility::LittleDouble(val.vec[2]); + } + return val; + } + template + inline atVec3d readVal(typename std::enable_if::value>::type* = 0) + {return readVec3d();} + + /** @brief Reads an atVec3d (24 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec3d readVec3dLittle() + { + atVec3d val; + readUBytesToBuf(&val, 24); + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + utility::LittleDouble(val.vec[2]); + return val; + } + template + inline atVec3d readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec3dLittle();} + + /** @brief Reads an atVec3d (24 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec3d readVec3dBig() + { + atVec3d val; + readUBytesToBuf(&val, 24); + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + utility::BigDouble(val.vec[2]); + return val; + } + template + inline atVec3d readValBig(typename std::enable_if::value>::type* = 0) + {return readVec3dBig();} + + /** @brief Reads an atVec4d (32 bytes), swaps to endianness specified by setEndian depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec4d readVec4d() + { + atVec4d val; + readUBytesToBuf(&val, 32); + if (m_endian == BigEndian) + { + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + utility::BigDouble(val.vec[2]); + utility::BigDouble(val.vec[3]); + } + else + { + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + utility::LittleDouble(val.vec[2]); + utility::LittleDouble(val.vec[3]); + } + return val; + } + template + inline atVec4d readVal(typename std::enable_if::value>::type* = 0) + {return readVec4d();} + + /** @brief Reads an atVec4d (32 bytes), swaps against little endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec4d readVec4dLittle() + { + atVec4d val; + readUBytesToBuf(&val, 32); + utility::LittleDouble(val.vec[0]); + utility::LittleDouble(val.vec[1]); + utility::LittleDouble(val.vec[2]); + utility::LittleDouble(val.vec[3]); + return val; + } + template + inline atVec4d readValLittle(typename std::enable_if::value>::type* = 0) + {return readVec4dLittle();} + + /** @brief Reads an atVec4d (32 bytes), swaps against big endianness depending on platform + * and advances the current position + * + * @return The value at the current address + */ + inline atVec4d readVec4dBig() + { + atVec4d val; + readUBytesToBuf(&val, 32); + utility::BigDouble(val.vec[0]); + utility::BigDouble(val.vec[1]); + utility::BigDouble(val.vec[2]); + utility::BigDouble(val.vec[3]); + return val; + } + template + inline atVec4d readValBig(typename std::enable_if::value>::type* = 0) + {return readVec4dBig();} + /** @brief Reads a wide-char string (using endianness from setEndian), * converts to UTF8 and advances the position in the file * @@ -1025,6 +1214,12 @@ public: protected: Endian m_endian; }; +template +IStreamReader& operator>>(IStreamReader& lhs, T& rhs) +{ + rhs = lhs.readVal(rhs); + return lhs; +} } } #endif // ISTREAMREADER diff --git a/include/Athena/IStreamWriter.hpp b/include/Athena/IStreamWriter.hpp index 7468589..dd85377 100644 --- a/include/Athena/IStreamWriter.hpp +++ b/include/Athena/IStreamWriter.hpp @@ -531,6 +531,159 @@ public: } inline void writeValBig(atVec4f val) {writeVec4fBig(val);} + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + inline void writeVec2d(atVec2d vec) + { + if (m_endian == BigEndian) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + } + else + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + } + writeUBytes((atUint8*)&vec, 16); + } + inline void writeVal(atVec2d val) {writeVec2d(val);} + + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec2dLittle(atVec2d vec) + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + writeUBytes((atUint8*)&vec, 16); + } + inline void writeValLittle(atVec2d val) {writeVec2dLittle(val);} + + /** @brief Writes an atVec2d (16 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec2dBig(atVec2d vec) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + writeUBytes((atUint8*)&vec, 16); + } + inline void writeValBig(atVec2d val) {writeVec2dBig(val);} + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + inline void writeVec3d(atVec3d vec) + { + if (m_endian == BigEndian) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + utility::BigDouble(vec.vec[2]); + } + else + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + utility::LittleDouble(vec.vec[2]); + } + writeUBytes((atUint8*)&vec, 24); + } + inline void writeVal(atVec3d val) {writeVec3d(val);} + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec3dLittle(atVec3d vec) + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + utility::LittleDouble(vec.vec[2]); + writeUBytes((atUint8*)&vec, 24); + } + inline void writeValLittle(atVec3d val) {writeVec3dLittle(val);} + + /** @brief Writes an atVec3d (24 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec3dBig(atVec3d vec) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + utility::BigDouble(vec.vec[2]); + writeUBytes((atUint8*)&vec, 24); + } + inline void writeValBig(atVec3d val) {writeVec3dBig(val);} + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes depending on the platform and Stream settings. + * + * @param vec The value to write to the buffer + */ + inline void writeVec4d(atVec4d vec) + { + if (m_endian == BigEndian) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + utility::BigDouble(vec.vec[2]); + utility::BigDouble(vec.vec[3]); + } + else + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + utility::LittleDouble(vec.vec[2]); + utility::LittleDouble(vec.vec[3]); + } + writeUBytes((atUint8*)&vec, 32); + } + inline void writeVal(atVec4d val) {writeVec4d(val);} + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against little depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec4dLittle(atVec4d vec) + { + utility::LittleDouble(vec.vec[0]); + utility::LittleDouble(vec.vec[1]); + utility::LittleDouble(vec.vec[2]); + utility::LittleDouble(vec.vec[3]); + writeUBytes((atUint8*)&vec, 32); + } + inline void writeValLittle(atVec4d val) {writeVec4dLittle(val);} + + /** @brief Writes an atVec4d (32 bytes) to the buffer and advances the buffer. + * It also swaps the bytes against big depending on the platform. + * + * @param vec The value to write to the buffer + */ + inline void writeVec4dBig(atVec4d vec) + { + utility::BigDouble(vec.vec[0]); + utility::BigDouble(vec.vec[1]); + utility::BigDouble(vec.vec[2]); + utility::BigDouble(vec.vec[3]); + writeUBytes((atUint8*)&vec, 32); + } + inline void writeValBig(atVec4d val) {writeVec4dBig(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. * @@ -911,6 +1064,13 @@ public: protected: Endian m_endian; }; + +template +IStreamWriter& operator<<(IStreamWriter& lhs, const T& rhs) +{ + lhs.writeVal(rhs); + return lhs; +} } } #endif // STREAMWRITER_HPP